我正在建立一个 monorepo,在其中构建一个 React 应用程序,我将在其中使用 TypeScript。我们想使用 jest 来测试后端功能,使用 React-Testing-Library 来测试前端功能。我应该安装 jest 并将配置文件添加到根目录中还是直接添加到“后端”包中?
做其中一项相对于另一项的优点/缺点是什么?
谢谢您的帮助。
只需在根目录中安装 jest 包即可。然后,添加 projects [array
jest.config.js
文件中的配置:
Jest 将同时在所有指定项目中运行测试。这对于单一存储库或同时处理多个项目时非常有用。
我的项目使用 lerna 来管理 mono 存储库。
文件夹结构:
⚡ tree -L 2 -I 'node_modules|examples'
.
├── LICENSE
├── coverage
│ ├── clover.xml
│ ├── coverage-final.json
│ ├── lcov-report
│ └── lcov.info
├── jest.config.js
├── jest.setup.js
├── lerna.json
├── package-lock.json
├── package.json
├── packages
│ ├── redux-saga-examples
│ └── redux-toolkit-example
└── tsconfig.json
5 directories, 10 files
有两个套餐:
redux-saga-examples
和redux-toolkit-example
。这些包中有很多测试文件。
根中的
package.json
:
{
"name": "root",
"private": true,
"scripts": {
"bootstrap": "lerna bootstrap",
"clean": "lerna clean",
"test": "jest"
},
"devDependencies": {
"@types/jest": "^26.0.24",
"lerna": "^4.0.0",
"jest": "^27.0.6",
"ts-jest": "^27.0.4",
"ts-node": "^9.1.1",
"typescript": "^4.3.5",
"prettier": "^2.3.1"
},
"dependencies": {
"axios": "^0.21.4"
}
}
jest.config.js
:
const reduxSagaExamplesPkg = require('./packages/redux-saga-examples/package.json');
const RTKExamplesPkg = require('./packages/redux-toolkit-example/package.json');
module.exports = {
verbose: true,
projects: [
{
preset: 'ts-jest/presets/js-with-ts',
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['./jest.setup.js'],
displayName: reduxSagaExamplesPkg.name,
testMatch: ['<rootDir>/packages/redux-saga-examples/**/?(*.)+(spec|test).[jt]s?(x)'],
},
{
preset: 'ts-jest/presets/js-with-ts',
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['./jest.setup.js'],
displayName: RTKExamplesPkg.name,
testMatch: ['<rootDir>/packages/redux-toolkit-example/**/?(*.)+(spec|test).[jt]s?(x)'],
},
],
};
现在,您可以在项目根目录中运行
npm t
npm 脚本来运行所有测试。
你需要在根项目中创建一个
jest.config.js
,你必须小心并在setupFilesAfterEnv
参数中更改每个项目的设置文件
有一些这样的内容:
module.exports = {
verbose: true,
projects: [
{
preset: 'ts-jest',
testEnvironment: 'node',
displayName: 'auth',
setupFilesAfterEnv: ['./src/auth/test/setup.ts'],
testMatch: ['<rootDir>/src/auth/**/*.test.ts'],
},
{
preset: 'ts-jest',
testEnvironment: 'node',
displayName: 'tickets',
setupFilesAfterEnv: ['./src/tickets/test/setup.ts'],
testMatch: ['<rootDir>/src/tickets/**/*.test.ts'],
},
],
};
并且必须从
package.json
中删除 jest 配置并更新每个项目的脚本
"scripts": {
"auth": "ts-node-dev src/auth/index.ts",
"tickets": "ts-node-dev src/tickets/index.ts",
"test:auth": "jest --selectProjects=auth --watchAll --no-cache",
"test:tickets": "jest --selectProjects=tickets --watchAll --no-cache"
}
在我的情况下,jest 是通过每个 package.json 中的
jest
为 packages/*
中的包配置的。
鉴于我在根包上有一个 jest.config.ts 以及
jest
和 ts-node
import { readdirSync, readFileSync } from 'fs';
import { join, resolve } from 'path';
import type { Config } from '@jest/types';
const packagesDir = resolve('./packages');
const projects: Config.InitialOptions['projects'] = readdirSync(packagesDir, {
withFileTypes: true,
})
.filter((dirent) => dirent.isDirectory())
.map((dirent) => {
const packageJsonPath = join(packagesDir, dirent.name, 'package.json');
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
return { dirent, packageJson };
})
.filter(({ packageJson }) => !!packageJson.jest)
.map(({ dirent, packageJson }) => ({
...packageJson.jest,
rootDir: join(packagesDir, dirent.name),
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
...packageJson.jest.moduleNameMapper, // preserve existing mappers if any
},
}));
const config: Config.InitialOptions = {
projects,
};
export default config;
这将扫描每个包并在根目录上组装
projects
,因此添加另一个包不需要更改配置文件。