Using with webpack
Jest може застосовуватися в проектах, які використовують webpack для керування ресурсами, стилями та компіляції коду. webpack does offer some unique challenges over other tools because it integrates directly with your application to allow managing stylesheets, assets like images and fonts, along with the expansive ecosystem of compile-to-JavaScript languages and tools.
Приклад використання з Webpack
Давайте почнемо із поширеного типу конфігурації webpack і створимо на його основі конфігурацію Jest.
// webpack.config.js
module.exports = {
module: {
loaders: [
{exclude: ['node_modules'], loader: 'babel', test: /\.jsx?$/},
{loader: 'style-loader!css-loader', test: /\.css$/},
{loader: 'url-loader', test: /\.gif$/},
{loader: 'file-loader', test: /\.(ttf|eot|svg)$/},
],
},
resolve: {
alias: {
config$: './configs/app-config.js',
react: './vendor/react-master',
},
extensions: ['', 'js', 'jsx'],
modules: [
'node_modules',
'bower_components',
'shared',
'/shared/vendor/modules',
],
},
};
If you have JavaScript files that are transformed by Babel, you can enable support for Babel by installing the babel-jest
plugin. Non-Babel JavaScript transformations can be handled with Jest's transform
config option.
Обробка статичних ресурсів
Тепер давайте налаштуємо Jest для коректної обробки статичних файлів, таких, к стилі та зображення. Зазвичай ці файли непотрібні для тестів, а отже ми можемо просто їх імітувати. Проте, якщо ви використовуєте CSS модулі, краще імітувати проксі об’єкт для пошуку ваших className.
// package.json
{
"jest": {
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js"
}
}
}
І вміст мок модулів:
// __mocks__/styleMock.js
module.exports = {};
// __mocks__/fileMock.js
module.exports = 'test-file-stub';
Імітація CSS модулів
Ви можете використати ES6 Proxy для іімтації CSS модулів:
yarn add --dev identity-obj-proxy
Тоді запит className з об’єкта стилів буде повернутий як є (наприклад, styles.foobar === 'foobar'
). Це дуже зручно для тестування зі знімками React компонентів.
// package.json (для CSS Modules)
{
"jest": {
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"\\.(css|less)$": "identity-obj-proxy"
}
}
}
Notice that Proxy is enabled in Node 6 by default. If you are not on Node 6 yet, make sure you invoke Jest using
node --harmony_proxies node_modules/.bin/jest
.
If moduleNameMapper
cannot fulfill your requirements, you can use Jest's transform
config option to specify how assets are transformed. For example, a transformer that returns the basename of a file (such that require('logo.jpg');
returns 'logo'
) can be written as:
// fileTransformer.js
const path = require('path');
module.exports = {
process(src, filename, config, options) {
return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';';
},
};
// package.json (for custom transformers and CSS Modules)
{
"jest": {
"moduleNameMapper": {
"\\.(css|less)$": "identity-obj-proxy"
},
"transform": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/fileTransformer.js"
}
}
}
Ми вказали Jest ігнорувати файли, які відповідають розширенню стилів та зображень, і, замість цього, викликати наші мок файли. Ви можете налаштувати решулярні вирази, щоб обробляти типи файлів, які обробляє ваша конфігурація webpack.
Примітка: якщо ви використовуєте babel-jest з додатковими препроцесорами коду, вам потрібно явно вказати babel-jest, як обробник вашого JavaScript коду, вказавши для трансформації файлів з розширеннями .js
модуль babel-jest.
"transform": {
"\\.js$": "babel-jest",
"\\.css$": "custom-transformer",
...
}
Налаштування Jest для пошуку файлів
Тепер, коли Jest знає як обробляти наші файли, нам потрібно пояснити йому, як їх знайти. Для параметрів webpack modulesDirectories
та extensions
є прямі аналоги в Jest: moduleDirectories
та moduleFileExtensions
.
// package.json
{
"jest": {
"moduleFileExtensions": ["js", "jsx"],
"moduleDirectories": ["node_modules", "bower_components", "shared"],
"moduleNameMapper": {
"\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js",
"\\.(gif|ttf|eot|svg)$": "<rootDir>/__mocks__/fileMock.js"
}
}
}
Note:
<rootDir>
is a special token that gets replaced by Jest with the root of your project. Most of the time this will be the folder where yourpackage.json
is located unless you specify a customrootDir
option in your configuration.
Similarly, webpack's resolve.root
option functions like setting the NODE_PATH
env variable, which you can set, or make use of the modulePaths
option.
// package.json
{
"jest": {
"modulePaths": ["/shared/vendor/modules"],
"moduleFileExtensions": ["js", "jsx"],
"moduleDirectories": ["node_modules", "bower_components", "shared"],
"moduleNameMapper": {
"\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js",
"\\.(gif|ttf|eot|svg)$": "<rootDir>/__mocks__/fileMock.js"
}
}
}
And finally, we have to handle the webpack alias
. For that, we can make use of the moduleNameMapper
option again.
// package.json
{
"jest": {
"modulePaths": ["/shared/vendor/modules"],
"moduleFileExtensions": ["js", "jsx"],
"moduleDirectories": ["node_modules", "bower_components", "shared"],
"moduleNameMapper": {
"\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js",
"\\.(gif|ttf|eot|svg)$": "<rootDir>/__mocks__/fileMock.js",
"^react(.*)$": "<rootDir>/vendor/react-master$1",
"^config$": "<rootDir>/configs/app-config.js"
}
}
}
Ось і все! webpack - це складний і гнучкий інструмент, тому вам, можливо, доведеться зробити деякі додаткові налаштування, щоб підтримувати специфічні вимоги вашого проекту. На щастя, для більшості проектів, Jest повинен бути більш ніж достатньо гнучкими, щоб підтримувати ваші конфігурації webpack.
Примітка: Для підтримки більш складних конфігурацій webpack ви також можете ознайомитися з такими проектами, як: babel-plugin-webpack-loaders.
Використання з webpack 2
webpack 2 пропонує вбудовану підтримку для ES модулів. However, Jest runs in Node, and thus requires ES modules to be transpiled to CommonJS modules. As such, if you are using webpack 2, you most likely will want to configure Babel to transpile ES modules to CommonJS modules only in the test
environment.
// .babelrc
{
"presets": [["env", {"modules": false}]],
"env": {
"test": {
"plugins": ["transform-es2015-modules-commonjs"]
}
}
}
Note: Jest caches files to speed up test execution. If you updated .babelrc and Jest is still not working, try running Jest with
--no-cache
.
If you use dynamic imports (import('some-file.js').then(module => ...)
), you need to enable the dynamic-import-node
plugin.
// .babelrc
{
"presets": [["env", {"modules": false}]],
"plugins": ["syntax-dynamic-import"],
"env": {
"test": {
"plugins": ["dynamic-import-node"]
}
}
}
For an example of how to use Jest with Webpack with React, Redux, and Node, you can view one here.