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',
],
},
};
Babelで変換されたJavaScriptファイルがある場合は、babel-jest
プラグインをインストールしてBabelのサポートを有効にすることができます。Babel以外のJavaScript変換は、Jestのtransform
設定オプションで処理できます。
静的アセットの処理
次に、スタイルシートや画像などのアセットファイルを適切に処理するようにJestを設定しましょう。通常、これらのファイルはテストでは特に有用ではないため、安全にモック化できます。ただし、CSS Modulesを使用している場合は、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 Modulesのモック化
ES6プロキシを使用してCSS Modulesをモック化できます。
- 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がファイルを検出するように構成する
Jestがファイルを処理する方法を理解したので、次にファイルを検出する方法をJestに指示する必要があります。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によって置き換えられる特別なトークンです。構成でカスタムのrootDir
オプションを指定しない限り、通常はpackage.json
が配置されているフォルダーになります。
同様に、Webpackのresolve.roots
(NODE_PATH
を設定する代替手段)に対応するJestは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',
},
};
最後に、webpackのalias
を処理する必要があります。そのためには、再びmoduleNameMapper
オプションを利用できます。
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はテスト実行を高速化するためにファイルをキャッシュします。.babelrc
を更新したのにJestが期待どおりに動作しない場合は、jest --clearCache
を実行してキャッシュをクリアしてみてください。
動的インポート(import('some-file.js').then(module => ...)
)を使用する場合は、dynamic-import-node
プラグインを有効にする必要があります。
{
"presets": [["env", {"modules": false}]],
"plugins": ["syntax-dynamic-import"],
"env": {
"test": {
"plugins": ["dynamic-import-node"]
}
}
}
Reactでwebpackを使用するJestの使用方法の例については、こちらをご覧ください。