import React from "react"; import { render, screen, waitFor } from "@testing-library/react"; import { toast } from "react-toastify"; import NotificationProvider, { notify } from "../../context/NotificationProvider"; import { SSEContext } from "../../context/SSEContext"; import { AuthContext } from "../../context/AuthContext"; // Mock axios to prevent import errors jest.mock("axios"); // Mock react-toastify jest.mock("react-toastify", () => ({ toast: { success: jest.fn(), error: jest.fn(), info: jest.fn(), warning: jest.fn(), dismiss: jest.fn(), }, })); describe("NotificationProvider", () => { let mockSSEContext; let mockAuthContext; beforeEach(() => { jest.clearAllMocks(); mockSSEContext = { connected: true, notifications: [], on: jest.fn(), off: jest.fn(), subscribe: jest.fn().mockResolvedValue({ subscribed: [] }), unsubscribe: jest.fn().mockResolvedValue({ unsubscribed: [] }), clearNotification: jest.fn(), clearAllNotifications: jest.fn(), }; mockAuthContext = { auth: { isAuthenticated: true, user: { id: "user123", name: "Test User" }, }, }; }); const renderWithProviders = (children) => { return render( {children} ); }; test("renders children correctly", () => { renderWithProviders(
Test Content
); expect(screen.getByText("Test Content")).toBeInTheDocument(); }); test("subscribes to custom events via context", () => { renderWithProviders(
Test
); // Verify custom event listeners were registered via context expect(mockSSEContext.on).toHaveBeenCalledWith("eventUpdate", expect.any(Function)); expect(mockSSEContext.on).toHaveBeenCalledWith("taskUpdate", expect.any(Function)); expect(mockSSEContext.on).toHaveBeenCalledWith("streetUpdate", expect.any(Function)); expect(mockSSEContext.on).toHaveBeenCalledWith("achievementUnlocked", expect.any(Function)); expect(mockSSEContext.on).toHaveBeenCalledWith("newPost", expect.any(Function)); expect(mockSSEContext.on).toHaveBeenCalledWith("newComment", expect.any(Function)); expect(mockSSEContext.on).toHaveBeenCalledWith("notification", expect.any(Function)); }); test("cleans up event listeners on unmount", () => { const { unmount } = renderWithProviders(
Test
); unmount(); // Verify custom event listeners were removed via context expect(mockSSEContext.off).toHaveBeenCalledWith("eventUpdate", expect.any(Function)); expect(mockSSEContext.off).toHaveBeenCalledWith("taskUpdate", expect.any(Function)); expect(mockSSEContext.off).toHaveBeenCalledWith("streetUpdate", expect.any(Function)); expect(mockSSEContext.off).toHaveBeenCalledWith("achievementUnlocked", expect.any(Function)); expect(mockSSEContext.off).toHaveBeenCalledWith("newPost", expect.any(Function)); expect(mockSSEContext.off).toHaveBeenCalledWith("newComment", expect.any(Function)); expect(mockSSEContext.off).toHaveBeenCalledWith("notification", expect.any(Function)); }); test("does not subscribe when not connected", () => { mockSSEContext.connected = false; renderWithProviders(
Test
); // Event listeners should not be registered when not connected expect(mockSSEContext.on).not.toHaveBeenCalled(); }); }); describe("notify utility", () => { beforeEach(() => { jest.clearAllMocks(); }); test("notify.success calls toast.success", () => { notify.success("Test message"); expect(toast.success).toHaveBeenCalledWith("Test message", {}); }); test("notify.error calls toast.error", () => { notify.error("Error message"); expect(toast.error).toHaveBeenCalledWith("Error message", {}); }); test("notify.info calls toast.info", () => { notify.info("Info message"); expect(toast.info).toHaveBeenCalledWith("Info message", {}); }); test("notify.warning calls toast.warning", () => { notify.warning("Warning message"); expect(toast.warning).toHaveBeenCalledWith("Warning message", {}); }); test("notify.success accepts custom options", () => { const options = { autoClose: 3000, position: "bottom-right" }; notify.success("Test", options); expect(toast.success).toHaveBeenCalledWith("Test", options); }); test("notify.dismiss calls toast.dismiss with toastId", () => { notify.dismiss("test-toast-id"); expect(toast.dismiss).toHaveBeenCalledWith("test-toast-id"); }); test("notify.dismissAll calls toast.dismiss without arguments", () => { notify.dismissAll(); expect(toast.dismiss).toHaveBeenCalledWith(); }); });