From c8d58d2e7cb4b0af3a35a4fe7009b9221e6e09e5 Mon Sep 17 00:00:00 2001 From: Can <159528514+eco-null@users.noreply.github.com> Date: Fri, 23 Oct 2026 08:01:17 +0300 Subject: [PATCH] fix(network): count omitted response content promptly (#6413) * fix(network): count omitted response content promptly * test(network): pin response omission timing --------- Co-authored-by: eco-null --- .../network/PlaywrightScenarioNetwork.test.ts | 27 +++++++++++++++++++ .../network/PlaywrightScenarioNetwork.ts | 15 +++++------ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/browser/network/PlaywrightScenarioNetwork.test.ts b/src/browser/network/PlaywrightScenarioNetwork.test.ts index 3a0705f22d..abd9889139 100644 --- a/src/browser/network/PlaywrightScenarioNetwork.test.ts +++ b/src/browser/network/PlaywrightScenarioNetwork.test.ts @@ -171,6 +171,33 @@ const bodyText = (event: BrowserScenarioEvent) => { afterEach(() => vi.useRealTimers()); +it.each(["finished", "failed", "unfinished"])( + "counts selected omitted response content when %s", + async (terminal) => { + const { collector, omittedEventCounts } = harness( + { request_body: false, response_body: true, header_values: false }, + undefined, + "fixture", + { max_network_transactions: 1 }, + ); + collector.request(new RequestFixture("admitted")); + const request = new RequestFixture("omitted"); + const response = new ResponseFixture(request, "response"); + collector.request(request); + collector.response(response); + expect(omittedEventCounts.get("network-content")).toBe(1); + collector.response(response); + expect(omittedEventCounts.get("network-content")).toBe(1); + if (terminal === "finished") collector.finished(request); + if (terminal === "failed") collector.failed(request); + expect(omittedEventCounts.get("network-content")).toBe(1); + await collector.finish(); + expect(omittedEventCounts.get("network-content")).toBe(1); + expect(response.bodyReads).toBe(0); + expect(request.bodyReads).toBe(0); + }, +); + it("redacts declared secrets in browser-produced form and JSON encodings", async () => { for (const secret of ["私密", 'space " and \n']) { const { collector, events } = harness(selection, undefined, secret); diff --git a/src/browser/network/PlaywrightScenarioNetwork.ts b/src/browser/network/PlaywrightScenarioNetwork.ts index b27702eedf..fa55d84b5f 100644 --- a/src/browser/network/PlaywrightScenarioNetwork.ts +++ b/src/browser/network/PlaywrightScenarioNetwork.ts @@ -208,7 +208,13 @@ export class PlaywrightScenarioNetwork { const transaction = this.transaction(request); if (transaction === undefined) { this.omitOmittedTransactionPhase(request, "response"); - this.observeOmittedTransactionPhase(request, "response"); + // Selection follows the observed response, independently of its eventual + // terminal state. No omitted response body is acquired. + if ( + this.options.selection.response_body || + this.options.selection.header_values + ) + this.omitOmittedTransactionContent(request, "response"); return; } if ( @@ -244,13 +250,6 @@ export class PlaywrightScenarioNetwork { const transaction = this.transaction(request); if (transaction === undefined) { this.omitOmittedTransactionPhase(request, "request-finished"); - const observed = this.omittedPhases.get(request); - if ( - observed?.has("response") && - (this.options.selection.response_body || - this.options.selection.header_values) - ) - this.omitOmittedTransactionContent(request, "response"); return; } if (!this.admitMetadata(transaction, "request-finished", request)) return;