diff --git a/packages/vitest/src/utils/graph.ts b/packages/vitest/src/utils/graph.ts index 6e714ce88..1c983fb11 100644 --- a/packages/vitest/src/utils/graph.ts +++ b/packages/vitest/src/utils/graph.ts @@ -17,7 +17,10 @@ export async function getModuleGraph( viteEnvironment?: string, ): Promise { const project = ctx.getProjectByName(projectName) - const environment = getModuleGraphEnvironment(project, testFilePath, viteEnvironment) + const environment = findModuleGraphEnvironment(project, testFilePath, viteEnvironment) + if (!environment) { + throw new Error(`Cannot find environment for ${testFilePath}`) + } const collector = createModuleGraphCollector(project, environment) const roots = collector.add(testFilePath) return { modules: collector.data.modules, roots } @@ -46,11 +49,15 @@ function getSharedModuleGraphByEnvironment( ): SharedModuleGraphByProject[string] { const collectors: { [environmentName: string]: ModuleGraphCollector } = {} for (const testModule of testModules) { - const environment = getModuleGraphEnvironment( + const environment = findModuleGraphEnvironment( project, testModule.moduleId, testModule.viteEnvironment?.name, ) + // test files that never ran (e.g. cancelled by bail) have no module graph + if (!environment) { + continue + } collectors[environment.name] ??= createModuleGraphCollector(project, environment) collectors[environment.name].add(testModule.moduleId) } @@ -62,26 +69,17 @@ function getSharedModuleGraphByEnvironment( ) } -function getModuleGraphEnvironment( +function findModuleGraphEnvironment( project: TestProject, testFilePath: string, viteEnvironment?: string, -): DevEnvironment { - let environment: DevEnvironment | undefined - +): DevEnvironment | undefined { if (viteEnvironment) { - environment = project.vite.environments[viteEnvironment] - } else { - environment = - project.config.experimental.viteModuleRunner === false - ? project.vite.environments.__vitest__ - : getTestFileEnvironment(project, testFilePath, project.config.browser.enabled) - } - - if (!environment) { - throw new Error(`Cannot find environment for ${testFilePath}`) + return project.vite.environments[viteEnvironment] } - return environment + return project.config.experimental.viteModuleRunner === false + ? project.vite.environments.__vitest__ + : getTestFileEnvironment(project, testFilePath, project.config.browser.enabled) } interface ModuleGraphCollector { diff --git a/test/e2e/test/reporters/html.test.ts b/test/e2e/test/reporters/html.test.ts index 3962c5bbc..7ef82c9af 100644 --- a/test/e2e/test/reporters/html.test.ts +++ b/test/e2e/test/reporters/html.test.ts @@ -1,6 +1,6 @@ import { playwright } from '@vitest/browser-playwright' import { expect, it } from 'vitest' -import { runInlineTests } from '#test-utils' +import { runInlineTests, StableTestFileOrderSorter } from '#test-utils' it('basic', async () => { const result = await runInlineTests( @@ -46,6 +46,56 @@ it('singleFile', async () => { expect(result.fs.statFile('.vitest/index.html').isFile()).toBe(true) }) +it('bail before all files run', async () => { + const result = await runInlineTests( + { + 'a-fail.test.ts': `test('fail', () => { expect(1).toBe(2) });`, + 'b-pass.test.ts': `test('pass', () => {});`, + }, + { + globals: true, + bail: 1, + // each file gets its own worker run, one at a time, so bail cancels b-pass.test.ts before a worker picks it up + isolate: true, + fileParallelism: false, + sequence: { sequencer: StableTestFileOrderSorter }, + reporters: ['default', 'html'], + }, + ) + expect(result.stderr).toMatchInlineSnapshot(` + " + ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯ + + FAIL a-fail.test.ts:1 > fail + AssertionError: expected 1 to be 2 // Object.is equality + + - Expected + + Received + + - 2 + + 1 + + ❯ a-fail.test.ts:1:32 + 1| test('fail', () => { expect(1).toBe(2) }); + | ^ + + ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯ + + " + `) + expect(result.errorTree()).toMatchInlineSnapshot(` + { + "a-fail.test.ts": { + "fail": [ + "expected 1 to be 2 // Object.is equality", + ], + }, + "b-pass.test.ts": {}, + } + `) + expect(result.fs.statFile('.vitest/index.html').isFile()).toBe(true) +}) + it('browser mode headless', async () => { const result = await runInlineTests( {