100 lines
3.5 KiB
TypeScript
100 lines
3.5 KiB
TypeScript
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: "系统通知已可用",
|
|
});
|
|
});
|
|
});
|