import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; describe("token", () => { beforeEach(() => { vi.resetModules(); localStorage.clear(); }); afterEach(() => { vi.restoreAllMocks(); }); it("читает токен, сохранённый прежней доской", async () => { localStorage.setItem("jira-hub-token", "abc"); const t = await import("./token.ts"); expect(t.getToken()).toBe("abc"); }); it("setToken и clearToken пишут в localStorage и оповещают подписчиков", async () => { const t = await import("./token.ts"); const fn = vi.fn(); t.subscribe(fn); t.setToken("xyz"); expect(localStorage.getItem("jira-hub-token")).toBe("xyz"); t.clearToken("bad"); expect(t.getAuth()).toEqual({ token: "", reason: "bad" }); expect(localStorage.getItem("jira-hub-token")).toBeNull(); expect(fn).toHaveBeenCalledTimes(2); }); it("закрытое хранилище: токен живёт в памяти, исключений нет", async () => { vi.spyOn(Storage.prototype, "getItem").mockImplementation(() => { throw new DOMException("closed", "SecurityError"); }); vi.spyOn(Storage.prototype, "setItem").mockImplementation(() => { throw new DOMException("closed", "SecurityError"); }); vi.spyOn(Storage.prototype, "removeItem").mockImplementation(() => { throw new DOMException("closed", "SecurityError"); }); const t = await import("./token.ts"); expect(t.getToken()).toBe(""); t.setToken("mem"); expect(t.getToken()).toBe("mem"); t.clearToken("bad"); expect(t.getAuth()).toEqual({ token: "", reason: "bad" }); }); it("TOKEN_RE пропускает только печатный ASCII без пробелов", async () => { const { TOKEN_RE } = await import("./token.ts"); expect(TOKEN_RE.test("Ab-_9~")).toBe(true); expect(TOKEN_RE.test("ab c")).toBe(false); expect(TOKEN_RE.test("токен")).toBe(false); }); });