From a5f6357bc4268bc2118994e0595a8b50b7010cfe Mon Sep 17 00:00:00 2001 From: charliesheh <59520443+charliesheh@users.noreply.github.com> Date: Fri, 15 May 2026 13:51:26 -0700 Subject: [PATCH] Preserve AggregateError nested errors in reporter output --- packages/playwright/src/util.ts | 9 +++++++-- tests/playwright-test/reporter-base.spec.ts | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/packages/playwright/src/util.ts b/packages/playwright/src/util.ts index ce7da5ef8bcc4..0d36df2c20d0f 100644 --- a/packages/playwright/src/util.ts +++ b/packages/playwright/src/util.ts @@ -36,17 +36,22 @@ import type { TestCase } from './common/test'; const PLAYWRIGHT_TEST_PATH = path.join(__dirname, '..'); const PLAYWRIGHT_CORE_PATH = path.dirname(require.resolve('playwright-core/package.json')); -export function filterStackTrace(e: Error): { message: string, stack: string, cause?: ReturnType } { +export function filterStackTrace(e: Error): { message: string, stack: string, cause?: ReturnType, errors?: ReturnType[] } { const name = e.name ? e.name + ': ' : ''; const cause = e.cause instanceof Error ? filterStackTrace(e.cause) : undefined; + const errors = e instanceof AggregateError + ? e.errors.filter(error => error instanceof Error).map(error => filterStackTrace(error)) + : undefined; + if (process.env.PWDEBUGIMPL) - return { message: name + e.message, stack: e.stack || '', cause }; + return { message: name + e.message, stack: e.stack || '', cause, errors }; const stackLines = stringifyStackFrames(filteredStackTrace(e.stack?.split('\n') || [])); return { message: name + e.message, stack: `${name}${e.message}${stackLines.map(line => '\n' + line).join('')}`, cause, + errors, }; } diff --git a/tests/playwright-test/reporter-base.spec.ts b/tests/playwright-test/reporter-base.spec.ts index afd5aa0543a9a..a82652354612e 100644 --- a/tests/playwright-test/reporter-base.spec.ts +++ b/tests/playwright-test/reporter-base.spec.ts @@ -165,6 +165,27 @@ for (const useIntermediateMergeReport of [false, true] as const) { expect(result.output).toContain('afterAll executed successfully'); }); + test('should print AggregateError nested errors', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'a.spec.ts': ` + import { test, expect } from '@playwright/test'; + + test('foobar', async () => { + throw new AggregateError([ + new Error('inner-message-1'), + new Error('inner-message-2'), + ], 'aggregate-message'); + }); + ` + }); + + expect(result.exitCode).toBe(1); + expect(result.failed).toBe(1); + expect(result.output).toContain('AggregateError: aggregate-message'); + expect(result.output).toContain('inner-message-1'); + expect(result.output).toContain('inner-message-2'); + }); + test('should print codeframe from a helper', async ({ runInlineTest }) => { const result = await runInlineTest({ 'helper.ts': `