Skip to content

[Question] How to handle subsequent GET requests returning server state during HAR replay? #18288

Closed
@leomelzer

Description

@leomelzer

Hello there! I have a question about HAR replay and subsequent (matching) GET requests.

Some details:

Context:

  • Playwright Version: 1.27.1
  • Operating System: macOS 12.5.1
  • Node.js version: 16.15.0
  • Browser: All
  • Extra: -

Code Snippet

  • Using npx playwright codegen I captured a test scenario + matching HAR file
  • When replaying, I noticed the same subsequent GET requests always only return the first match form the HAR file
  • This will be wrong, if a UI interaction modifies the server state
  • Example:
import path from "path";
import { test, expect } from "@playwright/test";

test("test", async ({ page }) => {
	await page.routeFromHAR(
		path.resolve(process.cwd(), "tests", "scenario.har"),
		{
			url: "https://api.local.dev/**",
		}
	);

	// When loading `/`, some client side javascript fetches from the api.local.dev
	// First GET returns initial value `{text: "Hello"}`
	await page.goto("/");
	await expect(page.locator(".message")).toHaveText("Hello");

	// Some POST requests modifying server state, setting `text = "World"`
	await page.getByRole("button", { name: "Submit" }).click();

	// Second GET still returns initial value `{text: "Hello"}`
	// I'd expect `{text: "World"}` though
	await page.goto("/");
	await expect(page.locator(".message")).toHaveText("World"); // ❌ This fails
});
  • The current behavior is in line with the documentation (matching headers etc, see https://playwright.dev/docs/network#replaying-from-har) but I find it weird to model a real application scenario with this
  • I believe the issue (?) lies within the way playwright decides which request to match here:
    // Disambiguate using headers - then one with most matching headers wins.
    if (entries.length > 1) {
    const list: { candidate: har.Entry, matchingHeaders: number }[] = [];
    for (const candidate of entries) {
    const matchingHeaders = countMatchingHeaders(candidate.request.headers, headers);
    list.push({ candidate, matchingHeaders });
    }
    list.sort((a, b) => b.matchingHeaders - a.matchingHeaders);
    entry = list[0].candidate;
    }
  • How do I get playwright to return the "next" GET response from the HAR file? I'm not sure if it would be within the semantics of HAR replay to only ever return a HAR log once (hence removing it once returned)?

Thank you for any pointers!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions