import { readFileSync } from "node:fs"; import { runInNewContext } from "node:vm"; import { describe, expect, it, vi } from "vitest"; function worker() { const handlers: Record void> = {}; const self = { addEventListener: (name: string, callback: (event: unknown) => void) => { handlers[name] = callback; }, location: { origin: "https://guide.example.test" }, registration: { showNotification: vi.fn().mockResolvedValue(undefined) }, clients: { matchAll: vi.fn().mockResolvedValue([]), openWindow: vi.fn().mockResolvedValue(undefined) } }; runInNewContext(readFileSync("public/commission-push-sw.js", "utf8"), { self, URL }); return { self, handlers }; } describe("reply notification navigation", () => { it("opens the exact root thread and reply from the notification", async () => { const { self, handlers } = worker(); const url = "/guide/comment?reply=reply-id#comment-root-id"; let task: Promise | undefined; const close = vi.fn(); handlers.notificationclick({ notification: { close, data: { url } }, waitUntil: (promise: Promise) => { task = promise; } }); await task; expect(close).toHaveBeenCalled(); expect(self.clients.openWindow).toHaveBeenCalledWith(`https://guide.example.test${url}`); }); it("opens the admin inbox at the notified comment", async () => { const { self, handlers } = worker(); const url = "/admin/comments?target=stygian%3A123&comment=comment-id"; let task: Promise | undefined; handlers.notificationclick({ notification: { close: vi.fn(), data: { url } }, waitUntil: (promise: Promise) => { task = promise; } }); await task; expect(self.clients.openWindow).toHaveBeenCalledWith(`https://guide.example.test${url}`); }); it("uses the comment icon and rejects off-site notification destinations", async () => { const { self, handlers } = worker(); const message = { id: "comment-id", title: "Reply", body: "Text", icon: "/icon/nav/Comment.webp", url: "/guide/comment#comment-root" }; handlers.push({ data: { json: () => message }, waitUntil: () => {} }); expect(self.registration.showNotification).toHaveBeenCalledWith("Reply", expect.objectContaining({ icon: message.icon, data: { url: message.url } })); handlers.notificationclick({ notification: { close: vi.fn(), data: { url: "https://evil.example" } }, waitUntil: vi.fn() }); expect(self.clients.openWindow).not.toHaveBeenCalled(); }); });