import { beforeEach, describe, expect, it, jest } from "@jest/globals"; import { deleteNotification, fetchNotifications, fetchUnreadCount, markAllAsRead, markAsRead, savePushToken, } from "../notifications"; import { apiClient, withAuth } from "../client"; jest.mock("../client", () => ({ apiClient: { get: jest.fn(), put: jest.fn(), post: jest.fn(), delete: jest.fn(), }, withAuth: jest.fn((token?: string | null) => token ? { headers: { Authorization: `Bearer ${token}` } } : {}, ), })); describe("notifications api", () => { const getMock = apiClient.get as any; const putMock = apiClient.put as any; const postMock = apiClient.post as any; const deleteMock = apiClient.delete as any; beforeEach(() => { jest.clearAllMocks(); }); it("returns notifications and normalizes createdAt", async () => { getMock.mockResolvedValue({ data: { success: true, data: [ { id: "n_1", userId: "u_1", title: "Hi", message: "Welcome", type: "system", read: false, createdAt: "2026-03-29T10:00:00.000Z", }, ], }, }); const result = await fetchNotifications("token_1"); expect(result).toHaveLength(1); expect(result[0].createdAt).toBeInstanceOf(Date); expect(withAuth).toHaveBeenCalledWith("token_1"); }); it("returns unread count from response wrapper", async () => { getMock.mockResolvedValue({ data: { success: true, data: { count: 3 }, }, }); const count = await fetchUnreadCount(null); expect(count).toBe(3); }); it("marks notification as read", async () => { putMock.mockResolvedValue({ data: { success: true, data: { id: "n_1", userId: "u_1", title: "Hi", message: "Welcome", type: "system", read: true, createdAt: "2026-03-29T10:00:00.000Z", }, }, }); const result = await markAsRead("n_1", "token_1"); expect(result.read).toBe(true); expect(putMock).toHaveBeenCalledWith( "/api/notifications/n_1", {}, expect.any(Object), ); }); it("calls mark-all, delete and save-token endpoints", async () => { postMock.mockResolvedValue({}); deleteMock.mockResolvedValue({}); await markAllAsRead("token_1"); await deleteNotification("n_2", "token_1"); await savePushToken("expo-token", "android", "token_1"); expect(postMock).toHaveBeenCalledWith( "/api/notifications/mark-all-read", {}, expect.any(Object), ); expect(deleteMock).toHaveBeenCalledWith( "/api/notifications/n_2", expect.any(Object), ); expect(postMock).toHaveBeenCalledWith( "/api/notifications/save-token", { expoPushToken: "expo-token", deviceType: "android" }, expect.any(Object), ); }); });