diff --git a/frontend/src/services/notification.test.tsx b/frontend/src/services/notification.test.tsx new file mode 100644 index 000000000000..7836e1e84c22 --- /dev/null +++ b/frontend/src/services/notification.test.tsx @@ -0,0 +1,80 @@ +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { sendNotification } from "./notification"; + +describe("sendNotification", () => { + beforeEach(() => { + // Clear localStorage + localStorage.clear(); + // Reset mocks + vi.clearAllMocks(); + // Reset Notification mock + vi.unstubAllGlobals(); + }); + + it("should not send notification when notifications are disabled", async () => { + const NotificationMock = vi.fn(); + NotificationMock.permission = "granted"; + NotificationMock.requestPermission = vi.fn().mockResolvedValue("granted"); + vi.stubGlobal("Notification", NotificationMock); + + localStorage.setItem("notifications-enabled", "false"); + await sendNotification("Test notification"); + + expect(NotificationMock).not.toHaveBeenCalled(); + }); + + it("should send notification when notifications are enabled and permission is granted", async () => { + const NotificationMock = vi.fn(); + NotificationMock.permission = "granted"; + NotificationMock.requestPermission = vi.fn().mockResolvedValue("granted"); + vi.stubGlobal("Notification", NotificationMock); + + localStorage.setItem("notifications-enabled", "true"); + await sendNotification("Test notification"); + + expect(NotificationMock).toHaveBeenCalledWith( + "Test notification", + undefined, + ); + }); + + it("should request permission when notifications are enabled but permission is not granted", async () => { + const NotificationMock = vi.fn(); + NotificationMock.permission = "default"; + NotificationMock.requestPermission = vi.fn().mockResolvedValue("granted"); + vi.stubGlobal("Notification", NotificationMock); + + localStorage.setItem("notifications-enabled", "true"); + await sendNotification("Test notification"); + + expect(NotificationMock.requestPermission).toHaveBeenCalled(); + expect(NotificationMock).toHaveBeenCalledWith( + "Test notification", + undefined, + ); + }); + + it("should not send notification when permission is denied", async () => { + const NotificationMock = vi.fn(); + NotificationMock.permission = "denied"; + NotificationMock.requestPermission = vi.fn().mockResolvedValue("denied"); + vi.stubGlobal("Notification", NotificationMock); + + localStorage.setItem("notifications-enabled", "true"); + await sendNotification("Test notification"); + + expect(NotificationMock).not.toHaveBeenCalled(); + }); + + it("should not request permission when permission is denied", async () => { + const NotificationMock = vi.fn(); + NotificationMock.permission = "denied"; + NotificationMock.requestPermission = vi.fn().mockResolvedValue("denied"); + vi.stubGlobal("Notification", NotificationMock); + + localStorage.setItem("notifications-enabled", "true"); + await sendNotification("Test notification"); + + expect(NotificationMock.requestPermission).not.toHaveBeenCalled(); + }); +}); diff --git a/frontend/src/services/notification.ts b/frontend/src/services/notification.ts index 784fc26653e0..994c9be7d693 100644 --- a/frontend/src/services/notification.ts +++ b/frontend/src/services/notification.ts @@ -1,4 +1,4 @@ -export const sendNotification = ( +export const sendNotification = async ( title: string, options?: NotificationOptions, ) => { @@ -17,5 +17,11 @@ export const sendNotification = ( if (Notification.permission === "granted") { // eslint-disable-next-line no-new new Notification(title, options); + } else if (Notification.permission !== "denied") { + const permission = await Notification.requestPermission(); + if (permission === "granted") { + // eslint-disable-next-line no-new + new Notification(title, options); + } } };