@@ -346,3 +346,118 @@ test('syntax errors remain failures after successful repeats', async () => {
346346 }
347347 ` )
348348} )
349+
350+ describe ( 'failure summary header' , ( ) => {
351+ function extractFailureHeaders ( stderr : string ) {
352+ return stderr
353+ . split ( '\n' )
354+ . filter ( ( line ) => / ^ F A I L | E r r o r : / . test ( line ) )
355+ . join ( '\n' )
356+ }
357+
358+ test ( 'prints one header for an error repeated on every attempt' , async ( ) => {
359+ const { stderr } = await runInlineTests ( {
360+ 'basic.test.js' : `
361+ import { expect, test } from 'vitest'
362+
363+ test('retry', { retry: 2 }, () => {
364+ expect(1).toBe(2)
365+ })
366+
367+ test('repeats', { repeats: 1 }, () => {
368+ expect(1).toBe(2)
369+ })
370+
371+ test('retry-repeats', { retry: 1, repeats: 1 }, () => {
372+ expect(1).toBe(2)
373+ })
374+ ` ,
375+ } )
376+
377+ expect ( extractFailureHeaders ( stderr ) ) . toMatchInlineSnapshot ( `
378+ " FAIL basic.test.js > retry (initial run, 1st retry, 2nd retry)
379+ AssertionError: expected 1 to be 2 // Object.is equality
380+ FAIL basic.test.js > repeats (initial run, 1st repeat)
381+ AssertionError: expected 1 to be 2 // Object.is equality
382+ FAIL basic.test.js > retry-repeats (initial run, 1st retry, 1st repeat, 1st retry of 1st repeat)
383+ AssertionError: expected 1 to be 2 // Object.is equality"
384+ ` )
385+ } )
386+
387+ test ( 'labels each header with the attempt of its error' , async ( ) => {
388+ const { stderr } = await runInlineTests ( {
389+ 'basic.test.js' : `
390+ import { expect, test } from 'vitest'
391+
392+ let attempt = 0
393+ test('fails differently', { retry: 3 }, () => {
394+ attempt++
395+ expect(attempt).toBe(10)
396+ })
397+ ` ,
398+ } )
399+
400+ expect ( extractFailureHeaders ( stderr ) ) . toMatchInlineSnapshot ( `
401+ " FAIL basic.test.js > fails differently (initial run)
402+ AssertionError: expected 1 to be 10 // Object.is equality
403+ FAIL basic.test.js > fails differently (1st retry)
404+ AssertionError: expected 2 to be 10 // Object.is equality
405+ FAIL basic.test.js > fails differently (2nd retry)
406+ AssertionError: expected 3 to be 10 // Object.is equality
407+ FAIL basic.test.js > fails differently (3rd retry)
408+ AssertionError: expected 4 to be 10 // Object.is equality"
409+ ` )
410+ } )
411+
412+ test ( 'labels only the repeats that failed' , async ( ) => {
413+ const { stderr } = await runInlineTests ( {
414+ 'basic.test.js' : `
415+ import { expect, test } from 'vitest'
416+
417+ let run = 0
418+ test('flaky repeats', { repeats: 3 }, () => {
419+ run++
420+ expect(run % 2).toBe(0)
421+ })
422+ ` ,
423+ } )
424+
425+ expect ( extractFailureHeaders ( stderr ) ) . toMatchInlineSnapshot ( `
426+ " FAIL basic.test.js > flaky repeats (initial run, 2nd repeat)
427+ AssertionError: expected 1 to be +0 // Object.is equality"
428+ ` )
429+ } )
430+
431+ test ( 'prints headers for soft errors repeated within an attempt' , async ( ) => {
432+ const { stderr } = await runInlineTests ( {
433+ 'basic.test.js' : `
434+ import { expect, test } from 'vitest'
435+
436+ test('soft-no-retry', () => {
437+ for (let i = 0; i < 2; i++) {
438+ expect.soft(1).toBe(2)
439+ }
440+ expect.soft(2).toBe(3)
441+ })
442+
443+ test('soft-retry', { retry: 1 }, () => {
444+ for (let i = 0; i < 2; i++) {
445+ expect.soft(1).toBe(2)
446+ }
447+ expect.soft(2).toBe(3)
448+ })
449+ ` ,
450+ } )
451+
452+ expect ( extractFailureHeaders ( stderr ) ) . toMatchInlineSnapshot ( `
453+ " FAIL basic.test.js > soft-no-retry (2 times)
454+ AssertionError: expected 1 to be 2 // Object.is equality
455+ FAIL basic.test.js > soft-no-retry
456+ AssertionError: expected 2 to be 3 // Object.is equality
457+ FAIL basic.test.js > soft-retry (2 times in initial run, 2 times in 1st retry)
458+ AssertionError: expected 1 to be 2 // Object.is equality
459+ FAIL basic.test.js > soft-retry (initial run, 1st retry)
460+ AssertionError: expected 2 to be 3 // Object.is equality"
461+ ` )
462+ } )
463+ } )
0 commit comments