mirror of
https://github.com/vitest-dev/vitest.git
synced 2025-12-08 18:26:03 +00:00
fix(reporter)!: remove deprecated APIs (#8223)
Co-authored-by: Vladimir Sheremet <sleuths.slews0s@icloud.com>
This commit is contained in:
parent
61703c9ea7
commit
149f8e5095
@ -25,6 +25,7 @@ Vitest has its own test run lifecycle. These are represented by reporter's metho
|
||||
- [`onHookEnd(afterAll)`](#onhookend)
|
||||
- [`onTestSuiteResult`](#ontestsuiteresult)
|
||||
- [`onTestModuleEnd`](#ontestmoduleend)
|
||||
- [`onCoverage`](#oncoverage)
|
||||
- [`onTestRunEnd`](#ontestrunend)
|
||||
|
||||
Tests and suites within a single module will be reported in order unless they were skipped. All skipped tests are reported at the end of suite/module.
|
||||
|
||||
@ -67,7 +67,7 @@ The function is called only once (unless the server config was updated), and it'
|
||||
|
||||
Vitest calls `runTest` when new tests are scheduled to run. It will not call it if `files` is empty. The first argument is an array of [TestSpecifications](/advanced/api/test-specification). Files are sorted using [`sequencer`](/config/#sequence-sequencer) before `runTests` is called. It's possible (but unlikely) to have the same file twice, but it will always have a different project - this is implemented via [`projects`](/guide/projects) configuration.
|
||||
|
||||
Vitest will wait until `runTests` is executed before finishing a run (i.e., it will emit [`onFinished`](/advanced/reporters) only after `runTests` is resolved).
|
||||
Vitest will wait until `runTests` is executed before finishing a run (i.e., it will emit [`onTestRunEnd`](/advanced/reporters) only after `runTests` is resolved).
|
||||
|
||||
If you are using a custom pool, you will have to provide test files and their results yourself - you can reference [`vitest.state`](https://github.com/vitest-dev/vitest/blob/main/packages/vitest/src/node/state.ts) for that (most important are `collectFiles` and `updateTasks`). Vitest uses `startTests` function from `@vitest/runner` package to do that.
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ And here is an example of a custom reporter:
|
||||
import { BaseReporter } from 'vitest/reporters'
|
||||
|
||||
export default class CustomReporter extends BaseReporter {
|
||||
onCollected() {
|
||||
onTestModuleCollected() {
|
||||
const files = this.ctx.state.getFiles(this.watchFilters)
|
||||
this.reportTestSummary(files)
|
||||
}
|
||||
@ -39,7 +39,7 @@ Or implement the `Reporter` interface:
|
||||
import type { Reporter } from 'vitest/node'
|
||||
|
||||
export default class CustomReporter implements Reporter {
|
||||
onCollected() {
|
||||
onTestModuleCollected() {
|
||||
// print something
|
||||
}
|
||||
}
|
||||
@ -65,22 +65,14 @@ Instead of using the tasks that reporters receive, it is recommended to use the
|
||||
You can get access to this API by calling `vitest.state.getReportedEntity(runnerTask)`:
|
||||
|
||||
```ts twoslash
|
||||
import type { Reporter, RunnerTestFile, TestModule, Vitest } from 'vitest/node'
|
||||
import type { Reporter, TestModule } from 'vitest/node'
|
||||
|
||||
class MyReporter implements Reporter {
|
||||
private vitest!: Vitest
|
||||
|
||||
onInit(vitest: Vitest) {
|
||||
this.vitest = vitest
|
||||
}
|
||||
|
||||
onFinished(files: RunnerTestFile[]) {
|
||||
for (const file of files) {
|
||||
// note that the old task implementation uses "file" instead of "module"
|
||||
const testModule = this.vitest.state.getReportedEntity(file) as TestModule
|
||||
onTestRunEnd(testModules: ReadonlyArray<TestModule>) {
|
||||
for (const testModule of testModules) {
|
||||
for (const task of testModule.children) {
|
||||
// ^?
|
||||
console.log('finished', task.type, task.fullName)
|
||||
console.log('test run end', task.type, task.fullName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,6 +200,7 @@ Vitest 4.0 removes some deprecated APIs, including:
|
||||
- `poolMatchGlobs` config option. Use [`projects`](/guide/projects) instead.
|
||||
- `environmentMatchGlobs` config option. Use [`projects`](/guide/projects) instead.
|
||||
- `workspace` config option. Use [`projects`](/guide/projects) instead.
|
||||
- Reporter APIs `onCollected`, `onSpecsCollected`, `onPathsCollected`, `onTaskUpdate` and `onFinished`. See [`Reporters API`](/advanced/api/reporters) for new alternatives. These APIs were introduced in Vitest `v3.0.0`.
|
||||
- `deps.external`, `deps.inline`, `deps.fallbackCJS` config options. Use `server.deps.external`, `server.deps.inline`, or `server.deps.fallbackCJS` instead.
|
||||
|
||||
This release also removes all deprecated types. This finally fixes an issue where Vitest accidentally pulled in `@types/node` (see [#5481](https://github.com/vitest-dev/vitest/issues/5481) and [#6141](https://github.com/vitest-dev/vitest/issues/6141)).
|
||||
|
||||
@ -63,11 +63,6 @@ export type Awaitable<T> = T | PromiseLike<T>
|
||||
|
||||
export interface WebSocketEvents {
|
||||
onCollected?: (files: RunnerTestFile[]) => Awaitable<void>
|
||||
onFinished?: (
|
||||
files: File[],
|
||||
errors: unknown[],
|
||||
coverage?: unknown
|
||||
) => Awaitable<void>
|
||||
onTaskUpdate?: (packs: TaskResultPack[]) => Awaitable<void>
|
||||
onUserConsoleLog?: (log: UserConsoleLog) => Awaitable<void>
|
||||
onPathsCollected?: (paths?: string[]) => Awaitable<void>
|
||||
|
||||
@ -71,7 +71,7 @@ export default class HTMLReporter implements Reporter {
|
||||
await fs.mkdir(resolve(this.reporterDir, 'assets'), { recursive: true })
|
||||
}
|
||||
|
||||
async onFinished(): Promise<void> {
|
||||
async onTestRunEnd(): Promise<void> {
|
||||
const result: HTMLReportData = {
|
||||
paths: this.ctx.state.getPaths(),
|
||||
files: this.ctx.state.getFiles(),
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import type { File, TaskEventPack, TaskResultPack, TestAnnotation } from '@vitest/runner'
|
||||
import type { SerializedError } from '@vitest/utils'
|
||||
import type { IncomingMessage } from 'node:http'
|
||||
import type { ViteDevServer } from 'vite'
|
||||
import type { WebSocket } from 'ws'
|
||||
import type { Vitest } from '../node/core'
|
||||
import type { TestCase } from '../node/reporters/reported-tasks'
|
||||
import type { TestCase, TestModule } from '../node/reporters/reported-tasks'
|
||||
import type { TestSpecification } from '../node/spec'
|
||||
import type { Reporter } from '../node/types/reporter'
|
||||
import type { SerializedTestSpecification } from '../runtime/types/utils'
|
||||
import type { Awaitable, LabelColor, ModuleGraphData, UserConsoleLog } from '../types/general'
|
||||
import type { LabelColor, ModuleGraphData, UserConsoleLog } from '../types/general'
|
||||
import type {
|
||||
TransformResultWithSource,
|
||||
WebSocketEvents,
|
||||
@ -163,21 +164,25 @@ export class WebSocketReporter implements Reporter {
|
||||
public clients: Map<WebSocket, WebSocketRPC>,
|
||||
) {}
|
||||
|
||||
onCollected(files?: File[]): void {
|
||||
onTestModuleCollected(testModule: TestModule): void {
|
||||
if (this.clients.size === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
this.clients.forEach((client) => {
|
||||
client.onCollected?.(files)?.catch?.(noop)
|
||||
client.onCollected?.([testModule.task])?.catch?.(noop)
|
||||
})
|
||||
}
|
||||
|
||||
onSpecsCollected(specs?: SerializedTestSpecification[] | undefined): Awaitable<void> {
|
||||
onTestRunStart(specifications: ReadonlyArray<TestSpecification>): void {
|
||||
if (this.clients.size === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const serializedSpecs = specifications.map(spec => spec.toJSON())
|
||||
|
||||
this.clients.forEach((client) => {
|
||||
client.onSpecsCollected?.(specs)?.catch?.(noop)
|
||||
client.onSpecsCollected?.(serializedSpecs)?.catch?.(noop)
|
||||
})
|
||||
}
|
||||
|
||||
@ -220,7 +225,14 @@ export class WebSocketReporter implements Reporter {
|
||||
})
|
||||
}
|
||||
|
||||
onFinished(files: File[], errors: unknown[]): void {
|
||||
onTestRunEnd(testModules: ReadonlyArray<TestModule>, unhandledErrors: ReadonlyArray<SerializedError>): void {
|
||||
if (!this.clients.size) {
|
||||
return
|
||||
}
|
||||
|
||||
const files = testModules.map(testModule => testModule.task)
|
||||
const errors = [...unhandledErrors]
|
||||
|
||||
this.clients.forEach((client) => {
|
||||
client.onFinished?.(files, errors)?.catch?.(noop)
|
||||
})
|
||||
|
||||
@ -446,7 +446,6 @@ export class Vitest {
|
||||
this.state.blobs = { files, errors, coverages, executionTimes }
|
||||
|
||||
await this.report('onInit', this)
|
||||
await this.report('onPathsCollected', files.flatMap(f => f.filepath))
|
||||
|
||||
const specifications: TestSpecification[] = []
|
||||
for (const file of files) {
|
||||
@ -455,7 +454,6 @@ export class Vitest {
|
||||
specifications.push(specification)
|
||||
}
|
||||
|
||||
await this.report('onSpecsCollected', specifications.map(spec => spec.toJSON()))
|
||||
await this._testRun.start(specifications).catch(noop)
|
||||
|
||||
for (const file of files) {
|
||||
@ -698,7 +696,6 @@ export class Vitest {
|
||||
}
|
||||
}
|
||||
finally {
|
||||
// TODO: wait for coverage only if `onFinished` is defined
|
||||
const coverage = await this.coverageProvider?.generateCoverage({ allTestsRun })
|
||||
|
||||
const errors = this.state.getUnhandledErrors()
|
||||
|
||||
@ -4,6 +4,7 @@ import type { Vitest } from '../core'
|
||||
import type { ProcessPool } from '../pool'
|
||||
import type { TestProject } from '../project'
|
||||
import type { TestSpecification } from '../spec'
|
||||
import type { TestRunEndReason } from '../types/reporter'
|
||||
import { hasFailed } from '@vitest/runner/utils'
|
||||
import { createDefer } from '@vitest/utils'
|
||||
import { Typechecker } from '../../typecheck/typechecker'
|
||||
@ -42,7 +43,15 @@ export function createTypecheckPool(vitest: Vitest): ProcessPool {
|
||||
|
||||
// triggered by TSC watcher, not Vitest watcher, so we need to emulate what Vitest does in this case
|
||||
if (vitest.config.watch && !vitest.runningPromise) {
|
||||
await vitest.report('onFinished', files, [])
|
||||
const modules = files.map(file => vitest.state.getReportedEntity(file)).filter(e => e?.type === 'module')
|
||||
|
||||
const state: TestRunEndReason = vitest.isCancelling
|
||||
? 'interrupted'
|
||||
: modules.some(m => !m.ok())
|
||||
? 'failed'
|
||||
: 'passed'
|
||||
|
||||
await vitest.report('onTestRunEnd', modules, [], state)
|
||||
await vitest.report('onWatcherStart', files, [
|
||||
...(project.config.typecheck.ignoreSourceErrors ? [] : sourceErrors),
|
||||
...vitest.state.getUnhandledErrors(),
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import type { File, Task } from '@vitest/runner'
|
||||
import type { SerializedError } from '@vitest/utils'
|
||||
import type { TestError, UserConsoleLog } from '../../types/general'
|
||||
import type { Vitest } from '../core'
|
||||
import type { Reporter } from '../types/reporter'
|
||||
import type { Reporter, TestRunEndReason } from '../types/reporter'
|
||||
import type { TestCase, TestCollection, TestModule, TestModuleState, TestResult, TestSuite, TestSuiteState } from './reported-tasks'
|
||||
import { performance } from 'node:perf_hooks'
|
||||
import { getFullName, getSuites, getTestName, getTests, hasFailed } from '@vitest/runner/utils'
|
||||
@ -57,7 +58,14 @@ export abstract class BaseReporter implements Reporter {
|
||||
return relative(this.ctx.config.root, path)
|
||||
}
|
||||
|
||||
onFinished(files: File[] = this.ctx.state.getFiles(), errors: unknown[] = this.ctx.state.getUnhandledErrors()): void {
|
||||
onTestRunEnd(
|
||||
testModules: ReadonlyArray<TestModule>,
|
||||
unhandledErrors: ReadonlyArray<SerializedError>,
|
||||
_reason: TestRunEndReason,
|
||||
): void {
|
||||
const files = testModules.map(testModule => testModule.task)
|
||||
const errors = [...unhandledErrors]
|
||||
|
||||
this.end = performance.now()
|
||||
if (!files.length && !errors.length) {
|
||||
this.ctx.logger.printNoTestFound(this.ctx.filenamePattern)
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import type { File, TaskResultPack } from '@vitest/runner'
|
||||
import type { TaskResultPack } from '@vitest/runner'
|
||||
import type { SerializedError } from '@vitest/utils'
|
||||
import type { Vitest } from '../../core'
|
||||
import type { TestRunEndReason } from '../../types/reporter'
|
||||
import type { TestModule, TestSuite } from '../reported-tasks'
|
||||
import fs from 'node:fs'
|
||||
import { getFullName } from '@vitest/runner/utils'
|
||||
@ -84,8 +86,12 @@ export class BenchmarkReporter extends DefaultReporter {
|
||||
}
|
||||
}
|
||||
|
||||
async onFinished(files: File[] = this.ctx.state.getFiles(), errors: unknown[] = this.ctx.state.getUnhandledErrors()): Promise<void> {
|
||||
super.onFinished(files, errors)
|
||||
async onTestRunEnd(
|
||||
testModules: ReadonlyArray<TestModule>,
|
||||
unhandledErrors: ReadonlyArray<SerializedError>,
|
||||
reason: TestRunEndReason,
|
||||
): Promise<void> {
|
||||
super.onTestRunEnd(testModules, unhandledErrors, reason)
|
||||
|
||||
// write output for future comparison
|
||||
let outputFile = this.ctx.config.benchmark?.outputJson
|
||||
@ -98,7 +104,9 @@ export class BenchmarkReporter extends DefaultReporter {
|
||||
await fs.promises.mkdir(outputDirectory, { recursive: true })
|
||||
}
|
||||
|
||||
const files = testModules.map(t => t.task.file)
|
||||
const output = createBenchmarkJsonReport(files)
|
||||
|
||||
await fs.promises.writeFile(outputFile, JSON.stringify(output, null, 2))
|
||||
this.log(`Benchmark report written to ${outputFile}`)
|
||||
}
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import type { File } from '@vitest/runner'
|
||||
import type { SerializedError } from '@vitest/utils'
|
||||
import type { Vitest } from '../core'
|
||||
import type { TestProject } from '../project'
|
||||
import type { Reporter } from '../types/reporter'
|
||||
import type { TestModule } from './reported-tasks'
|
||||
import { existsSync } from 'node:fs'
|
||||
import { mkdir, readdir, readFile, stat, writeFile } from 'node:fs/promises'
|
||||
import { parse, stringify } from 'flatted'
|
||||
@ -16,6 +18,7 @@ export class BlobReporter implements Reporter {
|
||||
start = 0
|
||||
ctx!: Vitest
|
||||
options: BlobOptions
|
||||
coverage: unknown | undefined
|
||||
|
||||
constructor(options: BlobOptions) {
|
||||
this.options = options
|
||||
@ -28,15 +31,20 @@ export class BlobReporter implements Reporter {
|
||||
|
||||
this.ctx = ctx
|
||||
this.start = performance.now()
|
||||
this.coverage = undefined
|
||||
}
|
||||
|
||||
async onFinished(
|
||||
files: File[] = [],
|
||||
errors: unknown[] = [],
|
||||
coverage: unknown,
|
||||
): Promise<void> {
|
||||
onCoverage(coverage: unknown): void {
|
||||
this.coverage = coverage
|
||||
}
|
||||
|
||||
async onTestRunEnd(testModules: ReadonlyArray<TestModule>, unhandledErrors: ReadonlyArray<SerializedError>): Promise<void> {
|
||||
const executionTime = performance.now() - this.start
|
||||
|
||||
const files = testModules.map(testModule => testModule.task)
|
||||
const errors = [...unhandledErrors]
|
||||
const coverage = this.coverage
|
||||
|
||||
let outputFile
|
||||
= this.options.outputFile ?? getOutputFile(this.ctx.config, 'blob')
|
||||
if (!outputFile) {
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import type { SerializedError } from '@vitest/utils'
|
||||
import type { Vitest } from '../core'
|
||||
import type { TestSpecification } from '../spec'
|
||||
import type { TestRunEndReason } from '../types/reporter'
|
||||
import type { BaseOptions } from './base'
|
||||
import type { ReportedHookContext, TestCase, TestModule } from './reported-tasks'
|
||||
import { BaseReporter } from './base'
|
||||
@ -43,6 +45,15 @@ export class DefaultReporter extends BaseReporter {
|
||||
this.summary?.onTestRunStart(specifications)
|
||||
}
|
||||
|
||||
onTestRunEnd(
|
||||
testModules: ReadonlyArray<TestModule>,
|
||||
unhandledErrors: ReadonlyArray<SerializedError>,
|
||||
reason: TestRunEndReason,
|
||||
): void {
|
||||
super.onTestRunEnd(testModules, unhandledErrors, reason)
|
||||
this.summary?.onTestRunEnd()
|
||||
}
|
||||
|
||||
onTestModuleQueued(file: TestModule): void {
|
||||
this.summary?.onTestModuleQueued(file)
|
||||
}
|
||||
@ -77,8 +88,4 @@ export class DefaultReporter extends BaseReporter {
|
||||
super.onInit(ctx)
|
||||
this.summary?.onInit(ctx, { verbose: this.verbose })
|
||||
}
|
||||
|
||||
onTestRunEnd(): void {
|
||||
this.summary?.onTestRunEnd()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import type { File, Test } from '@vitest/runner'
|
||||
import type { Test } from '@vitest/runner'
|
||||
import type { SerializedError } from '@vitest/utils'
|
||||
import type { Writable } from 'node:stream'
|
||||
import type { Vitest } from '../core'
|
||||
import type { TestRunEndReason } from '../types/reporter'
|
||||
import type { TestCase, TestModule } from './reported-tasks'
|
||||
import c from 'tinyrainbow'
|
||||
import { BaseReporter } from './base'
|
||||
@ -40,7 +42,11 @@ export class DotReporter extends BaseReporter {
|
||||
super.onWatcherRerun(files, trigger)
|
||||
}
|
||||
|
||||
onFinished(files?: File[], errors?: unknown[]): void {
|
||||
onTestRunEnd(
|
||||
testModules: ReadonlyArray<TestModule>,
|
||||
unhandledErrors: ReadonlyArray<SerializedError>,
|
||||
reason: TestRunEndReason,
|
||||
): void {
|
||||
if (this.isTTY) {
|
||||
const finalLog = formatTests(Array.from(this.tests.values()))
|
||||
this.ctx.logger.log(finalLog)
|
||||
@ -52,7 +58,7 @@ export class DotReporter extends BaseReporter {
|
||||
this.tests.clear()
|
||||
this.renderer?.finish()
|
||||
|
||||
super.onFinished(files, errors)
|
||||
super.onTestRunEnd(testModules, unhandledErrors, reason)
|
||||
}
|
||||
|
||||
onTestModuleCollected(module: TestModule): void {
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import type { File, TestAnnotation } from '@vitest/runner'
|
||||
import type { SerializedError } from '@vitest/utils'
|
||||
import type { Vitest } from '../core'
|
||||
import type { TestProject } from '../project'
|
||||
import type { Reporter } from '../types/reporter'
|
||||
import type { TestCase } from './reported-tasks'
|
||||
import type { TestCase, TestModule } from './reported-tasks'
|
||||
import { stripVTControlCharacters } from 'node:util'
|
||||
import { getFullName, getTasks } from '@vitest/runner/utils'
|
||||
import { capturePrintError } from '../printError'
|
||||
@ -42,7 +43,13 @@ export class GithubActionsReporter implements Reporter {
|
||||
this.ctx.logger.log(`\n${formatted}`)
|
||||
}
|
||||
|
||||
onFinished(files: File[] = [], errors: unknown[] = []): void {
|
||||
onTestRunEnd(
|
||||
testModules: ReadonlyArray<TestModule>,
|
||||
unhandledErrors: ReadonlyArray<SerializedError>,
|
||||
): void {
|
||||
const files = testModules.map(testModule => testModule.task)
|
||||
const errors = [...unhandledErrors]
|
||||
|
||||
// collect all errors and associate them with projects
|
||||
const projectErrors = new Array<{
|
||||
project: TestProject
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import type { File, Suite, TaskMeta, TaskState } from '@vitest/runner'
|
||||
import type { Suite, TaskMeta, TaskState } from '@vitest/runner'
|
||||
import type { SnapshotSummary } from '@vitest/snapshot'
|
||||
import type { CoverageMap } from 'istanbul-lib-coverage'
|
||||
import type { Vitest } from '../core'
|
||||
import type { Reporter } from '../types/reporter'
|
||||
import type { TestModule } from './reported-tasks'
|
||||
import { existsSync, promises as fs } from 'node:fs'
|
||||
import { getSuites, getTests } from '@vitest/runner/utils'
|
||||
import { dirname, resolve } from 'pathe'
|
||||
@ -78,6 +79,7 @@ export class JsonReporter implements Reporter {
|
||||
start = 0
|
||||
ctx!: Vitest
|
||||
options: JsonOptions
|
||||
coverageMap?: CoverageMap
|
||||
|
||||
constructor(options: JsonOptions) {
|
||||
this.options = options
|
||||
@ -86,9 +88,16 @@ export class JsonReporter implements Reporter {
|
||||
onInit(ctx: Vitest): void {
|
||||
this.ctx = ctx
|
||||
this.start = Date.now()
|
||||
this.coverageMap = undefined
|
||||
}
|
||||
|
||||
protected async logTasks(files: File[], coverageMap?: CoverageMap | null): Promise<void> {
|
||||
onCoverage(coverageMap: unknown): void {
|
||||
this.coverageMap = coverageMap as CoverageMap
|
||||
}
|
||||
|
||||
async onTestRunEnd(testModules: ReadonlyArray<TestModule>): Promise<void> {
|
||||
const files = testModules.map(testModule => testModule.task)
|
||||
|
||||
const suites = getSuites(files)
|
||||
const numTotalTestSuites = suites.length
|
||||
const tests = getTests(files)
|
||||
@ -190,16 +199,12 @@ export class JsonReporter implements Reporter {
|
||||
startTime: this.start,
|
||||
success,
|
||||
testResults,
|
||||
coverageMap,
|
||||
coverageMap: this.coverageMap,
|
||||
}
|
||||
|
||||
await this.writeReport(JSON.stringify(result))
|
||||
}
|
||||
|
||||
async onFinished(files: File[] = this.ctx.state.getFiles(), _errors: unknown[] = [], coverageMap?: unknown): Promise<void> {
|
||||
await this.logTasks(files, coverageMap as CoverageMap)
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the report to an output file if specified in the config,
|
||||
* or logs it to the console otherwise.
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import type { File, Task } from '@vitest/runner'
|
||||
import type { Task } from '@vitest/runner'
|
||||
import type { Vitest } from '../core'
|
||||
import type { Reporter } from '../types/reporter'
|
||||
import type { TestModule } from './reported-tasks'
|
||||
import { existsSync, promises as fs } from 'node:fs'
|
||||
|
||||
import { hostname } from 'node:os'
|
||||
@ -284,7 +285,9 @@ export class JUnitReporter implements Reporter {
|
||||
}
|
||||
}
|
||||
|
||||
async onFinished(files: File[] = this.ctx.state.getFiles()): Promise<void> {
|
||||
async onTestRunEnd(testModules: ReadonlyArray<TestModule>): Promise<void> {
|
||||
const files = testModules.map(testModule => testModule.task)
|
||||
|
||||
await this.logger.log('<?xml version="1.0" encoding="UTF-8" ?>')
|
||||
|
||||
const transformed = files.map((file) => {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import type { File, Task } from '@vitest/runner'
|
||||
import type { Task } from '@vitest/runner'
|
||||
import type { Vitest } from '../core'
|
||||
import type { TestModule } from './reported-tasks'
|
||||
import { TapReporter } from './tap'
|
||||
|
||||
function flattenTasks(task: Task, baseName = ''): Task[] {
|
||||
@ -25,10 +26,10 @@ export class TapFlatReporter extends TapReporter {
|
||||
super.onInit(ctx)
|
||||
}
|
||||
|
||||
onFinished(files: File[] = this.ctx.state.getFiles()): void {
|
||||
onTestRunEnd(testModules: ReadonlyArray<TestModule>): void {
|
||||
this.ctx.logger.log('TAP version 13')
|
||||
|
||||
const flatTasks = files.flatMap(task => flattenTasks(task))
|
||||
const flatTasks = testModules.flatMap(testModule => flattenTasks(testModule.task))
|
||||
|
||||
this.logTasks(flatTasks)
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import type { File, Task } from '@vitest/runner'
|
||||
import type { Task } from '@vitest/runner'
|
||||
import type { ParsedStack, TestError } from '@vitest/utils'
|
||||
import type { Vitest } from '../core'
|
||||
import type { Reporter } from '../types/reporter'
|
||||
import type { TestModule } from './reported-tasks'
|
||||
import { parseErrorStacktrace } from '../../utils/source-map'
|
||||
import { IndentedLogger } from './renderers/indented-logger'
|
||||
|
||||
@ -132,7 +133,9 @@ export class TapReporter implements Reporter {
|
||||
}
|
||||
}
|
||||
|
||||
onFinished(files: File[] = this.ctx.state.getFiles()): void {
|
||||
onTestRunEnd(testModules: ReadonlyArray<TestModule>): void {
|
||||
const files = testModules.map(testModule => testModule.task)
|
||||
|
||||
this.logger.log('TAP version 13')
|
||||
|
||||
this.logTasks(files)
|
||||
|
||||
@ -28,8 +28,6 @@ export class TestRun {
|
||||
const filepaths = specifications.map(spec => spec.moduleId)
|
||||
this.vitest.state.collectPaths(filepaths)
|
||||
|
||||
await this.vitest.report('onPathsCollected', Array.from(new Set(filepaths)))
|
||||
await this.vitest.report('onSpecsCollected', specifications.map(spec => spec.toJSON()))
|
||||
await this.vitest.report('onTestRunStart', [...specifications])
|
||||
}
|
||||
|
||||
@ -41,13 +39,12 @@ export class TestRun {
|
||||
|
||||
async collected(project: TestProject, files: RunnerTestFile[]): Promise<void> {
|
||||
this.vitest.state.collectFiles(project, files)
|
||||
await Promise.all([
|
||||
this.vitest.report('onCollected', files),
|
||||
...files.map((file) => {
|
||||
await Promise.all(
|
||||
files.map((file) => {
|
||||
const testModule = this.vitest.state.getReportedEntity(file) as TestModule
|
||||
return this.vitest.report('onTestModuleCollected', testModule)
|
||||
}),
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
async log(log: UserConsoleLog): Promise<void> {
|
||||
@ -86,9 +83,12 @@ export class TestRun {
|
||||
}
|
||||
|
||||
async end(specifications: TestSpecification[], errors: unknown[], coverage?: unknown): Promise<void> {
|
||||
if (coverage) {
|
||||
await this.vitest.report('onCoverage', coverage)
|
||||
}
|
||||
|
||||
// specification won't have the File task if they were filtered by the --shard command
|
||||
const modules = specifications.map(spec => spec.testModule).filter(s => s != null)
|
||||
const files = modules.map(m => m.task)
|
||||
|
||||
const state: TestRunEndReason = this.vitest.isCancelling
|
||||
? 'interrupted'
|
||||
@ -102,18 +102,7 @@ export class TestRun {
|
||||
process.exitCode = 1
|
||||
}
|
||||
|
||||
try {
|
||||
await Promise.all([
|
||||
this.vitest.report('onTestRunEnd', modules, [...errors] as SerializedError[], state),
|
||||
// TODO: in a perfect world, the coverage should be done in parallel to `onFinished`
|
||||
this.vitest.report('onFinished', files, errors, coverage),
|
||||
])
|
||||
}
|
||||
finally {
|
||||
if (coverage) {
|
||||
await this.vitest.report('onCoverage', coverage)
|
||||
}
|
||||
}
|
||||
this.vitest.report('onTestRunEnd', modules, [...errors] as SerializedError[], state)
|
||||
}
|
||||
|
||||
private hasFailed(modules: TestModule[]) {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import type { File, TaskEventPack, TaskResultPack, TestAnnotation } from '@vitest/runner'
|
||||
import type { SerializedError } from '@vitest/utils'
|
||||
import type { SerializedTestSpecification } from '../../runtime/types/utils'
|
||||
import type { Awaitable, UserConsoleLog } from '../../types/general'
|
||||
import type { Vitest } from '../core'
|
||||
import type { TestProject } from '../project'
|
||||
@ -17,29 +16,7 @@ export interface Reporter {
|
||||
* @experimental
|
||||
*/
|
||||
onBrowserInit?: (project: TestProject) => Awaitable<void>
|
||||
/**
|
||||
* @deprecated use `onTestRunStart` instead
|
||||
*/
|
||||
onPathsCollected?: (paths?: string[]) => Awaitable<void>
|
||||
/**
|
||||
* @deprecated use `onTestRunStart` instead
|
||||
*/
|
||||
onSpecsCollected?: (specs?: SerializedTestSpecification[]) => Awaitable<void>
|
||||
/**
|
||||
* @deprecated use `onTestModuleCollected` instead
|
||||
*/
|
||||
onCollected?: (files: File[]) => Awaitable<void>
|
||||
/**
|
||||
* @deprecated use `onTestRunEnd` instead
|
||||
*/
|
||||
onFinished?: (
|
||||
files: File[],
|
||||
errors: unknown[],
|
||||
coverage?: unknown
|
||||
) => Awaitable<void>
|
||||
/**
|
||||
* @deprecated use `onTestModuleQueued`, `onTestModuleStart`, `onTestModuleEnd`, `onTestCaseReady`, `onTestCaseResult` instead
|
||||
*/
|
||||
/** @internal */
|
||||
onTaskUpdate?: (packs: TaskResultPack[], events: TaskEventPack[]) => Awaitable<void>
|
||||
onTestRemoved?: (trigger?: string) => Awaitable<void>
|
||||
onWatcherStart?: (files?: File[], errors?: unknown[]) => Awaitable<void>
|
||||
|
||||
@ -33,10 +33,9 @@ describe('running browser tests', async () => {
|
||||
'json',
|
||||
{
|
||||
onInit: noop,
|
||||
onPathsCollected: noop,
|
||||
onCollected: noop,
|
||||
onFinished: noop,
|
||||
onTaskUpdate: noop,
|
||||
onTestRunStart: noop,
|
||||
onTestModuleCollected: noop,
|
||||
onTestRunEnd: noop,
|
||||
onTestRemoved: noop,
|
||||
onWatcherStart: noop,
|
||||
onWatcherRerun: noop,
|
||||
|
||||
@ -19,7 +19,7 @@ it('automatically assigns the port', async () => {
|
||||
onInit(ctx_) {
|
||||
ctx = ctx_
|
||||
},
|
||||
onFinished() {
|
||||
onTestRunEnd() {
|
||||
urls = ctx.projects.map(p => p.browser?.vite.resolvedUrls?.local[0])
|
||||
},
|
||||
},
|
||||
|
||||
@ -1,29 +1,28 @@
|
||||
import type { TestModule } from 'vitest/node'
|
||||
import { expect, it, vi } from 'vitest'
|
||||
import { createVitest } from 'vitest/node'
|
||||
|
||||
it(createVitest, async () => {
|
||||
const onFinished = vi.fn()
|
||||
const onTestRunEnd = vi.fn()
|
||||
const ctx = await createVitest('test', {
|
||||
watch: false,
|
||||
root: 'fixtures/create-vitest',
|
||||
reporters: [
|
||||
{
|
||||
onFinished,
|
||||
onTestRunEnd,
|
||||
},
|
||||
],
|
||||
})
|
||||
const testFiles = await ctx.globTestSpecifications()
|
||||
await ctx.runTestSpecifications(testFiles, false)
|
||||
expect(onFinished.mock.calls[0]).toMatchObject([
|
||||
[
|
||||
{
|
||||
name: 'basic.test.ts',
|
||||
result: {
|
||||
state: 'pass',
|
||||
},
|
||||
},
|
||||
],
|
||||
[],
|
||||
undefined,
|
||||
])
|
||||
|
||||
const [testModules, errors, reason] = onTestRunEnd.mock.calls[0]
|
||||
expect(testModules).toHaveLength(1)
|
||||
|
||||
const testModule = testModules[0]
|
||||
expect((testModule as TestModule).task?.name).toBe('basic.test.ts')
|
||||
expect((testModule as TestModule).state()).toBe('passed')
|
||||
|
||||
expect(errors).toHaveLength(0)
|
||||
expect(reason).toBe('passed')
|
||||
})
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { RunnerTaskResultPack, RunnerTestFile } from 'vitest'
|
||||
import type { TestUserConfig } from 'vitest/node'
|
||||
import type { TaskMeta } from '@vitest/runner'
|
||||
import type { TestModule, TestUserConfig } from 'vitest/node'
|
||||
import { resolve } from 'pathe'
|
||||
import { expect, it } from 'vitest'
|
||||
import { rolldownVersion } from 'vitest/node'
|
||||
@ -15,23 +15,28 @@ it.each([
|
||||
},
|
||||
},
|
||||
] as TestUserConfig[])('passes down metadata when $name', { timeout: 60_000, retry: 1 }, async (config) => {
|
||||
const taskUpdate: RunnerTaskResultPack[] = []
|
||||
const finishedFiles: RunnerTestFile[] = []
|
||||
const collectedFiles: RunnerTestFile[] = []
|
||||
const finishedTestCaseMetas: TaskMeta[] = []
|
||||
const finishedTestModuleMetas: TaskMeta[] = []
|
||||
|
||||
const finishedTestModules: TestModule[] = []
|
||||
const collectedTestModules: TestModule[] = []
|
||||
const { ctx, stdout, stderr } = await runVitest({
|
||||
root: resolve(__dirname, '..', 'fixtures', 'public-api'),
|
||||
include: ['**/*.spec.ts'],
|
||||
reporters: [
|
||||
['verbose', { isTTY: false }],
|
||||
{
|
||||
onTaskUpdate(packs) {
|
||||
taskUpdate.push(...packs.filter(i => i[1]?.state === 'pass'))
|
||||
onTestCaseResult(testCase) {
|
||||
finishedTestCaseMetas.push(testCase.meta())
|
||||
},
|
||||
onFinished(files) {
|
||||
finishedFiles.push(...files || [])
|
||||
onTestModuleEnd(testModule) {
|
||||
finishedTestModuleMetas.push(testModule.meta())
|
||||
},
|
||||
onCollected(files) {
|
||||
collectedFiles.push(...files || [])
|
||||
onTestRunEnd(testModules) {
|
||||
finishedTestModules.push(...testModules)
|
||||
},
|
||||
onTestModuleCollected(testModule) {
|
||||
collectedTestModules.push(testModule)
|
||||
},
|
||||
},
|
||||
],
|
||||
@ -46,39 +51,30 @@ it.each([
|
||||
const suiteMeta = { done: true }
|
||||
const testMeta = { custom: 'some-custom-hanlder' }
|
||||
|
||||
expect(taskUpdate).toHaveLength(4)
|
||||
expect(finishedFiles).toHaveLength(1)
|
||||
expect(finishedTestCaseMetas).toHaveLength(3)
|
||||
expect(finishedTestModuleMetas).toHaveLength(1)
|
||||
expect(finishedTestModules).toHaveLength(1)
|
||||
|
||||
const files = ctx?.state.getFiles() || []
|
||||
expect(files).toHaveLength(1)
|
||||
|
||||
expect(taskUpdate).toContainEqual(
|
||||
[
|
||||
expect.any(String),
|
||||
expect.anything(),
|
||||
suiteMeta,
|
||||
],
|
||||
)
|
||||
expect(finishedTestModuleMetas).toContainEqual(suiteMeta)
|
||||
|
||||
expect(taskUpdate).toContainEqual(
|
||||
[
|
||||
expect.any(String),
|
||||
expect.anything(),
|
||||
testMeta,
|
||||
],
|
||||
)
|
||||
expect(finishedTestCaseMetas).toContainEqual(testMeta)
|
||||
|
||||
expect(finishedFiles[0].meta).toEqual(suiteMeta)
|
||||
expect(finishedFiles[0].tasks[0].meta).toEqual(testMeta)
|
||||
const test = finishedTestModules[0].children.tests().next().value!
|
||||
|
||||
expect(finishedTestModules[0].meta()).toEqual(suiteMeta)
|
||||
expect(test.meta()).toEqual(testMeta)
|
||||
|
||||
expect(files[0].meta).toEqual(suiteMeta)
|
||||
expect(files[0].tasks[0].meta).toEqual(testMeta)
|
||||
|
||||
expect(finishedFiles[0].tasks[0].location).toEqual({
|
||||
expect(test.location).toEqual({
|
||||
line: 14,
|
||||
column: 1,
|
||||
})
|
||||
expect(collectedFiles[0].tasks[0].location).toEqual({
|
||||
expect(collectedTestModules[0].task.tasks[0].location).toEqual({
|
||||
line: 14,
|
||||
column: 1,
|
||||
})
|
||||
|
||||
@ -7,8 +7,7 @@ import { beforeAll, expect, it } from 'vitest'
|
||||
import { runVitest } from '../../test-utils'
|
||||
|
||||
const now = new Date()
|
||||
// const finishedFiles: File[] = []
|
||||
const collectedFiles: RunnerTestFile[] = []
|
||||
const collectedTestModules: TestModule[] = []
|
||||
let state: StateManager
|
||||
let project: WorkspaceProject
|
||||
let files: RunnerTestFile[]
|
||||
@ -23,11 +22,8 @@ beforeAll(async () => {
|
||||
reporters: [
|
||||
'verbose',
|
||||
{
|
||||
// onFinished(files) {
|
||||
// finishedFiles.push(...files || [])
|
||||
// },
|
||||
onCollected(files) {
|
||||
collectedFiles.push(...files || [])
|
||||
onTestModuleCollected(testModule) {
|
||||
collectedTestModules.push(testModule)
|
||||
},
|
||||
},
|
||||
],
|
||||
@ -40,6 +36,7 @@ beforeAll(async () => {
|
||||
expect(files).toHaveLength(1)
|
||||
testModule = state.getReportedEntity(files[0])! as TestModule
|
||||
expect(testModule).toBeDefined()
|
||||
expect(testModule).toBe(collectedTestModules[0])
|
||||
})
|
||||
|
||||
it('correctly reports a file', () => {
|
||||
|
||||
@ -3,7 +3,7 @@ export default class PackageReporter {
|
||||
this.ctx = ctx
|
||||
}
|
||||
|
||||
onFinished() {
|
||||
onTestRunEnd() {
|
||||
this.ctx.logger.log('hello from package reporter')
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,6 +44,7 @@ export function getContext(): Context {
|
||||
context.logger = {
|
||||
ctx: context as Vitest,
|
||||
log: (text: string) => output += `${text}\n`,
|
||||
highlight: () => {},
|
||||
} as unknown as Logger
|
||||
|
||||
return {
|
||||
|
||||
@ -3,7 +3,7 @@ export default class TestReporter {
|
||||
this.ctx = ctx
|
||||
}
|
||||
|
||||
onFinished() {
|
||||
onTestRunEnd() {
|
||||
this.ctx.logger.log('hello from custom reporter')
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ export default class TestReporter implements Reporter {
|
||||
this.ctx = ctx
|
||||
}
|
||||
|
||||
onFinished() {
|
||||
onTestRunEnd() {
|
||||
this.ctx.logger.log('hello from custom reporter')
|
||||
|
||||
if (this.options) {
|
||||
|
||||
@ -17,7 +17,7 @@ test('reporters, single', () => {
|
||||
|
||||
assertType<Configuration>({ reporters: 'custom-reporter' })
|
||||
assertType<Configuration>({ reporters: './reporter.mjs' })
|
||||
assertType<Configuration>({ reporters: { onFinished() {} } })
|
||||
assertType<Configuration>({ reporters: { onTestRunEnd() {} } })
|
||||
})
|
||||
|
||||
test('reporters, multiple', () => {
|
||||
|
||||
@ -7,7 +7,6 @@ import { runVitest } from '../../test-utils'
|
||||
|
||||
class LogReporter extends DefaultReporter {
|
||||
isTTY = true
|
||||
onTaskUpdate() {}
|
||||
}
|
||||
|
||||
test('should print logs correctly', async () => {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import type { TestModule } from '../../../packages/vitest/src/node/reporters/reported-tasks'
|
||||
import { existsSync, readFileSync, rmSync } from 'node:fs'
|
||||
import { normalize, resolve } from 'pathe'
|
||||
import { beforeEach, expect, test, vi } from 'vitest'
|
||||
@ -9,6 +10,9 @@ import { getContext } from '../src/context'
|
||||
import { files, passedFiles } from '../src/data'
|
||||
|
||||
const beautify = (json: string) => JSON.parse(json)
|
||||
function getTestModules(_files = files) {
|
||||
return _files.map(task => ({ task }) as TestModule)
|
||||
}
|
||||
|
||||
vi.mock('os', () => ({
|
||||
hostname: () => 'hostname',
|
||||
@ -25,10 +29,11 @@ test('tap reporter', async () => {
|
||||
// Arrange
|
||||
const reporter = new TapReporter()
|
||||
const context = getContext()
|
||||
const testModules = getTestModules()
|
||||
|
||||
// Act
|
||||
reporter.onInit(context.vitest)
|
||||
await reporter.onFinished(files)
|
||||
reporter.onTestRunEnd(testModules)
|
||||
|
||||
// Assert
|
||||
expect(context.output).toMatchSnapshot()
|
||||
@ -38,10 +43,11 @@ test('tap-flat reporter', async () => {
|
||||
// Arrange
|
||||
const reporter = new TapFlatReporter()
|
||||
const context = getContext()
|
||||
const testModules = getTestModules()
|
||||
|
||||
// Act
|
||||
reporter.onInit(context.vitest)
|
||||
await reporter.onFinished(files)
|
||||
reporter.onTestRunEnd(testModules)
|
||||
|
||||
// Assert
|
||||
expect(context.output).toMatchSnapshot()
|
||||
@ -54,7 +60,7 @@ test('JUnit reporter', async () => {
|
||||
|
||||
// Act
|
||||
await reporter.onInit(context.vitest)
|
||||
await reporter.onFinished([])
|
||||
await reporter.onTestRunEnd([])
|
||||
|
||||
// Assert
|
||||
expect(context.output).toMatchSnapshot()
|
||||
@ -64,11 +70,12 @@ test('JUnit reporter without classname', async () => {
|
||||
// Arrange
|
||||
const reporter = new JUnitReporter({})
|
||||
const context = getContext()
|
||||
const testModules = getTestModules(passedFiles)
|
||||
|
||||
// Act
|
||||
await reporter.onInit(context.vitest)
|
||||
|
||||
await reporter.onFinished(passedFiles)
|
||||
await reporter.onTestRunEnd(testModules)
|
||||
|
||||
// Assert
|
||||
expect(context.output).toMatchSnapshot()
|
||||
@ -78,11 +85,12 @@ test('JUnit reporter with custom string classname', async () => {
|
||||
// Arrange
|
||||
const reporter = new JUnitReporter({ classnameTemplate: 'my-custom-classname' })
|
||||
const context = getContext()
|
||||
const testModules = getTestModules(passedFiles)
|
||||
|
||||
// Act
|
||||
await reporter.onInit(context.vitest)
|
||||
|
||||
await reporter.onFinished(passedFiles)
|
||||
await reporter.onTestRunEnd(testModules)
|
||||
|
||||
// Assert
|
||||
expect(context.output).toMatchSnapshot()
|
||||
@ -92,11 +100,12 @@ test('JUnit reporter with custom function classnameTemplate', async () => {
|
||||
// Arrange
|
||||
const reporter = new JUnitReporter({ classnameTemplate: task => `filename:${task.filename} - filepath:${task.filepath}` })
|
||||
const context = getContext()
|
||||
const testModules = getTestModules(passedFiles)
|
||||
|
||||
// Act
|
||||
await reporter.onInit(context.vitest)
|
||||
|
||||
await reporter.onFinished(passedFiles)
|
||||
await reporter.onTestRunEnd(testModules)
|
||||
|
||||
// Assert
|
||||
expect(context.output).toMatchSnapshot()
|
||||
@ -105,11 +114,12 @@ test('JUnit reporter with custom string classnameTemplate', async () => {
|
||||
// Arrange
|
||||
const reporter = new JUnitReporter({ classnameTemplate: `filename:{filename} - filepath:{filepath}` })
|
||||
const context = getContext()
|
||||
const testModules = getTestModules(passedFiles)
|
||||
|
||||
// Act
|
||||
await reporter.onInit(context.vitest)
|
||||
|
||||
await reporter.onFinished(passedFiles)
|
||||
await reporter.onTestRunEnd(testModules)
|
||||
|
||||
// Assert
|
||||
expect(context.output).toMatchSnapshot()
|
||||
@ -123,7 +133,7 @@ test('JUnit reporter (no outputFile entry)', async () => {
|
||||
|
||||
// Act
|
||||
await reporter.onInit(context.vitest)
|
||||
await reporter.onFinished([])
|
||||
await reporter.onTestRunEnd([])
|
||||
|
||||
// Assert
|
||||
expect(context.output).toMatchSnapshot()
|
||||
@ -138,7 +148,7 @@ test('JUnit reporter with outputFile', async () => {
|
||||
|
||||
// Act
|
||||
await reporter.onInit(context.vitest)
|
||||
await reporter.onFinished([])
|
||||
await reporter.onTestRunEnd([])
|
||||
|
||||
// Assert
|
||||
expect(normalizeCwd(context.output)).toMatchSnapshot()
|
||||
@ -160,7 +170,7 @@ test('JUnit reporter with outputFile object', async () => {
|
||||
|
||||
// Act
|
||||
await reporter.onInit(context.vitest)
|
||||
await reporter.onFinished([])
|
||||
await reporter.onTestRunEnd([])
|
||||
|
||||
// Assert
|
||||
expect(normalizeCwd(context.output)).toMatchSnapshot()
|
||||
@ -181,7 +191,7 @@ test('JUnit reporter with outputFile in non-existing directory', async () => {
|
||||
|
||||
// Act
|
||||
await reporter.onInit(context.vitest)
|
||||
await reporter.onFinished([])
|
||||
await reporter.onTestRunEnd([])
|
||||
|
||||
// Assert
|
||||
expect(normalizeCwd(context.output)).toMatchSnapshot()
|
||||
@ -204,7 +214,7 @@ test('JUnit reporter with outputFile object in non-existing directory', async ()
|
||||
|
||||
// Act
|
||||
await reporter.onInit(context.vitest)
|
||||
await reporter.onFinished([])
|
||||
await reporter.onTestRunEnd([])
|
||||
|
||||
// Assert
|
||||
expect(normalizeCwd(context.output)).toMatchSnapshot()
|
||||
@ -219,12 +229,13 @@ test('json reporter', async () => {
|
||||
// Arrange
|
||||
const reporter = new JsonReporter({})
|
||||
const context = getContext()
|
||||
const testModules = getTestModules()
|
||||
|
||||
vi.setSystemTime(1642587001759)
|
||||
|
||||
// Act
|
||||
reporter.onInit(context.vitest)
|
||||
await reporter.onFinished(files)
|
||||
await reporter.onTestRunEnd(testModules)
|
||||
|
||||
// Assert
|
||||
expect(JSON.parse(context.output)).toMatchSnapshot()
|
||||
@ -235,12 +246,13 @@ test('json reporter (no outputFile entry)', async () => {
|
||||
const reporter = new JsonReporter({})
|
||||
const context = getContext()
|
||||
context.vitest.config.outputFile = {}
|
||||
const testModules = getTestModules()
|
||||
|
||||
vi.setSystemTime(1642587001759)
|
||||
|
||||
// Act
|
||||
reporter.onInit(context.vitest)
|
||||
await reporter.onFinished(files)
|
||||
await reporter.onTestRunEnd(testModules)
|
||||
|
||||
// Assert
|
||||
expect(JSON.parse(context.output)).toMatchSnapshot()
|
||||
@ -252,12 +264,13 @@ test('json reporter with outputFile', async () => {
|
||||
const outputFile = resolve('report.json')
|
||||
const context = getContext()
|
||||
context.vitest.config.outputFile = outputFile
|
||||
const testModules = getTestModules()
|
||||
|
||||
vi.setSystemTime(1642587001759)
|
||||
|
||||
// Act
|
||||
reporter.onInit(context.vitest)
|
||||
await reporter.onFinished(files)
|
||||
await reporter.onTestRunEnd(testModules)
|
||||
|
||||
// Assert
|
||||
expect(normalizeCwd(context.output)).toMatchSnapshot()
|
||||
@ -276,12 +289,13 @@ test('json reporter with outputFile object', async () => {
|
||||
context.vitest.config.outputFile = {
|
||||
json: outputFile,
|
||||
}
|
||||
const testModules = getTestModules()
|
||||
|
||||
vi.setSystemTime(1642587001759)
|
||||
|
||||
// Act
|
||||
reporter.onInit(context.vitest)
|
||||
await reporter.onFinished(files)
|
||||
await reporter.onTestRunEnd(testModules)
|
||||
|
||||
// Assert
|
||||
expect(normalizeCwd(context.output)).toMatchSnapshot()
|
||||
@ -299,12 +313,13 @@ test('json reporter with outputFile in non-existing directory', async () => {
|
||||
const outputFile = `${rootDirectory}/deeply/nested/report.json`
|
||||
const context = getContext()
|
||||
context.vitest.config.outputFile = outputFile
|
||||
const testModules = getTestModules()
|
||||
|
||||
vi.setSystemTime(1642587001759)
|
||||
|
||||
// Act
|
||||
reporter.onInit(context.vitest)
|
||||
await reporter.onFinished(files)
|
||||
await reporter.onTestRunEnd(testModules)
|
||||
|
||||
// Assert
|
||||
expect(normalizeCwd(context.output)).toMatchSnapshot()
|
||||
@ -324,12 +339,13 @@ test('json reporter with outputFile object in non-existing directory', async ()
|
||||
context.vitest.config.outputFile = {
|
||||
json: outputFile,
|
||||
}
|
||||
const testModules = getTestModules()
|
||||
|
||||
vi.setSystemTime(1642587001759)
|
||||
|
||||
// Act
|
||||
reporter.onInit(context.vitest)
|
||||
await reporter.onFinished(files)
|
||||
await reporter.onTestRunEnd(testModules)
|
||||
|
||||
// Assert
|
||||
expect(normalizeCwd(context.output)).toMatchSnapshot()
|
||||
|
||||
@ -101,5 +101,4 @@ Log from failed suite`,
|
||||
|
||||
class LogReporter extends DefaultReporter {
|
||||
isTTY = true
|
||||
onTaskUpdate() {}
|
||||
}
|
||||
|
||||
@ -2,6 +2,44 @@ import { expect, test } from 'vitest'
|
||||
import { runVitest } from '../../test-utils'
|
||||
|
||||
test('handle custom error without name', async () => {
|
||||
let { stdout, stderr } = await runVitest({ reporters: 'tap', root: './fixtures/custom-error' })
|
||||
stdout = stdout.replaceAll(/time=(\S*)/g, 'time=[...]') // strip non-deterministic output
|
||||
expect(stdout).toMatchInlineSnapshot(`
|
||||
"TAP version 13
|
||||
1..1
|
||||
not ok 1 - basic.test.ts # time=[...] {
|
||||
1..4
|
||||
not ok 1 - no name object # time=[...]
|
||||
---
|
||||
error:
|
||||
name: "Unknown Error"
|
||||
message: "undefined"
|
||||
...
|
||||
not ok 2 - string # time=[...]
|
||||
---
|
||||
error:
|
||||
name: "Unknown Error"
|
||||
message: "hi"
|
||||
...
|
||||
not ok 3 - number # time=[...]
|
||||
---
|
||||
error:
|
||||
name: "Unknown Error"
|
||||
message: "1234"
|
||||
...
|
||||
not ok 4 - number name object # time=[...]
|
||||
---
|
||||
error:
|
||||
name: "1234"
|
||||
message: "undefined"
|
||||
...
|
||||
}
|
||||
"
|
||||
`)
|
||||
expect(stderr).toBe('')
|
||||
})
|
||||
|
||||
test('tap-flat handles custom error without name', async () => {
|
||||
let { stdout, stderr } = await runVitest({ reporters: 'tap-flat', root: './fixtures/custom-error' })
|
||||
stdout = stdout.replaceAll(/time=(\S*)/g, 'time=[...]') // strip non-deterministic output
|
||||
expect(stdout).toMatchInlineSnapshot(`
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user