From 26707275ffe2214d7d6443d804cdd120cfd59423 Mon Sep 17 00:00:00 2001 From: meetsu <96637888+klNuno@users.noreply.github.com> Date: Mon, 19 Oct 2026 02:38:16 +0200 Subject: [PATCH] fix(ci): retry a quarantined test that fails in a run of several files --- scripts/ci/flaky.test.ts | 13 +++++++++++++ scripts/ci/flaky.ts | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/scripts/ci/flaky.test.ts b/scripts/ci/flaky.test.ts index b37dfacca..5748bcd84 100644 --- a/scripts/ci/flaky.test.ts +++ b/scripts/ci/flaky.test.ts @@ -19,6 +19,19 @@ test('failed tests are named only when every counted failure has a name', () => expect(failedTests('(fail) a\n 1 fail\n(fail) b\n 1 fail\n')).toEqual(['a', 'b']); }); +test('a run of several files names each failure once, not again in its closing recap', () => { + // bun test over several files lists every skip and failure again before the counts. + const several = [ + '(fail) relays reads [4246.43ms]', '(pass) other [1.00ms]', '', + '1 tests skipped:', '(skip) killed outright', '', '', + '1 tests failed:', '(fail) relays reads [4246.43ms]', '', + ' 111 pass', ' 1 skip', ' 1 fail', 'Ran 113 tests across 39 files. [447.52s]', '' + ].join('\r\n'); + expect(failedTests(several)).toEqual(['relays reads']); + const two = '(fail) a [1ms]\n(fail) b [1ms]\n\n2 tests failed:\n(fail) a [1ms]\n(fail) b [1ms]\n\n 2 fail\n'; + expect(failedTests(two)).toEqual(['a', 'b']); +}); + test('a retry needs every failure quarantined in a file that ran', () => { const list = [entry('tests/e2e/a.test.ts', 'one'), entry('tests/e2e/b.test.ts', 'two')]; const absolute = join(ROOT, 'tests', 'e2e', 'a.test.ts'); diff --git a/scripts/ci/flaky.ts b/scripts/ci/flaky.ts index b7a882c07..d096b5a53 100644 --- a/scripts/ci/flaky.ts +++ b/scripts/ci/flaky.ts @@ -14,7 +14,8 @@ export const QUARANTINE: Quarantined[] = JSON.parse(readFileSync(resolve(import. /** Names of the failed tests in bun test output, or undefined unless every counted failure has one. */ export function failedTests(output: string): string[] | undefined { - const clean = output.replace(/\x1b\[[0-9;]*m/g, ''); + // Over several files, bun lists every failure again under "N tests failed:" before the counts. + const clean = output.replace(/\x1b\[[0-9;]*m/g, '').replace(/^\d+ tests? failed:\r?\n(?:\(fail\) .*\r?\n)*/gm, ''); const names = [...clean.matchAll(/^\(fail\) (.+?)(?: \[[\d.]+m?s\])?\r?$/gm)].map(match => match[1]!); const count = [...clean.matchAll(/^\s*(\d+) fail\r?$/gm)].reduce((sum, match) => sum + Number(match[1]), 0); return names.length > 0 && names.length === count ? names : undefined;