From 171bbd1a8cb1b114bb23e4662199d0eb508fb347 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa <4232207+hi-ogawa@users.noreply.github.com> Date: Thu, 22 Oct 2026 15:53:56 +0900 Subject: [PATCH] feat: label repeats without retry index in failure header Co-Authored-By: Claude Opus 5.5 --- packages/vitest/src/node/reporters/base.ts | 23 +++++++++------------- test/e2e/test/retry.test.ts | 17 ++++++++++++++++ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/packages/vitest/src/node/reporters/base.ts b/packages/vitest/src/node/reporters/base.ts index 2c49039ab..de4e3e067 100644 --- a/packages/vitest/src/node/reporters/base.ts +++ b/packages/vitest/src/node/reporters/base.ts @@ -1562,20 +1562,15 @@ export abstract class BaseReporter implements Reporter { function formatErrorAttempts(task: Task, attempts: (TaskResultAttempt | undefined)[]): string { const maxRetries = typeof task.retry === 'number' ? task.retry : (task.retry?.count ?? 0) return [...Map.groupBy(attempts, (attempt) => attempt)] - .map(([attempt, occurrences]) => { - const parts: string[] = [] - if (attempt && (maxRetries || task.repeats)) { - parts.push( - task.repeats - ? `repeat ${attempt.repeatIndex} retry ${attempt.retryIndex}` - : `retry ${attempt.retryIndex}`, - ) - } - if (occurrences.length > 1) { - parts.push(`x${occurrences.length}`) - } - return parts.join(' ') - }) + .map(([attempt, occurrences]) => + [ + attempt && task.repeats && `repeat ${attempt.repeatIndex}`, + attempt && maxRetries && `retry ${attempt.retryIndex}`, + occurrences.length > 1 && `x${occurrences.length}`, + ] + .filter(Boolean) + .join(' '), + ) .filter(Boolean) .join(', ') } diff --git a/test/e2e/test/retry.test.ts b/test/e2e/test/retry.test.ts index 53ba92bfa..1234b8432 100644 --- a/test/e2e/test/retry.test.ts +++ b/test/e2e/test/retry.test.ts @@ -393,6 +393,23 @@ describe('failure summary header', () => { `) }) + test('labels repeats without retry', async () => { + const { stderr } = await runInlineTests({ + 'basic.test.js': ` + import { expect, test } from 'vitest' + + test('repeated', { repeats: 1 }, () => { + expect(1).toBe(2) + }) + `, + }) + + expect(extractFailureHeaders(stderr)).toMatchInlineSnapshot(` + " FAIL basic.test.js > repeated (repeat 0, repeat 1) + AssertionError: expected 1 to be 2 // Object.is equality" + `) + }) + test('prints headers for soft errors repeated within an attempt', async () => { const { stderr } = await runInlineTests({ 'basic.test.js': ` -- 2.54.0