Aller au contenu principal
Version: 27.0

Utilisation avec webpack

Jest peut être utilisé dans les projets qui utilisent webpack pour gérer les ressources, les styles et la compilation. webpack doit offrir quelques défis uniques par rapport à d'autres outils car il s'intègre directement à votre application pour permettre la gestion des feuilles de style, des ressources comme les images et les polices, ainsi que l'écosystème expansif des langages et outils de compilation vers JavaScript.

Un exemple avec Webpack#

Commençons par un fichier de configuration commun de webpack et transposons-le dans une configuration 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',
],
},
};

Si vous avez des fichiers JavaScript qui sont transformés par Babel, vous pouvez activer le support de Babel en installant le plugin babel-jest. Les transformations JavaScript non-Babel peuvent être gérées avec l'option de config transform de Jest.

Gestion des ressources statiques#

Ensuite, configurons Jest pour qu'il gère de manière efficace les fichiers de ressources tels que les feuilles de style et les images. En général, ces fichiers ne sont pas particulièrement utiles dans les tests, nous pouvons donc les éliminer sans risque. Toutefois, si vous utilisez des modules CSS, il est préférable de simuler un proxy pour vos recherches de 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"
}
}
}

Et les fichiers simulés eux-mêmes :

// __mocks__/styleMock.js
module.exports = {};
// __mocks__/fileMock.js
module.exports = 'test-file-stub';

Simulé CSS Modules#

Vous pouvez utiliser un ES6 Proxy pour simuler les modules CSS :

yarn add --dev identity-obj-proxy

Ensuite, toutes vos recherches de className sur l'objet styles seront retournées telles quelles (par exemple, styles.foobar === 'foobar'). C'est assez pratique pour le test de Snapshot de React.

// package.json (for 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"
}
}
}

Notez que le proxy est activé par défaut dans Node 6. Si vous n'êtes pas encore sur Node 6, assurez-vous d'appeler Jest en utilisant node --harmony_proxies node_modules/.bin/jest.

Si moduleNameMapper ne peut pas répondre à vos besoins, vous pouvez utiliser l'option de configuration transform de Jest pour spécifier comment les ressources sont transformées. Par exemple, un transformateur qui retourne le nom de base d'un fichier (tel que require('logo.jpg'); qui retourne 'logo') peut être écrit ainsi :

// fileTransformer.js
const path = require('path');
module.exports = {
process(src, filename, config, options) {
return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';';
},
};
// package.json (pour les transformateurs personnalisés et les modules CSS)
{
"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"
}
}
}

We've told Jest to ignore files matching a stylesheet or image extension, and instead, require our mock files. You can adjust the regular expression to match the file types your webpack config handles.

Note: if you are using babel-jest with additional code preprocessors, you have to explicitly define babel-jest as a transformer for your JavaScript code to map .js files to the babel-jest module.

"transform": {
"\\.js$": "babel-jest",
"\\.css$": "custom-transformer",
...
}

Configuring Jest to find our files#

Now that Jest knows how to process our files, we need to tell it how to find them. For webpack's modulesDirectories, and extensions options there are direct analogs in Jest's moduleDirectories and moduleFileExtensions options.

// 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"
}
}
}

That's it! webpack is a complex and flexible tool, so you may have to make some adjustments to handle your specific application's needs. Luckily for most projects, Jest should be more than flexible enough to handle your webpack config.

Note: For more complex webpack configurations, you may also want to investigate projects such as: babel-plugin-webpack-loaders.

Utilisation avec Webpack 2#

webpack 2 offers native support for ES modules. 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.