использовать плагин webpack с тестами Mocha

Я использовал приложение create-response-app для создания приложения и выбрал конфигурацию. В webpack.config.dev.js и webpack.config.prod.js я настроил NormalModuleReplacementPlugin следующим образом:

new webpack.NormalModuleReplacementPlugin(/(.*)CUSTOMER(\.*)/, function(resource) {
  const customerName = process.env.REACT_APP_CUSTOMER;
  resource.request = resource.request.replace(/CUSTOMER/, customerName);
})

Целью этого является замена импорта, такого как

import config from '../config/customer/CUSTOMER';

с

import config from '../config/customer/foo';

когда значение переменной REACT_APP_CUSTOMER задано как "foo".

Это отлично работает, когда приложение запускается, но у меня есть некоторые тесты Mocha, которые запускаются через скрипт test-mocha в package.json

"scripts": {
  "test-mocha": "NODE_ENV=test node_modules/.bin/mocha --require babel-register --recursive test"
}

Когда этот тест выполняется, замена импорта не происходит. Кажется, что одно из следующих решений проблемы:

  • настройте NormalModuleReplacementPlugin который будет использоваться при выполнении тестов
  • найти способ предоставить макет для config при выполнении тестов

Ответы

Ответ 1

Я остановился на простом/очевидном решении:

Создайте фиктивный файл config/customer/CUSTOMER.js который содержит минимальную ожидаемую конфигурацию, например

export default {
  customerName: 'Dummy'
}

когда тесты выполняются, импорт, такой как

import config from '../config/customer/CUSTOMER';

больше не будет работать, потому что этот модуль теперь существует.

Ответ 2

Посмотрите на mocha-webpack. Как упоминалось в документах, он в основном запускает webpack test.js output.js && mocha output.js с некоторыми оптимизациями. Итак, после npm я -D mocha-webpack, ваши scripts должны выглядеть так:

"scripts": {
  "test-mocha": "NODE_ENV=test node_modules/.bin/mocha-webpack --recursive test"
}

Другой вариант, вы можете попробовать, чтобы использовать макет -r эквайер, который отвечает за насмешливый node.js модули. В вашем случае вам понадобится mock-helper.js:

"test-mocha": "NODE_ENV=test node_modules/.bin/mocha -r babel-register -r./test/mock-helper.js --recursive test"

И ./test/mock-helper.js должно быть примерно так:

const mock = require('mock-require');
const defaultCustomer = require('../config/customer/default');
const fooCustomer = require('../config/customer/foo');

const customerMock = (function () {
  switch (process.env.REACT_APP_CUSTOMER) {
    case 'foo': return fooCustomer;
    default: return defaultCustomer;
  }
}())

mock('../config/customer/CUSTOMER', customerMock);

Надеюсь, поможет.

Ответ 3

Я предлагаю вам использовать Karmajs

Karmajs - тестовый бегун, поэтому вы можете настроить его на использование мокко для запуска тестов, также вы можете предварительно обработать ваши тесты с помощью webpack, поэтому доступна вся предварительная обработка (для NormalModuleReplacementPlugin и любой другой), которая была выполнена через конфигурацию webpack когда вы выполняете тесты с кармой.

В основном, установите Карма и связанные с ней пакеты в вашем приложении

yarn add karma karma-chai-plugins karma-chrome-launcher karma-cli karma-coverage karma-mocha karma-mocha-reporter karma-sinon-chai karma-sourcemap-loader karma-webpack

Создать karma.conf.js

const webpackConfig = require('./webpack.config');
const webpack = require('webpack');
webpackConfig.devtool = 'inline-source-map';
webpackConfig.plugins = [
  new webpack.ProvidePlugin({
    'es6-promise': 'es6-promise',
  }),
];

module.exports = function (config) {
  config.set({
    browsers: [ 'Chrome' ],
    // karma only needs to know about the test bundle
    files: [
      '../node_modules/babel-polyfill/dist/polyfill.js',
      'karma.globals.js',
      'tests.bundle.js',
    ],
    frameworks: [ 'chai', 'mocha' ],
    // run the bundle through the webpack and sourcemap plugins
    preprocessors: {
      'tests.bundle.js': [ 'webpack', 'sourcemap' ],
    },
    // reporters: [ 'mocha', 'coverage' ],
    reporters: [ 'mocha' ],
    // coverageReporter: {
    //   type: 'text-summary',
    //   includeAllSources: true
    // },
    singleRun: false,
    autoWatch: true,
    // webpack config object
    webpack: webpackConfig,
    webpackMiddleware: {
      noInfo: true,
    },
  });
};

Создайте tests.bundle.js для запуска тестов для всех ваших тестовых файлов. В этом примере все наши файлы тестов имеют расширение файла .spec.js и находятся в ./src.

tests.bundle.js

const context = require.context('./src', true, /\.spec\.js$/);
context.keys().forEach(context);

export default context;

Для настройки глобальных переменных, которые должны быть доступны во всех ваших приложениях/тестах, можно установить с karma.globals.js файла karma.globals.js.

karma.globals.js

const __DEV__ = false;

const INITIAL_STATE = {
  name: 'My App',
  version: 'v2.5.6'
};

После того, как это настроено, вы можете запустить все свои тесты из каталога, в котором вы создали karma.config.js и package.json, выполнив следующую команду.

yarn karma start

Примечание. Тесты могут быть настроены для выполнения в браузерах без головного мозга (например, phantomjs), в этом примере мы используем браузер Chrome для запуска наших тестов.

Ответ 4

Вы можете добавить это в свой тестовый скрипт:

REACT_APP_CUSTOMER=foo

Таким образом, ваш тестовый скрипт становится:

"test-mocha": "NODE_ENV=test REACT_APP_CUSTOMER=foo node_modules/.bin/mocha --require babel-register --recursive test"

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