Skip to content
Source
Sign inSign up

clientPersistenceStorage.test.ts

81 lines2.6 KB

1import { DEFAULT_CLIENT_SETTINGS } from "@t3tools/contracts";
2import { afterEach, describe, expect, it, vi } from "vite-plus/test";
3​
4function createLocalStorageStub(): Storage {
5 const store = new Map<string, string>();
6 return {
7 getItem: (key) => store.get(key) ?? null,
8 setItem: (key, value) => {
9 store.set(key, value);
10 },
11 removeItem: (key) => {
12 store.delete(key);
13 },
14 clear: () => {
15 store.clear();
16 },
17 key: (index) => [...store.keys()][index] ?? null,
18 get length() {
19 return store.size;
20 },
21 };
23​
24function getTestWindow(): Window & typeof globalThis {
25 const localStorage = createLocalStorageStub();
26 const testWindow = {
27 localStorage,
28 } as Window & typeof globalThis;
29 vi.stubGlobal("window", testWindow);
30 vi.stubGlobal("localStorage", localStorage);
31 return testWindow;
33​
34afterEach(() => {
35 vi.resetModules();
36 vi.unstubAllGlobals();
37 vi.restoreAllMocks();
38});
39​
40describe("clientPersistenceStorage", () => {
41 it.each(["not-json", '{"wordWrap":"invalid"}'])(
42 "does not treat invalid saved settings as absent: %s",
43 async (value) => {
44 const testWindow = getTestWindow();
45 testWindow.localStorage.setItem("t3code:client-settings:v1", value);
46 const { readBrowserClientSettings } = await import("./clientPersistenceStorage");
47​
48 expect(() => readBrowserClientSettings()).toThrow(
49 expect.objectContaining({
50 _tag: "LocalStorageOperationError",
51 operation: "decode",
52 storageKey: "t3code:client-settings:v1",
53 }),
54 );
55 expect(testWindow.localStorage.getItem("t3code:client-settings:v1")).toBe(value);
56 },
57 );
58​
59 it("preserves saved settings across a transient read failure", async () => {
60 const testWindow = getTestWindow();
61 const settings = { ...DEFAULT_CLIENT_SETTINGS, timestampFormat: "12-hour" as const };
62 testWindow.localStorage.setItem("t3code:client-settings:v1", JSON.stringify(settings));
63 const write = vi.spyOn(testWindow.localStorage, "setItem");
64 const failure = new Error("storage unavailable");
65 vi.spyOn(testWindow.localStorage, "getItem").mockImplementationOnce(() => {
66 throw failure;
67 });
68 const { readBrowserClientSettings } = await import("./clientPersistenceStorage");
69​
70 expect(() => readBrowserClientSettings()).toThrow(
71 expect.objectContaining({
72 _tag: "LocalStorageOperationError",
73 operation: "read",
74 storageKey: "t3code:client-settings:v1",
75 cause: failure,
76 }),
77 );
78 expect(readBrowserClientSettings()).toEqual(settings);
79 expect(write).not.toHaveBeenCalled();
80 });
81});