Подтвердить что ты не робот

Как использовать шутки с webpack?

Я использую webpack для разработки компонента React. Вот его простая версия:

'use strict';

require('./MyComponent.less');

var React = require('react');

var MyComponent = React.createClass({
  render() {
    return (
      <div className="my-component">
        Hello World
      </div>
    );
  }
});

module.exports = MyComponent;

Теперь я хотел бы протестировать этот компонент, используя jest. Вот соответствующий бит из моего package.json:

"scripts": {
  "test": "jest"
},
"jest": {
  "rootDir": ".",
  "testDirectoryName": "tests",
  "scriptPreprocessor": "<rootDir>/node_modules/babel-jest",
  "unmockedModulePathPatterns": [
    "react"
  ]
}

При запуске npm test я получаю следующую ошибку:

SyntaxError:/Users/mishamoroshko/react-component/src/tests/MyComponent.js:/Users/mishamoroshko/react-component/src/MyComponent.js:/Пользователи/mishamoroshko/react-component/src/MyComponent. less: Неожиданный токен ILLEGAL

Похоже, веб-пакет должен обрабатывать require('./MyComponent.less'), прежде чем jest сможет запустить тест.

Интересно, нужно ли мне использовать что-то вроде jest-webpack. Если да, есть ли способ указать несколько scriptPreprocessor s? (обратите внимание, что я уже использую babel-jest)

4b9b3361

Ответ 1

Я закончил со следующим хаком:

// package.json

"jest": {
  "scriptPreprocessor": "<rootDir>/jest-script-preprocessor",
  ...
}


// jest-script-preprocessor.js
var babelJest = require("babel-jest");

module.exports = {
  process: function(src, filename) {
    return babelJest.process(src, filename)
      .replace(/^require.*\.less.*;$/gm, '');
  }
};

Но мне все еще интересно, какое правильное решение этой проблемы.

Ответ 2

Самое чистое решение, которое я нашел для игнорирования требуемого модуля, - это использовать moduleNameMapper config (работает с последней версией 0.9.2)

Документацию трудно выполнить. Я надеюсь, что следующее поможет.

Добавьте ключ moduleNameMapper в конфигурацию packages.json. Ключ для элемента должен быть регулярным выражением нужной строки. Пример с файлами ".less":

"moduleNameMapper": { "^.*[.](less|LESS)$": "EmptyModule" },

Добавьте EmptyModule.js в корневую папку:

/**
 * @providesModule EmptyModule
 */
module.exports = '';

Комментарий важен, так как moduleNameMapper использует EmptyModule как псевдоним этого модуля (больше о предоставленииМодуля).

Теперь каждая из них требует ссылки, которая соответствует регулярному выражению, будет заменена пустой строкой.

Если вы используете конфигурацию moduleFileExtensions с файлом "js", убедитесь, что вы также добавили EmptyModule к своим "unmockedModulePathPatterns".

Вот конфигурация jest, в которую я закончил:

"jest": {
"scriptPreprocessor": "<rootDir>/node_modules/babel-jest",
"moduleFileExtensions": ["js", "json","jsx" ],
"moduleNameMapper": {
  "^.*[.](jpg|JPG|gif|GIF|png|PNG|less|LESS|css|CSS)$": "EmptyModule"
},
"preprocessorIgnorePatterns": [ "/node_modules/" ],
"unmockedModulePathPatterns": [
  "<rootDir>/node_modules/react",
  "<rootDir>/node_modules/react-dom",
  "<rootDir>/node_modules/react-addons-test-utils",
  "<rootDir>/EmptyModule.js"
]
}

Ответ 3

Я просто обнаружил, что он еще проще с конфигурацией Jest moduleNameMapper.

// package.json

"jest": {
    "moduleNameMapper": {
      "^.+\\.scss$": "<rootDir>/scripts/mocks/style-mock.js"
    }
}

// style-mock.js

module.exports = {};

Ответ 4

Недавно я опубликовал Jestpack, который может помочь. Сначала он создает ваши тестовые файлы с помощью Webpack, поэтому любое пользовательское разрешение/загрузчики модулей/плагины и т.д. Просто работают, и вы получаете JavaScript. Затем он предоставляет настраиваемый загрузчик модулей для Jest, который понимает время выполнения модуля Webpack.

Ответ 5

Я думаю, что менее взломанным решением было бы превратить ваш препроцессор в условное имя файла, соответствующее файлу javascript:

if (filename.match(/\.jsx?$/)) {
    return babelJest.process(src, filename);
} else {
    return '';
}

Это работает, даже если вы явно не устанавливаете расширение в строке require и не нуждаетесь в подстановке регулярных выражений в источнике.

Ответ 6

У меня возникла аналогичная проблема с таким шаблоном

import React, { PropTypes, Component } from 'react';
import styles from './ContactPage.css';
import withStyles from '../../decorators/withStyles';

@withStyles(styles)
class ContactPage extends Component {

см. пример https://github.com/kriasoft/react-starter-kit/blob/9204f2661ebee15dcb0b2feed4ae1d2137a8d213/src/components/ContactPage/ContactPage.js#L4-L7

Для запуска Jest у меня есть 2 проблемы:

  • импорт .css
  • Применение декоратора @withStyles (TypeError: <...> (0 , _appDecoratorsWithStyles2.default)(...) is not a function)

Первая была решена путем издевательства .css в препроцессоре script.

Вторая была решена путем исключения декораторов из автомонинга с помощью unmockedModulePathPatterns

module.exports = {
  process: function (src, filename) {

    ...

    if (filename.match(/\.css$/)) src = '';

    ...

    babel.transform(src, ...
  }
}

на основе https://github.com/babel/babel-jest/blob/77a24a71ae2291af64f51a237b2a9146fa38b136/index.js

Обратите внимание: при работе с препроцессором jest вы должны очистить кеш:

$ rm node_modules/jest-cli/.haste_cache -r

Ответ 7

Вдохновляя ответ Миши, я создал пакет NPM, который решает эту проблему, а также обрабатывает еще несколько сценариев, с которыми я столкнулся:

webpack-babel-jest

Надеюсь, это может спасти следующего человека за несколько часов.

Ответ 8

Если вы используете babel, вы можете удалить нежелательный импорт во время преобразования babel, используя что-то вроде https://github.com/Shyp/babel-plugin-import-noop и настроив .babelrc test env, чтобы использовать плагин, например:

{
  "env": {
    "development": {
      ...
    },
    "test": {
      "presets": [ ... ],
      "plugins": [
        ["import-noop", {
          "extensions": ["scss", "css"]
        }]
      ]
    }
  }
}

Ответ 9

Webpack - отличный инструмент, но мне не нужно тестировать его поведение с помощью модульных тестов Jest, а добавление сборки webpack до запуска модульных тестов только замедляет процесс. Ответ текстовой книги заключается в том, чтобы высмеять некодовые зависимости с помощью опции "moduleNameMapper"

https://facebook.github.io/jest/docs/webpack.html#handling-static-assets

Ответ 10

От Jest docs:

// in terminal, add new dependency: identity-obj-proxy
npm install --save-dev identity-obj-proxy

// package.json (for CSS Modules)
{
  "jest": {
    "moduleNameMapper": {
      "\\.(css|less)$": "identity-obj-proxy"
    }
  }
}

Вышеприведенный фрагмент перенаправляет все .less файлы в новую зависимость identity-obj-proxy, которая будет возвращать строку с именем класса при вызове, например. 'styleName' для styles.styleName.