From f2b803761192f8718c369f2f62bee20c9a57489a Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Thu, 28 Aug 2025 14:30:50 +0200 Subject: [PATCH 01/18] fix!: always print test cases in verbose reporter even in TTY --- packages/vitest/src/node/reporters/verbose.ts | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/packages/vitest/src/node/reporters/verbose.ts b/packages/vitest/src/node/reporters/verbose.ts index a840bec5320c..99fdfa5cd2d4 100644 --- a/packages/vitest/src/node/reporters/verbose.ts +++ b/packages/vitest/src/node/reporters/verbose.ts @@ -10,14 +10,8 @@ export class VerboseReporter extends DefaultReporter { protected verbose = true renderSucceed = true - printTestModule(module: TestModule): void { - // still print the test module in TTY, - // but don't print it in the CLI because we - // print all the tests when they finish - // instead of printing them when the test file finishes - if (this.isTTY) { - return super.printTestModule(module) - } + printTestModule(_module: TestModule): void { + // don't print test module, only print tests } onTestCaseResult(test: TestCase): void { @@ -25,9 +19,6 @@ export class VerboseReporter extends DefaultReporter { // don't print tests in TTY as they go, only print them // in the CLI when they finish - if (this.isTTY) { - return - } const testResult = test.result() From 5ec3bd372ca96ed1a19c8b62a546d4850abf1743 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Thu, 28 Aug 2025 14:31:54 +0200 Subject: [PATCH 02/18] chore: migration --- docs/guide/migration.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/guide/migration.md b/docs/guide/migration.md index eaf92cfa9414..cd064e22c64f 100644 --- a/docs/guide/migration.md +++ b/docs/guide/migration.md @@ -267,6 +267,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. - 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`. +- The `verbose` reporter now always prints tests cases even if the terminal is TTY (previously, it would fallback to the `default` reporter in that case). - `deps.external`, `deps.inline`, `deps.fallbackCJS` config options. Use `server.deps.external`, `server.deps.inline`, or `server.deps.fallbackCJS` instead. - `browser.testerScripts` config option. Use [`browser.testerHtmlPath`](/guide/browser/config#browser-testerhtmlpath) instead. - `minWorkers` config option. Only `maxWorkers` has any effect on how tests are running, so we are removing this public option. From 8c1d6b489afc0f8cf42a68a24c7d37b076b68d24 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Thu, 28 Aug 2025 15:06:47 +0200 Subject: [PATCH 03/18] fix: print retry/repeat --- packages/vitest/src/node/reporters/verbose.ts | 12 +++- test/reporters/tests/verbose.test.ts | 62 +++++++------------ 2 files changed, 33 insertions(+), 41 deletions(-) diff --git a/packages/vitest/src/node/reporters/verbose.ts b/packages/vitest/src/node/reporters/verbose.ts index 99fdfa5cd2d4..9ccedb42dade 100644 --- a/packages/vitest/src/node/reporters/verbose.ts +++ b/packages/vitest/src/node/reporters/verbose.ts @@ -33,9 +33,19 @@ export class VerboseReporter extends DefaultReporter { } title += getFullName(test.task, c.dim(' > ')) - title += this.getDurationPrefix(test.task) const diagnostic = test.diagnostic() + const { retryCount, repeatCount } = diagnostic || {} + if (retryCount != null && retryCount > 0) { + title += c.yellow(` (retry x${retryCount})`) + } + + if (repeatCount != null && repeatCount > 0) { + title += c.yellow(` (repeat x${repeatCount})`) + } + + title += this.getDurationPrefix(test.task) + if (diagnostic?.heap != null) { title += c.magenta(` ${Math.floor(diagnostic.heap / 1024 / 1024)} MB heap used`) } diff --git a/test/reporters/tests/verbose.test.ts b/test/reporters/tests/verbose.test.ts index 9fa7b59e246e..a804578d2f6a 100644 --- a/test/reporters/tests/verbose.test.ts +++ b/test/reporters/tests/verbose.test.ts @@ -33,13 +33,10 @@ test('prints skipped tests by default', async () => { }) expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(` - "✓ fixtures/pass-and-skip-test-suites.test.ts (4 tests | 2 skipped) [...]ms - ✓ passing test #1 [...]ms - ✓ passing suite (1) - ✓ passing test #2 [...]ms - ↓ skipped test #1 - ↓ skipped suite (1) - ↓ skipped test #2" + "✓ fixtures/pass-and-skip-test-suites.test.ts > passing test #1 [...]ms + ✓ fixtures/pass-and-skip-test-suites.test.ts > passing suite > passing test #2 [...]ms + ↓ fixtures/pass-and-skip-test-suites.test.ts > skipped test #1 + ↓ fixtures/pass-and-skip-test-suites.test.ts > skipped suite > skipped test #2" `) }) @@ -52,10 +49,8 @@ test('hides skipped tests when --hideSkippedTests', async () => { }) expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(` - "✓ fixtures/pass-and-skip-test-suites.test.ts (4 tests | 2 skipped) [...]ms - ✓ passing test #1 [...]ms - ✓ passing suite (1) - ✓ passing test #2 [...]ms" + "✓ fixtures/pass-and-skip-test-suites.test.ts > passing test #1 [...]ms + ✓ fixtures/pass-and-skip-test-suites.test.ts > passing suite > passing test #2 [...]ms" `) }) @@ -67,10 +62,7 @@ test('prints retry count', async () => { config: false, }) - expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(` - "✓ fixtures/retry.test.ts (1 test) [...]ms - ✓ pass after retries [...]ms (retry x3)" - `) + expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`"✓ fixtures/retry.test.ts > pass after retries (retry x3) [...]ms"`) }) test('prints repeat count', async () => { @@ -80,10 +72,7 @@ test('prints repeat count', async () => { config: false, }) - expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(` - "✓ fixtures/repeats.test.ts (1 test) [...]ms - ✓ repeat couple of times [...]ms (repeat x3)" - `) + expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`"✓ fixtures/repeats.test.ts > repeat couple of times (repeat x3) [...]ms"`) }) test('renders tree when in TTY', async () => { @@ -106,27 +95,20 @@ test('renders tree when in TTY', async () => { }) expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(` - "❯ fixtures/verbose/example-1.test.ts (10 tests | 1 failed | 4 skipped) [...]ms - ✓ test pass in root [...]ms - ↓ test skip in root - ❯ suite in root (5) - ✓ test pass in 1. suite #1 [...]ms - ✓ test pass in 1. suite #2 [...]ms - ❯ suite in suite (3) - ✓ test pass in nested suite #1 [...]ms - ✓ test pass in nested suite #2 [...]ms - ❯ suite in nested suite (1) - × test failure in 2x nested suite [...]ms - ↓ suite skip in root (3) - ↓ test 1.3 - ↓ suite in suite (2) - ↓ test in nested suite - ↓ test failure in nested suite of skipped suite - ✓ fixtures/verbose/example-2.test.ts (3 tests | 1 skipped) [...]ms - ✓ test 0.1 [...]ms - ↓ test 0.2 - ✓ suite 1.1 (1) - ✓ test 1.1 [...]ms" + "✓ fixtures/verbose/example-1.test.ts > test pass in root [...]ms + ↓ fixtures/verbose/example-1.test.ts > test skip in root + ✓ fixtures/verbose/example-1.test.ts > suite in root > test pass in 1. suite #1 [...]ms + ✓ fixtures/verbose/example-1.test.ts > suite in root > test pass in 1. suite #2 [...]ms + ✓ fixtures/verbose/example-1.test.ts > suite in root > suite in suite > test pass in nested suite #1 [...]ms + ✓ fixtures/verbose/example-1.test.ts > suite in root > suite in suite > test pass in nested suite #2 [...]ms + × fixtures/verbose/example-1.test.ts > suite in root > suite in suite > suite in nested suite > test failure in 2x nested suite [...]ms + → expected 'should fail' to be 'as expected' // Object.is equality + ↓ fixtures/verbose/example-1.test.ts > suite skip in root > test 1.3 + ↓ fixtures/verbose/example-1.test.ts > suite skip in root > suite in suite > test in nested suite + ↓ fixtures/verbose/example-1.test.ts > suite skip in root > suite in suite > test failure in nested suite of skipped suite + ✓ fixtures/verbose/example-2.test.ts > test 0.1 [...]ms + ↓ fixtures/verbose/example-2.test.ts > test 0.2 + ✓ fixtures/verbose/example-2.test.ts > suite 1.1 > test 1.1 [...]ms" `) }) From d718f7724c62f0db15ca6c5c4440df21c8dcc329 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Fri, 29 Aug 2025 11:30:52 +0200 Subject: [PATCH 04/18] chore: remove test --- test/reporters/tests/verbose.test.ts | 37 ---------------------------- 1 file changed, 37 deletions(-) diff --git a/test/reporters/tests/verbose.test.ts b/test/reporters/tests/verbose.test.ts index a804578d2f6a..71ccf12180d8 100644 --- a/test/reporters/tests/verbose.test.ts +++ b/test/reporters/tests/verbose.test.ts @@ -75,43 +75,6 @@ test('prints repeat count', async () => { expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`"✓ fixtures/repeats.test.ts > repeat couple of times (repeat x3) [...]ms"`) }) -test('renders tree when in TTY', async () => { - const { stdout } = await runVitest({ - include: ['fixtures/verbose/*.test.ts'], - reporters: [['verbose', { isTTY: true, summary: false }]], - config: false, - fileParallelism: false, - sequence: { - sequencer: class StableTestFileOrderSorter { - sort(files: TestSpecification[]) { - return files.sort((a, b) => a.moduleId.localeCompare(b.moduleId)) - } - - shard(files: TestSpecification[]) { - return files - } - }, - }, - }) - - expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(` - "✓ fixtures/verbose/example-1.test.ts > test pass in root [...]ms - ↓ fixtures/verbose/example-1.test.ts > test skip in root - ✓ fixtures/verbose/example-1.test.ts > suite in root > test pass in 1. suite #1 [...]ms - ✓ fixtures/verbose/example-1.test.ts > suite in root > test pass in 1. suite #2 [...]ms - ✓ fixtures/verbose/example-1.test.ts > suite in root > suite in suite > test pass in nested suite #1 [...]ms - ✓ fixtures/verbose/example-1.test.ts > suite in root > suite in suite > test pass in nested suite #2 [...]ms - × fixtures/verbose/example-1.test.ts > suite in root > suite in suite > suite in nested suite > test failure in 2x nested suite [...]ms - → expected 'should fail' to be 'as expected' // Object.is equality - ↓ fixtures/verbose/example-1.test.ts > suite skip in root > test 1.3 - ↓ fixtures/verbose/example-1.test.ts > suite skip in root > suite in suite > test in nested suite - ↓ fixtures/verbose/example-1.test.ts > suite skip in root > suite in suite > test failure in nested suite of skipped suite - ✓ fixtures/verbose/example-2.test.ts > test 0.1 [...]ms - ↓ fixtures/verbose/example-2.test.ts > test 0.2 - ✓ fixtures/verbose/example-2.test.ts > suite 1.1 > test 1.1 [...]ms" - `) -}) - test('does not render tree when in non-TTY', async () => { const { stdout } = await runVitest({ include: ['fixtures/verbose/*.test.ts'], From 3fe70b154bd30cca1809d59a38b3bd9ace7116b3 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Fri, 29 Aug 2025 12:08:56 +0200 Subject: [PATCH 05/18] feat: add tree reporter --- docs/guide/migration.md | 2 +- packages/vitest/src/node/reporters/base.ts | 120 +++++++++++------- packages/vitest/src/node/reporters/index.ts | 3 + packages/vitest/src/node/reporters/tree.ts | 5 + packages/vitest/src/node/reporters/verbose.ts | 62 +-------- 5 files changed, 90 insertions(+), 102 deletions(-) create mode 100644 packages/vitest/src/node/reporters/tree.ts diff --git a/docs/guide/migration.md b/docs/guide/migration.md index cd064e22c64f..0f3d0d529347 100644 --- a/docs/guide/migration.md +++ b/docs/guide/migration.md @@ -267,7 +267,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. - 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`. -- The `verbose` reporter now always prints tests cases even if the terminal is TTY (previously, it would fallback to the `default` reporter in that case). +- The `verbose` reporter now prints test cases as a flat list. To revert to the previous behaviour, use `--reporter=tree`. - `deps.external`, `deps.inline`, `deps.fallbackCJS` config options. Use `server.deps.external`, `server.deps.inline`, or `server.deps.fallbackCJS` instead. - `browser.testerScripts` config option. Use [`browser.testerHtmlPath`](/guide/browser/config#browser-testerhtmlpath) instead. - `minWorkers` config option. Only `maxWorkers` has any effect on how tests are running, so we are removing this public option. diff --git a/packages/vitest/src/node/reporters/base.ts b/packages/vitest/src/node/reporters/base.ts index 8150d86139a7..0560c9de5c0e 100644 --- a/packages/vitest/src/node/reporters/base.ts +++ b/packages/vitest/src/node/reporters/base.ts @@ -5,15 +5,28 @@ import type { Vitest } from '../core' 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' +import { getFullName, getSuites, getTests, hasFailed } from '@vitest/runner/utils' import { toArray } from '@vitest/utils' import { parseStacktrace } from '@vitest/utils/source-map' import { relative } from 'pathe' import c from 'tinyrainbow' import { isTTY } from '../../utils/env' import { hasFailedSnapshot } from '../../utils/tasks' -import { F_CHECK, F_DOWN_RIGHT, F_POINTER, F_RIGHT } from './renderers/figures' -import { countTestErrors, divider, errorBanner, formatProjectName, formatTime, formatTimeString, getStateString, getStateSymbol, padSummaryTitle, renderSnapshotSummary, taskFail, withLabel } from './renderers/utils' +import { F_CHECK, F_DOWN_RIGHT, F_POINTER } from './renderers/figures' +import { + countTestErrors, + divider, + errorBanner, + formatProjectName, + formatTime, + formatTimeString, + getStateString, + getStateSymbol, + padSummaryTitle, + renderSnapshotSummary, + taskFail, + withLabel, +} from './renderers/utils' const BADGE_PADDING = ' ' @@ -170,33 +183,16 @@ export abstract class BaseReporter implements Reporter { protected printTestCase(moduleState: TestModuleState, test: TestCase): void { const testResult = test.result() - const { duration, retryCount, repeatCount } = test.diagnostic() || {} + const { duration = 0 } = test.diagnostic() || {} const padding = this.getTestIndentation(test.task) - let suffix = this.getDurationPrefix(test.task) - - if (retryCount != null && retryCount > 0) { - suffix += c.yellow(` (retry x${retryCount})`) - } - - if (repeatCount != null && repeatCount > 0) { - suffix += c.yellow(` (repeat x${repeatCount})`) - } + const suffix = this.getTestCaseSuffix(test) if (testResult.state === 'failed') { this.log(c.red(` ${padding}${taskFail} ${this.getTestName(test.task, c.dim(' > '))}`) + suffix) - - // print short errors, full errors will be at the end in summary - testResult.errors.forEach((error) => { - const message = this.formatShortError(error) - - if (message) { - this.log(c.red(` ${padding}${message}`)) - } - }) } // also print slow tests - else if (duration && duration > this.ctx.config.slowTestThreshold) { + else if (duration > this.ctx.config.slowTestThreshold) { this.log(` ${padding}${c.yellow(c.dim(F_CHECK))} ${this.getTestName(test.task, c.dim(' > '))} ${suffix}`) } @@ -204,13 +200,8 @@ export abstract class BaseReporter implements Reporter { // Skipped tests are hidden when --hideSkippedTests } - // also print skipped tests that have notes - else if (testResult.state === 'skipped' && testResult.note) { - this.log(` ${padding}${getStateSymbol(test.task)} ${this.getTestName(test.task, c.dim(' > '))}${c.dim(c.gray(` [${testResult.note}]`))}`) - } - else if (this.renderSucceed || moduleState === 'failed') { - this.log(` ${padding}${getStateSymbol(test.task)} ${this.getTestName(test.task, c.dim(' > '))}${suffix}`) + this.log(` ${padding}${this.getStateSymbol(test)} ${this.getTestName(test.task, c.dim(' > '))}${suffix}`) } } @@ -236,7 +227,7 @@ export abstract class BaseReporter implements Reporter { suffix += c.magenta(` ${Math.floor(diagnostic.heap / 1024 / 1024)} MB heap used`) } - let title = getStateSymbol(testModule.task) + let title = this.getStateSymbol(testModule) if (testModule.meta().typecheck) { title += ` ${c.bgBlue(c.bold(' TS '))}` @@ -249,24 +240,28 @@ export abstract class BaseReporter implements Reporter { return ` ${title} ${testModule.task.name} ${suffix}` } - protected printTestSuite(_suite: TestSuite): void { - // Suite name is included in getTestName by default + protected printTestSuite(testSuite: TestSuite): void { + if (!this.renderSucceed) { + return + } + + const indentation = ' '.repeat(getIndentation(testSuite.task)) + const tests = Array.from(testSuite.children.allTests()) + const state = this.getStateSymbol(testSuite) + + this.log(` ${indentation}${state} ${testSuite.name} ${c.dim(`(${tests.length})`)}`) } - protected getTestName(test: Task, separator?: string): string { - return getTestName(test, separator) + protected getTestName(test: Task, _separator?: string): string { + return test.name } protected getFullName(test: Task, separator?: string): string { return getFullName(test, separator) } - protected formatShortError(error: TestError): string { - return `${F_RIGHT} ${error.message}` - } - - protected getTestIndentation(_test: Task) { - return ' ' + protected getTestIndentation(test: Task): string { + return ' '.repeat(getIndentation(test)) } protected printAnnotations(test: TestCase, console: 'log' | 'error', padding = 0): void { @@ -289,16 +284,45 @@ export abstract class BaseReporter implements Reporter { }) } - protected getDurationPrefix(task: Task): string { - if (!task.result?.duration) { + protected getTestCaseSuffix(testCase: TestCase): string { + const { heap, retryCount, repeatCount } = testCase.diagnostic() || {} + const testResult = testCase.result() + let suffix = this.getDurationPrefix(testCase.task) + + if (retryCount != null && retryCount > 0) { + suffix += c.yellow(` (retry x${retryCount})`) + } + + if (repeatCount != null && repeatCount > 0) { + suffix += c.yellow(` (repeat x${repeatCount})`) + } + + if (heap != null) { + suffix += c.magenta(` ${Math.floor(heap / 1024 / 1024)} MB heap used`) + } + + if (testResult.state === 'skipped') { + suffix += c.dim(c.gray(` [${testResult.note}]`)) + } + + return suffix + } + + protected getStateSymbol(test: TestCase | TestModule | TestSuite): string { + return getStateSymbol(test.task) + } + + private getDurationPrefix(task: Task): string { + const duration = task.result?.duration && Math.round(task.result?.duration) + if (!duration) { return '' } - const color = task.result.duration > this.ctx.config.slowTestThreshold + const color = duration > this.ctx.config.slowTestThreshold ? c.yellow : c.green - return color(` ${Math.round(task.result.duration)}${c.dim('ms')}`) + return color(` ${Math.round(duration)}${c.dim('ms')}`) } onWatcherStart(files: File[] = this.ctx.state.getFiles(), errors: unknown[] = this.ctx.state.getUnhandledErrors()): void { @@ -710,3 +734,11 @@ function sum(items: T[], cb: (_next: T) => number | undefined) { return total + Math.max(cb(next) || 0, 0) }, 0) } + +function getIndentation(suite: Task, level = 1): number { + if (suite.suite && !('filepath' in suite.suite)) { + return getIndentation(suite.suite, level + 1) + } + + return level +} diff --git a/packages/vitest/src/node/reporters/index.ts b/packages/vitest/src/node/reporters/index.ts index 946d8a609918..f3940ab08838 100644 --- a/packages/vitest/src/node/reporters/index.ts +++ b/packages/vitest/src/node/reporters/index.ts @@ -14,6 +14,7 @@ import { JsonReporter } from './json' import { JUnitReporter } from './junit' import { TapReporter } from './tap' import { TapFlatReporter } from './tap-flat' +import { TreeReporter } from './tree' import { VerboseReporter } from './verbose' export { @@ -25,6 +26,7 @@ export { JUnitReporter, TapFlatReporter, TapReporter, + TreeReporter, VerboseReporter, } export type { BaseReporter, Reporter, TestRunEndReason } @@ -50,6 +52,7 @@ export const ReportersMap = { 'tap': TapReporter as typeof TapReporter, 'tap-flat': TapFlatReporter as typeof TapFlatReporter, 'junit': JUnitReporter as typeof JUnitReporter, + 'tree': TreeReporter as typeof TreeReporter, 'hanging-process': HangingProcessReporter as typeof HangingProcessReporter, 'github-actions': GithubActionsReporter as typeof GithubActionsReporter, } diff --git a/packages/vitest/src/node/reporters/tree.ts b/packages/vitest/src/node/reporters/tree.ts new file mode 100644 index 000000000000..f6db9af5bfda --- /dev/null +++ b/packages/vitest/src/node/reporters/tree.ts @@ -0,0 +1,5 @@ +import { DefaultReporter } from './default' + +export class TreeReporter extends DefaultReporter { + renderSucceed = true +} diff --git a/packages/vitest/src/node/reporters/verbose.ts b/packages/vitest/src/node/reporters/verbose.ts index 9ccedb42dade..f24be8d65b23 100644 --- a/packages/vitest/src/node/reporters/verbose.ts +++ b/packages/vitest/src/node/reporters/verbose.ts @@ -1,10 +1,9 @@ -import type { Task } from '@vitest/runner' -import type { TestCase, TestModule, TestSuite } from './reported-tasks' +import type { TestCase, TestModule } from './reported-tasks' import { getFullName } from '@vitest/runner/utils' import c from 'tinyrainbow' import { DefaultReporter } from './default' import { F_RIGHT } from './renderers/figures' -import { formatProjectName, getStateSymbol } from './renderers/utils' +import { formatProjectName } from './renderers/utils' export class VerboseReporter extends DefaultReporter { protected verbose = true @@ -17,47 +16,25 @@ export class VerboseReporter extends DefaultReporter { onTestCaseResult(test: TestCase): void { super.onTestCaseResult(test) - // don't print tests in TTY as they go, only print them - // in the CLI when they finish - const testResult = test.result() if (this.ctx.config.hideSkippedTests && testResult.state === 'skipped') { return } - let title = ` ${getStateSymbol(test.task)} ` + let title = ` ${this.getStateSymbol(test)} ` if (test.project.name) { title += formatProjectName(test.project) } title += getFullName(test.task, c.dim(' > ')) - - const diagnostic = test.diagnostic() - const { retryCount, repeatCount } = diagnostic || {} - if (retryCount != null && retryCount > 0) { - title += c.yellow(` (retry x${retryCount})`) - } - - if (repeatCount != null && repeatCount > 0) { - title += c.yellow(` (repeat x${repeatCount})`) - } - - title += this.getDurationPrefix(test.task) - - if (diagnostic?.heap != null) { - title += c.magenta(` ${Math.floor(diagnostic.heap / 1024 / 1024)} MB heap used`) - } - - if (testResult.state === 'skipped' && testResult.note) { - title += c.dim(c.gray(` [${testResult.note}]`)) - } + title += this.getTestCaseSuffix(test) this.log(title) if (testResult.state === 'failed') { - testResult.errors.forEach(error => this.log(c.red(` ${F_RIGHT} ${error?.message}`))) + testResult.errors.forEach(error => this.log(c.red(` ${F_RIGHT} ${error.message}`))) } if (test.annotations().length) { @@ -66,33 +43,4 @@ export class VerboseReporter extends DefaultReporter { this.log() } } - - protected printTestSuite(testSuite: TestSuite): void { - const indentation = ' '.repeat(getIndentation(testSuite.task)) - const tests = Array.from(testSuite.children.allTests()) - const state = getStateSymbol(testSuite.task) - - this.log(` ${indentation}${state} ${testSuite.name} ${c.dim(`(${tests.length})`)}`) - } - - protected getTestName(test: Task): string { - return test.name - } - - protected getTestIndentation(test: Task): string { - return ' '.repeat(getIndentation(test)) - } - - protected formatShortError(): string { - // Short errors are not shown in tree-view - return '' - } -} - -function getIndentation(suite: Task, level = 1): number { - if (suite.suite && !('filepath' in suite.suite)) { - return getIndentation(suite.suite, level + 1) - } - - return level } From 34d561541aceca05eec531727683e4d6a96a01df Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Fri, 29 Aug 2025 12:20:12 +0200 Subject: [PATCH 06/18] fix: print ts consistently --- packages/vitest/src/node/reporters/base.ts | 15 +++++++++------ packages/vitest/src/node/reporters/verbose.ts | 4 ++++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/vitest/src/node/reporters/base.ts b/packages/vitest/src/node/reporters/base.ts index 0560c9de5c0e..155f5ea96eab 100644 --- a/packages/vitest/src/node/reporters/base.ts +++ b/packages/vitest/src/node/reporters/base.ts @@ -229,14 +229,14 @@ export abstract class BaseReporter implements Reporter { let title = this.getStateSymbol(testModule) - if (testModule.meta().typecheck) { - title += ` ${c.bgBlue(c.bold(' TS '))}` - } - if (testModule.project.name) { title += ` ${formatProjectName(testModule.project, '')}` } + if (testModule.meta().typecheck) { + title += ` ${c.bgBlue(c.bold(' TS '))}` + } + return ` ${title} ${testModule.task.name} ${suffix}` } @@ -314,7 +314,10 @@ export abstract class BaseReporter implements Reporter { private getDurationPrefix(task: Task): string { const duration = task.result?.duration && Math.round(task.result?.duration) - if (!duration) { + if (duration == null) { + return '' + } + if (!duration && task.mode === 'skip') { return '' } @@ -470,7 +473,7 @@ export abstract class BaseReporter implements Reporter { const entity = task && this.ctx.state.getReportedEntity(task) const shouldLog = this.ctx.config.onConsoleLog(log.content, log.type, entity) if (shouldLog === false) { - return shouldLog + return false } } return true diff --git a/packages/vitest/src/node/reporters/verbose.ts b/packages/vitest/src/node/reporters/verbose.ts index f24be8d65b23..ceb250179908 100644 --- a/packages/vitest/src/node/reporters/verbose.ts +++ b/packages/vitest/src/node/reporters/verbose.ts @@ -28,6 +28,10 @@ export class VerboseReporter extends DefaultReporter { title += formatProjectName(test.project) } + if (test.task.meta.typecheck) { + title += `${c.bgBlue(c.bold(' TS '))} ` + } + title += getFullName(test.task, c.dim(' > ')) title += this.getTestCaseSuffix(test) From a91659cb52a5a8250effb0e0984e6f3d3e7962dc Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Fri, 29 Aug 2025 12:47:24 +0200 Subject: [PATCH 07/18] refactor: add `getEntityPrefix` --- packages/vitest/src/node/reporters/base.ts | 37 +++++++++++-------- .../src/node/reporters/benchmark/reporter.ts | 4 +- .../src/node/reporters/renderers/utils.ts | 1 + packages/vitest/src/node/reporters/verbose.ts | 14 ++----- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/packages/vitest/src/node/reporters/base.ts b/packages/vitest/src/node/reporters/base.ts index 155f5ea96eab..64ef46c36fc7 100644 --- a/packages/vitest/src/node/reporters/base.ts +++ b/packages/vitest/src/node/reporters/base.ts @@ -24,6 +24,7 @@ import { getStateSymbol, padSummaryTitle, renderSnapshotSummary, + separator, taskFail, withLabel, } from './renderers/utils' @@ -188,12 +189,12 @@ export abstract class BaseReporter implements Reporter { const suffix = this.getTestCaseSuffix(test) if (testResult.state === 'failed') { - this.log(c.red(` ${padding}${taskFail} ${this.getTestName(test.task, c.dim(' > '))}`) + suffix) + this.log(c.red(` ${padding}${taskFail} ${this.getTestName(test.task, separator)}`) + suffix) } // also print slow tests else if (duration > this.ctx.config.slowTestThreshold) { - this.log(` ${padding}${c.yellow(c.dim(F_CHECK))} ${this.getTestName(test.task, c.dim(' > '))} ${suffix}`) + this.log(` ${padding}${c.yellow(c.dim(F_CHECK))} ${this.getTestName(test.task, separator)} ${suffix}`) } else if (this.ctx.config.hideSkippedTests && (testResult.state === 'skipped')) { @@ -201,7 +202,7 @@ export abstract class BaseReporter implements Reporter { } else if (this.renderSucceed || moduleState === 'failed') { - this.log(` ${padding}${this.getStateSymbol(test)} ${this.getTestName(test.task, c.dim(' > '))}${suffix}`) + this.log(` ${padding}${this.getStateSymbol(test)} ${this.getTestName(test.task, separator)}${suffix}`) } } @@ -227,15 +228,7 @@ export abstract class BaseReporter implements Reporter { suffix += c.magenta(` ${Math.floor(diagnostic.heap / 1024 / 1024)} MB heap used`) } - let title = this.getStateSymbol(testModule) - - if (testModule.project.name) { - title += ` ${formatProjectName(testModule.project, '')}` - } - - if (testModule.meta().typecheck) { - title += ` ${c.bgBlue(c.bold(' TS '))}` - } + const title = this.getEntityPrefix(testModule) return ` ${title} ${testModule.task.name} ${suffix}` } @@ -284,6 +277,20 @@ export abstract class BaseReporter implements Reporter { }) } + protected getEntityPrefix(entity: TestCase | TestModule | TestSuite): string { + let title = this.getStateSymbol(entity) + + if (entity.project.name) { + title += ` ${formatProjectName(entity.project, '')}` + } + + if (entity.meta().typecheck) { + title += ` ${c.bgBlue(c.bold(' TS '))}` + } + + return title + } + protected getTestCaseSuffix(testCase: TestCase): string { const { heap, retryCount, repeatCount } = testCase.diagnostic() || {} const testResult = testCase.result() @@ -413,7 +420,7 @@ export abstract class BaseReporter implements Reporter { const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : undefined if (task) { - headerText = this.getFullName(task, c.dim(' > ')) + headerText = this.getFullName(task, separator) } else if (log.taskId && log.taskId !== '__vitest__unknown_test__') { headerText = log.taskId @@ -622,7 +629,7 @@ export abstract class BaseReporter implements Reporter { continue } - const groupName = this.getFullName(group, c.dim(' > ')) + const groupName = this.getFullName(group, separator) const project = this.ctx.projects.find(p => p.name === bench.file.projectName) this.log(` ${formatProjectName(project)}${bench.name}${c.dim(` - ${groupName}`)}`) @@ -679,7 +686,7 @@ export abstract class BaseReporter implements Reporter { const projectName = (task as File)?.projectName || task.file?.projectName || '' const project = this.ctx.projects.find(p => p.name === projectName) - let name = this.getFullName(task, c.dim(' > ')) + let name = this.getFullName(task, separator) if (filepath) { name += c.dim(` [ ${this.relative(filepath)} ]`) diff --git a/packages/vitest/src/node/reporters/benchmark/reporter.ts b/packages/vitest/src/node/reporters/benchmark/reporter.ts index 2c2e820f9a77..1abc7f376a4b 100644 --- a/packages/vitest/src/node/reporters/benchmark/reporter.ts +++ b/packages/vitest/src/node/reporters/benchmark/reporter.ts @@ -8,7 +8,7 @@ import { getFullName } from '@vitest/runner/utils' import * as pathe from 'pathe' import c from 'tinyrainbow' import { DefaultReporter } from '../default' -import { formatProjectName, getStateSymbol } from '../renderers/utils' +import { formatProjectName, getStateSymbol, separator } from '../renderers/utils' import { createBenchmarkJsonReport, flattenFormattedBenchmarkReport } from './json-formatter' import { renderTable } from './tableRender' @@ -67,7 +67,7 @@ export class BenchmarkReporter extends DefaultReporter { const duration = testTask.task.result?.duration || 0 if (benches.length > 0 && benches.every(t => t.result?.state !== 'run' && t.result?.state !== 'queued')) { - let title = `\n ${getStateSymbol(testTask.task)} ${formatProjectName(testTask.project)}${getFullName(testTask.task, c.dim(' > '))}` + let title = `\n ${getStateSymbol(testTask.task)} ${formatProjectName(testTask.project)}${getFullName(testTask.task, separator)}` if (duration != null && duration > this.ctx.config.slowTestThreshold) { title += c.yellow(` ${Math.round(duration)}${c.dim('ms')}`) diff --git a/packages/vitest/src/node/reporters/renderers/utils.ts b/packages/vitest/src/node/reporters/renderers/utils.ts index 8f78c72cd944..b7d800d26744 100644 --- a/packages/vitest/src/node/reporters/renderers/utils.ts +++ b/packages/vitest/src/node/reporters/renderers/utils.ts @@ -23,6 +23,7 @@ export const testPass: string = c.green(F_CHECK) export const taskFail: string = c.red(F_CROSS) export const suiteFail: string = c.red(F_POINTER) export const pending: string = c.gray('·') +export const separator: string = c.dim(' > ') const labelDefaultColors = [c.bgYellow, c.bgCyan, c.bgGreen, c.bgMagenta] as const diff --git a/packages/vitest/src/node/reporters/verbose.ts b/packages/vitest/src/node/reporters/verbose.ts index ceb250179908..570f1cafd4a0 100644 --- a/packages/vitest/src/node/reporters/verbose.ts +++ b/packages/vitest/src/node/reporters/verbose.ts @@ -3,7 +3,7 @@ import { getFullName } from '@vitest/runner/utils' import c from 'tinyrainbow' import { DefaultReporter } from './default' import { F_RIGHT } from './renderers/figures' -import { formatProjectName } from './renderers/utils' +import { separator } from './renderers/utils' export class VerboseReporter extends DefaultReporter { protected verbose = true @@ -22,17 +22,9 @@ export class VerboseReporter extends DefaultReporter { return } - let title = ` ${this.getStateSymbol(test)} ` + let title = ` ${this.getEntityPrefix(test)} ` - if (test.project.name) { - title += formatProjectName(test.project) - } - - if (test.task.meta.typecheck) { - title += `${c.bgBlue(c.bold(' TS '))} ` - } - - title += getFullName(test.task, c.dim(' > ')) + title += getFullName(test.task, separator) title += this.getTestCaseSuffix(test) this.log(title) From 96a42d4480633805a296088e13eb467cb9d85171 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Fri, 29 Aug 2025 13:03:47 +0200 Subject: [PATCH 08/18] fix: print location if available in the verbose reporter --- packages/vitest/src/node/reporters/base.ts | 10 ++++++++-- packages/vitest/src/node/reporters/verbose.ts | 11 +++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/packages/vitest/src/node/reporters/base.ts b/packages/vitest/src/node/reporters/base.ts index 64ef46c36fc7..c53c08652cb9 100644 --- a/packages/vitest/src/node/reporters/base.ts +++ b/packages/vitest/src/node/reporters/base.ts @@ -308,7 +308,7 @@ export abstract class BaseReporter implements Reporter { suffix += c.magenta(` ${Math.floor(heap / 1024 / 1024)} MB heap used`) } - if (testResult.state === 'skipped') { + if (testResult.state === 'skipped' && testResult.note) { suffix += c.dim(c.gray(` [${testResult.note}]`)) } @@ -686,7 +686,13 @@ export abstract class BaseReporter implements Reporter { const projectName = (task as File)?.projectName || task.file?.projectName || '' const project = this.ctx.projects.find(p => p.name === projectName) - let name = this.getFullName(task, separator) + // let name = this.getFullName(task, separator) + let name = task.file.name + if (task.location) { + name += c.dim(`:${task.location.line}:${task.location.column}`) + } + name += separator + name += this.getTestName(task, separator) if (filepath) { name += c.dim(` [ ${this.relative(filepath)} ]`) diff --git a/packages/vitest/src/node/reporters/verbose.ts b/packages/vitest/src/node/reporters/verbose.ts index 570f1cafd4a0..960faa9ad460 100644 --- a/packages/vitest/src/node/reporters/verbose.ts +++ b/packages/vitest/src/node/reporters/verbose.ts @@ -1,5 +1,5 @@ import type { TestCase, TestModule } from './reported-tasks' -import { getFullName } from '@vitest/runner/utils' +import { getTestName } from '@vitest/runner/utils' import c from 'tinyrainbow' import { DefaultReporter } from './default' import { F_RIGHT } from './renderers/figures' @@ -24,7 +24,14 @@ export class VerboseReporter extends DefaultReporter { let title = ` ${this.getEntityPrefix(test)} ` - title += getFullName(test.task, separator) + title += test.module.task.name + if (test.location) { + title += c.dim(`:${test.location.line}:${test.location.column}`) + } + title += separator + + title += getTestName(test.task, separator) + title += this.getTestCaseSuffix(test) this.log(title) From 2bf776eec2c93fe2ea15c2397f62124268e1768d Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Fri, 29 Aug 2025 13:18:08 +0200 Subject: [PATCH 09/18] chore: update tests --- packages/vitest/src/node/reporters/base.ts | 22 +++-- packages/vitest/src/node/reporters/verbose.ts | 1 - .../fixtures/metadata/metadata.test.ts | 4 +- test/reporters/tests/default.test.ts | 94 ++++++++++--------- test/reporters/tests/merge-reports.test.ts | 6 +- test/reporters/tests/verbose.test.ts | 44 ++++++++- 6 files changed, 107 insertions(+), 64 deletions(-) diff --git a/packages/vitest/src/node/reporters/base.ts b/packages/vitest/src/node/reporters/base.ts index c53c08652cb9..4e53b1192ee8 100644 --- a/packages/vitest/src/node/reporters/base.ts +++ b/packages/vitest/src/node/reporters/base.ts @@ -5,7 +5,7 @@ import type { Vitest } from '../core' 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, getTests, hasFailed } from '@vitest/runner/utils' +import { getSuites, getTestName, getTests, hasFailed } from '@vitest/runner/utils' import { toArray } from '@vitest/utils' import { parseStacktrace } from '@vitest/utils/source-map' import { relative } from 'pathe' @@ -250,7 +250,17 @@ export abstract class BaseReporter implements Reporter { } protected getFullName(test: Task, separator?: string): string { - return getFullName(test, separator) + if (test === test.file) { + return test.name + } + + let name = test.file.name + if (test.location) { + name += c.dim(`:${test.location.line}:${test.location.column}`) + } + name += separator + name += getTestName(test, separator) + return name } protected getTestIndentation(test: Task): string { @@ -686,13 +696,7 @@ export abstract class BaseReporter implements Reporter { const projectName = (task as File)?.projectName || task.file?.projectName || '' const project = this.ctx.projects.find(p => p.name === projectName) - // let name = this.getFullName(task, separator) - let name = task.file.name - if (task.location) { - name += c.dim(`:${task.location.line}:${task.location.column}`) - } - name += separator - name += this.getTestName(task, separator) + let name = this.getFullName(task, separator) if (filepath) { name += c.dim(` [ ${this.relative(filepath)} ]`) diff --git a/packages/vitest/src/node/reporters/verbose.ts b/packages/vitest/src/node/reporters/verbose.ts index 960faa9ad460..7686a8d4a150 100644 --- a/packages/vitest/src/node/reporters/verbose.ts +++ b/packages/vitest/src/node/reporters/verbose.ts @@ -31,7 +31,6 @@ export class VerboseReporter extends DefaultReporter { title += separator title += getTestName(test.task, separator) - title += this.getTestCaseSuffix(test) this.log(title) diff --git a/test/reporters/fixtures/metadata/metadata.test.ts b/test/reporters/fixtures/metadata/metadata.test.ts index 9a9dd9e1d8d0..c9ef44ff40d2 100644 --- a/test/reporters/fixtures/metadata/metadata.test.ts +++ b/test/reporters/fixtures/metadata/metadata.test.ts @@ -1,11 +1,11 @@ import {expect, test } from 'vitest'; -test('pass', ( { task }) => { +test('pass', ({ task }) => { task.meta.custom = "Passing test added this" }); -test('fails', ( { task }) => { +test('fails', ({ task }) => { task.meta.custom = "Failing test added this" expect(true).toBe(false) diff --git a/test/reporters/tests/default.test.ts b/test/reporters/tests/default.test.ts index aeea8296fcc3..39ffb3b6dd0a 100644 --- a/test/reporters/tests/default.test.ts +++ b/test/reporters/tests/default.test.ts @@ -25,35 +25,33 @@ describe('default reporter', async () => { expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(` "❯ b1.test.ts (13 tests | 1 failed) [...]ms - ✓ b1 passed > b1 test [...]ms - ✓ b1 passed > b2 test [...]ms - ✓ b1 passed > b3 test [...]ms - ✓ b1 passed > nested b > nested b1 test [...]ms - ✓ b1 passed > nested b > nested b2 test [...]ms - ✓ b1 passed > nested b > nested b3 test [...]ms - ✓ b1 failed > b1 test [...]ms - ✓ b1 failed > b2 test [...]ms - ✓ b1 failed > b3 test [...]ms - × b1 failed > b failed test [...]ms - → expected 1 to be 2 // Object.is equality - ✓ b1 failed > nested b > nested b1 test [...]ms - ✓ b1 failed > nested b > nested b2 test [...]ms - ✓ b1 failed > nested b > nested b3 test [...]ms + ✓ b1 test [...]ms + ✓ b2 test [...]ms + ✓ b3 test [...]ms + ✓ nested b1 test [...]ms + ✓ nested b2 test [...]ms + ✓ nested b3 test [...]ms + ✓ b1 test [...]ms + ✓ b2 test [...]ms + ✓ b3 test [...]ms + × b failed test [...]ms + ✓ nested b1 test [...]ms + ✓ nested b2 test [...]ms + ✓ nested b3 test [...]ms ❯ b2.test.ts (13 tests | 1 failed) [...]ms - ✓ b2 passed > b1 test [...]ms - ✓ b2 passed > b2 test [...]ms - ✓ b2 passed > b3 test [...]ms - ✓ b2 passed > nested b > nested b1 test [...]ms - ✓ b2 passed > nested b > nested b2 test [...]ms - ✓ b2 passed > nested b > nested b3 test [...]ms - ✓ b2 failed > b1 test [...]ms - ✓ b2 failed > b2 test [...]ms - ✓ b2 failed > b3 test [...]ms - × b2 failed > b failed test [...]ms - → expected 1 to be 2 // Object.is equality - ✓ b2 failed > nested b > nested b1 test [...]ms - ✓ b2 failed > nested b > nested b2 test [...]ms - ✓ b2 failed > nested b > nested b3 test [...]ms" + ✓ b1 test [...]ms + ✓ b2 test [...]ms + ✓ b3 test [...]ms + ✓ nested b1 test [...]ms + ✓ nested b2 test [...]ms + ✓ nested b3 test [...]ms + ✓ b1 test [...]ms + ✓ b2 test [...]ms + ✓ b3 test [...]ms + × b failed test [...]ms + ✓ nested b1 test [...]ms + ✓ nested b2 test [...]ms + ✓ nested b3 test [...]ms" `) }) @@ -64,9 +62,12 @@ describe('default reporter', async () => { reporters: 'none', }) - expect(stdout).toContain('✓ a passed > a1 test') - expect(stdout).toContain('✓ a passed > nested a > nested a3 test') - expect(stdout).toContain('× a failed > a failed test') + expect(stdout).toContain('✓ a passed') + expect(stdout).toContain('✓ a1 test') + expect(stdout).toContain('✓ nested a') + expect(stdout).toContain('✓ nested a3 test') + expect(stdout).toContain('× a failed') + expect(stdout).toContain('× a failed test') expect(stdout).toContain('nested a failed 1 test') expect(stdout).toContain('[note]') expect(stdout).toContain('[reason]') @@ -89,8 +90,10 @@ describe('default reporter', async () => { await vitest.waitForStdout('Filename pattern: a') await vitest.waitForStdout('Waiting for file changes...') - expect(vitest.stdout).contain('✓ a passed > a1 test') - expect(vitest.stdout).contain('✓ a passed > nested a > nested a3 test') + expect(vitest.stdout).toContain('✓ a passed') + expect(vitest.stdout).toContain('✓ a1 test') + expect(vitest.stdout).toContain('✓ nested a') + expect(vitest.stdout).toContain('✓ nested a3 test') // rerun and two files vitest.write('p') @@ -99,9 +102,7 @@ describe('default reporter', async () => { await vitest.waitForStdout('Waiting for file changes...') expect(vitest.stdout).toContain('✓ b1.test.ts') expect(vitest.stdout).toContain('✓ b2.test.ts') - expect(vitest.stdout).not.toContain('✓ nested b1 test') - expect(vitest.stdout).not.toContain('✓ b1 test') - expect(vitest.stdout).not.toContain('✓ b2 test') + expect(vitest.stdout).not.toContain('✓ b2 failed') }) test('doesn\'t print error properties', async () => { @@ -139,9 +140,11 @@ describe('default reporter', async () => { expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(` "✓ fixtures/pass-and-skip-test-suites.test.ts (4 tests | 2 skipped) [...]ms ✓ passing test #1 [...]ms - ✓ passing suite > passing test #2 [...]ms + ✓ passing suite (1) + ✓ passing test #2 [...]ms ↓ skipped test #1 - ↓ skipped suite > skipped test #2" + ↓ skipped suite (1) + ↓ skipped test #2" `) }) @@ -156,7 +159,8 @@ describe('default reporter', async () => { expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(` "✓ fixtures/pass-and-skip-test-suites.test.ts (4 tests | 2 skipped) [...]ms ✓ passing test #1 [...]ms - ✓ passing suite > passing test #2 [...]ms" + ✓ passing suite (1) + ✓ passing test #2 [...]ms" `) }) @@ -190,13 +194,13 @@ describe('default reporter', async () => { reporters: 'none', }) - expect(stdout).toContain('✓ passed > 0-based index of the test case is 0') - expect(stdout).toContain('✓ passed > 0-based index of the test case is 1') - expect(stdout).toContain('✓ passed > 0-based index of the test case is 2') + expect(stdout).toContain('✓ 0-based index of the test case is 0') + expect(stdout).toContain('✓ 0-based index of the test case is 1') + expect(stdout).toContain('✓ 0-based index of the test case is 2') - expect(stdout).toContain('✓ passed > 1-based index of the test case is 1') - expect(stdout).toContain('✓ passed > 1-based index of the test case is 2') - expect(stdout).toContain('✓ passed > 1-based index of the test case is 3') + expect(stdout).toContain('✓ 1-based index of the test case is 1') + expect(stdout).toContain('✓ 1-based index of the test case is 2') + expect(stdout).toContain('✓ 1-based index of the test case is 3') }) test('test.each/for title format', async () => { diff --git a/test/reporters/tests/merge-reports.test.ts b/test/reporters/tests/merge-reports.test.ts index abdfa205a5dc..abe5480a5932 100644 --- a/test/reporters/tests/merge-reports.test.ts +++ b/test/reporters/tests/merge-reports.test.ts @@ -97,15 +97,13 @@ test('merge reports', async () => { ❯ first.test.ts (2 tests | 1 failed)