From 721d84f17a0e3b906fc1c5dd91d6932073342072 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Tue, 6 Feb 2024 10:17:29 -0800 Subject: [PATCH] fix(har): do not throw on -1 status code (#29371) Fixes https://github.com/microsoft/playwright/issues/29311 --- .../playwright-core/src/client/harRouter.ts | 7 ++++ tests/library/browsercontext-har.spec.ts | 32 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/packages/playwright-core/src/client/harRouter.ts b/packages/playwright-core/src/client/harRouter.ts index 5604ddc6eb..5fe32a39be 100644 --- a/packages/playwright-core/src/client/harRouter.ts +++ b/packages/playwright-core/src/client/harRouter.ts @@ -62,6 +62,13 @@ export class HarRouter { } if (response.action === 'fulfill') { + // If the response status is -1, the request was canceled or stalled, so we just stall it here. + // See https://github.com/microsoft/playwright/issues/29311. + // TODO: it'd be better to abort such requests, but then we likely need to respect the timing, + // because the request might have been stalled for a long time until the very end of the + // test when HAR was recorded but we'd abort it immediately. + if (response.status === -1) + return; await route.fulfill({ status: response.status, headers: Object.fromEntries(response.headers!.map(h => [h.name, h.value])), diff --git a/tests/library/browsercontext-har.spec.ts b/tests/library/browsercontext-har.spec.ts index 6afd8c54ea..6c31346e07 100644 --- a/tests/library/browsercontext-har.spec.ts +++ b/tests/library/browsercontext-har.spec.ts @@ -486,3 +486,35 @@ it('context.unrouteAll should stop context.routeFromHAR', async ({ contextFactor const response = await page1.goto(server.EMPTY_PAGE); expect(response.ok()).toBeTruthy(); }); + +it('should ignore aborted requests', async ({ contextFactory, server }) => { + it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/29311' }); + const path = it.info().outputPath('test.har'); + { + server.setRoute('/x', (req, res) => { req.destroy(); }); + const context1 = await contextFactory(); + await context1.routeFromHAR(path, { update: true }); + const page1 = await context1.newPage(); + await page1.goto(server.EMPTY_PAGE); + const reqPromise = server.waitForRequest('/x'); + const evalPromise = page1.evaluate(url => fetch(url).catch(e => 'cancelled'), server.PREFIX + '/x'); + await reqPromise; + const req = await evalPromise; + expect(req).toBe('cancelled'); + await context1.close(); + } + server.reset(); + { + server.setRoute('/x', (req, res) => { + res.writeHead(200, { 'Content-Type': 'text/plain' }); + res.end('test'); + }); + const context2 = await contextFactory(); + await context2.routeFromHAR(path); + const page2 = await context2.newPage(); + await page2.goto(server.EMPTY_PAGE); + const evalPromise = page2.evaluate(url => fetch(url).catch(e => 'cancelled'), server.PREFIX + '/x'); + const result = await Promise.race([evalPromise, page2.waitForTimeout(1000).then(() => 'timeout')]); + expect(result).toBe('timeout'); + } +}); \ No newline at end of file