Разрешение импорта с использованием webpack worker-loader в тестах Jest

Я пишу тест Jest, и у меня проблема с решением этого импорта, в котором используется webpack worker-loader

import ImageInfoWorker from '[email protected]/image-info';

У меня есть некоторые другие псевдонимы, которые правильно разрешаются в моих тестах, например:

import Store from '@SUPPORT/store';
import * as api from '@SUPPORT/api';

Вот соответствующий фрагмент из package.json

  "jest": {
    "moduleFileExtensions": ["js", "jsx"],
    "moduleNameMapper": {
      "^@CSS/(.*)$": "<rootDir>/css/$1",
      "^@COMPONENTS/(.*)$": "<rootDir>/js/components/$1",
      "^@MODELS/(.*)$": "<rootDir>/js/models/$1",
      "^@STORES/(.*)$": "<rootDir>/js/stores/$1",
      "^@SUPPORT/(.*)$": "<rootDir>/js/support/$1",
      "^(.*?)@WORKERS/(.*)$": "$1<rootDir>/js/workers/$2"
  }
}

И вот раздел resolve моей конфигурации webpack:

        resolve: {
          extensions: ['.js', '.jsx'],
          modules: [process.env.NODE_PATH, 'node_modules'],
          alias: {
            '@CSS':        path.join(projectRoot, 'css'),
            '@COMPONENTS': path.join(projectRoot, 'js', 'components'),
            '@MODELS':     path.join(projectRoot, 'js', 'models'),
            '@STORES':     path.join(projectRoot, 'js', 'stores'),
            '@SUPPORT':    path.join(projectRoot, 'js', 'support'),
            '@WORKERS':    path.join(projectRoot, 'js', 'workers')
        }
      },

Ответ 1

По словам cpojer, веб-работники не поддерживаются в Jest. Вы должны использовать насмешку, читайте больше здесь

Ответ 3

Этот подход сработал для меня при импорте рабочих как в линейном, так и в конфигурационном стиле.

Jest еще не поддерживает WebWorkers в комплекте с Webpack (не то, что я знаю), так что вы должны высмеивать работника. Просто извлеките функциональность вашего работника во внешний файл, а в рабочем файле выполните только рабочие биты.

@WORKERS/imageInfo.js - "мясо" вашего работника:

export default imageInfoFunction(data) {
    //...
}

@WORKERS/imageInfo.worker.js, рабочий соус:

import imageInfoFunction from "./imageInfo";

self.onmessage = async function (e) {
  self.postMessage(imageInfoFunction(e.data));
};

Таким образом, вы можете высмеивать только рабочую часть своей реализации, тестируя действительную функциональность:

mocks/imageInfo.worker.js

import imageInfoFunction from "@WORKERS/imageInfo";

export default class ImageInfoWorker {
  constructor() {
    // should be overwritten by the code using the worker
    this.onmessage = () => { };
  }

  // mock expects data: { } instead of e: { data: { } }
  postMessage(data) {
    // actual worker implementation wraps argument into { data: arg },
    // so the mock needs to fake it 
    this.onmessage({ data: imageInfoFunction (data) });
  }
}

Теперь в jest.config.js:

module.exports = {
  moduleNameMapper: {
    "@WORKERS/(.*\\.worker\\.js)$": "<rootDir>/mocks/$1",
    "@WORKERS/(.*)$": "<rootDir>/js/workers/$1",
  },
};

Обратите внимание, что я не включил встроенную конфигурацию worker-loader, но я пропустил ^(.*). Это работает, потому что нам больше не нужен worker-loader, потому что мы издеваемся над работником. Первый путь - для файлов .worker.js, которые мы хотим смоделировать, а второй - для реальной функциональности, которую мы хотим протестировать. Следующее также будет работать:

    "^(.*?)@WORKERS/(.*\\.worker\\.js)$": "<rootDir>/mocks/$2",
    "^(.*?)@WORKERS/(.*)$": "<rootDir>/js/workers/$2",

Это решение, вероятно, можно обобщить так, чтобы все работники смеялись одновременно, предложения приветствуются.