From a084ceafb371b1f6078bf3b63ae0b3fd47bdd4d6 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Mon, 18 Sep 2023 12:59:24 +0200 Subject: [PATCH] fix(vitest): rerun tests if a file loaded with query changes (#4130) --- packages/vitest/src/node/core.ts | 50 ++++++++++++--------------- packages/vitest/src/node/workspace.ts | 7 ++++ test/watch/fixtures/42.txt | 1 + test/watch/fixtures/example.test.ts | 7 ++++ test/watch/test/file-watching.test.ts | 12 +++++++ 5 files changed, 50 insertions(+), 27 deletions(-) create mode 100644 test/watch/fixtures/42.txt diff --git a/packages/vitest/src/node/core.ts b/packages/vitest/src/node/core.ts index dd3baec355e8..3b34455b8080 100644 --- a/packages/vitest/src/node/core.ts +++ b/packages/vitest/src/node/core.ts @@ -586,7 +586,7 @@ export class Vitest { public getModuleProjects(id: string) { return this.projects.filter((project) => { - return project.getModuleById(id) + return project.getModulesByFilepath(id).size // TODO: reevaluate || project.browser?.moduleGraph.getModulesByFile(id)?.size }) } @@ -596,9 +596,13 @@ export class Vitest { const updateLastChanged = (id: string) => { const projects = this.getModuleProjects(id) projects.forEach(({ server, browser }) => { - const mod = server.moduleGraph.getModuleById(id) || browser?.moduleGraph.getModuleById(id) - if (mod) - server.moduleGraph.invalidateModule(mod) + const serverMods = server.moduleGraph.getModulesByFile(id) + serverMods?.forEach(mod => server.moduleGraph.invalidateModule(mod)) + + if (browser) { + const browserMods = browser.moduleGraph.getModulesByFile(id) + browserMods?.forEach(mod => browser.moduleGraph.invalidateModule(mod)) + } }) } @@ -675,22 +679,10 @@ export class Vitest { const files: string[] = [] for (const project of projects) { - const { server, browser } = project - const mod = server.moduleGraph.getModuleById(id) || browser?.moduleGraph.getModuleById(id) - if (!mod) { - // files with `?v=` query from the browser - const mods = browser?.moduleGraph.getModulesByFile(id) - if (!mods?.size) - return [] - let rerun = false - mods.forEach((m) => { - if (m.id && this.handleFileChanged(m.id)) - rerun = true - }) - if (rerun) - files.push(id) + const { server } = project + const mods = project.getModulesByFilepath(id) + if (!mods.size) continue - } // remove queries from id id = normalizeRequestId(id, server.config.base) @@ -705,14 +697,18 @@ export class Vitest { } let rerun = false - mod.importers.forEach((i) => { - if (!i.id) - return - - const heedsRerun = this.handleFileChanged(i.id) - if (heedsRerun) - rerun = true - }) + for (const mod of mods) { + if (!mod.id) + continue + mod.importers.forEach((i) => { + if (!i.id) + return + + const heedsRerun = this.handleFileChanged(i.id) + if (heedsRerun) + rerun = true + }) + } if (rerun) files.push(id) diff --git a/packages/vitest/src/node/workspace.ts b/packages/vitest/src/node/workspace.ts index 02a3ce48d4e4..96638ab67fe3 100644 --- a/packages/vitest/src/node/workspace.ts +++ b/packages/vitest/src/node/workspace.ts @@ -77,6 +77,13 @@ export class WorkspaceProject { return this.ctx.getCoreWorkspaceProject() === this } + // it's possible that file path was imported with different queries (?raw, ?url, etc) + getModulesByFilepath(file: string) { + const set = this.server.moduleGraph.getModulesByFile(file) + || this.browser?.moduleGraph.getModulesByFile(file) + return set || new Set() + } + getModuleById(id: string) { return this.server.moduleGraph.getModuleById(id) || this.browser?.moduleGraph.getModuleById(id) diff --git a/test/watch/fixtures/42.txt b/test/watch/fixtures/42.txt new file mode 100644 index 000000000000..d81cc0710eb6 --- /dev/null +++ b/test/watch/fixtures/42.txt @@ -0,0 +1 @@ +42 diff --git a/test/watch/fixtures/example.test.ts b/test/watch/fixtures/example.test.ts index 4fd8bd10912c..8ca564f5fb2e 100644 --- a/test/watch/fixtures/example.test.ts +++ b/test/watch/fixtures/example.test.ts @@ -2,6 +2,13 @@ import { expect, test } from 'vitest' import { getHelloWorld } from './example' +// @ts-expect-error not typed txt +import answer from './42.txt?raw' + +test('answer is 42', () => { + expect(answer).toContain('42') +}) + test('getHello', async () => { expect(getHelloWorld()).toBe('Hello world') }) diff --git a/test/watch/test/file-watching.test.ts b/test/watch/test/file-watching.test.ts index c79754985307..6533a78ad1d8 100644 --- a/test/watch/test/file-watching.test.ts +++ b/test/watch/test/file-watching.test.ts @@ -50,6 +50,18 @@ test('editing source file triggers re-run', async () => { await vitest.waitForStdout('1 passed') }) +test('editing file that was imported with a query reruns suite', async () => { + const vitest = await runVitestCli(...cliArgs) + + testUtils.editFile( + testUtils.resolvePath(import.meta.url, '../fixtures/42.txt'), + file => `${file}\n`, + ) + + await vitest.waitForStdout('RERUN ../42.txt') + await vitest.waitForStdout('1 passed') +}) + test('editing force rerun trigger reruns all tests', async () => { const vitest = await runVitestCli(...cliArgs)