diff --git a/packages/playwright/src/index.ts b/packages/playwright/src/index.ts index dabfa5f357..9b88af9251 100644 --- a/packages/playwright/src/index.ts +++ b/packages/playwright/src/index.ts @@ -487,6 +487,7 @@ function attachConnectedHeaderIfNeeded(testInfo: TestInfo, browser: Browser | nu const kTracingStarted = Symbol('kTracingStarted'); const kIsReusedContext = Symbol('kReusedContext'); const kStartedContextTearDown = Symbol('kStartedContextTearDown'); +let traceOrdinal = 0; function connectOptionsFromEnv() { const wsEndpoint = process.env.PW_TEST_CONNECT_WS_ENDPOINT; @@ -512,7 +513,6 @@ class ArtifactsRecorder { private _temporaryTraceFiles: string[] = []; private _temporaryScreenshots: string[] = []; private _reusedContexts = new Set(); - private _traceOrdinal = 0; private _screenshotOrdinal = 0; private _screenshottedSymbol: symbol; private _startedCollectingArtifacts: symbol; @@ -693,9 +693,10 @@ class ArtifactsRecorder { private async _startTraceChunkOnContextCreation(tracing: Tracing) { if (this._captureTrace) { const title = [path.relative(this._testInfo.project.testDir, this._testInfo.file) + ':' + this._testInfo.line, ...this._testInfo.titlePath.slice(1)].join(' › '); - const ordinalSuffix = this._traceOrdinal ? `-context${this._traceOrdinal}` : ''; - ++this._traceOrdinal; + const ordinalSuffix = traceOrdinal ? `-context${traceOrdinal}` : ''; + ++traceOrdinal; const retrySuffix = this._testInfo.retry ? `-retry${this._testInfo.retry}` : ''; + // Note that trace name must start with testId for live tracing to work. const name = `${this._testInfo.testId}${retrySuffix}${ordinalSuffix}`; if (!(tracing as any)[kTracingStarted]) { await tracing.start({ ...this._traceOptions, title, name }); diff --git a/tests/playwright-test/playwright.spec.ts b/tests/playwright-test/playwright.spec.ts index e77428b069..691149a8c1 100644 --- a/tests/playwright-test/playwright.spec.ts +++ b/tests/playwright-test/playwright.spec.ts @@ -801,3 +801,56 @@ test('should use actionTimeout for APIRequestContext', async ({ runInlineTest, s expect(result.exitCode).toBe(0); expect(result.passed).toBe(3); }); + +test('should save trace in two APIRequestContexts', async ({ runInlineTest, server }) => { + const result = await runInlineTest({ + 'playwright.config.js': ` + module.exports = { + timeout: 5000, + use: { + trace: 'on', + } + }; + `, + 'a.test.ts': ` + import { test, request, BrowserContext, Page, APIRequestContext } from '@playwright/test'; + + test.describe('Example', () => { + let firstContext: APIRequestContext; + let secondContext: APIRequestContext; + let context: BrowserContext; + let page: Page; + + test.beforeAll(async () => { + firstContext = await request.newContext({ baseURL: 'http://example.com' }); + secondContext = await request.newContext({ baseURL: 'http://example.com' }); + }); + + test.afterAll(async () => { + console.log('afterAll start'); + await firstContext.dispose(); + console.log('afterAll middle'); + await secondContext.dispose(); + console.log('afterAll end'); + }); + + test.describe('inner tests', () => { + test.beforeAll(async ({ browser }) => { + context = await browser.newContext(); + page = await context.newPage(); + await page.goto('${server.EMPTY_PAGE}'); + }); + + test.afterAll(async () => { + await page.close(); + await context.close(); + }); + + test('test', async () => {}); + }); + }) + `, + }, { workers: 1 }); + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); +});