// SPDX-License-Identifier: AGPL-3.0-or-later /** * notifications.handleClick is the one piece of the notifications service * that actually consumes the LayoutManager contract — focus the source * webview when its notification is clicked. The rest of the module is * DOM-bound and not unit-testable without jsdom; verify it through e2e. */ import { test } from "node:test"; import { strict as assert } from "node:assert"; // notifications.js touches `document` and `toastManager` at module load via // the helpers that mutate the DOM, but `handleClick` itself does not. To // keep this unit test environment-free, stub the bits the module reaches // for at import time. globalThis.document = { getElementById: () => null, }; const { handleClick } = await import( "../../ui/system/services/notifications.js" ); import { LayoutManager } from "../../ui/system/core/layout_manager.js"; class MockLayoutManager extends LayoutManager { constructor() { super(); this.calls = { setActiveWebView: [] }; } addWebView(view) { this._views.set(view.id, view); this._activeId = view.id; } setActiveWebView(id) { this.calls.setActiveWebView.push(id); this._activeId = id; } removeWebView(id) { this._views.delete(id); } } test("notifications.handleClick — webview notification focuses source", () => { const lm = new MockLayoutManager(); lm.addWebView({ id: "wv-1", webView: { title: "first" } }); lm.addWebView({ id: "wv-2", webView: { title: "second" } }); const panel = { open: true }; handleClick( { id: "n1", webviewId: "wv-2" }, { layoutManager: lm, panel, pairingHandler: { hasPendingRequests: false } }, ); assert.deepEqual(lm.calls.setActiveWebView, ["wv-2"]); assert.equal(panel.open, false, "panel closes after dispatch"); }); test("notifications.handleClick — pairing-requests tag opens dialog without touching layout", () => { const lm = new MockLayoutManager(); lm.addWebView({ id: "wv-1", webView: {} }); let dialogShown = false; const panel = { open: true }; handleClick( { id: "n1", tag: "pairing-requests" }, { layoutManager: lm, panel, pairingHandler: { hasPendingRequests: true, showPairingDialog: () => { dialogShown = true; }, }, }, ); assert.equal(dialogShown, true); assert.equal(panel.open, false); assert.deepEqual(lm.calls.setActiveWebView, [], "no layout side-effect"); }); test("notifications.handleClick — pairing-requests with no pending requests is a no-op past closing the panel", () => { const lm = new MockLayoutManager(); let dialogShown = false; const panel = { open: true }; handleClick( { id: "n1", tag: "pairing-requests" }, { layoutManager: lm, panel, pairingHandler: { hasPendingRequests: false, showPairingDialog: () => { dialogShown = true; }, }, }, ); assert.equal(dialogShown, false); assert.equal(panel.open, false); }); test("notifications.handleClick — webviewId with no matching webview just dismisses", () => { const lm = new MockLayoutManager(); lm.addWebView({ id: "wv-1", webView: {} }); const panel = { open: true }; handleClick( { id: "n1", webviewId: "wv-missing" }, { layoutManager: lm, panel, pairingHandler: { hasPendingRequests: false } }, ); assert.deepEqual(lm.calls.setActiveWebView, [], "no layout change for unknown id"); assert.equal(panel.open, false); });