Skip to content
File

Blob: tests/client/lib/install-gate.dom.test.ts

typescript87 lines
1import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2import { SESSION_MODES } from "@/client/lib/constants";
3 
4let installManifestGate: typeof import("@/client/lib/install-gate").installManifestGate;
5let useAuthStore: typeof import("@/client/stores/auth-store").useAuthStore;
6 
7beforeEach(async () => {
8 localStorage.clear();
9 document.head.querySelectorAll('link[rel="manifest"]').forEach((el) => el.remove());
10 vi.resetModules();
11 const authMod = await import("@/client/stores/auth-store");
12 useAuthStore = authMod.useAuthStore;
13 const gateMod = await import("@/client/lib/install-gate");
14 installManifestGate = gateMod.installManifestGate;
15});
16 
17afterEach(() => {
18 document.head.querySelectorAll('link[rel="manifest"]').forEach((el) => el.remove());
19 localStorage.clear();
20 vi.restoreAllMocks();
21});
22 
23function hasManifestLink(): boolean {
24 return document.head.querySelector('link[rel="manifest"]') !== null;
25}
26 
27describe("installManifestGate", () => {
28 it("does not mount the manifest link for an anonymous session", () => {
29 useAuthStore.setState({ sessionMode: SESSION_MODES.ANONYMOUS, user: null });
30 installManifestGate();
31 expect(hasManifestLink()).toBe(false);
32 });
33 
34 it("mounts the manifest link when the user has a local session at startup", () => {
35 useAuthStore.setState({
36 sessionMode: SESSION_MODES.AUTHENTICATED,
37 user: { id: "u1", email: "a@b", name: "A", avatar_url: null, created_at: "2024-01-01T00:00:00Z" },
38 accessToken: "tok",
39 });
40 installManifestGate();
41 expect(hasManifestLink()).toBe(true);
42 });
43 
44 it("mounts the link on login and removes it on logout", () => {
45 useAuthStore.setState({ sessionMode: SESSION_MODES.ANONYMOUS, user: null });
46 installManifestGate();
47 expect(hasManifestLink()).toBe(false);
48 
49 useAuthStore.setState({
50 sessionMode: SESSION_MODES.AUTHENTICATED,
51 user: { id: "u1", email: "a@b", name: "A", avatar_url: null, created_at: "2024-01-01T00:00:00Z" },
52 accessToken: "tok",
53 });
54 expect(hasManifestLink()).toBe(true);
55 
56 useAuthStore.getState().clearAuth();
57 expect(hasManifestLink()).toBe(false);
58 });
59 
60 it("keeps the link mounted through LOCAL_ONLY and EXPIRED transitions", () => {
61 useAuthStore.setState({
62 sessionMode: SESSION_MODES.AUTHENTICATED,
63 user: { id: "u1", email: "a@b", name: "A", avatar_url: null, created_at: "2024-01-01T00:00:00Z" },
64 accessToken: "tok",
65 });
66 installManifestGate();
67 expect(hasManifestLink()).toBe(true);
68 
69 useAuthStore.getState().markLocalOnly();
70 expect(hasManifestLink()).toBe(true);
71 
72 useAuthStore.getState().markExpired();
73 expect(hasManifestLink()).toBe(true);
74 });
75 
76 it("is idempotent when called twice", () => {
77 useAuthStore.setState({
78 sessionMode: SESSION_MODES.AUTHENTICATED,
79 user: { id: "u1", email: "a@b", name: "A", avatar_url: null, created_at: "2024-01-01T00:00:00Z" },
80 accessToken: "tok",
81 });
82 installManifestGate();
83 installManifestGate();
84 expect(document.head.querySelectorAll('link[rel="manifest"]').length).toBe(1);
85 });
86});