diff --git a/packages/playwright-test/src/index.ts b/packages/playwright-test/src/index.ts index 0ecd1ebb79..7ad2e389d6 100644 --- a/packages/playwright-test/src/index.ts +++ b/packages/playwright-test/src/index.ts @@ -239,7 +239,7 @@ const playwrightFixtures: Fixtures = ({ _snapshotSuffix: [process.platform, { scope: 'worker' }], - _setupContextOptionsAndArtifacts: [async ({ playwright, _snapshotSuffix, _combinedContextOptions, _reuseContext, _artifactsDir, trace, screenshot, actionTimeout, navigationTimeout, testIdAttribute }, use, testInfo) => { + _setupContextOptionsAndArtifacts: [async ({ playwright, _snapshotSuffix, _combinedContextOptions, _artifactsDir, trace, screenshot, actionTimeout, navigationTimeout, testIdAttribute }, use, testInfo) => { if (testIdAttribute) playwrightLibrary.selectors.setTestIdAttribute(testIdAttribute); testInfo.snapshotSuffix = _snapshotSuffix; @@ -376,11 +376,15 @@ const playwrightFixtures: Fixtures = ({ (browserType as any)._onDidCreateContext = onDidCreateBrowserContext; (browserType as any)._onWillCloseContext = onWillCloseContext; (browserType as any)._defaultContextOptions = _combinedContextOptions; + const promises: Promise[] = []; const existingContexts = Array.from((browserType as any)._contexts) as BrowserContext[]; - if (_reuseContext) - existingContexts.forEach(c => reusedContexts.add(c)); - else - await Promise.all(existingContexts.map(onDidCreateBrowserContext)); + for (const context of existingContexts) { + if ((context as any)[kIsReusedContext]) + reusedContexts.add(context); + else + promises.push(onDidCreateBrowserContext(context)); + } + await Promise.all(promises); } { (playwright.request as any)._onDidCreateContext = onDidCreateRequestContext; @@ -540,6 +544,7 @@ const playwrightFixtures: Fixtures = ({ const defaultContextOptions = (playwright.chromium as any)._defaultContextOptions as BrowserContextOptions; const context = await (browser as any)._newContextForReuse(defaultContextOptions); + (context as any)[kIsReusedContext] = true; await use(context); }, @@ -631,6 +636,7 @@ function normalizeScreenshotMode(screenshot: PlaywrightWorkerOptions['screenshot } const kTracingStarted = Symbol('kTracingStarted'); +const kIsReusedContext = Symbol('kReusedContext'); function connectOptionsFromEnv() { const wsEndpoint = process.env.PW_TEST_CONNECT_WS_ENDPOINT; diff --git a/tests/playwright-test/playwright.reuse.spec.ts b/tests/playwright-test/playwright.reuse.spec.ts index e521e7d486..5601c5f302 100644 --- a/tests/playwright-test/playwright.reuse.spec.ts +++ b/tests/playwright-test/playwright.reuse.spec.ts @@ -516,3 +516,38 @@ test('should not delete others contexts', async ({ runInlineTest }) => { expect(result.exitCode).toBe(0); expect(result.passed).toBe(1); }); + +test('should survive serial mode with tracing and reuse', async ({ runInlineTest }, testInfo) => { + const result = await runInlineTest({ + 'playwright.config.ts': ` + import { defineConfig } from '@playwright/test'; + export default defineConfig({ use: { trace: 'on' } }); + `, + 'reuse.spec.ts': ` + import { test, expect } from '@playwright/test'; + let page; + + test.describe.configure({ mode: 'serial' }); + + test.beforeAll(async ({ browser }) => { + page = await browser.newPage(); + }); + + test('one', async ({}) => { + await page.setContent(''); + await page.click('button'); + }); + + test('two', async ({}) => { + await page.setContent(''); + await page.fill('input', 'value'); + }); + `, + }, { workers: 1 }, { PW_TEST_REUSE_CONTEXT: '1' }); + + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(2); + + expect(fs.existsSync(testInfo.outputPath('test-results', 'reuse-one', 'trace.zip'))).toBe(true); + expect(fs.existsSync(testInfo.outputPath('test-results', 'reuse-two', 'trace.zip'))).toBe(true); +});