Skip to content

Commit 488c046

Browse files
authored
fix: invalidate resolved setup files (fix #11073) (#11081)
1 parent 3cd019a commit 488c046

4 files changed

Lines changed: 64 additions & 11 deletions

File tree

packages/vitest/src/runtime/moduleRunner/moduleRunner.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export class VitestModuleRunner
108108
return exports
109109
}
110110

111-
public async import(rawId: string): Promise<any> {
111+
public async import(rawId: string, options?: { invalidate?: boolean }): Promise<any> {
112112
const resolved = await this._otel.$(
113113
'vitest.module.resolve_id',
114114
{
@@ -128,7 +128,14 @@ export class VitestModuleRunner
128128
return result
129129
},
130130
)
131-
return super.import(resolved ? resolved.url : rawId)
131+
const url = resolved ? resolved.url : rawId
132+
if (options?.invalidate) {
133+
const module = this.evaluatedModules.getModuleByUrl(url)
134+
if (module?.evaluated) {
135+
this.evaluatedModules.invalidateModule(module)
136+
}
137+
}
138+
return super.import(url)
132139
}
133140

134141
public async fetchModule(url: string, importer?: string): Promise<EvaluatedModuleNode> {

packages/vitest/src/runtime/moduleRunner/testModuleRunner.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ import type { ModuleExecutionInfo } from './moduleDebug'
44
export interface TestModuleRunner {
55
moduleExecutionInfo?: ModuleExecutionInfo
66
mocker?: TestModuleMocker
7-
import: <T = any>(moduleId: string) => Promise<T>
7+
import: <T = any>(moduleId: string, options?: { invalidate?: boolean }) => Promise<T>
88
}

packages/vitest/src/runtime/runners/test.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import type { SpanOptions } from '@opentelemetry/api'
22
import type { ExpectStatic } from '@vitest/expect'
3-
import type { ModuleRunner } from 'vite/module-runner'
43
import type { Traces } from '../../utils/traces'
54
import type { Bench } from '../benchmark'
65
import type { SerializedConfig } from '../config'
6+
import type { TestModuleRunner } from '../moduleRunner/testModuleRunner'
77
import type {
88
CancelReason,
99
File,
@@ -36,7 +36,7 @@ import { getWorkerState } from '../utils'
3636
export class TestRunner implements VitestTestRunner {
3737
private snapshotClient = getSnapshotClient()
3838
private workerState = getWorkerState()
39-
private moduleRunner!: ModuleRunner
39+
private moduleRunner!: TestModuleRunner
4040
private cancelRun = false
4141

4242
private assertionsErrors = new WeakMap<Readonly<Task>, Error>()
@@ -63,10 +63,6 @@ export class TestRunner implements VitestTestRunner {
6363
}
6464

6565
importFile(filepath: string, source: VitestRunnerImportSource): unknown {
66-
const moduleNode = this.workerState.evaluatedModules.getModuleById(filepath)
67-
if (moduleNode && (source === 'setup' || moduleNode.evaluated)) {
68-
this.workerState.evaluatedModules.invalidateModule(moduleNode)
69-
}
7066
return this._otel.$(
7167
`vitest.module.import_${source === 'setup' ? 'setup' : 'spec'}`,
7268
{
@@ -78,7 +74,8 @@ export class TestRunner implements VitestTestRunner {
7874
if (!this.viteModuleRunner) {
7975
filepath = `${filepath}?vitest=${Date.now()}`
8076
}
81-
return this.moduleRunner.import(filepath)
77+
const options = this.viteModuleRunner ? { invalidate: true } : undefined
78+
return this.moduleRunner.import(filepath, options)
8279
},
8380
)
8481
}

test/e2e/test/setup-files.test.ts

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { promises as fs } from 'node:fs'
22
import { describe, expect, it, test } from 'vitest'
3-
import { editFile, runVitest } from '../../test-utils'
3+
import { editFile, runInlineTests, runVitest } from '../../test-utils'
44

55
test.each(['threads', 'vmThreads'])('%s: print stdout and stderr correctly when called in the setup file', async (pool) => {
66
const { stdout, stderr } = await runVitest({
@@ -83,3 +83,52 @@ it('setup files resolution in nested folder with bare name', async () => {
8383
}
8484
`)
8585
})
86+
87+
it('re-evaluates an extensionless setup file when isolation is disabled', async () => {
88+
const { stderr, testTree } = await runInlineTests({
89+
'vitest.config.js': `
90+
export default {
91+
test: {
92+
isolate: false,
93+
maxWorkers: 1,
94+
setupFiles: ['./setup'],
95+
},
96+
}
97+
`,
98+
'setup.js': `
99+
import { beforeEach } from 'vitest'
100+
101+
beforeEach(() => {
102+
globalThis.setupFileHookCalled = true
103+
})
104+
`,
105+
'a.test.js': `
106+
import { expect, test } from 'vitest'
107+
108+
test('runs setup hook in a', () => {
109+
expect(globalThis.setupFileHookCalled).toBe(true)
110+
globalThis.setupFileHookCalled = false
111+
})
112+
`,
113+
'b.test.js': `
114+
import { expect, test } from 'vitest'
115+
116+
test('runs setup hook in b', () => {
117+
expect(globalThis.setupFileHookCalled).toBe(true)
118+
globalThis.setupFileHookCalled = false
119+
})
120+
`,
121+
})
122+
123+
expect(stderr).toBe('')
124+
expect(testTree()).toMatchInlineSnapshot(`
125+
{
126+
"a.test.js": {
127+
"runs setup hook in a": "passed",
128+
},
129+
"b.test.js": {
130+
"runs setup hook in b": "passed",
131+
},
132+
}
133+
`)
134+
})

0 commit comments

Comments
 (0)
Sponsor
SponsoredKunjungi sekarang
Promo