From a763e12ba821a4c267873fed7ac308f5e8e11d8d Mon Sep 17 00:00:00 2001 From: alexander-akait <4567934+alexander-akait@users.noreply.github.com> Date: Fri, 2 Oct 2026 13:54:11 +0000 Subject: [PATCH] fix(client): read `autoConnect` off the query like every other boolean MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It tested `=== "true"` where the rest of them test `!== "false"`, so a value it did not recognise turned the client off: ?autoConnect=1 -> was off, is now left on ?hmr=1 -> left on, as it always was ?autoConnect=false -> off, unchanged The default is already on, so turning it off is the only thing anyone writes this option for — which makes the odd reading a trap rather than a stricter policy. The existing coverage could not catch it: it only used `autoConnect=false`, which both readings treat the same way. Two tests now, one for each half, and the first was checked against the old reading to be sure it fails there. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA --- .changeset/autoconnect-query-parsing.md | 5 ++++ client-src/index.js | 5 +++- test/e2e/client.test.js | 40 +++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 .changeset/autoconnect-query-parsing.md diff --git a/.changeset/autoconnect-query-parsing.md b/.changeset/autoconnect-query-parsing.md new file mode 100644 index 000000000..348e50de2 --- /dev/null +++ b/.changeset/autoconnect-query-parsing.md @@ -0,0 +1,5 @@ +--- +"webpack-dev-middleware": patch +--- + +Fixed `autoConnect` on the client's query being read differently from every other boolean there. It tested `=== "true"` while the rest test `!== "false"`, so a value it did not recognise — `?autoConnect=1` — turned the client off rather than leaving it on, and since the default is already on, turning it off is the only thing anyone writes it for. diff --git a/client-src/index.js b/client-src/index.js index 77df4f2aa..d4645227e 100644 --- a/client-src/index.js +++ b/client-src/index.js @@ -170,7 +170,10 @@ function turnedOffByUrl(setting) { */ function setOverrides(overrides) { if (overrides.autoConnect) { - options.autoConnect = overrides.autoConnect === "true"; + // `!== "false"` like every other boolean here, not `=== "true"`: the + // default is already on, so the only thing anyone writes this for is + // turning it off, and `?autoConnect=1` used to do that by accident. + options.autoConnect = overrides.autoConnect !== "false"; } if (overrides.transport === "sse" || overrides.transport === "ws") { options.transport = overrides.transport; diff --git a/test/e2e/client.test.js b/test/e2e/client.test.js index 076a19c04..73e86ebfd 100644 --- a/test/e2e/client.test.js +++ b/test/e2e/client.test.js @@ -100,6 +100,46 @@ describe("hot client (browser)", () => { expect(await readReloadMarker(page)).toBeUndefined(); }); + // Every boolean on the query turns off on `false` and is left alone by + // anything else. `autoConnect` read `=== "true"` instead, so a value it did + // not recognise turned it off — and since the default is on, turning it off + // is the only thing anyone writes it for. + it("stays connected for an autoConnect value that is not `false`", async () => { + app = await createHotApp({ + query: "?autoConnect=1", + code: acceptedApp("v1"), + }); + ({ page, browser } = await runBrowser()); + const console_ = collectConsole(page); + + await page.goto(app.url); + await waitForAppText(page, "v1"); + await console_.waitFor("connected"); + + // Connected, so a build reaches the page. + app.edit(acceptedApp("v2")); + await waitForAppText(page, "v2"); + + expect( + await page.evaluate(() => document.getElementById("app").textContent), + ).toBe("v2"); + expect(console_.messages.join("\n")).toContain("connected"); + }); + + it("does not connect when autoConnect is `false`", async () => { + app = await createHotApp({ + query: "?autoConnect=false", + code: acceptedApp("v1"), + }); + ({ page, browser } = await runBrowser()); + const console_ = collectConsole(page); + + await page.goto(app.url); + await waitForAppText(page, "v1"); + + expect(console_.messages.join("\n")).not.toContain("connected"); + }); + it("warns instead of reloading when reload=false", async () => { app = await createHotApp({ query: "?reload=false",