import { beforeEach, describe, expect, it, jest } from "@jest/globals"; import { InMemoryNotificationRepository } from "../../src/repositories/InMemoryNotificationRepository"; import { NotificationEvent } from "../../src/repositories/NotificationRepository"; describe("InMemoryNotificationRepository", () => { let repo: InMemoryNotificationRepository; beforeEach(() => { repo = new InMemoryNotificationRepository(); }) const notification = { deviceId: "device1", shuttleId: "shuttle1", stopId: "stop1", secondsThreshold: 180 }; describe("getAllNotificationsForShuttleAndStopId", () => { it("gets notifications correctly", async () => { await repo.addOrUpdateNotification(notification); const result = await repo.getAllNotificationsForShuttleAndStopId("shuttle1", "stop1"); expect(result).toHaveLength(1); expect(result[0]).toEqual(notification); }); it("returns empty array if no notifications", async () => { const result = await repo.getAllNotificationsForShuttleAndStopId("shuttle1", "stop1"); expect(result).toEqual([]); }); }); describe("getSecondsThresholdForNotificationIfExists", () => { it("gets the seconds threshold if exists", async () => { await repo.addOrUpdateNotification(notification); const result = await repo.getSecondsThresholdForNotificationIfExists({ deviceId: "device1", shuttleId: "shuttle1", stopId: "stop1" }); expect(result).toBe(180); }); it("returns null if there is no seconds threshold", async () => { const result = await repo.getSecondsThresholdForNotificationIfExists({ deviceId: "device1", shuttleId: "shuttle1", stopId: "stop1" }); expect(result).toBeNull(); }); }); describe("addOrUpdateNotification", () => { // Add/get flow is covered in getAllNotificationsForShuttleAndStopId it("updates the seconds threshold if the notification exists already", async () => { await repo.addOrUpdateNotification(notification); await repo.addOrUpdateNotification({...notification, secondsThreshold: 300}); const result = await repo.getSecondsThresholdForNotificationIfExists({ deviceId: "device1", shuttleId: "shuttle1", stopId: "stop1" }); expect(result).toBe(300); }); }); describe("deleteNotificationIfExists", () => { it("deletes the notification", async () => { await repo.addOrUpdateNotification(notification); await repo.deleteNotificationIfExists(notification); const result = await repo.getAllNotificationsForShuttleAndStopId("shuttle1", "stop1"); expect(result).toHaveLength(0); }); it("does nothing if there's no notification", async () => { await expect(repo.deleteNotificationIfExists({ deviceId: "device1", shuttleId: "shuttle1", stopId: "stop1" })).resolves.not.toThrow(); }); }); describe("subscribeToNotificationChanges", () => { it("calls subscribers when something is added", async () => { const mockCallback = jest.fn(); repo.subscribeToNotificationChanges(mockCallback); await repo.addOrUpdateNotification(notification); const expectedEvent: NotificationEvent = { event: 'addOrUpdate', notification, } expect(mockCallback).toHaveBeenCalledTimes(1); expect(mockCallback).toHaveBeenCalledWith(expectedEvent); }); it("calls subscribers when something is updated", async () => { const mockCallback = jest.fn(); repo.subscribeToNotificationChanges(mockCallback); await repo.addOrUpdateNotification(notification); const updatedNotification = { ...notification, secondsThreshold: notification.secondsThreshold + 60, }; await repo.addOrUpdateNotification(updatedNotification); const expectedEvent: NotificationEvent = { event: 'addOrUpdate', notification, } expect(mockCallback).toHaveBeenCalledTimes(2); expect(mockCallback).toHaveBeenCalledWith(expectedEvent); }); it("calls subscribers when something is deleted", async () => { await repo.addOrUpdateNotification(notification); const mockCallback = jest.fn(); repo.subscribeToNotificationChanges(mockCallback); await repo.deleteNotificationIfExists(notification); expect(mockCallback).toHaveBeenCalledTimes(1); const expectedEvent: NotificationEvent = { event: 'delete', notification, }; expect(mockCallback).toHaveBeenCalledWith(expectedEvent); }); }) });