You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

React Monorepo(Vite+npm工作区)Cypress E2E测试覆盖率未采集/上报问题求助

React Monorepo(Vite+npm工作区)Cypress E2E测试覆盖率未采集/上报问题求助

各位开发者大佬好,我目前碰到一个卡了好久的问题,想请教下大家:我用Vite+npm工作区搭建了一个React monorepo,项目结构如下:

myapp
  - packages
     - app1
       - src
         ...
       package.json
     - app2
       - src
         ...
       package.json
     - app3
       - src
         ...
       package.json
  - cypress
    - support
      e2e.js
  package.json
  cypress.config.js

先给大家看下我的核心配置:

根目录package.json

{
  "name": "myapp",
  "type": "module",
  "scripts": {
     "preview:watch": "npm run preview --workspaces --if-present",
     "e2e:open": "concurrently --kill-others \"npm run preview:watch\" \"cypress open --e2e --browser chrome\"",
     "e2e:headless": "cypress run --e2e --headless",
     "e2e:coverage": "nyc report --reporter=text --reporter=text-summary --reporter=lcov"
  },
  "nyc": {
    "report-dir": "cypress-coverage"
  },
  "dependencies": {
     "react": "^18.2.0",
     "react-dom": "^18.2.0"
  },
  "devDependencies": {
      "@cypress/code-coverage": "^3.12.44",
      "vite": "^5.0.8",
      "vite-plugin-istanbul": "^6.0.2"
  },
  "workspaces": [
    "packages/app1",
    "packages/app2",
    "packages/app3"
  ]
}

cypress.config.js

import { defineConfig } from "cypress";
import coverage from "@cypress/code-coverage/task.js";

export default defineConfig({
  e2e: {
    baseUrl: "http://localhost:3000/",
    setupNodeEvents(on, config) {
      on("task", {
        log(message) {
          console.info(message);
          return null;
        },
      });
      coverage(on, config);
      return config;
    },
  },
});

cypress/support/e2e.js

import '@cypress/code-coverage/support'
...

vite.config.js

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import istanbul from "vite-plugin-istanbul";
import path from 'path';
import { resolve } from 'path';

export default ({ mode }, packagePath, chunks) => {
  return defineConfig({
    define: {
      "process.env": JSON.stringify(process.env),
    },
    plugins: [
      react(),
      istanbul({
        include: "**",
        forceBuildInstrument: true,
        cwd: "../.."
      }),
    ],
    esbuild: {
      loader: "jsx",
    },
    build: {
      lib: {
        entry: resolve(__dirname, `${packagePath}/src/App.jsx`),
        name: "myapp",
        fileName: "index",
        formats: ["es"],
      },
      rollupOptions: {
        output: {
          entryFileNames: "index.js",
          assetFileNames: "index.css",
          manualChunks: chunks,
        },
      },
    },
    preview: {
      port: 3000,
      open: "http://localhost:8080/landing.html",
    },
    resolve: {
      alias: {
        "@parent": path.resolve(__dirname, "."),
        "@app1": path.resolve(__dirname, "./packages/app1"),
        "@app2": path.resolve(__dirname, "./packages/app2"),
        "@app3": path.resolve(__dirname, "./packages/app3")
      },
    },
  });
};

问题描述

我现在是通过npm run preview在构建阶段用vite-plugin-istanbul做代码插桩,然后运行npm run e2e:open跑E2E测试。奇怪的是,我在测试iframe里能明确看到window.__coverage__对象,说明代码确实被插桩成功了,但cypress-coverage就是没法正确采集数据,一直报这个错误:

⚠️ file /Users/abc/projects/myapp/.nyc_output/out.json has no coverage information
[1] Did you forget to instrument your web application? Read https://github.com/cypress-io/code-coverage#instrument-your-application
[1]   code-coverage ⚠️ file /Users/abc/projects/myapp/.nyc_output/out.json has no coverage information +18s

我注意到运行npm run preview时,工作目录是packages/app1,所以特意在Vite配置里把istanbul的cwd设为../..,想让它覆盖所有packages下的src文件,但还是没效果。附上截图证明iframe里确实存在__coverage__

测试iframe中的window.__coverage__

有没有大佬遇到过类似的monorepo覆盖率采集问题?求指点怎么让cypress-coverage正确识别到所有包的覆盖率数据!

备注:内容来源于stack exchange,提问作者RollADie

火山引擎 最新活动