codecamp

Jest 与 Webpack 一起使用

Jest 可以用于使用 webpack 来管理资源、 样式和编译的项目中。 webpack 确实 相比超过其他类似工具来说,展示出一些特有的优势,因为它直接与你的app整合,允许管理资源文件,如图像和字体,并带有可以将系统编译为JavaScript 语言和工具。

Webpack 示例

我们通过以下常见的webpack 配置文件,将其转化为符合Jest使用的配置。

  1. // webpack.config.js
  2. module.exports = {
  3. module: {
  4. loaders: [
  5. {exclude: ['node_modules'], loader: 'babel', test: /\.jsx?$/},
  6. {loader: 'style-loader!css-loader', test: /\.css$/},
  7. {loader: 'url-loader', test: /\.gif$/},
  8. {loader: 'file-loader', test: /\.(ttf|eot|svg)$/},
  9. ],
  10. },
  11. resolve: {
  12. alias: {
  13. config$: './configs/app-config.js',
  14. react: './vendor/react-master',
  15. },
  16. extensions: ['', 'js', 'jsx'],
  17. modules: [
  18. 'node_modules',
  19. 'bower_components',
  20. 'shared',
  21. '/shared/vendor/modules',
  22. ],
  23. },
  24. };

如果你有 Babel 转换的 JavaScript 文件,你可以通过安装babel-jest​插件来启用对 Babel 的支持。可以使用 Jest 的transform配置选项处理非 Babel JavaScript 转换。

处理静态文件

接下来,让我们配置Jest,使其优雅地处理资源文件,如样式表和图像。 通常,这些文件在测试中无足轻重,因为我们可以安全地模拟他们。 然而, 如果你使用CSS模块,那么最好是给你的类名查找模拟一个代理。

  1. // package.json
  2. {
  3. "jest": {
  4. "moduleNameMapper": {
  5. "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
  6. "\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js"
  7. }
  8. }
  9. }

所有mock文件本身:

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

模拟 CSS 模块

你可以使用 ES6 Proxy来模拟一个 CSS :

  1. yarn add --dev identity-obj-proxy

然后在样式对象上,你的所有​className​查找都会原样返回 (如 ​styles.foobar === 'foobar'​) 这对React的快照测试是相当方便的.

  1. // package.json (for CSS Modules)
  2. {
  3. "jest": {
  4. "moduleNameMapper": {
  5. "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
  6. "\\.(css|less)$": "identity-obj-proxy"
  7. }
  8. }
  9. }
请注意,代理在节点 6 中默认启用。如果你还没有使用 Node 6,请确保你使用​node --harmony_proxies node_modules/.bin/jest​.

如果​moduleNameMapper​不能满足你的要求,可以使用 Jest 的transform配置选项来指定如何转换资产。例如,一个返回文件基名的转换器(如​require('logo.jpg');​return 'logo'​)可以写成:

  1. // fileTransformer.js
  2. const path = require('path');
  3. module.exports = {
  4. process(src, filename, config, options) {
  5. return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';';
  6. },
  7. };
  1. // package.json (for custom transformers and CSS Modules)
  2. {
  3. "jest": {
  4. "moduleNameMapper": {
  5. "\\.(css|less)$": "identity-obj-proxy"
  6. },
  7. "transform": {
  8. "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/fileTransformer.js"
  9. }
  10. }
  11. }

我们已经告知Jest忽略相关匹配的样式表或者图像文件,相反,导入我们的模拟文件。 你可以通过调整正规表达式来匹配webpack可以处理的文件类型。

注:如果你babel-jest和额外的代码预处理器,你必须明确的定义babel-jest为你的Js代码的转换器,并且你需要映射所有​.js​文件到babel-jest模块。

  1. "transform": {
  2. "^.+\\.js$": "babel-jest",
  3. "^.+\\.css$": "custom-transformer",
  4. ...
  5. }

配置Jest来搜寻文件

现在Jest知道如何处理我们的文件了, 接下来我们需要告诉它如何找到它们。 webpack的​modulesDirectories​ 和 ​extensions ​选项都是和Jest的​moduleDirectories ​和 ​moduleFileExtensions​选项类似的.

  1. // package.json
  2. {
  3. "jest": {
  4. "moduleFileExtensions": ["js", "jsx"],
  5. "moduleDirectories": ["node_modules", "bower_components", "shared"],
  6. "moduleNameMapper": {
  7. "\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js",
  8. "\\.(gif|ttf|eot|svg)$": "<rootDir>/__mocks__/fileMock.js"
  9. }
  10. }
  11. }
注意:​<rootDir>​是一个特殊的标记,它会被 Jest 替换为项目的根目录。大多数情况下,这将是​package.json​所在的文件夹,​​除非​rootDir​在配置中指定自定义选项。

同样,webpack 的​resolve.root​选项功能类似于设置​​NODE_PATH​ ​可变​​变量,可以设置或使用该​modulePaths​选项。

  1. // package.json
  2. {
  3. "jest": {
  4. "modulePaths": ["/shared/vendor/modules"],
  5. "moduleFileExtensions": ["js", "jsx"],
  6. "moduleDirectories": ["node_modules", "bower_components", "shared"],
  7. "moduleNameMapper": {
  8. "\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js",
  9. "\\.(gif|ttf|eot|svg)$": "<rootDir>/__mocks__/fileMock.js"
  10. }
  11. }
  12. }

最后,我们必须处理 webpack ​alias​。为此,我们可以​moduleNameMapper​再次使用该选项。

  1. // package.json
  2. {
  3. "jest": {
  4. "modulePaths": ["/shared/vendor/modules"],
  5. "moduleFileExtensions": ["js", "jsx"],
  6. "moduleDirectories": ["node_modules", "bower_components", "shared"],
  7. "moduleNameMapper": {
  8. "\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js",
  9. "\\.(gif|ttf|eot|svg)$": "<rootDir>/__mocks__/fileMock.js",
  10. "^react(.*)$": "<rootDir>/vendor/react-master$1",
  11. "^config$": "<rootDir>/configs/app-config.js"
  12. }
  13. }
  14. }

配置完成。 webpack 是一个复杂和灵活的工具,所以你可能需要做一些调整,以符合你的特定应用的需要。 幸运的是对于大多数项目来说,使用Jest来处理webpack配置,应该会更灵活。

注︰ 对于更复杂的 webpack 配置,你可能需要研究一些项目,例如︰ babel-plugin-webpack-loaders

使用 webpack 2

webpack 2 提供原生支持ES模块。但是Jest运行在Node中,因此需要将ES模块转译为CommonJS模块。因此,如果使用 webpack 2,很可能希望配置 Babel 以仅在​test​环境中将 ES 模块转换为 CommonJS 模块。

  1. // .babelrc
  2. {
  3. "presets": [["env", {"modules": false}]],
  4. "env": {
  5. "test": {
  6. "plugins": ["transform-es2015-modules-commonjs"]
  7. }
  8. }
  9. }
注意:Jest 缓存文件以加快测试执行速度。如果更新了 .babelrc 并且 Jest 仍然无法正常工作,请尝试使用 .babelrc 运行 Jest​ --no-cache​。

如果使用动态导入 ( ​import('some-file.js').then(module => ...)​),则需要启用该​dynamic-import-node​插件。

  1. // .babelrc
  2. {
  3. "presets": [["env", {"modules": false}]],
  4. "plugins": ["syntax-dynamic-import"],
  5. "env": {
  6. "test": {
  7. "plugins": ["dynamic-import-node"]
  8. }
  9. }
  10. }

有关如何将 Jest 与 Webpack 与 React、Redux 和 Node 结合使用的示例,可以在此处查看


Jest 绕过模块模拟
Jest 与 puppeteer 一起使用
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }