test(e2e): a localhost connect the machine dropped is tried again on the test side
On a Windows host a burst of test traffic can drop a loopback connect now and then (every port, any program — measured on the dev desktop). The browser resends it and only waits; Node (libuv) sends a loopback SYN once and fails at ~300 ms with "connect ETIMEDOUT". `e2e/retryConnect.ts` wraps Playwright's request context so that one error is tried again (0.5 / 1 / 2 / 4 / 8 s, the system's own retry waits) while every other failure goes straight to the test; global.setup's health check, login and /api/me and speed.measure's share probe go through it. Unit-tested; e2e 61/61.
This commit is contained in:
@@ -3,6 +3,7 @@ import { execFileSync } from "node:child_process";
|
||||
import { mkdirSync, readFileSync } from "node:fs";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { retryConnect } from "./retryConnect";
|
||||
|
||||
/**
|
||||
* One-time setup for the characterization net (the `setup` project the tests depend on):
|
||||
@@ -32,8 +33,12 @@ setup("seed + authenticate", async ({ page }) => {
|
||||
"E2E_PASSWORD is not set — run the suite through `siftlode e2e` (it reads the secret store)",
|
||||
).not.toBe("");
|
||||
|
||||
// These requests run in Node (sharing the page's cookie jar), so a localhost connect the machine
|
||||
// dropped is tried again (retryConnect).
|
||||
const api = retryConnect(page.request);
|
||||
|
||||
// 1. Preflight: fail fast (with a useful message) if the stack isn't running.
|
||||
const health = await page.request.get("/healthz");
|
||||
const health = await api.get("/healthz");
|
||||
expect(
|
||||
health.ok(),
|
||||
`localdev stack not reachable at ${BASE_URL} — start it with \`siftlode dev\``,
|
||||
@@ -66,12 +71,12 @@ setup("seed + authenticate", async ({ page }) => {
|
||||
|
||||
// 3. Authenticate. page.request shares the browser context's cookie jar, so the `session`
|
||||
// cookie it receives is captured by storageState below.
|
||||
const login = await page.request.post("/auth/password-login", {
|
||||
const login = await api.post("/auth/password-login", {
|
||||
data: { email: EMAIL, password: PASSWORD },
|
||||
});
|
||||
expect(login.ok(), "password-login failed — is the E2E account seeded?").toBeTruthy();
|
||||
|
||||
const me = await (await page.request.get("/api/me")).json();
|
||||
const me = await (await api.get("/api/me")).json();
|
||||
expect(me.authenticated, "session not established after login").toBeTruthy();
|
||||
|
||||
// 4. Pin the UI locale, suppress the first-login onboarding wizard (a full-screen overlay
|
||||
|
||||
Reference in New Issue
Block a user