fix(trace): ensure har entry _monotonicTime is always start time

Fixes https://github.com/microsoft/playwright/issues/31133
This commit is contained in:
Yury Semikhatsky 2024-06-19 11:22:42 -07:00
parent f6972c1e23
commit 571409c066
3 changed files with 39 additions and 6 deletions

View file

@ -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(),

View file

@ -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;
}
}
}

View file

@ -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);
});