-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
index.ts
106 lines (90 loc) · 3.93 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import type { VitestRunner, VitestRunnerConstructor } from '@vitest/runner'
import { resolve } from 'pathe'
import type { ResolvedConfig } from '../../types/config'
import type { VitestExecutor } from '../execute'
import { distDir } from '../../paths'
import { getWorkerState } from '../../utils/global'
import { rpc } from '../rpc'
import { takeCoverageInsideWorker } from '../../integrations/coverage'
import { loadDiffConfig, loadSnapshotSerializers } from '../setup-common'
const commonRunnersFile = resolve(distDir, 'runners.js')
const nodeRunnersFile = resolve(distDir, 'runners-node.js')
async function getTestRunnerConstructor(config: ResolvedConfig, executor: VitestExecutor): Promise<VitestRunnerConstructor> {
if (!config.runner) {
if (config.detectAsyncLeaks) {
if (config.browser?.enabled)
throw new Error('"--detectAsyncLeaks" flag is not supported in browser mode.')
const { WithAsyncLeaksDetecter } = await executor.executeFile(nodeRunnersFile)
return WithAsyncLeaksDetecter as VitestRunnerConstructor
}
const { VitestTestRunner, NodeBenchmarkRunner } = await executor.executeFile(commonRunnersFile)
return (config.mode === 'test' ? VitestTestRunner : NodeBenchmarkRunner) as VitestRunnerConstructor
}
const mod = await executor.executeId(config.runner)
if (!mod.default && typeof mod.default !== 'function')
throw new Error(`Runner must export a default function, but got ${typeof mod.default} imported from ${config.runner}`)
return mod.default as VitestRunnerConstructor
}
export async function resolveTestRunner(config: ResolvedConfig, executor: VitestExecutor): Promise<VitestRunner> {
const TestRunner = await getTestRunnerConstructor(config, executor)
const testRunner = new TestRunner(config)
// inject private executor to every runner
Object.defineProperty(testRunner, '__vitest_executor', {
value: executor,
enumerable: false,
configurable: false,
})
if (!testRunner.config)
testRunner.config = config
if (!testRunner.importFile)
throw new Error('Runner must implement "importFile" method.')
const [diffOptions] = await Promise.all([
loadDiffConfig(config, executor),
loadSnapshotSerializers(config, executor),
])
testRunner.config.diffOptions = diffOptions
// patch some methods, so custom runners don't need to call RPC
const originalOnTaskUpdate = testRunner.onTaskUpdate
testRunner.onTaskUpdate = async (task) => {
const p = rpc().onTaskUpdate(task)
await originalOnTaskUpdate?.call(testRunner, task)
return p
}
const originalOnCollected = testRunner.onCollected
testRunner.onCollected = async (files) => {
const state = getWorkerState()
files.forEach((file) => {
file.prepareDuration = state.durations.prepare
file.environmentLoad = state.durations.environment
// should be collected only for a single test file in a batch
state.durations.prepare = 0
state.durations.environment = 0
})
rpc().onCollected(files)
await originalOnCollected?.call(testRunner, files)
}
const originalOnAfterRun = testRunner.onAfterRunFiles
testRunner.onAfterRunFiles = async (files) => {
const state = getWorkerState()
const coverage = await takeCoverageInsideWorker(config.coverage, executor)
rpc().onAfterSuiteRun({
coverage,
transformMode: state.environment.transformMode,
projectName: state.ctx.projectName,
})
await originalOnAfterRun?.call(testRunner, files)
}
const originalOnAfterRunTask = testRunner.onAfterRunTask
testRunner.onAfterRunTask = async (test) => {
if (config.bail && test.result?.state === 'fail') {
const previousFailures = await rpc().getCountOfFailedTests()
const currentFailures = 1 + previousFailures
if (currentFailures >= config.bail) {
rpc().onCancel('test-failure')
testRunner.onCancel?.('test-failure')
}
}
await originalOnAfterRunTask?.call(testRunner, test)
}
return testRunner
}