Aller au contenu principal
Version: Suivant

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

Nous avons dit à Jest d'ignorer les fichiers correspondant à une extension de feuille de style ou d'image, et à la place, de demander nos fichiers simulés. Vous pouvez ajuster l'expression régulière pour qu'elle corresponde aux types de fichiers que votre configuration webpack gère.

Remarque : si vous utilisez babel-jest avec des préprocesseurs de code supplémentaires, vous devez définir explicitement babel-jest comme transformateur pour votre code JavaScript afin de faire correspondre les fichiers .js au module babel-jest.

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

Configuration de Jest pour trouver nos fichiers#

Maintenant que Jest sait comment traiter nos fichiers, nous devons lui dire comment les trouver. Pour les options modulesDirectories, et extensions de webpack, il existe des analogues directs dans les options moduleDirectories et moduleFileExtensions de Jest.

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

Remarque : <rootDir> est un jeton spécial qui est remplacé par Jest avec la racine de votre projet. La plupart du temps, il s'agira du dossier où se trouve votre package.json, sauf si vous spécifiez une option rootDir personnalisée dans votre configuration.

De même, l'option resolve.root de webpack fonctionne comme la définition de la variable env NODE_PATH, que vous pouvez définir, ou faire appel à l'option modulePaths.

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

Et enfin, nous devons gérer l'alias webpack. Pour cela, nous pouvons à nouveau utiliser l'option moduleNameMapper.

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

C'est tout ! webpack est un outil complexe et flexible. Il se peut donc que vous deviez procéder à quelques ajustements pour répondre aux besoins spécifiques de votre application. Heureusement pour la plupart des projets, Jest devrait être plus que suffisamment flexible pour gérer votre configuration webpack.

Remarque : pour des configurations plus complexes de webpack, vous pouvez également étudier des projets tels que : babel-plugin-webpack-loaders.

Utilisation avec Webpack 2#

webpack 2 offre un support natif pour les modules ES. Cependant, Jest s'exécute dans Node, et nécessite donc que les modules ES soient transpilés dans des modules CommonJS. En tant que tel, si vous utilisez webpack 2, vous voudrez probablement configurer Babel pour transposer des modules ES dans des modules CommonJS uniquement dans l'environnement test.

// .babelrc
{
"presets": [["env", {"modules": false}]],
"env": {
"test": {
"plugins": ["transform-es2015-modules-commonjs"]
}
}
}

Remarque : Jest met en cache les fichiers pour accélérer l'exécution du test. Si vous avez mis à jour .babelrc et que Jest ne fonctionne toujours pas, essayez d'exécuter Jest avec --no-cache.

Si vous utilisez des importations dynamiques (import('some-file.js').then(module => ...)), vous devez activer le plugin dynamic-import-node.

// .babelrc
{
"presets": [["env", {"modules": false}]],
"plugins": ["syntax-dynamic-import"],
"env": {
"test": {
"plugins": ["dynamic-import-node"]
}
}
}

Pour un exemple d'utilisation de Jest avec Webpack, React, Redux et Node, vous pouvez en voir un ici.