121 lines · 3.3 KB · TypeScript
RawDownload
import * as Schema from "effect/Schema";import { afterEach, describe, expect, it, vi } from "vite-plus/test"; function createStorage(overrides: Partial<Storage> = {}): Storage {  const store = new Map<string, string>();  return {    clear: () => store.clear(),    getItem: (key) => store.get(key) ?? null,    key: (index) => [...store.keys()][index] ?? null,    get length() {      return store.size;    },    removeItem: (key) => {      store.delete(key);    },    setItem: (key, value) => {      store.set(key, value);    },    ...overrides,  };} async function loadWithStorage(storage: Storage) {  vi.stubGlobal("window", { localStorage: storage });  vi.stubGlobal("localStorage", storage);  return import("./useLocalStorage");} afterEach(() => {  vi.resetModules();  vi.unstubAllGlobals();}); describe("local storage errors", () => {  it("preserves read failure context", async () => {    const cause = new Error("storage unavailable");    const { getLocalStorageItem, LocalStorageOperationError } = await loadWithStorage(      createStorage({        getItem: () => {          throw cause;        },      }),    );     try {      getLocalStorageItem("read-key", Schema.String);      expect.unreachable("expected the read to fail");    } catch (error) {      expect(error).toBeInstanceOf(LocalStorageOperationError);      expect(error).toMatchObject({        operation: "read",        storageKey: "read-key",        cause,      });    }  });   it("preserves decode failure context", async () => {    const { getLocalStorageItem, LocalStorageOperationError } = await loadWithStorage(      createStorage({ getItem: () => "not-json" }),    );     try {      getLocalStorageItem("decode-key", Schema.String);      expect.unreachable("expected decoding to fail");    } catch (error) {      expect(error).toBeInstanceOf(LocalStorageOperationError);      expect(error).toMatchObject({        operation: "decode",        storageKey: "decode-key",        cause: expect.anything(),      });    }  });   it("preserves write failure context", async () => {    const cause = new Error("storage quota exceeded");    const { LocalStorageOperationError, setLocalStorageItem } = await loadWithStorage(      createStorage({        setItem: () => {          throw cause;        },      }),    );     try {      setLocalStorageItem("write-key", "value", Schema.String);      expect.unreachable("expected the write to fail");    } catch (error) {      expect(error).toBeInstanceOf(LocalStorageOperationError);      expect(error).toMatchObject({        operation: "write",        storageKey: "write-key",        cause,      });    }  });   it("preserves removal failure context", async () => {    const cause = new Error("storage unavailable");    const { LocalStorageOperationError, removeLocalStorageItem } = await loadWithStorage(      createStorage({        removeItem: () => {          throw cause;        },      }),    );     try {      removeLocalStorageItem("remove-key");      expect.unreachable("expected the removal to fail");    } catch (error) {      expect(error).toBeInstanceOf(LocalStorageOperationError);      expect(error).toMatchObject({        operation: "remove",        storageKey: "remove-key",        cause,      });    }  });});