import { beforeEach, describe, expect, it, jest } from "@jest/globals"; import { NotificationService } from "../../src/services/NotificationService"; import { UnoptimizedInMemoryRepository } from "../../src/repositories/UnoptimizedInMemoryRepository"; import fs from "fs"; import { IEta } from "../../src/entities/entities"; import { updateGlobalFetchMockJson } from "../testHelpers/fetchMockHelpers"; jest.mock("fs"); const sampleKey = `-----BEGIN PRIVATE KEY----- MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgsrmSAZIagOfCP8sB Wi2CBXG1Oo7v1bispIZCwIr4RDegCgYIKoZIzj0DAQehRANCAATZHxV2wQJLMBq+ ya+yfGi3g2ZUv6hrfe+j08ytekPHjXS0qzJoVELzKHa6EL9YAoZDXBtB6h+fGhXe SOcONbaf -----END PRIVATE KEY-----` describe("NotificationService", () => { let repository: UnoptimizedInMemoryRepository let notificationService: NotificationService; beforeEach(() => { repository = new UnoptimizedInMemoryRepository(); notificationService = new NotificationService(repository); // Ensure that tests don't hit the server process.env = { ...process.env, APNS_KEY_ID: "1", APNS_TEAM_ID: "1", APNS_KEY_PATH: "./dummy-path.p8" }; (fs.readFileSync as jest.Mock).mockReturnValue(sampleKey); }) describe("reloadAPNsTokenIfTimePassed", () => { it("reloads the token if token hasn't been generated yet", async () => { notificationService.reloadAPNsTokenIfTimePassed(); expect(notificationService.lastRefreshedTimeMs).toBeDefined(); }); it("doesn't reload the token if last refreshed time is recent", async () => { notificationService.reloadAPNsTokenIfTimePassed(); const lastRefreshedTimeMs = notificationService.lastRefreshedTimeMs; notificationService.reloadAPNsTokenIfTimePassed(); // Expect no change to have occurred expect(lastRefreshedTimeMs).toEqual(notificationService.lastRefreshedTimeMs); }); }) describe("scheduleNotification", () => { it("schedules the notification", async () => { // arrange const notificationData = { deviceId: "1", shuttleId: "1", stopId: "1" }; await notificationService.scheduleNotification(notificationData); const isNotificationScheduled = notificationService.isNotificationScheduled(notificationData); expect(isNotificationScheduled).toEqual(true); }); it("sends and clears correct notification after ETA changed", async () => { // Arrange const eta: IEta = { shuttleId: "1", stopId: "1", secondsRemaining: 120, }; // Simulate 200 + empty object for successful push notification updateGlobalFetchMockJson({}); // Act const notificationData1 = { deviceId: "1", shuttleId: eta.shuttleId, stopId: eta.stopId, } const notificationData2 = { ...notificationData1, deviceId: "2", } await notificationService.scheduleNotification(notificationData1); await notificationService.scheduleNotification(notificationData2); await repository.addOrUpdateEta(eta); // Assert expect(fetch as jest.Mock).toHaveBeenCalledTimes(1); const isFirstNotificationScheduled = notificationService.isNotificationScheduled(notificationData1); const isSecondNotificationScheduled = notificationService.isNotificationScheduled(notificationData2); // No longer scheduled after being sent expect(isFirstNotificationScheduled).toBe(false); expect(isSecondNotificationScheduled).toBe(false); }); it("leaves notification in array if delivery unsuccessful", async () => { }); }); describe("cancelNotification", () => { it("stops notification from sending to given shuttle/stop ID", async () => { }); }); describe("cancelAllNotifications", () => { it("clears all notifications scheduled to be sent", async () => { }); }) });