diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dfff4de34fc92..0ecf249f6c88b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2061,6 +2061,9 @@ importers: test/workspaces: devDependencies: + '@ampproject/remapping': + specifier: ^2.2.1 + version: 2.2.1 '@types/istanbul-lib-coverage': specifier: ^2.0.4 version: 2.0.4 diff --git a/test/workspaces/coverage-report-tests/check-coverage.test.ts b/test/workspaces/coverage-report-tests/check-coverage.test.ts index 846cbaa5d7d7a..704d6a978a436 100644 --- a/test/workspaces/coverage-report-tests/check-coverage.test.ts +++ b/test/workspaces/coverage-report-tests/check-coverage.test.ts @@ -19,3 +19,25 @@ test('file coverage summary matches', () => { expect(branches.total - branches.covered).toBe(1) expect(functions.total - functions.covered).toBe(1) }) + +test('coverage of file transformed by multiple plugins is merged correctly', async () => { + const coverageJson = JSON.parse(readFileSync('./coverage/coverage-final.json', 'utf-8')) + const coverageMap = libCoverage.createCoverageMap(coverageJson) + const fileCoverage = coverageMap.fileCoverageFor(resolve('./space-multi-transform/src/multi-transform.ts')) + const lineCoverage = fileCoverage.getLineCoverage() + + // Condition not covered by any test + expect(lineCoverage[13]).toBe(0) + + // Condition covered by Project #1 but not by Project #2 + expect(lineCoverage[18]).toBe(1) + + // Condition not covered by any test + expect(lineCoverage[22]).toBe(0) + + // Condition covered by Project #2 but not by Project #1 + expect(lineCoverage[26]).toBe(1) + + // Condition covered by both tests + expect(lineCoverage[30]).toBe(2) +}) diff --git a/test/workspaces/package.json b/test/workspaces/package.json index 10bc7a91f8bff..064db8df4f8d3 100644 --- a/test/workspaces/package.json +++ b/test/workspaces/package.json @@ -8,6 +8,7 @@ "test:coverage": "vitest run --root coverage-report-tests" }, "devDependencies": { + "@ampproject/remapping": "^2.2.1", "@types/istanbul-lib-coverage": "^2.0.4", "istanbul-lib-coverage": "^3.2.0", "jsdom": "latest", diff --git a/test/workspaces/space-multi-transform/src/multi-transform.ts b/test/workspaces/space-multi-transform/src/multi-transform.ts new file mode 100644 index 0000000000000..ee8748ba9f2e3 --- /dev/null +++ b/test/workspaces/space-multi-transform/src/multi-transform.ts @@ -0,0 +1,31 @@ +/** + * The variable below is modified by custom Vite plugin + */ +export const padding = 'default-padding' + +export function run(name: string) { + /* + * These if-branches should show correctly on coverage report. + * Otherwise source maps are off. + */ + if (name === 'not-covered') { + // This is not covered by any test + return 0 + } + // Comment + else if (name === 'project-1') { + // This is covered by Project #1 + return 1 + } + else if (name === 'not-covered-2') { + // This is not covered by any test + return 0 + } + else if (name === 'project-2') { + // This is covered by Project #2 + return 2 + } + + // This is covered by both projects, should show 2x hits + return 3 +} diff --git a/test/workspaces/space-multi-transform/test/project-1.test.ts b/test/workspaces/space-multi-transform/test/project-1.test.ts new file mode 100644 index 0000000000000..e36ba28c0484f --- /dev/null +++ b/test/workspaces/space-multi-transform/test/project-1.test.ts @@ -0,0 +1,9 @@ +import { expect, test } from 'vitest' + +import { run } from '../src/multi-transform' + +test('cover some branches', () => { + expect(run('project-1')).toBe(1) + + expect(run('last branch')).toBe(3) +}) diff --git a/test/workspaces/space-multi-transform/test/project-2.test.ts b/test/workspaces/space-multi-transform/test/project-2.test.ts new file mode 100644 index 0000000000000..ba9b85713d61e --- /dev/null +++ b/test/workspaces/space-multi-transform/test/project-2.test.ts @@ -0,0 +1,9 @@ +import { expect, test } from 'vitest' + +import { run } from '../src/multi-transform' + +test('cover some branches', () => { + expect(run('project-2')).toBe(2) + + expect(run('last branch')).toBe(3) +}) diff --git a/test/workspaces/vitest.workspace.ts b/test/workspaces/vitest.workspace.ts index 4c31ef3957cb0..08876bcbd56eb 100644 --- a/test/workspaces/vitest.workspace.ts +++ b/test/workspaces/vitest.workspace.ts @@ -1,4 +1,7 @@ import { defineWorkspace } from 'vitest/config' +import MagicString from 'magic-string' +import remapping from '@ampproject/remapping' +import type { Plugin } from 'vite' export default defineWorkspace([ './space_2/*', @@ -19,4 +22,45 @@ export default defineWorkspace([ setupFiles: ['./setup.node.ts'], }, }, + + // These two projects run on same environment but still transform + // a single file differently due to Vite plugins + { + plugins: [customPlugin(0)], + test: { + name: 'Project with custom plugin #1', + environment: 'node', + include: ['./space-multi-transform/test/project-1.test.ts'], + }, + }, + { + plugins: [customPlugin(15)], + test: { + name: 'Project with custom plugin #2', + environment: 'node', + include: ['./space-multi-transform/test/project-2.test.ts'], + }, + }, ]) + +function customPlugin(offset: number): Plugin { + return { + name: 'vitest-custom-multi-transform', + enforce: 'pre', + transform(code, id) { + if (id.includes('space-multi-transform/src/multi-transform.ts')) { + const padding = '\n*****'.repeat(offset) + + const transformed = new MagicString(code) + transformed.replace('\'default-padding\'', `\`${padding}\``) + + const map = remapping( + [transformed.generateMap({ hires: true }), this.getCombinedSourcemap() as any], + () => null, + ) as any + + return { code: transformed.toString(), map } + } + }, + } +}