From dbbbe4304ad2eda3077a680aa550d2895498a416 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Mon, 6 May 2024 11:56:47 +0200 Subject: [PATCH] feat!: remove the empty suite from the runner (#5435) --- packages/runner/src/collect.ts | 42 +- packages/runner/src/run.ts | 19 +- packages/runner/src/suite.ts | 19 +- packages/runner/src/types/tasks.ts | 9 +- packages/runner/src/utils/tasks.ts | 7 +- .../vitest/src/integrations/chai/index.ts | 16 +- .../vitest/src/integrations/snapshot/chai.ts | 2 +- packages/vitest/src/node/reporters/base.ts | 2 +- packages/vitest/src/node/reporters/junit.ts | 1 + .../node/reporters/renderers/listRenderer.ts | 2 +- packages/vitest/src/node/reporters/verbose.ts | 4 +- packages/vitest/src/node/state.ts | 33 +- packages/vitest/src/runtime/console.ts | 4 +- packages/vitest/src/runtime/runners/test.ts | 18 +- packages/vitest/src/typecheck/collect.ts | 3 +- packages/vitest/src/typecheck/typechecker.ts | 10 +- packages/vitest/src/utils/tasks.ts | 4 + .../fixtures/custom-pool/pool/custom-pool.ts | 3 + test/config/test/mixed-environments.test.ts | 11 +- test/reporters/fixtures/console.test.ts | 24 +- test/reporters/src/data.ts | 26 +- .../tests/__snapshots__/html.test.ts.snap | 67 +-- .../tests/__snapshots__/json.test.ts.snap | 6 +- .../__snapshots__/reporters.spec.ts.snap | 521 +++++++++++++++++- test/reporters/tests/console.test.ts | 29 +- test/reporters/tests/junit.test.ts | 23 +- test/reporters/tests/reporters.spec.ts | 10 +- 27 files changed, 694 insertions(+), 221 deletions(-) diff --git a/packages/runner/src/collect.ts b/packages/runner/src/collect.ts index 0a9a69bb540d..5cf3f3ba4e00 100644 --- a/packages/runner/src/collect.ts +++ b/packages/runner/src/collect.ts @@ -1,9 +1,9 @@ import { relative } from 'pathe' import { processError } from '@vitest/utils/error' -import type { File } from './types' +import type { File, SuiteHooks } from './types' import type { VitestRunner } from './types/runner' import { calculateSuiteHash, generateHash, interpretTaskModes, someTasksAreOnly } from './utils/collect' -import { clearCollectorContext, getDefaultSuite } from './suite' +import { clearCollectorContext, createSuiteHooks, getDefaultSuite } from './suite' import { getHooks, setHooks } from './map' import { collectorContext } from './context' import { runSetupFiles } from './setup' @@ -26,7 +26,9 @@ export async function collectTests(paths: string[], runner: VitestRunner): Promi tasks: [], meta: Object.create(null), projectName: config.name, + file: undefined!, } + file.file = file clearCollectorContext(filepath, runner) @@ -41,24 +43,27 @@ export async function collectTests(paths: string[], runner: VitestRunner): Promi const defaultTasks = await getDefaultSuite().collect(file) - setHooks(file, getHooks(defaultTasks)) + const fileHooks = createSuiteHooks() + mergeHooks(fileHooks, getHooks(defaultTasks)) for (const c of [...defaultTasks.tasks, ...collectorContext.tasks]) { - if (c.type === 'test') { - file.tasks.push(c) - } - else if (c.type === 'custom') { - file.tasks.push(c) - } - else if (c.type === 'suite') { + if (c.type === 'test' || c.type === 'custom' || c.type === 'suite') { file.tasks.push(c) } else if (c.type === 'collector') { const suite = await c.collect(file) - if (suite.name || suite.tasks.length) + if (suite.name || suite.tasks.length) { + mergeHooks(fileHooks, getHooks(suite)) file.tasks.push(suite) + } + } + else { + // check that types are exhausted + c satisfies never } } + + setHooks(file, fileHooks) file.collectDuration = now() - collectStart } catch (e) { @@ -74,8 +79,23 @@ export async function collectTests(paths: string[], runner: VitestRunner): Promi const hasOnlyTasks = someTasksAreOnly(file) interpretTaskModes(file, config.testNamePattern, hasOnlyTasks, false, config.allowOnly) + file.tasks.forEach((task) => { + // task.suite refers to the internal default suite object + // it should not be reported + if (task.suite?.id === '') + delete task.suite + }) files.push(file) } return files } + +function mergeHooks(baseHooks: SuiteHooks, hooks: SuiteHooks): SuiteHooks { + for (const _key in hooks) { + const key = _key as keyof SuiteHooks + baseHooks[key].push(...hooks[key] as any) + } + + return baseHooks +} diff --git a/packages/runner/src/run.ts b/packages/runner/src/run.ts index c0d55c414b21..46f287dbd9db 100644 --- a/packages/runner/src/run.ts +++ b/packages/runner/src/run.ts @@ -57,9 +57,14 @@ export async function callSuiteHook( const sequence = runner.config.sequence.hooks const callbacks: HookCleanupCallback[] = [] - if (name === 'beforeEach' && suite.suite) { + // stop at file level + const parentSuite: Suite | null = 'filepath' in suite + ? null + : (suite.suite || suite.file) + + if (name === 'beforeEach' && parentSuite) { callbacks.push( - ...await callSuiteHook(suite.suite, currentTask, name, runner, args), + ...await callSuiteHook(parentSuite, currentTask, name, runner, args), ) } @@ -77,9 +82,9 @@ export async function callSuiteHook( updateSuiteHookState(currentTask, name, 'pass', runner) - if (name === 'afterEach' && suite.suite) { + if (name === 'afterEach' && parentSuite) { callbacks.push( - ...await callSuiteHook(suite.suite, currentTask, name, runner, args), + ...await callSuiteHook(parentSuite, currentTask, name, runner, args), ) } @@ -150,6 +155,8 @@ export async function runTest(test: Test | Custom, runner: VitestRunner) { setCurrentTest(test) + const suite = test.suite || test.file + const repeats = test.repeats ?? 0 for (let repeatCount = 0; repeatCount <= repeats; repeatCount++) { const retry = test.retry ?? 0 @@ -160,7 +167,7 @@ export async function runTest(test: Test | Custom, runner: VitestRunner) { test.result.repeatCount = repeatCount - beforeEachCleanups = await callSuiteHook(test.suite, test, 'beforeEach', runner, [test.context, test.suite]) + beforeEachCleanups = await callSuiteHook(suite, test, 'beforeEach', runner, [test.context, suite]) if (runner.runTask) { await runner.runTask(test) @@ -202,7 +209,7 @@ export async function runTest(test: Test | Custom, runner: VitestRunner) { } try { - await callSuiteHook(test.suite, test, 'afterEach', runner, [test.context, test.suite]) + await callSuiteHook(suite, test, 'afterEach', runner, [test.context, suite]) await callCleanupHooks(beforeEachCleanups) await callFixtureCleanup(test.context) } diff --git a/packages/runner/src/suite.ts b/packages/runner/src/suite.ts index 80d5ee283628..0167fc6a36cc 100644 --- a/packages/runner/src/suite.ts +++ b/packages/runner/src/suite.ts @@ -40,9 +40,15 @@ export function getRunner() { return runner } +function createDefaultSuite(runner: VitestRunner) { + const config = runner.config.sequence + const api = config.shuffle ? suite.shuffle : suite + return api('', { concurrent: config.concurrent }, () => {}) +} + export function clearCollectorContext(filepath: string, currentRunner: VitestRunner) { if (!defaultSuite) - defaultSuite = currentRunner.config.sequence.shuffle ? suite.shuffle('') : currentRunner.config.sequence.concurrent ? suite.concurrent('') : suite('') + defaultSuite = createDefaultSuite(currentRunner) runner = currentRunner currentTestFilepath = filepath collectorContext.tasks.length = 0 @@ -121,6 +127,7 @@ function createSuiteCollector(name: string, factory: SuiteFactory = () => { }, m fails: options.fails, context: undefined!, type: 'custom', + file: undefined!, retry: options.retry ?? runner.config.retry, repeats: options.repeats, mode: options.only ? 'only' : options.skip ? 'skip' : options.todo ? 'todo' : 'run', @@ -211,10 +218,10 @@ function createSuiteCollector(name: string, factory: SuiteFactory = () => { }, m name, mode, each, + file: undefined!, shuffle, tasks: [], meta: Object.create(null), - projectName: '', } if (runner && includeLocation && runner.config.includeTaskLocation) { @@ -236,7 +243,10 @@ function createSuiteCollector(name: string, factory: SuiteFactory = () => { }, m initSuite(false) } - async function collect(file?: File) { + async function collect(file: File) { + if (!file) + throw new TypeError('File is required to collect tasks.') + factoryQueue.length = 0 if (factory) await runWithSuite(collector, () => factory(test)) @@ -251,8 +261,7 @@ function createSuiteCollector(name: string, factory: SuiteFactory = () => { }, m allChildren.forEach((task) => { task.suite = suite - if (file) - task.file = file + task.file = file }) return suite diff --git a/packages/runner/src/types/tasks.ts b/packages/runner/src/types/tasks.ts index 9e1ac191dc92..6938c3fc55e2 100644 --- a/packages/runner/src/types/tasks.ts +++ b/packages/runner/src/types/tasks.ts @@ -14,7 +14,6 @@ export interface TaskBase { concurrent?: boolean shuffle?: boolean suite?: Suite - file?: File result?: TaskResult retry?: number repeats?: number @@ -25,7 +24,7 @@ export interface TaskBase { } export interface TaskPopulated extends TaskBase { - suite: Suite + file: File pending?: boolean result?: TaskResult fails?: boolean @@ -54,14 +53,14 @@ export interface TaskResult { export type TaskResultPack = [id: string, result: TaskResult | undefined, meta: TaskMeta] export interface Suite extends TaskBase { + file: File type: 'suite' tasks: Task[] - filepath?: string - projectName: string } export interface File extends Suite { filepath: string + projectName: string collectDuration?: number setupDuration?: number } @@ -301,7 +300,7 @@ export interface SuiteCollector { test: TestAPI tasks: (Suite | Custom | Test | SuiteCollector)[] task: (name: string, options?: TaskCustomOptions) => Custom - collect: (file?: File) => Promise + collect: (file: File) => Promise clear: () => void on: >(name: T, ...fn: SuiteHooks[T]) => void } diff --git a/packages/runner/src/utils/tasks.ts b/packages/runner/src/utils/tasks.ts index 8ed37bc5a1b2..8898fa1cfaf2 100644 --- a/packages/runner/src/utils/tasks.ts +++ b/packages/runner/src/utils/tasks.ts @@ -48,11 +48,14 @@ export function getNames(task: Task) { const names = [task.name] let current: Task | undefined = task - while (current?.suite || current?.file) { - current = current.suite || current.file + while (current?.suite) { + current = current.suite if (current?.name) names.unshift(current.name) } + if (current !== task.file) + names.unshift(task.file.name) + return names } diff --git a/packages/vitest/src/integrations/chai/index.ts b/packages/vitest/src/integrations/chai/index.ts index fb0f6d0bca1f..9ed4c439202c 100644 --- a/packages/vitest/src/integrations/chai/index.ts +++ b/packages/vitest/src/integrations/chai/index.ts @@ -7,8 +7,8 @@ import { getCurrentTest } from '@vitest/runner' import { ASYMMETRIC_MATCHERS_OBJECT, GLOBAL_EXPECT, addCustomEqualityTesters, getState, setState } from '@vitest/expect' import type { Assertion, ExpectStatic } from '@vitest/expect' import type { MatcherState } from '../../types/chai' -import { getFullName } from '../../utils/tasks' -import { getCurrentEnvironment } from '../../utils/global' +import { getTestName } from '../../utils/tasks' +import { getCurrentEnvironment, getWorkerState } from '../../utils/global' export function createExpect(test?: TaskPopulated) { const expect = ((value: any, message?: string): Assertion => { @@ -31,6 +31,7 @@ export function createExpect(test?: TaskPopulated) { // @ts-expect-error global is not typed const globalState = getState(globalThis[GLOBAL_EXPECT]) || {} + const testPath = getTestFile(test) setState({ // this should also add "snapshotState" that is added conditionally ...globalState, @@ -40,8 +41,8 @@ export function createExpect(test?: TaskPopulated) { expectedAssertionsNumber: null, expectedAssertionsNumberErrorGen: null, environment: getCurrentEnvironment(), - testPath: test ? test.suite.file?.filepath : globalState.testPath, - currentTestName: test ? getFullName(test as Test) : globalState.currentTestName, + testPath, + currentTestName: test ? getTestName(test as Test) : globalState.currentTestName, }, expect) // @ts-expect-error untyped @@ -89,6 +90,13 @@ export function createExpect(test?: TaskPopulated) { return expect } +function getTestFile(test?: TaskPopulated) { + if (test) + return test.file.filepath + const state = getWorkerState() + return state.filepath +} + const globalExpect = createExpect() Object.defineProperty(globalThis, GLOBAL_EXPECT, { diff --git a/packages/vitest/src/integrations/snapshot/chai.ts b/packages/vitest/src/integrations/snapshot/chai.ts index 6f9ebbd6b79c..377160c0c792 100644 --- a/packages/vitest/src/integrations/snapshot/chai.ts +++ b/packages/vitest/src/integrations/snapshot/chai.ts @@ -42,7 +42,7 @@ export const SnapshotPlugin: ChaiPlugin = (chai, utils) => { if (!test) return {} return { - filepath: test.file?.filepath, + filepath: test.file.filepath, name: getNames(test).slice(1).join(' > '), } } diff --git a/packages/vitest/src/node/reporters/base.ts b/packages/vitest/src/node/reporters/base.ts index b4e1cd8f601f..36a6454f3a1b 100644 --- a/packages/vitest/src/node/reporters/base.ts +++ b/packages/vitest/src/node/reporters/base.ts @@ -326,7 +326,7 @@ export abstract class BaseReporter implements Reporter { logger.log(`\n${c.cyan(c.inverse(c.bold(' BENCH ')))} ${c.cyan('Summary')}\n`) for (const bench of topBenches) { - const group = bench.suite + const group = bench.suite || bench.file if (!group) continue const groupName = getFullName(group, c.dim(' > ')) diff --git a/packages/vitest/src/node/reporters/junit.ts b/packages/vitest/src/node/reporters/junit.ts index e5490209c13c..ccbae37ddd99 100644 --- a/packages/vitest/src/node/reporters/junit.ts +++ b/packages/vitest/src/node/reporters/junit.ts @@ -248,6 +248,7 @@ export class JUnitReporter implements Reporter { // NOTE: not used in JUnitReporter context: null as any, suite: null as any, + file: null as any, } satisfies Task) } diff --git a/packages/vitest/src/node/reporters/renderers/listRenderer.ts b/packages/vitest/src/node/reporters/renderers/listRenderer.ts index 017ea9628b1e..af281339b31e 100644 --- a/packages/vitest/src/node/reporters/renderers/listRenderer.ts +++ b/packages/vitest/src/node/reporters/renderers/listRenderer.ts @@ -96,7 +96,7 @@ function renderTree(tasks: Task[], options: ListRendererOptions, level = 0, maxR let suffix = '' let prefix = ` ${getStateSymbol(task)} ` - if (level === 0 && task.type === 'suite' && task.projectName) + if (level === 0 && task.type === 'suite' && 'projectName' in task) prefix += formatProjectName(task.projectName) if (task.type === 'test' && task.result?.retryCount && task.result.retryCount > 0) diff --git a/packages/vitest/src/node/reporters/verbose.ts b/packages/vitest/src/node/reporters/verbose.ts index 9d157d21223b..437336e8e696 100644 --- a/packages/vitest/src/node/reporters/verbose.ts +++ b/packages/vitest/src/node/reporters/verbose.ts @@ -18,8 +18,8 @@ export class VerboseReporter extends DefaultReporter { const task = this.ctx.state.idMap.get(pack[0]) if (task && task.type === 'test' && task.result?.state && task.result?.state !== 'run') { let title = ` ${getStateSymbol(task)} ` - if (task.suite?.projectName) - title += formatProjectName(task.suite.projectName) + if (task.file.projectName) + title += formatProjectName(task.file.projectName) title += getFullName(task, c.dim(' > ')) if (task.result.duration != null && task.result.duration > this.ctx.config.slowTestThreshold) title += c.yellow(` ${Math.round(task.result.duration)}${c.dim('ms')}`) diff --git a/packages/vitest/src/node/state.ts b/packages/vitest/src/node/state.ts index 128bdf66c01a..7e14cc0bb5e4 100644 --- a/packages/vitest/src/node/state.ts +++ b/packages/vitest/src/node/state.ts @@ -150,19 +150,24 @@ export class StateManager { } cancelFiles(files: string[], root: string, projectName: string) { - this.collectFiles(files.map(filepath => ({ - filepath, - name: relative(root, filepath), - id: filepath, - mode: 'skip', - type: 'suite', - result: { - state: 'skip', - }, - meta: {}, - // Cancelled files have not yet collected tests - tasks: [], - projectName, - }))) + this.collectFiles(files.map((filepath) => { + const file: File = { + filepath, + name: relative(root, filepath), + id: filepath, + mode: 'skip', + type: 'suite', + result: { + state: 'skip', + }, + meta: {}, + // Cancelled files have not yet collected tests + tasks: [], + projectName, + file: null!, + } + file.file = file + return file + })) } } diff --git a/packages/vitest/src/runtime/console.ts b/packages/vitest/src/runtime/console.ts index 6ea6feb98c74..a7b1a70715bf 100644 --- a/packages/vitest/src/runtime/console.ts +++ b/packages/vitest/src/runtime/console.ts @@ -88,7 +88,7 @@ export function createCustomConsole() { const stdout = new Writable({ write(data, encoding, callback) { const s = state() - const id = s?.current?.id || s?.current?.file?.id || getTaskIdByStack(s.config.root) + const id = s?.current?.id || s?.current?.suite?.id || s.current?.file.id || getTaskIdByStack(s.config.root) let timer = timers.get(id) if (timer) { timer.stdoutTime = timer.stdoutTime || RealDate.now() @@ -110,7 +110,7 @@ export function createCustomConsole() { const stderr = new Writable({ write(data, encoding, callback) { const s = state() - const id = s?.current?.id || s?.current?.file?.id || getTaskIdByStack(s.config.root) + const id = s?.current?.id || s?.current?.suite?.id || s.current?.file.id || getTaskIdByStack(s.config.root) let timer = timers.get(id) if (timer) { timer.stderrTime = timer.stderrTime || RealDate.now() diff --git a/packages/vitest/src/runtime/runners/test.ts b/packages/vitest/src/runtime/runners/test.ts index e567506e75fc..3f4f5a34bc0b 100644 --- a/packages/vitest/src/runtime/runners/test.ts +++ b/packages/vitest/src/runtime/runners/test.ts @@ -1,9 +1,9 @@ -import type { CancelReason, Custom, ExtendedContext, Suite, Task, TaskContext, Test, VitestRunner, VitestRunnerImportSource } from '@vitest/runner' +import type { CancelReason, Custom, ExtendedContext, File, Suite, Task, TaskContext, Test, VitestRunner, VitestRunnerImportSource } from '@vitest/runner' import type { ExpectStatic } from '@vitest/expect' import { GLOBAL_EXPECT, getState, setState } from '@vitest/expect' import { getSnapshotClient } from '../../integrations/snapshot/chai' import { vi } from '../../integrations/vi' -import { getFullName, getNames, getTests, getWorkerState } from '../../utils' +import { getNames, getTestName, getTests, getWorkerState } from '../../utils' import { createExpect } from '../../integrations/chai/index' import type { ResolvedConfig } from '../../types/config' import type { VitestExecutor } from '../execute' @@ -35,7 +35,7 @@ export class VitestTestRunner implements VitestRunner { if (this.config.logHeapUsage && typeof process !== 'undefined') suite.result!.heap = process.memoryUsage().heapUsed - if (suite.mode !== 'skip' && typeof suite.filepath !== 'undefined') { + if (suite.mode !== 'skip' && 'filepath' in suite) { // mark snapshots in skipped tests as not obsolete for (const test of getTests(suite)) { if (test.mode === 'skip') { @@ -49,7 +49,7 @@ export class VitestTestRunner implements VitestRunner { await rpc().snapshotSaved(result) } - this.workerState.current = suite.suite + this.workerState.current = suite.suite || suite.file } onAfterRunTask(test: Task) { @@ -58,7 +58,7 @@ export class VitestTestRunner implements VitestRunner { if (this.config.logHeapUsage && typeof process !== 'undefined') test.result!.heap = process.memoryUsage().heapUsed - this.workerState.current = test.suite + this.workerState.current = test.suite || test.file } onCancel(_reason: CancelReason) { @@ -82,10 +82,10 @@ export class VitestTestRunner implements VitestRunner { suite.mode = 'skip' // initialize snapshot state before running file suite - if (suite.mode !== 'skip' && typeof suite.filepath !== 'undefined') { + if (suite.mode !== 'skip' && 'filepath' in suite) { // default "name" is irrelevant for Vitest since each snapshot assertion // (e.g. `toMatchSnapshot`) specifies "filepath" / "name" pair explicitly - await this.snapshotClient.startCurrentRun(suite.filepath, '__default_name_', this.workerState.config.snapshotOptions) + await this.snapshotClient.startCurrentRun((suite as File).filepath, '__default_name_', this.workerState.config.snapshotOptions) } this.workerState.current = suite @@ -98,8 +98,8 @@ export class VitestTestRunner implements VitestRunner { isExpectingAssertionsError: null, expectedAssertionsNumber: null, expectedAssertionsNumberErrorGen: null, - testPath: test.suite?.file?.filepath, - currentTestName: getFullName(test), + testPath: test.file.filepath, + currentTestName: getTestName(test), snapshotState: this.snapshotClient.snapshotState, }, (globalThis as any)[GLOBAL_EXPECT]) } diff --git a/packages/vitest/src/typecheck/collect.ts b/packages/vitest/src/typecheck/collect.ts index 3a23683a91c6..b12421f0cc2f 100644 --- a/packages/vitest/src/typecheck/collect.ts +++ b/packages/vitest/src/typecheck/collect.ts @@ -56,7 +56,9 @@ export async function collectTests(ctx: WorkspaceProject, filepath: string): Pro end: ast.end, projectName: ctx.getName(), meta: { typecheck: true }, + file: null!, } + file.file = file const definitions: LocalCallDefinition[] = [] const getName = (callee: any): string | null => { if (!callee) @@ -119,7 +121,6 @@ export async function collectTests(ctx: WorkspaceProject, filepath: string): Pro name: definition.name, end: definition.end, start: definition.start, - projectName: ctx.getName(), meta: { typecheck: true, }, diff --git a/packages/vitest/src/typecheck/typechecker.ts b/packages/vitest/src/typecheck/typechecker.ts index c4cd3109397c..984efb0153a7 100644 --- a/packages/vitest/src/typecheck/typechecker.ts +++ b/packages/vitest/src/typecheck/typechecker.ts @@ -138,6 +138,8 @@ export class Typechecker { } if (task.suite) markState(task.suite, state) + else if (task.file && task !== task.file) + markState(task.file, state) } errors.forEach(({ error, originalError }) => { const processedPos = traceMap @@ -159,8 +161,12 @@ export class Typechecker { errors, } errors.push(error) - if (state === 'fail' && suite.suite) - markState(suite.suite, 'fail') + if (state === 'fail') { + if (suite.suite) + markState(suite.suite, 'fail') + else if (suite.file && suite !== suite.file) + markState(suite.file, 'fail') + } }) this.markPassed(file) diff --git a/packages/vitest/src/utils/tasks.ts b/packages/vitest/src/utils/tasks.ts index 54b613b76f73..518863486226 100644 --- a/packages/vitest/src/utils/tasks.ts +++ b/packages/vitest/src/utils/tasks.ts @@ -18,3 +18,7 @@ export function hasFailedSnapshot(suite: Arrayable): boolean { export function getFullName(task: Task, separator = ' > ') { return getNames(task).join(separator) } + +export function getTestName(task: Task, separator = ' > ') { + return getNames(task).slice(1).join(separator) +} diff --git a/test/cli/fixtures/custom-pool/pool/custom-pool.ts b/test/cli/fixtures/custom-pool/pool/custom-pool.ts index 0ab30ef9b2b5..eaaf2d54d10c 100644 --- a/test/cli/fixtures/custom-pool/pool/custom-pool.ts +++ b/test/cli/fixtures/custom-pool/pool/custom-pool.ts @@ -28,7 +28,9 @@ export default (ctx: Vitest): ProcessPool => { result: { state: 'pass', }, + file: null!, } + taskFile.file = taskFile const taskTest: Test = { type: 'test', name: 'custom test', @@ -37,6 +39,7 @@ export default (ctx: Vitest): ProcessPool => { suite: taskFile, mode: 'run', meta: {}, + file: taskFile, result: { state: 'pass', }, diff --git a/test/config/test/mixed-environments.test.ts b/test/config/test/mixed-environments.test.ts index e7f1d470114d..9962e6e4799f 100644 --- a/test/config/test/mixed-environments.test.ts +++ b/test/config/test/mixed-environments.test.ts @@ -18,10 +18,13 @@ test.each(configs)('should isolate environments when %s', async (config) => { expect(stderr).toBe('') - expect(stdout).toContain('✓ test/node.test.ts') - expect(stdout).toContain('✓ test/jsdom.test.ts') - expect(stdout).toContain('✓ test/happy-dom.test.ts') - expect(stdout).toContain('✓ test/workspace-project.test.ts') + expect(stdout).toContain('✓ |Project #1| test/node.test.ts') + expect(stdout).toContain('✓ |Project #1| test/jsdom.test.ts') + expect(stdout).toContain('✓ |Project #2| test/jsdom.test.ts') + expect(stdout).toContain('✓ |Project #1| test/happy-dom.test.ts') + expect(stdout).toContain('✓ |Project #2| test/happy-dom.test.ts') + expect(stdout).toContain('✓ |Project #1| test/workspace-project.test.ts') + expect(stdout).toContain('✓ |Project #2| test/workspace-project.test.ts') expect(stdout).toContain('Test Files 8 passed (8)') expect(stdout).toContain('Tests 8 passed (8)') }) diff --git a/test/reporters/fixtures/console.test.ts b/test/reporters/fixtures/console.test.ts index dde0264286f0..f7bedf3aee94 100644 --- a/test/reporters/fixtures/console.test.ts +++ b/test/reporters/fixtures/console.test.ts @@ -1,35 +1,35 @@ import { afterAll, beforeAll, describe, expect, test } from 'vitest' beforeAll(() => { - console.log('beforeAll') - console.error('beforeAll') + console.log('global stdin beforeAll') + console.error('global stderr beforeAll') }) afterAll(() => { - console.log('afterAll') - console.error('afterAll') + console.log('global stdin afterAll') + console.error('global stderr afterAll') }) describe('suite', () => { beforeAll(() => { - console.log('beforeAll') - console.error('beforeAll') + console.log('suite stdin beforeAll') + console.error('suite stderr beforeAll') }) afterAll(() => { - console.log('afterAll') - console.error('afterAll') + console.log('suite stdin afterAll') + console.error('suite stderr afterAll') }) describe('nested suite', () => { beforeAll(() => { - console.log('beforeAll') - console.error('beforeAll') + console.log('nested suite stdin beforeAll') + console.error('nested suite stderr beforeAll') }) afterAll(() => { - console.log('afterAll') - console.error('afterAll') + console.log('nested suite stdin afterAll') + console.error('nested suite stderr afterAll') }) test('test', () => { diff --git a/test/reporters/src/data.ts b/test/reporters/src/data.ts index 4eef9c028e57..cba908cde209 100644 --- a/test/reporters/src/data.ts +++ b/test/reporters/src/data.ts @@ -11,7 +11,9 @@ const file: File = { result: { state: 'fail', duration: 145.99284195899963 }, tasks: [], projectName: '', + file: null!, } +file.file = file const suite: Suite = { id: '', @@ -22,20 +24,6 @@ const suite: Suite = { file, result: { state: 'pass', duration: 1.90183687210083 }, tasks: [], - projectName: '', -} - -const innerSuite: Suite = { - id: '', - type: 'suite', - name: 'inner suite', - mode: 'run', - file, - meta: {}, - suite, - result: { state: 'pass', duration: 1.90183687210083 }, - tasks: [], - projectName: '', } const error: ErrorWithDiff = new AssertionError({ @@ -57,16 +45,16 @@ error.stack = 'AssertionError: expected 2.23606797749979 to equal 2\n' + ' at async run (/vitest/packages/vitest/dist/entry.js:1797:5)\n' + ' at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20' -const innerTasks: Task[] = [ +const tasks: Task[] = [ { id: '1223128da3_0', type: 'test', name: 'Math.sqrt()', mode: 'run', - suite: innerSuite, fails: undefined, meta: {}, file, + suite, result: { state: 'fail', errors: [error], @@ -74,12 +62,6 @@ const innerTasks: Task[] = [ }, context: null as any, }, -] - -innerSuite.tasks = innerTasks - -const tasks: Task[] = [ - innerSuite, { id: '1223128da3_1', type: 'test', diff --git a/test/reporters/tests/__snapshots__/html.test.ts.snap b/test/reporters/tests/__snapshots__/html.test.ts.snap index 15110447cb09..8f765c937cfe 100644 --- a/test/reporters/tests/__snapshots__/html.test.ts.snap +++ b/test/reporters/tests/__snapshots__/html.test.ts.snap @@ -7,6 +7,7 @@ exports[`html reporter > resolves to "failing" status for test file "json-fail" { "collectDuration": 0, "environmentLoad": 0, + "file": [Circular], "filepath": "/test/reporters/fixtures/json-fail.test.ts", "id": 0, "meta": {}, @@ -69,18 +70,6 @@ exports[`html reporter > resolves to "failing" status for test file "json-fail" "startTime": 0, "state": "fail", }, - "suite": { - "file": [Circular], - "id": "", - "meta": {}, - "mode": "run", - "name": "", - "projectName": "", - "tasks": [ - [Circular], - ], - "type": "suite", - }, "type": "test", }, ], @@ -112,6 +101,7 @@ exports[`html reporter > resolves to "passing" status for test file "all-passing { "collectDuration": 0, "environmentLoad": 0, + "file": [Circular], "filepath": "/test/reporters/fixtures/all-passing-or-skipped.test.ts", "id": 0, "meta": {}, @@ -146,27 +136,6 @@ exports[`html reporter > resolves to "passing" status for test file "all-passing "startTime": 0, "state": "pass", }, - "suite": { - "file": [Circular], - "id": "", - "meta": {}, - "mode": "run", - "name": "", - "projectName": "", - "tasks": [ - [Circular], - { - "file": [Circular], - "id": "1111755131_1", - "meta": {}, - "mode": "skip", - "name": "3 + 3 = 6", - "suite": [Circular], - "type": "test", - }, - ], - "type": "suite", - }, "type": "test", }, { @@ -175,38 +144,6 @@ exports[`html reporter > resolves to "passing" status for test file "all-passing "meta": {}, "mode": "skip", "name": "3 + 3 = 6", - "suite": { - "file": [Circular], - "id": "", - "meta": {}, - "mode": "run", - "name": "", - "projectName": "", - "tasks": [ - { - "file": [Circular], - "id": 0, - "meta": {}, - "mode": "run", - "name": "2 + 3 = 5", - "result": { - "duration": 0, - "hooks": { - "afterEach": "pass", - "beforeEach": "pass", - }, - "repeatCount": 0, - "retryCount": 0, - "startTime": 0, - "state": "pass", - }, - "suite": [Circular], - "type": "test", - }, - [Circular], - ], - "type": "suite", - }, "type": "test", }, ], diff --git a/test/reporters/tests/__snapshots__/json.test.ts.snap b/test/reporters/tests/__snapshots__/json.test.ts.snap index db3d630ef28a..ed1ca9b34363 100644 --- a/test/reporters/tests/__snapshots__/json.test.ts.snap +++ b/test/reporters/tests/__snapshots__/json.test.ts.snap @@ -2,13 +2,11 @@ exports[`json reporter > generates correct report 1`] = ` { - "ancestorTitles": [ - "", - ], + "ancestorTitles": [], "failureMessages": [ "expected 2 to deeply equal 1", ], - "fullName": " should fail", + "fullName": "should fail", "location": { "column": 13, "line": 8, diff --git a/test/reporters/tests/__snapshots__/reporters.spec.ts.snap b/test/reporters/tests/__snapshots__/reporters.spec.ts.snap index b4e8c95b87ec..bb65ce023b30 100644 --- a/test/reporters/tests/__snapshots__/reporters.spec.ts.snap +++ b/test/reporters/tests/__snapshots__/reporters.spec.ts.snap @@ -66,12 +66,12 @@ exports[`json reporter (no outputFile entry) 1`] = ` { "numFailedTestSuites": 0, "numFailedTests": 1, - "numPassedTestSuites": 3, + "numPassedTestSuites": 2, "numPassedTests": 8, "numPendingTestSuites": 0, "numPendingTests": 0, "numTodoTests": 1, - "numTotalTestSuites": 3, + "numTotalTestSuites": 2, "numTotalTests": 9, "startTime": 1642587001759, "success": false, @@ -81,13 +81,12 @@ exports[`json reporter (no outputFile entry) 1`] = ` { "ancestorTitles": [ "suite", - "inner suite", ], "duration": 1.4422860145568848, "failureMessages": [ "expected 2.23606797749979 to equal 2", ], - "fullName": "suite inner suite Math.sqrt()", + "fullName": "suite Math.sqrt()", "location": { "column": 32, "line": 8, @@ -188,12 +187,12 @@ exports[`json reporter 1`] = ` { "numFailedTestSuites": 0, "numFailedTests": 1, - "numPassedTestSuites": 3, + "numPassedTestSuites": 2, "numPassedTests": 8, "numPendingTestSuites": 0, "numPendingTests": 0, "numTodoTests": 1, - "numTotalTestSuites": 3, + "numTotalTestSuites": 2, "numTotalTests": 9, "startTime": 1642587001759, "success": false, @@ -203,13 +202,12 @@ exports[`json reporter 1`] = ` { "ancestorTitles": [ "suite", - "inner suite", ], "duration": 1.4422860145568848, "failureMessages": [ "expected 2.23606797749979 to equal 2", ], - "fullName": "suite inner suite Math.sqrt()", + "fullName": "suite Math.sqrt()", "location": { "column": 32, "line": 8, @@ -311,28 +309,504 @@ exports[`json reporter with outputFile 1`] = ` " `; -exports[`json reporter with outputFile 2`] = `"{"numTotalTestSuites":3,"numPassedTestSuites":3,"numFailedTestSuites":0,"numPendingTestSuites":0,"numTotalTests":9,"numPassedTests":8,"numFailedTests":1,"numPendingTests":0,"numTodoTests":1,"startTime":1642587001759,"success":false,"testResults":[{"assertionResults":[{"ancestorTitles":["suite","inner suite"],"fullName":"suite inner suite Math.sqrt()","status":"failed","title":"Math.sqrt()","duration":1.4422860145568848,"failureMessages":["expected 2.23606797749979 to equal 2"],"location":{"line":8,"column":32}},{"ancestorTitles":["suite"],"fullName":"suite JSON","status":"passed","title":"JSON","duration":1.0237109661102295,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite async with timeout","status":"skipped","title":"async with timeout","failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite timeout","status":"passed","title":"timeout","duration":100.50598406791687,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite callback setup success ","status":"passed","title":"callback setup success ","duration":20.184875011444092,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite callback test success ","status":"passed","title":"callback test success ","duration":0.33245420455932617,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite callback setup success done(false)","status":"passed","title":"callback setup success done(false)","duration":19.738605976104736,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite callback test success done(false)","status":"passed","title":"callback test success done(false)","duration":0.1923508644104004,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite todo test","status":"todo","title":"todo test","failureMessages":[]}],"startTime":1642587001759,"endTime":1642587001759,"status":"failed","message":"","name":"/vitest/test/core/test/basic.test.ts"}]}"`; +exports[`json reporter with outputFile 2`] = ` +{ + "numFailedTestSuites": 0, + "numFailedTests": 1, + "numPassedTestSuites": 2, + "numPassedTests": 8, + "numPendingTestSuites": 0, + "numPendingTests": 0, + "numTodoTests": 1, + "numTotalTestSuites": 2, + "numTotalTests": 9, + "startTime": 1642587001759, + "success": false, + "testResults": [ + { + "assertionResults": [ + { + "ancestorTitles": [ + "suite", + ], + "duration": 1.4422860145568848, + "failureMessages": [ + "expected 2.23606797749979 to equal 2", + ], + "fullName": "suite Math.sqrt()", + "location": { + "column": 32, + "line": 8, + }, + "status": "failed", + "title": "Math.sqrt()", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 1.0237109661102295, + "failureMessages": [], + "fullName": "suite JSON", + "status": "passed", + "title": "JSON", + }, + { + "ancestorTitles": [ + "suite", + ], + "failureMessages": [], + "fullName": "suite async with timeout", + "status": "skipped", + "title": "async with timeout", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 100.50598406791687, + "failureMessages": [], + "fullName": "suite timeout", + "status": "passed", + "title": "timeout", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 20.184875011444092, + "failureMessages": [], + "fullName": "suite callback setup success ", + "status": "passed", + "title": "callback setup success ", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 0.33245420455932617, + "failureMessages": [], + "fullName": "suite callback test success ", + "status": "passed", + "title": "callback test success ", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 19.738605976104736, + "failureMessages": [], + "fullName": "suite callback setup success done(false)", + "status": "passed", + "title": "callback setup success done(false)", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 0.1923508644104004, + "failureMessages": [], + "fullName": "suite callback test success done(false)", + "status": "passed", + "title": "callback test success done(false)", + }, + { + "ancestorTitles": [ + "suite", + ], + "failureMessages": [], + "fullName": "suite todo test", + "status": "todo", + "title": "todo test", + }, + ], + "endTime": 1642587001759, + "message": "", + "name": "/vitest/test/core/test/basic.test.ts", + "startTime": 1642587001759, + "status": "failed", + }, + ], +} +`; exports[`json reporter with outputFile in non-existing directory 1`] = ` "JSON report written to /jsonReportDirectory/deeply/nested/report.json " `; -exports[`json reporter with outputFile in non-existing directory 2`] = `"{"numTotalTestSuites":3,"numPassedTestSuites":3,"numFailedTestSuites":0,"numPendingTestSuites":0,"numTotalTests":9,"numPassedTests":8,"numFailedTests":1,"numPendingTests":0,"numTodoTests":1,"startTime":1642587001759,"success":false,"testResults":[{"assertionResults":[{"ancestorTitles":["suite","inner suite"],"fullName":"suite inner suite Math.sqrt()","status":"failed","title":"Math.sqrt()","duration":1.4422860145568848,"failureMessages":["expected 2.23606797749979 to equal 2"],"location":{"line":8,"column":32}},{"ancestorTitles":["suite"],"fullName":"suite JSON","status":"passed","title":"JSON","duration":1.0237109661102295,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite async with timeout","status":"skipped","title":"async with timeout","failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite timeout","status":"passed","title":"timeout","duration":100.50598406791687,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite callback setup success ","status":"passed","title":"callback setup success ","duration":20.184875011444092,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite callback test success ","status":"passed","title":"callback test success ","duration":0.33245420455932617,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite callback setup success done(false)","status":"passed","title":"callback setup success done(false)","duration":19.738605976104736,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite callback test success done(false)","status":"passed","title":"callback test success done(false)","duration":0.1923508644104004,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite todo test","status":"todo","title":"todo test","failureMessages":[]}],"startTime":1642587001759,"endTime":1642587001759,"status":"failed","message":"","name":"/vitest/test/core/test/basic.test.ts"}]}"`; +exports[`json reporter with outputFile in non-existing directory 2`] = ` +{ + "numFailedTestSuites": 0, + "numFailedTests": 1, + "numPassedTestSuites": 2, + "numPassedTests": 8, + "numPendingTestSuites": 0, + "numPendingTests": 0, + "numTodoTests": 1, + "numTotalTestSuites": 2, + "numTotalTests": 9, + "startTime": 1642587001759, + "success": false, + "testResults": [ + { + "assertionResults": [ + { + "ancestorTitles": [ + "suite", + ], + "duration": 1.4422860145568848, + "failureMessages": [ + "expected 2.23606797749979 to equal 2", + ], + "fullName": "suite Math.sqrt()", + "location": { + "column": 32, + "line": 8, + }, + "status": "failed", + "title": "Math.sqrt()", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 1.0237109661102295, + "failureMessages": [], + "fullName": "suite JSON", + "status": "passed", + "title": "JSON", + }, + { + "ancestorTitles": [ + "suite", + ], + "failureMessages": [], + "fullName": "suite async with timeout", + "status": "skipped", + "title": "async with timeout", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 100.50598406791687, + "failureMessages": [], + "fullName": "suite timeout", + "status": "passed", + "title": "timeout", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 20.184875011444092, + "failureMessages": [], + "fullName": "suite callback setup success ", + "status": "passed", + "title": "callback setup success ", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 0.33245420455932617, + "failureMessages": [], + "fullName": "suite callback test success ", + "status": "passed", + "title": "callback test success ", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 19.738605976104736, + "failureMessages": [], + "fullName": "suite callback setup success done(false)", + "status": "passed", + "title": "callback setup success done(false)", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 0.1923508644104004, + "failureMessages": [], + "fullName": "suite callback test success done(false)", + "status": "passed", + "title": "callback test success done(false)", + }, + { + "ancestorTitles": [ + "suite", + ], + "failureMessages": [], + "fullName": "suite todo test", + "status": "todo", + "title": "todo test", + }, + ], + "endTime": 1642587001759, + "message": "", + "name": "/vitest/test/core/test/basic.test.ts", + "startTime": 1642587001759, + "status": "failed", + }, + ], +} +`; exports[`json reporter with outputFile object 1`] = ` "JSON report written to /report_object.json " `; -exports[`json reporter with outputFile object 2`] = `"{"numTotalTestSuites":3,"numPassedTestSuites":3,"numFailedTestSuites":0,"numPendingTestSuites":0,"numTotalTests":9,"numPassedTests":8,"numFailedTests":1,"numPendingTests":0,"numTodoTests":1,"startTime":1642587001759,"success":false,"testResults":[{"assertionResults":[{"ancestorTitles":["suite","inner suite"],"fullName":"suite inner suite Math.sqrt()","status":"failed","title":"Math.sqrt()","duration":1.4422860145568848,"failureMessages":["expected 2.23606797749979 to equal 2"],"location":{"line":8,"column":32}},{"ancestorTitles":["suite"],"fullName":"suite JSON","status":"passed","title":"JSON","duration":1.0237109661102295,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite async with timeout","status":"skipped","title":"async with timeout","failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite timeout","status":"passed","title":"timeout","duration":100.50598406791687,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite callback setup success ","status":"passed","title":"callback setup success ","duration":20.184875011444092,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite callback test success ","status":"passed","title":"callback test success ","duration":0.33245420455932617,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite callback setup success done(false)","status":"passed","title":"callback setup success done(false)","duration":19.738605976104736,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite callback test success done(false)","status":"passed","title":"callback test success done(false)","duration":0.1923508644104004,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite todo test","status":"todo","title":"todo test","failureMessages":[]}],"startTime":1642587001759,"endTime":1642587001759,"status":"failed","message":"","name":"/vitest/test/core/test/basic.test.ts"}]}"`; +exports[`json reporter with outputFile object 2`] = ` +{ + "numFailedTestSuites": 0, + "numFailedTests": 1, + "numPassedTestSuites": 2, + "numPassedTests": 8, + "numPendingTestSuites": 0, + "numPendingTests": 0, + "numTodoTests": 1, + "numTotalTestSuites": 2, + "numTotalTests": 9, + "startTime": 1642587001759, + "success": false, + "testResults": [ + { + "assertionResults": [ + { + "ancestorTitles": [ + "suite", + ], + "duration": 1.4422860145568848, + "failureMessages": [ + "expected 2.23606797749979 to equal 2", + ], + "fullName": "suite Math.sqrt()", + "location": { + "column": 32, + "line": 8, + }, + "status": "failed", + "title": "Math.sqrt()", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 1.0237109661102295, + "failureMessages": [], + "fullName": "suite JSON", + "status": "passed", + "title": "JSON", + }, + { + "ancestorTitles": [ + "suite", + ], + "failureMessages": [], + "fullName": "suite async with timeout", + "status": "skipped", + "title": "async with timeout", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 100.50598406791687, + "failureMessages": [], + "fullName": "suite timeout", + "status": "passed", + "title": "timeout", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 20.184875011444092, + "failureMessages": [], + "fullName": "suite callback setup success ", + "status": "passed", + "title": "callback setup success ", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 0.33245420455932617, + "failureMessages": [], + "fullName": "suite callback test success ", + "status": "passed", + "title": "callback test success ", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 19.738605976104736, + "failureMessages": [], + "fullName": "suite callback setup success done(false)", + "status": "passed", + "title": "callback setup success done(false)", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 0.1923508644104004, + "failureMessages": [], + "fullName": "suite callback test success done(false)", + "status": "passed", + "title": "callback test success done(false)", + }, + { + "ancestorTitles": [ + "suite", + ], + "failureMessages": [], + "fullName": "suite todo test", + "status": "todo", + "title": "todo test", + }, + ], + "endTime": 1642587001759, + "message": "", + "name": "/vitest/test/core/test/basic.test.ts", + "startTime": 1642587001759, + "status": "failed", + }, + ], +} +`; exports[`json reporter with outputFile object in non-existing directory 1`] = ` "JSON report written to /jsonReportDirectory_object/deeply/nested/report.json " `; -exports[`json reporter with outputFile object in non-existing directory 2`] = `"{"numTotalTestSuites":3,"numPassedTestSuites":3,"numFailedTestSuites":0,"numPendingTestSuites":0,"numTotalTests":9,"numPassedTests":8,"numFailedTests":1,"numPendingTests":0,"numTodoTests":1,"startTime":1642587001759,"success":false,"testResults":[{"assertionResults":[{"ancestorTitles":["suite","inner suite"],"fullName":"suite inner suite Math.sqrt()","status":"failed","title":"Math.sqrt()","duration":1.4422860145568848,"failureMessages":["expected 2.23606797749979 to equal 2"],"location":{"line":8,"column":32}},{"ancestorTitles":["suite"],"fullName":"suite JSON","status":"passed","title":"JSON","duration":1.0237109661102295,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite async with timeout","status":"skipped","title":"async with timeout","failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite timeout","status":"passed","title":"timeout","duration":100.50598406791687,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite callback setup success ","status":"passed","title":"callback setup success ","duration":20.184875011444092,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite callback test success ","status":"passed","title":"callback test success ","duration":0.33245420455932617,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite callback setup success done(false)","status":"passed","title":"callback setup success done(false)","duration":19.738605976104736,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite callback test success done(false)","status":"passed","title":"callback test success done(false)","duration":0.1923508644104004,"failureMessages":[]},{"ancestorTitles":["suite"],"fullName":"suite todo test","status":"todo","title":"todo test","failureMessages":[]}],"startTime":1642587001759,"endTime":1642587001759,"status":"failed","message":"","name":"/vitest/test/core/test/basic.test.ts"}]}"`; +exports[`json reporter with outputFile object in non-existing directory 2`] = ` +{ + "numFailedTestSuites": 0, + "numFailedTests": 1, + "numPassedTestSuites": 2, + "numPassedTests": 8, + "numPendingTestSuites": 0, + "numPendingTests": 0, + "numTodoTests": 1, + "numTotalTestSuites": 2, + "numTotalTests": 9, + "startTime": 1642587001759, + "success": false, + "testResults": [ + { + "assertionResults": [ + { + "ancestorTitles": [ + "suite", + ], + "duration": 1.4422860145568848, + "failureMessages": [ + "expected 2.23606797749979 to equal 2", + ], + "fullName": "suite Math.sqrt()", + "location": { + "column": 32, + "line": 8, + }, + "status": "failed", + "title": "Math.sqrt()", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 1.0237109661102295, + "failureMessages": [], + "fullName": "suite JSON", + "status": "passed", + "title": "JSON", + }, + { + "ancestorTitles": [ + "suite", + ], + "failureMessages": [], + "fullName": "suite async with timeout", + "status": "skipped", + "title": "async with timeout", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 100.50598406791687, + "failureMessages": [], + "fullName": "suite timeout", + "status": "passed", + "title": "timeout", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 20.184875011444092, + "failureMessages": [], + "fullName": "suite callback setup success ", + "status": "passed", + "title": "callback setup success ", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 0.33245420455932617, + "failureMessages": [], + "fullName": "suite callback test success ", + "status": "passed", + "title": "callback test success ", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 19.738605976104736, + "failureMessages": [], + "fullName": "suite callback setup success done(false)", + "status": "passed", + "title": "callback setup success done(false)", + }, + { + "ancestorTitles": [ + "suite", + ], + "duration": 0.1923508644104004, + "failureMessages": [], + "fullName": "suite callback test success done(false)", + "status": "passed", + "title": "callback test success done(false)", + }, + { + "ancestorTitles": [ + "suite", + ], + "failureMessages": [], + "fullName": "suite todo test", + "status": "todo", + "title": "todo test", + }, + ], + "endTime": 1642587001759, + "message": "", + "name": "/vitest/test/core/test/basic.test.ts", + "startTime": 1642587001759, + "status": "failed", + }, + ], +} +`; exports[`tap reporter 1`] = ` "TAP version 13 @@ -341,18 +815,15 @@ not ok 1 - test/core/test/basic.test.ts # time=145.99ms { 1..1 ok 1 - suite # time=1.90ms { 1..9 - ok 1 - inner suite # time=1.90ms { - 1..1 - not ok 1 - Math.sqrt() # time=1.44ms - --- - error: - name: "AssertionError" - message: "expected 2.23606797749979 to equal 2" - at: "/vitest/test/core/test/basic.test.ts:8:32" - actual: "2.23606797749979" - expected: "2" - ... - } + not ok 1 - Math.sqrt() # time=1.44ms + --- + error: + name: "AssertionError" + message: "expected 2.23606797749979 to equal 2" + at: "/vitest/test/core/test/basic.test.ts:8:32" + actual: "2.23606797749979" + expected: "2" + ... ok 2 - JSON # time=1.02ms ok 3 - async with timeout # SKIP ok 4 - timeout # time=100.51ms @@ -369,7 +840,7 @@ not ok 1 - test/core/test/basic.test.ts # time=145.99ms { exports[`tap-flat reporter 1`] = ` "TAP version 13 1..9 -not ok 1 - test/core/test/basic.test.ts > suite > inner suite > Math.sqrt() # time=1.44ms +not ok 1 - test/core/test/basic.test.ts > suite > Math.sqrt() # time=1.44ms --- error: name: "AssertionError" diff --git a/test/reporters/tests/console.test.ts b/test/reporters/tests/console.test.ts index 8e965ee3ee94..51640783898c 100644 --- a/test/reporters/tests/console.test.ts +++ b/test/reporters/tests/console.test.ts @@ -9,33 +9,32 @@ test('should print logs correctly', async () => { expect(stdout).toBeTruthy() expect(stderr).toBeTruthy() - expect(stdout.replace('\n ✓ console.test.ts > suite > nested suite > test', '')).toContain( -` -stdout | console.test.ts > suite > nested suite -beforeAll -afterAll + expect(stdout).toContain( +`stdout | console.test.ts > suite > nested suite +nested suite stdin beforeAll +nested suite stdin afterAll stdout | console.test.ts > suite -beforeAll -afterAll +suite stdin beforeAll +suite stdin afterAll stdout | console.test.ts -beforeAll -afterAll +global stdin beforeAll +global stdin afterAll `, ) expect(stderr).toContain( `stderr | console.test.ts > suite > nested suite -beforeAll -afterAll +nested suite stderr beforeAll +nested suite stderr afterAll stderr | console.test.ts > suite -beforeAll -afterAll +suite stderr beforeAll +suite stderr afterAll stderr | console.test.ts -beforeAll -afterAll`, +global stderr beforeAll +global stderr afterAll`, ) }) diff --git a/test/reporters/tests/junit.test.ts b/test/reporters/tests/junit.test.ts index be577887de7c..a6f5f695ab6e 100644 --- a/test/reporters/tests/junit.test.ts +++ b/test/reporters/tests/junit.test.ts @@ -1,4 +1,4 @@ -import type { Suite, Task, TaskResult } from 'vitest' +import type { File, Suite, Task, TaskResult } from 'vitest' import { expect, test } from 'vitest' import { resolve } from 'pathe' import { runVitest } from '../../test-utils' @@ -8,25 +8,40 @@ const root = resolve(__dirname, '../fixtures') test('calc the duration used by junit', () => { const result: TaskResult = { state: 'pass', duration: 0 } - const suite: Suite = { + const file: File = { id: '1', + filepath: 'test.ts', + file: null!, + projectName: '', + type: 'suite', + tasks: [], + name: 'test.ts', + mode: 'run', + meta: {}, + } + file.file = file + const suite: Suite = { + id: '1_0', type: 'suite', name: 'suite', mode: 'run', tasks: [], + file, meta: {}, - projectName: '', } const task: Task = { - id: '1', + id: '1_0_0', type: 'test', name: 'timeout', mode: 'run', result, + file, context: null as any, suite, meta: {}, } + file.tasks = [suite] + suite.tasks = [task] expect(getDuration(task)).toBe('0') result.duration = 0.12 expect(getDuration(task)).toBe('0.00012') diff --git a/test/reporters/tests/reporters.spec.ts b/test/reporters/tests/reporters.spec.ts index d9a7af45457c..e785252e4796 100644 --- a/test/reporters/tests/reporters.spec.ts +++ b/test/reporters/tests/reporters.spec.ts @@ -8,6 +8,8 @@ import { TapFlatReporter } from '../../../packages/vitest/src/node/reporters/tap import { getContext } from '../src/context' import { files } from '../src/data' +const beautify = (json: string) => JSON.parse(json) + vi.mock('os', () => ({ hostname: () => 'hostname', })) @@ -205,7 +207,7 @@ test('json reporter with outputFile', async () => { // Assert expect(normalizeCwd(context.output)).toMatchSnapshot() expect(existsSync(outputFile)).toBe(true) - expect(readFileSync(outputFile, 'utf8')).toMatchSnapshot() + expect(beautify(readFileSync(outputFile, 'utf8'))).toMatchSnapshot() // Cleanup rmSync(outputFile) @@ -229,7 +231,7 @@ test('json reporter with outputFile object', async () => { // Assert expect(normalizeCwd(context.output)).toMatchSnapshot() expect(existsSync(outputFile)).toBe(true) - expect(readFileSync(outputFile, 'utf8')).toMatchSnapshot() + expect(beautify(readFileSync(outputFile, 'utf8'))).toMatchSnapshot() // Cleanup rmSync(outputFile) @@ -252,7 +254,7 @@ test('json reporter with outputFile in non-existing directory', async () => { // Assert expect(normalizeCwd(context.output)).toMatchSnapshot() expect(existsSync(outputFile)).toBe(true) - expect(readFileSync(outputFile, 'utf8')).toMatchSnapshot() + expect(beautify(readFileSync(outputFile, 'utf8'))).toMatchSnapshot() // Cleanup rmSync(rootDirectory, { recursive: true }) @@ -277,7 +279,7 @@ test('json reporter with outputFile object in non-existing directory', async () // Assert expect(normalizeCwd(context.output)).toMatchSnapshot() expect(existsSync(outputFile)).toBe(true) - expect(readFileSync(outputFile, 'utf8')).toMatchSnapshot() + expect(beautify(readFileSync(outputFile, 'utf8'))).toMatchSnapshot() // Cleanup rmSync(rootDirectory, { recursive: true })