All checks were successful
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <jason@diversecanvas.com> Co-committed-by: Jason Woltje <jason@diversecanvas.com>
107 lines
3.1 KiB
TypeScript
107 lines
3.1 KiB
TypeScript
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<void> {
|
|
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(<CalendarWidget id="calendar-1" />);
|
|
|
|
expect(screen.getByText("Loading events...")).toBeInTheDocument();
|
|
});
|
|
|
|
it("fetches and renders upcoming events after loading", async (): Promise<void> => {
|
|
render(<CalendarWidget id="calendar-1" />);
|
|
|
|
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<void> => {
|
|
render(<CalendarWidget id="calendar-1" />);
|
|
|
|
await finishWidgetLoad();
|
|
|
|
expect(screen.getAllByText("Today").length).toBeGreaterThan(0);
|
|
expect(screen.getByText("Tomorrow")).toBeInTheDocument();
|
|
});
|
|
|
|
it("shows event locations when present", async (): Promise<void> => {
|
|
render(<CalendarWidget id="calendar-1" />);
|
|
|
|
await finishWidgetLoad();
|
|
|
|
expect(screen.getByText("Zoom")).toBeInTheDocument();
|
|
expect(screen.getByText("Room 1")).toBeInTheDocument();
|
|
});
|
|
|
|
it("shows empty state when no events are returned", async (): Promise<void> => {
|
|
vi.mocked(fetchEvents).mockResolvedValueOnce([]);
|
|
|
|
render(<CalendarWidget id="calendar-1" />);
|
|
await finishWidgetLoad();
|
|
|
|
expect(screen.getByText("No upcoming events")).toBeInTheDocument();
|
|
});
|
|
});
|