Skip to content

Commit f918ed3

Browse files
Erick Teowarangclaude
andcommitted
test(e2e): assert auth guard does not flash on reload with valid session
Companion to the existing "maintains session on page reload" test: that one verifies the authenticated content is eventually visible after reload, but does not catch a single-frame guardComponent flash during the `!isReady` window. Inject a MutationObserver via `addInitScript` so it is attached before any post-reload render, and assert the auth-guard testid never enters the DOM while the session is being re-checked. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 659ddd6 commit f918ed3

1 file changed

Lines changed: 68 additions & 0 deletions

File tree

e2e/tests/auth.spec.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,4 +176,72 @@ test.describe("AuthProvider", () => {
176176
});
177177
await expect(page.getByTestId("auth-status")).toHaveText("Logged in");
178178
});
179+
180+
test("reloading an authenticated session does not flash the auth guard", async ({ page }) => {
181+
// Regression for the AuthGuard flash on reload: while the initial
182+
// auth check is in flight (`!isReady`), the guardComponent slot
183+
// must not render — even for a single frame — when the user has
184+
// a valid persisted session. We catch a flash by installing a
185+
// MutationObserver via addInitScript (which runs before any page
186+
// render), so we observe the very first DOM mutations after
187+
// reload.
188+
const email = process.env.E2E_USER_EMAIL;
189+
const password = process.env.E2E_USER_PASSWORD;
190+
191+
if (!email || !password) {
192+
test.skip(true, "E2E_USER_EMAIL and E2E_USER_PASSWORD must be set");
193+
return;
194+
}
195+
196+
// The init script re-runs on every navigation and reload, so the
197+
// sentinel starts `false` on the reloaded page regardless of what
198+
// happened on previous navigations.
199+
await page.addInitScript(() => {
200+
(window as unknown as { __authGuardEverSeen: boolean }).__authGuardEverSeen = false;
201+
const check = () => {
202+
if (document.querySelector("[data-testid='auth-guard']")) {
203+
(window as unknown as { __authGuardEverSeen: boolean }).__authGuardEverSeen = true;
204+
}
205+
};
206+
const startObserving = () => {
207+
if (document.body) {
208+
new MutationObserver(check).observe(document.body, {
209+
childList: true,
210+
subtree: true,
211+
});
212+
check();
213+
} else {
214+
requestAnimationFrame(startObserving);
215+
}
216+
};
217+
startObserving();
218+
});
219+
220+
// Log in first to establish a persisted session.
221+
await page.goto("/");
222+
await page.getByTestId("login-button").click();
223+
await page.waitForURL(/idp\.erp\.dev\/.*\/signin/);
224+
await page.getByLabel(/email/i).fill(email);
225+
await page.locator("#password").fill(password);
226+
await page.getByRole("button", { name: /sign in|log in|submit/i }).click();
227+
await page.waitForURL("http://localhost:3100/**");
228+
await expect(page.getByTestId("authenticated-content")).toBeVisible({
229+
timeout: 10000,
230+
});
231+
232+
// Reload — the init script reinstalls a fresh observer on the new
233+
// document before any React render, so any moment the auth guard
234+
// appears (even for one frame) sets the sentinel.
235+
await page.reload();
236+
await expect(page.getByTestId("authenticated-content")).toBeVisible({
237+
timeout: 10000,
238+
});
239+
240+
const guardSeenOnReload = await page.evaluate(
241+
() => (window as unknown as { __authGuardEverSeen: boolean }).__authGuardEverSeen,
242+
);
243+
expect(guardSeenOnReload, "auth-guard appeared during reload of authenticated session").toBe(
244+
false,
245+
);
246+
});
179247
});

0 commit comments

Comments
 (0)