From a2b116aa39c1b4980594834bdf6661c80a60410b Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Wed, 19 Jun 2024 15:06:20 -0700 Subject: [PATCH] fix(trace): ensure har entry _monotonicTime is always start time (#31385) * Revert harTracer change from https://github.com/microsoft/playwright/commit/aeba083da0d8da9591e2a72c571477691a095d74 to make sure that har.Entry._monotonicTime always represents request start time. The issue from the corresponding report was due to HEAD and GET request sent for the same URL, that use case is still addressed as we match by url + method * Adjust resources monotonic time as well when several contexts are shown in the trace viewer. Fixes https://github.com/microsoft/playwright/issues/31133 --- .../src/server/har/harTracer.ts | 6 ---- packages/trace-viewer/src/ui/modelUtil.ts | 4 +++ tests/library/trace-viewer.spec.ts | 35 +++++++++++++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/packages/playwright-core/src/server/har/harTracer.ts b/packages/playwright-core/src/server/har/harTracer.ts index 289a4f6d87..268da9e84d 100644 --- a/packages/playwright-core/src/server/har/harTracer.ts +++ b/packages/playwright-core/src/server/har/harTracer.ts @@ -434,12 +434,6 @@ export class HarTracer { const pageEntry = this._createPageEntryIfNeeded(page); const request = response.request(); - // Prefer "response received" time over "request sent" time - // for the purpose of matching requests that were used in a particular snapshot. - // Note that both snapshot time and request time are taken here in the Node process. - if (this._options.includeTraceInfo) - harEntry._monotonicTime = monotonicTime(); - harEntry.response = { status: response.status(), statusText: response.statusText(), diff --git a/packages/trace-viewer/src/ui/modelUtil.ts b/packages/trace-viewer/src/ui/modelUtil.ts index ba866ad7ca..94d42ba4a8 100644 --- a/packages/trace-viewer/src/ui/modelUtil.ts +++ b/packages/trace-viewer/src/ui/modelUtil.ts @@ -285,6 +285,10 @@ function adjustMonotonicTime(contexts: ContextEntry[], monotonicTimeDelta: numbe for (const frame of page.screencastFrames) frame.timestamp += monotonicTimeDelta; } + for (const resource of context.resources) { + if (resource._monotonicTime) + resource._monotonicTime += monotonicTimeDelta; + } } } diff --git a/tests/library/trace-viewer.spec.ts b/tests/library/trace-viewer.spec.ts index c2634df148..69864380d8 100644 --- a/tests/library/trace-viewer.spec.ts +++ b/tests/library/trace-viewer.spec.ts @@ -1236,3 +1236,38 @@ test('should open snapshot in new browser context', async ({ browser, page, runA await expect(newPage.getByText('hello')).toBeVisible(); await newPage.close(); }); + +function parseMillis(s: string): number { + const matchMs = s.match(/(\d+)ms/); + if (matchMs) + return +matchMs[1]; + const matchSeconds = s.match(/([\d.]+)s/); + if (!matchSeconds) + throw new Error('Failed to parse to millis: ' + s); + return (+matchSeconds[1]) * 1000; +} + +test('should show correct request start time', { + annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31133' }, +}, async ({ page, runAndTrace, server }) => { + server.setRoute('/api', (req, res) => { + setTimeout(() => { + res.writeHead(200, { 'Content-Type': 'text/plain' }); + res.end('done'); + }, 1100); + }); + const traceViewer = await runAndTrace(async () => { + await page.goto(server.EMPTY_PAGE); + await page.evaluate(() => { + return fetch('/api').then(r => r.text()); + }); + }); + await traceViewer.selectAction('page.evaluate'); + await traceViewer.showNetworkTab(); + await expect(traceViewer.networkRequests).toContainText([/apiGET200text/]); + const line = traceViewer.networkRequests.getByText(/apiGET200text/); + const start = await line.locator('.grid-view-column-start').textContent(); + const duration = await line.locator('.grid-view-column-duration').textContent(); + expect(parseMillis(duration)).toBeGreaterThan(1000); + expect(parseMillis(start)).toBeLessThan(1000); +});