Використання з webpack
Jest може застосовуватися в проектах, які використовують webpack для керування ресурсами, стилями та компіляції коду. Порівнюючи з іншими, webpack ставить перед користувачами деякі особливі задачі, бо він напряму інтегрується у ваш застосунок для керування таблицями стилів, статичними файлами (зображень, шрифтів), разом з дедалі більшою екосистемою мов, що компілюють JavaScript, та інструментів.
Приклад використання з Webpack
Давайте почнемо із поширеного типу конфігурації webpack і створимо на його основі конфігурацію Jest.
module.exports = {
module: {
rules: [
{
test: /\.jsx?$/,
exclude: ['node_modules'],
use: ['babel-loader'],
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.gif$/,
type: 'asset/inline',
},
{
test: /\.(ttf|eot|svg)$/,
type: 'asset/resource',
},
],
},
resolve: {
alias: {
config$: './configs/app-config.js',
react: './vendor/react-master',
},
extensions: ['.js', '.jsx'],
modules: [
'node_modules',
'bower_components',
'shared',
'/shared/vendor/modules',
],
},
};
Якщо у вас є JavaScript файли, трансформовані за допомогою Babel, ви можете увімкнути підтримку Babel, встановивши плагін babel-jest
. JavaScript перетворення, до яких не залучено Babel, Jest може проводити за допомогою опції конфігурації transform
.
Обробка статичних ресурсів
Тепер давайте налаштуємо Jest для коректної обробки статичних файлів, таких, к стилі та зображення. Зазвичай ці файли непотрібні для тестів, а отже ми можемо просто їх імітувати. Проте, якщо ви використовуєте CSS модулі, краще імітувати проксі об’єкт для пошуку ваших className.
module.exports = {
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',
},
};
І вміст мок модулів:
module.exports = {};
module.exports = 'test-file-stub';
Імітація CSS модулів
Ви можете використати ES6 Proxy для імітації CSS модулів:
- npm
- Yarn
- pnpm
npm install --save-dev identity-obj-proxy
yarn add --dev identity-obj-proxy
pnpm add --save-dev identity-obj-proxy
Тоді запит className з об’єкта стилів буде повернутий як є (наприклад, styles.foobar === 'foobar'
). Це дуже зручно для тестування зі знімками React компонентів.
module.exports = {
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',
},
};
Якщо moduleNameMapper
не відповідає вашим вимогам, можна використовувати опцію конфігурації Jest transform
для вказання способу трансформації статичних файлів. Наприклад, перетворювач, що повертає базове ім'я файлу (як require('logo.jpg');
повертає 'logo'
) може мати наступний вигляд:
const path = require('path');
module.exports = {
process(sourceText, sourcePath, options) {
return {
code: `module.exports = ${JSON.stringify(path.basename(sourcePath))};`,
};
},
};
module.exports = {
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
, якщо ви хочете використовувати його разом з додатковими препроцесорами коду:
"transform": {
"\\.[jt]sx?$": "babel-jest",
"\\.css$": "some-css-transformer",
}
Налаштування Jest для пошуку файлів
Now that Jest knows how to process our files, we need to tell it how to find them. Для webpack параметрів modules
та extensions
в Jest маються аналоги у вигляді moduleDirectories
та moduleFileExtensions
.
module.exports = {
moduleFileExtensions: ['js', 'jsx'],
moduleDirectories: ['node_modules', 'bower_components', 'shared'],
moduleNameMapper: {
'\\.(css|less)$': '<rootDir>/__mocks__/styleMock.js',
'\\.(gif|ttf|eot|svg)$': '<rootDir>/__mocks__/fileMock.js',
},
};
<rootDir>
- це спеціальний токен, який Jest замінює на кореневий каталог вашого проєкту. В більшості випадків, це буде каталог, який містить ваш package.json
, за винятком, коли ви вказали власний параметр rootDir
у вашій конфігурації.
Аналогічно, Jest варіацією Webpack параметру resolve.roots
(альтернатива заданню NODE_PATH
) є modulePaths
.
module.exports = {
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.
module.exports = {
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
На додачу до встановлення babel-jest
, як описувалось раніше, вам треба буде додати @babel/preset-env
:
- npm
- Yarn
- pnpm
npm install --save-dev @babel/preset-env
yarn add --dev @babel/preset-env
pnpm add --save-dev @babel/preset-env
Після цього, ви можете налаштувати Babel наступним чином:
{
"presets": ["@babel/preset-env"]
}
Jest caches files to speed up test execution. If you updated .babelrc
and Jest is not working as expected, try clearing the cache by running jest --clearCache
.
If you use dynamic imports (import('some-file.js').then(module => ...)
), you need to enable the dynamic-import-node
plugin.
{
"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, you can view one here.