diff --git a/tests/e2e/specs/23-audiobookshelf-sso.spec.ts b/tests/e2e/specs/23-audiobookshelf-sso.spec.ts index 9dc341c..a29bdb9 100644 --- a/tests/e2e/specs/23-audiobookshelf-sso.spec.ts +++ b/tests/e2e/specs/23-audiobookshelf-sso.spec.ts @@ -26,11 +26,11 @@ test("SSO round trip boots the SPA and grants a real Audiobookshelf session", as }) => { test.setTimeout(180_000); - const scripts: { url: string; type: string }[] = []; + const scripts: { url: string; type: string; status: number }[] = []; page.on("response", (res) => { const u = new URL(res.url()); if (u.host === HOST && u.pathname.endsWith(".js")) { - scripts.push({ url: u.pathname, type: res.headers()["content-type"] ?? "" }); + scripts.push({ url: u.pathname, type: res.headers()["content-type"] ?? "", status: res.status() }); } }); @@ -59,8 +59,11 @@ test("SSO round trip boots the SPA and grants a real Audiobookshelf session", as // Defect 1 gate: nothing the app loaded may be HTML dressed as a script. The render proof // is the SSO button above — it only exists once the bundle has executed, so no DOM-shape // guess is needed (the shell's own mount markup says nothing about whether it booted). - expect(scripts.length, "the SPA loaded no JavaScript").toBeGreaterThan(2); - for (const s of scripts) { + // Only responses that carried a body can be judged: the OIDC bounce re-validates the entry + // script (Cache-Control: max-age=0 + ETag) and a 304 carries no Content-Type by spec. + const bodies = scripts.filter((s) => s.status === 200); + expect(bodies.length, "the SPA loaded no JavaScript").toBeGreaterThan(2); + for (const s of bodies) { expect(s.type, `${s.url} arrived as ${s.type}`).toContain("javascript"); }