import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; import { render, screen, waitFor } from "@testing-library/react"; import type { Event } from "@mosaic/shared"; import { CalendarWidget } from "../CalendarWidget"; import { fetchEvents } from "@/lib/api/events"; vi.mock("@/lib/api/events", () => ({ fetchEvents: vi.fn(), })); const mockEvents: Event[] = [ { id: "event-1", title: "API Planning", description: null, startTime: new Date("2026-02-01T09:00:00Z"), endTime: new Date("2026-02-01T09:30:00Z"), allDay: false, location: "Zoom", recurrence: null, creatorId: "user-1", workspaceId: "workspace-1", projectId: null, metadata: {}, createdAt: new Date("2026-01-30T09:00:00Z"), updatedAt: new Date("2026-01-30T09:00:00Z"), }, { id: "event-2", title: "API Review", description: null, startTime: new Date("2026-02-02T10:00:00Z"), endTime: new Date("2026-02-02T11:00:00Z"), allDay: false, location: "Room 1", recurrence: null, creatorId: "user-1", workspaceId: "workspace-1", projectId: null, metadata: {}, createdAt: new Date("2026-01-30T09:00:00Z"), updatedAt: new Date("2026-01-30T09:00:00Z"), }, ]; async function finishWidgetLoad(): Promise { await waitFor(() => { expect(screen.queryByText("Loading events...")).not.toBeInTheDocument(); }); } describe("CalendarWidget", (): void => { beforeEach((): void => { vi.clearAllMocks(); vi.mocked(fetchEvents).mockResolvedValue(mockEvents); vi.setSystemTime(new Date("2026-02-01T08:00:00Z")); }); afterEach((): void => { vi.useRealTimers(); }); it("renders loading state initially", (): void => { render(); expect(screen.getByText("Loading events...")).toBeInTheDocument(); }); it("fetches and renders upcoming events after loading", async (): Promise => { render(); await finishWidgetLoad(); expect(fetchEvents).toHaveBeenCalledTimes(1); expect(screen.getByText("Upcoming Events")).toBeInTheDocument(); expect(screen.getByText("API Planning")).toBeInTheDocument(); expect(screen.getByText("API Review")).toBeInTheDocument(); }); it("shows relative day labels", async (): Promise => { render(); await finishWidgetLoad(); expect(screen.getAllByText("Today").length).toBeGreaterThan(0); expect(screen.getByText("Tomorrow")).toBeInTheDocument(); }); it("shows event locations when present", async (): Promise => { render(); await finishWidgetLoad(); expect(screen.getByText("Zoom")).toBeInTheDocument(); expect(screen.getByText("Room 1")).toBeInTheDocument(); }); it("shows empty state when no events are returned", async (): Promise => { vi.mocked(fetchEvents).mockResolvedValueOnce([]); render(); await finishWidgetLoad(); expect(screen.getByText("No upcoming events")).toBeInTheDocument(); }); });