如何在Turborepo中配置ts-jest以兼容packages与apps目录测试?
Turborepo环境下ts-jest无法解析应用目录JSX测试文件的解决方案
问题场景
在Turborepo单体仓库中,/packages/ui下的组件测试能通过ts-jest正常运行,但/apps/my-app下的相同测试报错,核心错误为JSX语法无法解析:
FAIL my-app src/components/MyButton.test.tsx ● Test suite failed to run Jest encountered an unexpected token ... Details: /Users/me/repos/monorepo-root/apps/my-app/src/components/MyButton.test.tsx:14 (0, test_utils_1.render)(<MyButton_1.MyButton onClick={onClick}/>); ^ SyntaxError: Unexpected token '<'
当前公共jest配置(/packages/jest-config/jest-preset.js):
module.exports = { moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], modulePathIgnorePatterns: [ '<rootDir>/test/__fixtures__', '<rootDir>/node_modules', '<rootDir>/dist', ], projects: [{ displayName: 'ui', preset: 'ts-jest', testEnvironment: 'jest-environment-jsdom', testMatch: ['<rootDir>/../ui/**/*.@(spec|test).ts?(x)'], }, { displayName: 'my-app', preset: 'ts-jest', testEnvironment: 'jest-environment-jsdom', testMatch: ['<rootDir>/../../apps/my-app/**/*.@(spec|test).ts?(x)'], }], transform: { '^.+\\.tsx?$': 'ts-jest', }, };
仓库目录结构:
monorepo-root ├─ packages │ ├─ ui/ │ │ └─ MyButton.test.tsx # 测试通过 │ └─ jest-config/ │ └─ jest-preset.js └─ apps/ └─ my-app/ └─ MyButton.test.tsx # 测试失败
核心原因
<rootDir>路径解析混乱:多项目配置中,每个子项目的<rootDir>默认指向自身根目录,但当前testMatch使用跨目录相对路径,导致全局transform规则未正确匹配到应用目录的文件。- 子项目未继承/触发transform规则:全局配置的
transform未被每个子项目正确继承,应用目录的tsx文件未经过ts-jest转译就被Jest执行,导致JSX语法报错。
解决方法
方法1:为每个子项目明确配置根目录与transform
修改公共jest配置文件,给每个项目单独指定rootDir和transform,确保路径匹配与转译规则生效:
module.exports = { moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], modulePathIgnorePatterns: [ '<rootDir>/test/__fixtures__', '<rootDir>/node_modules', '<rootDir>/dist', ], projects: [{ displayName: 'ui', rootDir: '<rootDir>/../ui', // 明确指定ui包根目录 preset: 'ts-jest', testEnvironment: 'jest-environment-jsdom', testMatch: ['**/*.@(spec|test).ts?(x)'], transform: { '^.+\\.tsx?$': 'ts-jest', }, }, { displayName: 'my-app', rootDir: '<rootDir>/../../apps/my-app', // 明确指定应用根目录 preset: 'ts-jest', testEnvironment: 'jest-environment-jsdom', testMatch: ['**/*.@(spec|test).ts?(x)'], transform: { '^.+\\.tsx?$': 'ts-jest', }, }], };
方法2:分项目配置jest文件
在apps/my-app目录下创建独立的jest.config.js,继承公共配置:
// apps/my-app/jest.config.js module.exports = { preset: '../../packages/jest-config/jest-preset.js', rootDir: '.', testMatch: ['**/*.@(spec|test).ts?(x)'], };
同时修改公共配置为基础预设(移除多项目配置):
// packages/jest-config/jest-preset.js module.exports = { moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], modulePathIgnorePatterns: [ '<rootDir>/test/__fixtures__', '<rootDir>/node_modules', '<rootDir>/dist', ], preset: 'ts-jest', testEnvironment: 'jest-environment-jsdom', transform: { '^.+\\.tsx?$': 'ts-jest', }, };
最后在仓库根目录创建jest.config.js统一管理多项目:
// monorepo-root/jest.config.js module.exports = { projects: [ '<rootDir>/packages/ui/jest.config.js', '<rootDir>/apps/my-app/jest.config.js', ], };
方法3:排查依赖转译问题(可选)
如果应用依赖了未预编译的第三方包,需要在配置中添加transformIgnorePatterns,允许ts-jest转译这些包:
// 在对应项目的jest配置中添加 transformIgnorePatterns: [ 'node_modules/(?!(your-uncompiled-package-name)/)', ],
验证
修改配置后,运行以下命令测试应用目录的测试是否正常:
npx jest --projects apps/my-app
内容的提问来源于stack exchange,提问作者Ben Wong
相关产品推荐
相关产品推荐

