[READ-ONLY] Mirror of https://github.com/vitest-dev/vitest. Next generation testing framework powered by Vite. vitest.dev
test testing-tools vite
12

Configure Feed

Select the types of activity you want to include in your feed.

fix: don't merge errors with different diffs for reporting (#8871)

authored by

Hiroshi Ogawa and committed by
GitHub
(Oct 30, 2025, 11:17 AM +0100) 3e19f27d ed9fc710

+146 -1
+9
test/reporters/tests/default.test.ts
··· 290 290 291 291 expect(stderr).toMatch('FAIL > { name: fails, meta: Failing test added this } (Custom getFullName here') 292 292 }) 293 + 294 + test('merge identical errors', async () => { 295 + const { stderr } = await runVitest({ 296 + root: 'fixtures/merge-errors', 297 + reporters: [['default', { isTTY: true, summary: false }]], 298 + config: false, 299 + }) 300 + expect(stderr).toMatchSnapshot() 301 + }) 293 302 }, 120000)
+25
test/reporters/fixtures/merge-errors/basic.test.ts
··· 1 + import { expect, test } from "vitest"; 2 + 3 + // not merged 4 + test.for([1, 2])("test-a %$", (n) => { 5 + expect(n).toBe(0); 6 + }); 7 + 8 + // merged 9 + test.for([1, 2])("test-b %$", (n) => { 10 + expect(1).toBe(0); 11 + }); 12 + 13 + // not merged 14 + test.each([ 15 + { 16 + actual: ["a".repeat(50)], 17 + expected: ["b".repeat(50)], 18 + }, 19 + { 20 + actual: ["c".repeat(50)], 21 + expected: ["d".repeat(50)], 22 + }, 23 + ])("test-c %$", async ({ actual, expected }) => { 24 + expect(actual).toEqual(expect.arrayContaining(expected)); 25 + });
+110
test/reporters/tests/__snapshots__/default.test.ts.snap
··· 1 + // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 + 3 + exports[`default reporter > merge identical errors 1`] = ` 4 + " 5 + ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 6 ⎯⎯⎯⎯⎯⎯⎯ 6 + 7 + FAIL basic.test.ts > test-a 1 8 + AssertionError: expected 1 to be +0 // Object.is equality 9 + 10 + - Expected 11 + + Received 12 + 13 + - 0 14 + + 1 15 + 16 + ❯ basic.test.ts:5:13 17 + 3| // not merged 18 + 4| test.for([1, 2])("test-a %$", (n) => { 19 + 5| expect(n).toBe(0); 20 + | ^ 21 + 6| }); 22 + 7| 23 + 24 + ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/6]⎯ 25 + 26 + FAIL basic.test.ts > test-a 2 27 + AssertionError: expected 2 to be +0 // Object.is equality 28 + 29 + - Expected 30 + + Received 31 + 32 + - 0 33 + + 2 34 + 35 + ❯ basic.test.ts:5:13 36 + 3| // not merged 37 + 4| test.for([1, 2])("test-a %$", (n) => { 38 + 5| expect(n).toBe(0); 39 + | ^ 40 + 6| }); 41 + 7| 42 + 43 + ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/6]⎯ 44 + 45 + FAIL basic.test.ts > test-b 1 46 + FAIL basic.test.ts > test-b 2 47 + AssertionError: expected 1 to be +0 // Object.is equality 48 + 49 + - Expected 50 + + Received 51 + 52 + - 0 53 + + 1 54 + 55 + ❯ basic.test.ts:10:13 56 + 8| // merged 57 + 9| test.for([1, 2])("test-b %$", (n) => { 58 + 10| expect(1).toBe(0); 59 + | ^ 60 + 11| }); 61 + 12| 62 + 63 + ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/6]⎯ 64 + 65 + FAIL basic.test.ts > test-c 1 66 + AssertionError: expected [ Array(1) ] to deeply equal ArrayContaining{…} 67 + 68 + - Expected 69 + + Received 70 + 71 + - ArrayContaining [ 72 + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", 73 + + [ 74 + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 75 + ] 76 + 77 + ❯ basic.test.ts:24:18 78 + 22| }, 79 + 23| ])("test-c %$", async ({ actual, expected }) => { 80 + 24| expect(actual).toEqual(expect.arrayContaining(expected)); 81 + | ^ 82 + 25| }); 83 + 26| 84 + 85 + ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/6]⎯ 86 + 87 + FAIL basic.test.ts > test-c 2 88 + AssertionError: expected [ Array(1) ] to deeply equal ArrayContaining{…} 89 + 90 + - Expected 91 + + Received 92 + 93 + - ArrayContaining [ 94 + - "dddddddddddddddddddddddddddddddddddddddddddddddddd", 95 + + [ 96 + + "cccccccccccccccccccccccccccccccccccccccccccccccccc", 97 + ] 98 + 99 + ❯ basic.test.ts:24:18 100 + 22| }, 101 + 23| ])("test-c %$", async ({ actual, expected }) => { 102 + 24| expect(actual).toEqual(expect.arrayContaining(expected)); 103 + | ^ 104 + 25| }); 105 + 26| 106 + 107 + ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/6]⎯ 108 + 109 + " 110 + `;
+2 -1
packages/vitest/src/node/reporters/base.ts
··· 617 617 const failedTests = tests.filter(i => i.result?.state === 'fail') 618 618 const failedTotal = countTestErrors(failedSuites) + countTestErrors(failedTests) 619 619 620 + // TODO: error divider should take into account merged errors for counting 620 621 let current = 1 621 622 const errorDivider = () => this.error(`${c.red(c.dim(divider(`[${current++}/${failedTotal}]`, undefined, 1)))}\n`) 622 623 ··· 677 678 678 679 if (error?.stack) { 679 680 previous = errorsQueue.find((i) => { 680 - if (i[0]?.stack !== error.stack) { 681 + if (i[0]?.stack !== error.stack || i[0]?.diff !== error.diff) { 681 682 return false 682 683 } 683 684