diff --git a/packages/trace-viewer/src/ui/networkResourceDetails.tsx b/packages/trace-viewer/src/ui/networkResourceDetails.tsx index 63be975e26953..9a99a3a9a921f 100644 --- a/packages/trace-viewer/src/ui/networkResourceDetails.tsx +++ b/packages/trace-viewer/src/ui/networkResourceDetails.tsx @@ -150,7 +150,7 @@ const HeadersTab: React.FunctionComponent<{ Object.entries({ 'URL': resource.request.url, 'Method': resource.request.method, - 'Status Code': resource.response.status !== -1 && {resource.response.status} {resource.response.statusText}, + 'Status Code': resource.response.status === -1 ? 'canceled' : resource.response.status > 0 && {resource.response.status} {resource.response.statusText}, 'Start': msToString(startTimeOffset), 'Duration': msToString(resource.time), }).map(([name, value]) => ({ name, value })), diff --git a/packages/trace-viewer/src/ui/networkTab.tsx b/packages/trace-viewer/src/ui/networkTab.tsx index 4d02cc558e710..f3c32a97489ff 100644 --- a/packages/trace-viewer/src/ui/networkTab.tsx +++ b/packages/trace-viewer/src/ui/networkTab.tsx @@ -196,8 +196,8 @@ const renderCell = (entry: RenderedEntry, column: ColumnName): RenderedGridCell return { body: entry.method }; if (column === 'status') { return { - body: entry.status.code > 0 ? entry.status.code : '', - title: entry.status.text + body: entry.status.code === -1 ? 'canceled' : entry.status.code > 0 ? entry.status.code : '', + title: entry.status.code === -1 ? 'canceled' : entry.status.text, }; } if (column === 'contentType') diff --git a/tests/library/trace-viewer.spec.ts b/tests/library/trace-viewer.spec.ts index b4e1478132633..661a9dafe06aa 100644 --- a/tests/library/trace-viewer.spec.ts +++ b/tests/library/trace-viewer.spec.ts @@ -556,10 +556,28 @@ test('should have network request overrides', async ({ page, server, runAndTrace await traceViewer.selectAction('Navigate'); await traceViewer.showNetworkTab(); await expect(traceViewer.networkRequests).toContainText([/frame.htmlGET200text\/html/]); - await expect(traceViewer.networkRequests).toContainText([/style.cssGETx-unknown.*aborted/]); + await expect(traceViewer.networkRequests).toContainText([/style.cssGETcanceledx-unknown.*aborted/]); await expect(traceViewer.networkRequests).not.toContainText([/continued/]); }); +test('should show canceled status for requests canceled by navigation', async ({ page, server, runAndTrace }) => { + server.setRoute('/slow', (_req, _res) => { + // Never respond so the request stays in-flight until navigation cancels it. + }); + const traceViewer = await runAndTrace(async () => { + await page.goto(server.PREFIX + '/empty.html'); + const requestPromise = page.waitForRequest(server.PREFIX + '/slow'); + page.evaluate(url => fetch(url).catch(() => {}), server.PREFIX + '/slow').catch(() => {}); + await requestPromise; + // Navigate away to cancel the in-flight request. + await page.goto(server.PREFIX + '/empty.html?navigated=1'); + }); + await traceViewer.showNetworkTab(); + const slowRequest = traceViewer.networkRequests.filter({ hasText: 'slow' }); + await expect(slowRequest).toContainText([/GETcanceled/]); + await expect(slowRequest).toHaveCSS('background-color', 'rgb(242, 222, 222)'); +}); + test('should have network request overrides 2', async ({ page, server, runAndTrace }) => { const traceViewer = await runAndTrace(async () => { await page.route('**/script.js', route => route.continue());