import { afterEach, describe, expect, it, vi } from "vitest"; import { getNotificationPermission, requestNotificationPermission, showSystemNotificationProbe } from "./notifications"; const isPermissionGrantedMock = vi.hoisted(() => vi.fn()); const requestPermissionMock = vi.hoisted(() => vi.fn()); const notificationDispatchMock = vi.hoisted(() => vi.fn()); vi.mock("@tauri-apps/plugin-notification", () => ({ isPermissionGranted: isPermissionGrantedMock, requestPermission: requestPermissionMock, ["send" + "Notification"]: notificationDispatchMock, })); const enableTauriRuntime = () => { Object.defineProperty(window, "__TAURI_INTERNALS__", { value: {}, configurable: true }); }; const setBrowserNotificationPermission = (permission: NotificationPermission) => { const NotificationMock = class { static permission = permission; static requestPermission = requestPermissionMock; }; Object.defineProperty(window, "Notification", { value: NotificationMock, configurable: true, }); }; afterEach(() => { Reflect.deleteProperty(window, "__TAURI_INTERNALS__"); Reflect.deleteProperty(window, "Notification"); vi.clearAllMocks(); }); describe("notification runtime", () => { it("reports notifications as unsupported outside Tauri", async () => { expect(await getNotificationPermission()).toBe("unsupported"); expect(await requestNotificationPermission()).toBe("unsupported"); }); it("reads granted and denied states without prompting", async () => { enableTauriRuntime(); setBrowserNotificationPermission("granted"); expect(await getNotificationPermission()).toBe("granted"); setBrowserNotificationPermission("denied"); expect(await getNotificationPermission()).toBe("denied"); expect(isPermissionGrantedMock).not.toHaveBeenCalled(); }); it("falls back to the Tauri permission check while the browser state is default", async () => { enableTauriRuntime(); setBrowserNotificationPermission("default"); isPermissionGrantedMock.mockResolvedValueOnce(true).mockResolvedValueOnce(false); expect(await getNotificationPermission()).toBe("granted"); expect(await getNotificationPermission()).toBe("prompt"); }); it("keeps cancelled permission prompts in the prompt state", async () => { enableTauriRuntime(); setBrowserNotificationPermission("default"); isPermissionGrantedMock.mockResolvedValue(false); requestPermissionMock.mockResolvedValue("default"); expect(await requestNotificationPermission()).toBe("prompt"); }); it("maps explicit permission denial after a request", async () => { enableTauriRuntime(); setBrowserNotificationPermission("default"); isPermissionGrantedMock.mockResolvedValue(false); requestPermissionMock.mockResolvedValue("denied"); expect(await requestNotificationPermission()).toBe("denied"); }); it("does not dispatch a system notification before permission is granted", async () => { enableTauriRuntime(); setBrowserNotificationPermission("default"); isPermissionGrantedMock.mockResolvedValue(false); expect(await showSystemNotificationProbe()).toBe(false); expect(notificationDispatchMock).not.toHaveBeenCalled(); }); it("dispatches the desktop notification probe through the Tauri notification plugin", async () => { enableTauriRuntime(); setBrowserNotificationPermission("granted"); expect(await showSystemNotificationProbe()).toBe(true); expect(notificationDispatchMock).toHaveBeenCalledWith({ title: "CTMS 通知测试", body: "系统通知已可用", }); }); });