Jest 可以用于使用 webpack 來管理資源、 樣式和編譯的項(xiàng)目中。 webpack 確實(shí) 相比超過其他類似工具來說,展示出一些特有的優(yōu)勢,因?yàn)樗苯优c你的app整合,允許管理資源文件,如圖像和字體,并帶有可以將系統(tǒng)編譯為JavaScript 語言和工具。
我們通過以下常見的webpack 配置文件,將其轉(zhuǎn)化為符合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',
],
},
};
如果你有 Babel 轉(zhuǎn)換的 JavaScript 文件,你可以通過安裝babel-jest
?插件來啟用對 Babel 的支持??梢允褂?Jest 的transform配置選項(xiàng)處理非 Babel JavaScript 轉(zhuǎn)換。
接下來,讓我們配置Jest,使其優(yōu)雅地處理資源文件,如樣式表和圖像。 通常,這些文件在測試中無足輕重,因?yàn)槲覀兛梢园踩啬M他們。 然而, 如果你使用CSS模塊,那么最好是給你的類名查找模擬一個(gè)代理。
// 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"
}
}
}
所有mock文件本身:
// __mocks__/styleMock.js
module.exports = {};
// __mocks__/fileMock.js
module.exports = 'test-file-stub';
你可以使用 ES6 Proxy來模擬一個(gè) CSS :
yarn add --dev identity-obj-proxy
然后在樣式對象上,你的所有?className
?查找都會原樣返回 (如 ?styles.foobar === 'foobar'
?) 這對React的快照測試是相當(dāng)方便的.
// 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"
}
}
}
請注意,代理在節(jié)點(diǎn) 6 中默認(rèn)啟用。如果你還沒有使用 Node 6,請確保你使用?node --harmony_proxies node_modules/.bin/jest
?.
如果?moduleNameMapper
?不能滿足你的要求,可以使用 Jest 的transform配置選項(xiàng)來指定如何轉(zhuǎn)換資產(chǎn)。例如,一個(gè)返回文件基名的轉(zhuǎn)換器(如?require('logo.jpg');
?return 'logo'
?)可以寫成:
// fileTransformer.js
const path = require('path');
module.exports = {
process(src, filename, config, options) {
return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';';
},
};
// package.json (for custom transformers and CSS Modules)
{
"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"
}
}
}
我們已經(jīng)告知Jest忽略相關(guān)匹配的樣式表或者圖像文件,相反,導(dǎo)入我們的模擬文件。 你可以通過調(diào)整正規(guī)表達(dá)式來匹配webpack可以處理的文件類型。
注:如果你babel-jest和額外的代碼預(yù)處理器,你必須明確的定義babel-jest為你的Js代碼的轉(zhuǎn)換器,并且你需要映射所有?.js
?文件到babel-jest模塊。
"transform": {
"^.+\\.js$": "babel-jest",
"^.+\\.css$": "custom-transformer",
...
}
現(xiàn)在Jest知道如何處理我們的文件了, 接下來我們需要告訴它如何找到它們。 webpack的?modulesDirectories
? 和 ?extensions
?選項(xiàng)都是和Jest的?moduleDirectories
?和 ?moduleFileExtensions
?選項(xiàng)類似的.
// 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"
}
}
}
注意:?<rootDir>
?是一個(gè)特殊的標(biāo)記,它會被 Jest 替換為項(xiàng)目的根目錄。大多數(shù)情況下,這將是?package.json
?所在的文件夾,??除非?rootDir
?在配置中指定自定義選項(xiàng)。
同樣,webpack 的?resolve.root
?選項(xiàng)功能類似于設(shè)置??NODE_PATH
? ?可變??變量,可以設(shè)置或使用該?modulePaths
?選項(xiàng)。
// 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"
}
}
}
最后,我們必須處理 webpack ?alias
?。為此,我們可以?moduleNameMapper
?再次使用該選項(xiàng)。
// 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"
}
}
}
配置完成。 webpack 是一個(gè)復(fù)雜和靈活的工具,所以你可能需要做一些調(diào)整,以符合你的特定應(yīng)用的需要。 幸運(yùn)的是對于大多數(shù)項(xiàng)目來說,使用Jest來處理webpack配置,應(yīng)該會更靈活。
注︰ 對于更復(fù)雜的 webpack 配置,你可能需要研究一些項(xiàng)目,例如︰ babel-plugin-webpack-loaders。
webpack 2 提供原生支持ES模塊。但是Jest運(yùn)行在Node中,因此需要將ES模塊轉(zhuǎn)譯為CommonJS模塊。因此,如果使用 webpack 2,很可能希望配置 Babel 以僅在?test
?環(huán)境中將 ES 模塊轉(zhuǎn)換為 CommonJS 模塊。
// .babelrc
{
"presets": [["env", {"modules": false}]],
"env": {
"test": {
"plugins": ["transform-es2015-modules-commonjs"]
}
}
}
注意:Jest 緩存文件以加快測試執(zhí)行速度。如果更新了 .babelrc 并且 Jest 仍然無法正常工作,請嘗試使用 .babelrc 運(yùn)行 Jest? --no-cache
?。
如果使用動態(tài)導(dǎo)入 ( ?import('some-file.js').then(module => ...)
?),則需要啟用該?dynamic-import-node
?插件。
// .babelrc
{
"presets": [["env", {"modules": false}]],
"plugins": ["syntax-dynamic-import"],
"env": {
"test": {
"plugins": ["dynamic-import-node"]
}
}
}
有關(guān)如何將 Jest 與 Webpack 與 React、Redux 和 Node 結(jié)合使用的示例,可以在此處查看。
更多建議: