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",