Перейти до основного змісту
Version: Next

Використання з 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'). This is pretty handy for React Snapshot Testing.

// 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 для пошуку файлів#

Now that Jest knows how to process our files, we need to tell it how to find them. Для параметрів 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 your package.json is located unless you specify a custom rootDir 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.