UNPKG

vitest

Version:

Next generation testing framework powered by Vite

257 lines (253 loc) 7.98 kB
import { updateTask } from '@vitest/runner'; import { createDefer, getSafeTimers } from '@vitest/utils'; import { a as getBenchOptions, g as getBenchFn } from './chunks/benchmark.BKUatJGy.js'; import { g as getWorkerState } from './chunks/utils.CtocqOoE.js'; import { setState, GLOBAL_EXPECT, getState } from '@vitest/expect'; import { getTests, getNames, getTestName } from '@vitest/runner/utils'; import { g as getSnapshotClient, i as inject, c as createExpect, v as vi } from './chunks/vi.B-PuvDzu.js'; import { r as rpc } from './chunks/rpc.DGgL5dw7.js'; import 'chai'; import './chunks/_commonjsHelpers.BFTU3MAI.js'; import '@vitest/snapshot'; import '@vitest/utils/error'; import '@vitest/spy'; import '@vitest/utils/source-map'; import './chunks/date.CDOsz-HY.js'; import './chunks/index.68735LiX.js'; function createBenchmarkResult(name) { return { name, rank: 0, rme: 0, samples: [] }; } const benchmarkTasks = new WeakMap(); async function runBenchmarkSuite(suite, runner) { const { Task, Bench } = await runner.importTinybench(); const start = performance.now(); const benchmarkGroup = []; const benchmarkSuiteGroup = []; for (const task of suite.tasks) { if (task.mode !== "run" && task.mode !== "queued") { continue; } if (task.meta?.benchmark) { benchmarkGroup.push(task); } else if (task.type === "suite") { benchmarkSuiteGroup.push(task); } } for (const subSuite of benchmarkSuiteGroup) { await runBenchmarkSuite(subSuite, runner); } if (benchmarkGroup.length) { const defer = createDefer(); suite.result = { state: "run", startTime: start, benchmark: createBenchmarkResult(suite.name) }; updateTask$1("suite-prepare", suite); const addBenchTaskListener = (task, benchmark) => { task.addEventListener("complete", (e) => { const task = e.task; const taskRes = task.result; const result = benchmark.result.benchmark; benchmark.result.state = "pass"; Object.assign(result, taskRes); const samples = result.samples; result.sampleCount = samples.length; result.median = samples.length % 2 ? samples[Math.floor(samples.length / 2)] : (samples[samples.length / 2] + samples[samples.length / 2 - 1]) / 2; if (!runner.config.benchmark?.includeSamples) { result.samples.length = 0; } updateTask$1("test-finished", benchmark); }, { once: true }); task.addEventListener("error", (e) => { const task = e.task; defer.reject(benchmark ? task.result.error : e); }, { once: true }); }; benchmarkGroup.forEach((benchmark) => { const options = getBenchOptions(benchmark); const benchmarkInstance = new Bench(options); const benchmarkFn = getBenchFn(benchmark); benchmark.result = { state: "run", startTime: start, benchmark: createBenchmarkResult(benchmark.name) }; const task = new Task(benchmarkInstance, benchmark.name, benchmarkFn); benchmarkTasks.set(benchmark, task); addBenchTaskListener(task, benchmark); }); const { setTimeout } = getSafeTimers(); const tasks = []; for (const benchmark of benchmarkGroup) { const task = benchmarkTasks.get(benchmark); updateTask$1("test-prepare", benchmark); await task.warmup(); tasks.push([await new Promise((resolve) => setTimeout(async () => { resolve(await task.run()); })), benchmark]); } suite.result.duration = performance.now() - start; suite.result.state = "pass"; updateTask$1("suite-finished", suite); defer.resolve(null); await defer; } function updateTask$1(event, task) { updateTask(event, task, runner); } } class NodeBenchmarkRunner { __vitest_executor; constructor(config) { this.config = config; } async importTinybench() { return await import('tinybench'); } importFile(filepath, source) { if (source === "setup") { getWorkerState().moduleCache.delete(filepath); } return this.__vitest_executor.executeId(filepath); } async runSuite(suite) { await runBenchmarkSuite(suite, this); } async runTask() { throw new Error("`test()` and `it()` is only available in test mode."); } } class VitestTestRunner { snapshotClient = getSnapshotClient(); workerState = getWorkerState(); __vitest_executor; cancelRun = false; assertionsErrors = new WeakMap(); pool = this.workerState.ctx.pool; constructor(config) { this.config = config; } importFile(filepath, source) { if (source === "setup") { this.workerState.moduleCache.delete(filepath); } return this.__vitest_executor.executeId(filepath); } onCollectStart(file) { this.workerState.current = file; } onAfterRunFiles() { this.snapshotClient.clear(); this.workerState.current = undefined; } async onAfterRunSuite(suite) { if (this.config.logHeapUsage && typeof process !== "undefined") { suite.result.heap = process.memoryUsage().heapUsed; } if (suite.mode !== "skip" && "filepath" in suite) { for (const test of getTests(suite)) { if (test.mode === "skip") { const name = getNames(test).slice(1).join(" > "); this.snapshotClient.skipTest(suite.file.filepath, name); } } const result = await this.snapshotClient.finish(suite.file.filepath); await rpc().snapshotSaved(result); } this.workerState.current = suite.suite || suite.file; } onAfterRunTask(test) { if (this.config.logHeapUsage && typeof process !== "undefined") { test.result.heap = process.memoryUsage().heapUsed; } this.workerState.current = test.suite || test.file; } onCancel(_reason) { this.cancelRun = true; } injectValue(key) { return inject(key); } async onBeforeRunTask(test) { if (this.cancelRun) { test.mode = "skip"; } if (test.mode !== "run" && test.mode !== "queued") { return; } clearModuleMocks(this.config); this.workerState.current = test; } async onBeforeRunSuite(suite) { if (this.cancelRun) { suite.mode = "skip"; } if (suite.mode !== "skip" && "filepath" in suite) { await this.snapshotClient.setup(suite.file.filepath, this.workerState.config.snapshotOptions); } this.workerState.current = suite; } onBeforeTryTask(test) { this.snapshotClient.clearTest(test.file.filepath, test.id); setState({ assertionCalls: 0, isExpectingAssertions: false, isExpectingAssertionsError: null, expectedAssertionsNumber: null, expectedAssertionsNumberErrorGen: null, currentTestName: getTestName(test), snapshotState: this.snapshotClient.getSnapshotState(test.file.filepath) }, globalThis[GLOBAL_EXPECT]); } onAfterTryTask(test) { const { assertionCalls, expectedAssertionsNumber, expectedAssertionsNumberErrorGen, isExpectingAssertions, isExpectingAssertionsError } = "context" in test && test.context._local ? test.context.expect.getState() : getState(globalThis[GLOBAL_EXPECT]); if (expectedAssertionsNumber !== null && assertionCalls !== expectedAssertionsNumber) { throw expectedAssertionsNumberErrorGen(); } if (isExpectingAssertions === true && assertionCalls === 0) { throw isExpectingAssertionsError; } if (this.config.expect.requireAssertions && assertionCalls === 0) { throw this.assertionsErrors.get(test); } } extendTaskContext(context) { if (this.config.expect.requireAssertions) { this.assertionsErrors.set(context.task, new Error("expected any number of assertion, but got none")); } let _expect; Object.defineProperty(context, "expect", { get() { if (!_expect) { _expect = createExpect(context.task); } return _expect; } }); Object.defineProperty(context, "_local", { get() { return _expect != null; } }); return context; } } function clearModuleMocks(config) { const { clearMocks, mockReset, restoreMocks, unstubEnvs, unstubGlobals } = config; if (restoreMocks) { vi.restoreAllMocks(); } else if (mockReset) { vi.resetAllMocks(); } else if (clearMocks) { vi.clearAllMocks(); } if (unstubEnvs) { vi.unstubAllEnvs(); } if (unstubGlobals) { vi.unstubAllGlobals(); } } export { NodeBenchmarkRunner, VitestTestRunner };