使用 webpack

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

Webpack 示例

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

webpack.config.js

  1. module.exports = {
  2. module: {
  3. rules: [
  4. {
  5. test: /\.jsx?$/,
  6. exclude: ['node_modules'],
  7. use: ['babel-loader'],
  8. },
  9. {
  10. test: /\.css$/,
  11. use: ['style-loader', 'css-loader'],
  12. },
  13. {
  14. test: /\.gif$/,
  15. type: 'asset/inline',
  16. },
  17. {
  18. test: /\.(ttf|eot|svg)$/,
  19. type: 'asset/resource',
  20. },
  21. ],
  22. },
  23. resolve: {
  24. alias: {
  25. config$: './configs/app-config.js',
  26. react: './vendor/react-master',
  27. },
  28. extensions: ['.js', '.jsx'],
  29. modules: [
  30. 'node_modules',
  31. 'bower_components',
  32. 'shared',
  33. '/shared/vendor/modules',
  34. ],
  35. },
  36. };

If you have JavaScript files that are transformed by Babel, you can enable support for Babel by installing the babel-jest plugin. Non-Babel JavaScript transformations can be handled with Jest’s transform config option. Non-Babel JavaScript transformations can be handled with Jest’s transform config option.

处理静态文件

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

jest.config.js

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

所有mock文件本身:

__mocks__/styleMock.js

  1. module.exports = {};

__mocks__/fileMock.js

  1. module.exports = 'test-file-stub';

模拟 CSS 模块

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

  • npm
  • Yarn
  1. npm install --save-dev identity-obj-proxy
  1. yarn add --dev identity-obj-proxy

然后在样式对象上,你的所有className查找都会原样返回 (如 styles.foobar === 'foobar') 这对React的Snapshot Testing是相当方便的. This is pretty handy for React Snapshot Testing.

jest.config.js (for CSS Modules)

  1. module.exports = {
  2. moduleNameMapper: {
  3. '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
  4. '<rootDir>/__mocks__/fileMock.js',
  5. '\\.(css|less)$': 'identity-obj-proxy',
  6. },
  7. };

如果 moduleNameMapper 不能满足你的需要,你就需要使用Jest的transform 来自定义对那些文件后缀应该如何转译。 例如,一个输出不带文件后缀的文件名 (such that require('logo. jpg'); returns 'logo') 应该这样写:

fileTransformer.js

  1. const path = require('path');
  2. module.exports = {
  3. process(sourceText, sourcePath, options) {
  4. return {
  5. code: `module.exports = ${JSON.stringify(path.basename(sourcePath))};`,
  6. };
  7. },
  8. };

jest.config.js (for custom transformers and CSS Modules)

  1. module.exports = {
  2. moduleNameMapper: {
  3. '\\.(css|less)$': 'identity-obj-proxy',
  4. },
  5. transform: {
  6. '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
  7. '<rootDir>/fileTransformer.js',
  8. },
  9. };

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

使用 webpack - 图1tip

记住,如果你想将它和其他代码预处理器一起使用,那必须要显式地引入默认的 babel-jest 转译器,

  1. "transform": {
  2. "\\.[jt]sx?$": "babel-jest",
  3. "\\.css$": "some-css-transformer",
  4. }

配置Jest来搜寻文件

现在Jest知道如何处理我们的文件了, 接下来我们需要告诉它如何找到它们。 For webpack’s modules, and extensions options there are direct analogs in Jest’s moduleDirectories and moduleFileExtensions options.

jest.config.js

  1. module.exports = {
  2. moduleFileExtensions: ['js', 'jsx'],
  3. moduleDirectories: ['node_modules', 'bower_components', 'shared'],
  4. moduleNameMapper: {
  5. '\\.(css|less)$': '<rootDir>/__mocks__/styleMock.js',
  6. '\\.(gif|ttf|eot|svg)$': '<rootDir>/__mocks__/fileMock.js',
  7. },
  8. };

使用 webpack - 图2note

<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, Jest’s counterpart for Webpack’s resolve.roots (an alternative to setting NODE_PATH) is modulePaths.

jest.config.js

  1. module.exports = {
  2. modulePaths: ['/shared/vendor/modules'],
  3. moduleFileExtensions: ['js', 'jsx'],
  4. moduleDirectories: ['node_modules', 'bower_components', 'shared'],
  5. moduleNameMapper: {
  6. '\\.(css|less)$': '<rootDir>/__mocks__/styleMock.js',
  7. '\\.(gif|ttf|eot|svg)$': '<rootDir>/__mocks__/fileMock.js',
  8. },
  9. };

最后,我们关注一下Webpack的alias。 在这里,我们可以再次使用 moduleNameMapper

jest.config.js

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

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

使用 webpack - 图3tip

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

使用 webpack

In addition to installing babel-jest as described earlier, you’ll need to add @babel/preset-env like so:

  • npm
  • Yarn
  1. npm install --save-dev @babel/preset-env
  1. yarn add --dev @babel/preset-env

Then, you’ll want to configure Babel as follows:

.babelrc

  1. {
  2. "presets": ["@babel/preset-env"]
  3. }

使用 webpack - 图4tip

Jest caches files to speed up test execution. If you updated .babelrc and Jest is not working as expected, try clearing the cache by running jest --clearCache.

使用 webpack - 图5tip

如果你使用动态加载 (import('some-file.js').then(module => ...)),你还需要引入Babel的动态加载插件( dynamic-import-node )。

.babelrc

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

For an example of how to use Jest with webpack with React, you can view one here.