You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Yarn PNP Monorepo中配置lint-staged+Jest ESM测试遇问题求助

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 --passWithNoTests to exit with code 0 In /Users/Saud/git/monorepo 5641 files checked across 84 projects. Run with --verbose for 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 03:38:14