From 71d315f497ccd7aec146be6872416be89fbfdff7 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Mon, 20 May 2024 09:05:21 -0700 Subject: [PATCH] feat(trace): record trace during context option fixture override --- packages/playwright/src/index.ts | 7 +++ .../playwright-test/playwright.trace.spec.ts | 44 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/packages/playwright/src/index.ts b/packages/playwright/src/index.ts index 0a6651f362..e114bd0125 100644 --- a/packages/playwright/src/index.ts +++ b/packages/playwright/src/index.ts @@ -148,6 +148,13 @@ const playwrightFixtures: Fixtures = ({ contextOptions: [{}, { option: true }], _combinedContextOptions: async ({ + // Note: we depend on _setupArtifacts here to make sure artifacts are recorded + // for any custom context option fixture function. + // + // For example, "once per worker" authentication guide suggests to make the `storageState` fixture + // dependent on a worker-scoped `workerStorageState` fixture. The latter performs some actions that + // should be visible in the trace. + _setupArtifacts, acceptDownloads, bypassCSP, colorScheme, diff --git a/tests/playwright-test/playwright.trace.spec.ts b/tests/playwright-test/playwright.trace.spec.ts index dee65c9a52..595b0e280e 100644 --- a/tests/playwright-test/playwright.trace.spec.ts +++ b/tests/playwright-test/playwright.trace.spec.ts @@ -1112,3 +1112,47 @@ test('trace:retain-on-first-failure should create trace if request context is di expect(trace.apiNames).toContain('apiRequestContext.get'); expect(result.failed).toBe(1); }); + +test('should record trace in workerStorageState', async ({ runInlineTest, server }) => { + test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/30287' }); + + const result = await runInlineTest({ + 'a.spec.ts': ` + import { test as base, expect } from '@playwright/test'; + const test = base.extend({ + storageState: ({ workerStorageState }, use) => use(workerStorageState), + workerStorageState: [async ({ browser }, use) => { + const page = await browser.newPage({ storageState: undefined }); + await page.setContent('
hello
'); + await page.close(); + await use(undefined); + }, { scope: 'worker' }], + }) + test('pass', async ({ page }) => { + await page.goto('data:text/html,
hi
'); + }); + `, + }, { trace: 'on' }); + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + + const tracePath = test.info().outputPath('test-results', 'a-pass', 'trace.zip'); + const trace = await parseTrace(tracePath); + expect(trace.actionTree).toEqual([ + 'Before Hooks', + ' fixture: browser', + ' browserType.launch', + ' fixture: workerStorageState', + ' browser.newPage', + ' page.setContent', + ' page.close', + ' fixture: context', + ' browser.newContext', + ' fixture: page', + ' browserContext.newPage', + 'page.goto', + 'After Hooks', + ' fixture: page', + ' fixture: context', + ]); +});