import assert from "node:assert/strict" import {after, before, beforeEach, test} from "node:test" const originalSelf = globalThis.self const listeners = new Map() const shownNotifications = [] let windowClients = [] let openedWindow = null before(async () => { globalThis.self = { addEventListener(type, handler) { listeners.set(type, handler) }, location: {origin: "https://whoneedhelp.com"}, registration: { async showNotification(title, options) { shownNotifications.push({title, options}) } }, clients: { async matchAll(options) { assert.deepEqual(options, {type: "window", includeUncontrolled: true}) return windowClients }, async openWindow(url) { openedWindow = url return {url} } } } await import("../../priv/static/sw.js") }) beforeEach(() => { shownNotifications.length = 0 windowClients = [] openedWindow = null }) after(() => { globalThis.self = originalSelf }) test("push keeps a safe same-origin path in the operating-system notification", async () => { const event = pushEvent({ title: "Request accepted", body: "Open the private request chat.", path: "/requests/7f84fc06-0fae-4e9d-b266-041ca87678d1?section=chat", tag: "request-update" }) listeners.get("push")(event) await event.completion assert.deepEqual(shownNotifications, [ { title: "Request accepted", options: { body: "Open the private request chat.", icon: "/images/pwa-192.png", badge: "/images/favicon-48.png", tag: "request-update", data: { path: "/requests/7f84fc06-0fae-4e9d-b266-041ca87678d1?section=chat" } } } ]) }) test("push rejects an external path instead of leaving the application origin", async () => { const event = pushEvent({ title: "Unsafe target", path: "//attacker.example/redirect" }) listeners.get("push")(event) await event.completion assert.equal(shownNotifications[0].options.data.path, "/notifications") }) test("notification click navigates and focuses an existing application window", async () => { const navigation = [] let focused = false windowClients = [ { url: "https://whoneedhelp.com/notifications?section=settings", async navigate(url) { navigation.push(url) }, async focus() { focused = true } }, {url: "https://example.com/"} ] const event = clickEvent("/requests/request-id") listeners.get("notificationclick")(event) await event.completion assert.equal(event.closed, true) assert.deepEqual(navigation, ["https://whoneedhelp.com/requests/request-id"]) assert.equal(focused, true) assert.equal(openedWindow, null) }) test("notification click opens the application when no application window exists", async () => { windowClients = [{url: "https://example.com/"}] const event = clickEvent("/notifications") listeners.get("notificationclick")(event) await event.completion assert.equal(event.closed, true) assert.equal(openedWindow, "https://whoneedhelp.com/notifications") }) function pushEvent(payload) { return waitableEvent({ data: { json() { return payload } } }) } function clickEvent(path) { const event = waitableEvent({ closed: false, notification: { data: {path}, close() { event.closed = true } } }) return event } function waitableEvent(properties) { return { ...properties, completion: Promise.resolve(), waitUntil(completion) { this.completion = completion } } }