Skip to content
File

Blob: tests/client/lib/session-bootstrap.dom.test.ts

typescript76 lines
1import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2import { performBootstrapRefresh, stripOidcMarker } from "@/client/lib/session-bootstrap";
3 
4beforeEach(() => {
5 window.history.replaceState(null, "", "/");
6});
7 
8afterEach(() => {
9 window.history.replaceState(null, "", "/");
10});
11 
12describe("stripOidcMarker", () => {
13 it("removes the oidc query param while preserving the path", () => {
14 window.history.replaceState(null, "", "/workspaces?oidc=1");
15 stripOidcMarker();
16 expect(window.location.search).toBe("");
17 expect(window.location.pathname).toBe("/workspaces");
18 });
19 
20 it("preserves other query params", () => {
21 window.history.replaceState(null, "", "/invite/abc?accept=1&oidc=1");
22 stripOidcMarker();
23 expect(window.location.search).toBe("?accept=1");
24 expect(window.location.pathname).toBe("/invite/abc");
25 });
26 
27 it("is a no-op when the marker is absent", () => {
28 window.history.replaceState(null, "", "/workspaces?accept=1");
29 stripOidcMarker();
30 expect(window.location.search).toBe("?accept=1");
31 });
32});
33 
34describe("performBootstrapRefresh", () => {
35 it("continues without redirect on successful refresh", async () => {
36 window.history.replaceState(null, "", "/workspaces?oidc=1");
37 const clearAuth = vi.fn();
38 const navigate = vi.fn();
39 const refreshSession = vi.fn().mockResolvedValue({ ok: true });
40 
41 const outcome = await performBootstrapRefresh(true, { refreshSession, clearAuth, navigate });
42 
43 expect(outcome).toBe("continue");
44 expect(clearAuth).not.toHaveBeenCalled();
45 expect(navigate).not.toHaveBeenCalled();
46 expect(window.location.search).toBe("");
47 });
48 
49 it("continues when refresh fails outside a post-OIDC return", async () => {
50 window.history.replaceState(null, "", "/workspaces");
51 const clearAuth = vi.fn();
52 const navigate = vi.fn();
53 const refreshSession = vi.fn().mockResolvedValue({ ok: false });
54 
55 const outcome = await performBootstrapRefresh(false, { refreshSession, clearAuth, navigate });
56 
57 expect(outcome).toBe("continue");
58 expect(clearAuth).not.toHaveBeenCalled();
59 expect(navigate).not.toHaveBeenCalled();
60 });
61 
62 it("fails closed when refresh fails after a post-OIDC return", async () => {
63 window.history.replaceState(null, "", "/workspaces?oidc=1");
64 const clearAuth = vi.fn();
65 const navigate = vi.fn();
66 const refreshSession = vi.fn().mockResolvedValue({ ok: false });
67 
68 const outcome = await performBootstrapRefresh(true, { refreshSession, clearAuth, navigate });
69 
70 expect(outcome).toBe("redirected");
71 expect(clearAuth).toHaveBeenCalledTimes(1);
72 expect(navigate).toHaveBeenCalledWith("/login?error=oidc_post_callback_refresh_failed");
73 expect(window.location.search).toBe("");
74 });
75});