在Yarn PNP Monorepo中配置lint-staged+Jest ESM测试遇问题求助
问题背景
在Yarn PNP monorepo环境运行Jest ESM测试时,配置了lint-staged和对应的测试脚本,但提交代码时出现异常:
- 未指定
--onlyChanged/--findRelatedTests参数,Jest却自动匹配修改的文件,导致报错找不到测试 - 单独执行
yarn run staged正常,但通过lint-staged调用时失败 - 添加
--findRelatedTests参数后,提交日志显示任务成功但未实际执行测试(对应测试文件/example-project/pages/tests/CheckoutPage.test.js存在)
相关配置文件
lint-staged.config.js
// lint-staged.config.js export default { '**/*.js': [ 'eslint', 'yarn run staged', 'git add', ] }
根目录package.json(scripts片段)
"scripts": { "staged": "yarn node --experimental-vm-modules $(yarn bin jest)", ... }
根目录jest.config.js
import collectCoverageFrom from './jest.collectCoverageFrom.js' export default { collectCoverageFrom, coverageReporters: ['lcov'], modulePathIgnorePatterns: [ '<rootDir>/example-project', ], projects: [ '<rootDir>/example-project', ], testEnvironment: 'jsdom', }
example-project/jest.config.js
import { readFile } from 'fs/promises' import excludeCoverageFrom from '@monorepo/root/jest.excludeCoverageFrom.js' export default { collectCoverageFrom: [ '<rootDir>/example-project/**/*.js', ...excludeCoverageFrom, ], displayName: 'example-project', rootDir: '../', roots: ['<rootDir>/example-project'], setupFilesAfterEnv: [ // '<rootDir>/jest.window.setImmediate.js', '<rootDir>/jest.window.scrollTo.js', '<rootDir>/jest.window.TextEncoder.js', '@testing-library/jest-dom/extend-expect', ], testEnvironment: 'jsdom', moduleNameMapper: { '\\.(jpg|jpeg|png|svg|webp)$': '<rootDir>/__mocks__/mockImage.js', }, testPathIgnorePatterns: [ '/cdk.out/', '/assets-.*/', '/bundles-.*/', '/lambda-.*/', ], coverageThreshold: { global: { branches: 50, functions: 50, lines: 50, statements: 50, }, }, transformIgnorePatterns: ['node_modules/(?!uuid)'], }
错误信息
No tests found, exiting with code 1 Run with
--passWithNoTeststo exit with code 0 In /Users/Saud/git/monorepo 5641 files checked across 84 projects. Run with--verbosefor more details. Pattern: /Users/Saud/git/monorepo/example-project/pages/CheckoutPage.js - 0 matches
解决方案
1. 修复Lint-Staged自动传参问题
Lint-Staged默认会将匹配到的文件路径作为参数传递给后续命令,导致Jest尝试运行被修改的业务文件(而非测试文件)。需改用函数形式避免自动传参:
// lint-staged.config.js export default { '**/*.js': async (files) => { return [ 'eslint', 'yarn run staged', // 不自动传入修改的文件路径 'git add', ]; }, };
若要实现--findRelatedTests功能,可手动传递文件路径:
// lint-staged.config.js export default { '**/*.js': async (files) => { return [ 'eslint', `yarn run staged --findRelatedTests ${files.join(' ')}`, 'git add', ]; }, };
2. 修正Jest配置冲突
根目录jest.config.js中modulePathIgnorePatterns忽略了example-project,但又在projects中包含该子项目,导致路径匹配异常。移除该忽略规则:
// 根目录jest.config.js import collectCoverageFrom from './jest.collectCoverageFrom.js' export default { collectCoverageFrom, coverageReporters: ['lcov'], // 移除对example-project的忽略 // modulePathIgnorePatterns: [ // '<rootDir>/example-project', // ], projects: [ '<rootDir>/example-project', ], testEnvironment: 'jsdom', }
3. 确保Jest识别测试文件路径
在example-project的jest.config.js中显式指定测试文件匹配规则,避免默认规则遗漏:
// example-project/jest.config.js export default { // ...其他配置 testMatch: [ '<rootDir>/example-project/**/__tests__/**/*.js', '<rootDir>/example-project/**/?(*.)+(test).js', ], }
4. 优化Yarn PNP环境下的Jest调用
Yarn PNP环境中直接使用yarn jest替代$(yarn bin jest),避免路径解析问题:
// 根目录package.json "scripts": { "staged": "yarn node --experimental-vm-modules yarn jest", ... }
验证
修改配置后,执行git add和git commit提交修改的文件,检查测试是否正常执行。
内容的提问来源于stack exchange,提问作者Saud Punjwani

