Usando com webpack
Jest can be used in projects that use webpack to manage assets, styles, and compilation. 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.
Um exemplo de webpack
Vamos começar com um tipo comum de arquivo de configuração webpack e traduzi-lo para uma instalação de 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',
],
},
};
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.
Manipulação de assets estáticos
Em seguida, vamos configurar o Jest para manipular elegantemente arquivos de assets, tais como folhas de estilo e imagens. Normalmente, esses arquivos não são particularmente úteis em testes, por isso podemos com segurança fazer a simulação (mock, em inglês) deles. No entanto, se você estiver usando CSS Modules é melhor simular (mock, em inglês) de um proxy para suas pesquisas 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',
},
};
E os próprios arquivos de simulação (mock, em inglês):
module.exports = {};
module.exports = 'test-file-stub';
Simulando CSS Modules
You can use an ES6 Proxy to mock CSS Modules:
- npm
- Yarn
- pnpm
- Bun
npm install --save-dev identity-obj-proxy
yarn add --dev identity-obj-proxy
pnpm add --save-dev identity-obj-proxy
bun add --dev identity-obj-proxy
Then all your className lookups on the styles object will be returned as-is (e.g., styles.foobar === 'foobar'). This is pretty handy for React Snapshot Testing.
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',
},
};
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:
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',
},
};
Nós dissemos para Jest ignorar arquivos que correspondam a uma folha de estilo ou extensão de imagem, e em vez disso, exigem nossos arquivos de simulação (mock, em inglês). Você pode ajustar a expressão regular para coincidir com os tipos de arquivo que sua configuração do webpack lida.
Remember to include the default babel-jest transformer explicitly, if you wish to use it alongside with additional code preprocessors:
"transform": {
"\\.[jt]sx?$": "babel-jest",
"\\.css$": "some-css-transformer",
}
Configurando Jest para encontrar nossos arquivos
Now that Jest knows how to process our files, we need to tell it how to find them. For webpack's modules, and extensions options there are direct analogs in Jest's moduleDirectories and moduleFileExtensions options.
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> 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, Jest's counterpart for Webpack's resolve.roots (an alternative to setting NODE_PATH) is 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',
},
};
É isso! webpack é uma ferramenta complexa e flexível, então você pode ter que fazer alguns ajustes para atender às necessidades específicas do seu aplicativo. Felizmente, na maioria dos projetos, Jest deve ser flexível o suficiente para lidar com sua configuração do webpack.
For more complex webpack configurations, you may also want to investigate projects such as: babel-plugin-webpack-loaders.
Usando com webpack
In addition to installing babel-jest as described earlier, you'll need to add @babel/preset-env like so:
- npm
- Yarn
- pnpm
- Bun
npm install --save-dev @babel/preset-env
yarn add --dev @babel/preset-env
pnpm add --save-dev @babel/preset-env
bun add --dev @babel/preset-env
Then, you'll want to configure Babel as follows:
{
"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.