import { describe, it, expect } from "vitest";
import { render, screen } from "@testing-library/react";
import { BrowserRouter } from "react-router";
import { UpcomingCalendarPanel } from "../UpcomingCalendarPanel";
import type { CalendarPanelEvent } from "../UpcomingCalendarPanel";
function renderWithRouter(ui: React.ReactElement) {
return render({ui});
}
function makeEvent(overrides: Partial = {}): CalendarPanelEvent {
return {
id: overrides.id ?? "event-1",
name: overrides.name ?? "UCL Quarterfinals",
// Use explicit key check so callers can pass null to test the null-date path
eventDate: "eventDate" in overrides ? (overrides.eventDate as string | null) : "2099-04-09",
earliestGameTime: "earliestGameTime" in overrides ? (overrides.earliestGameTime as string | null) : null,
matchLabel: overrides.matchLabel ?? null,
eventType: overrides.eventType ?? "playoff_game",
sportsSeasonId: overrides.sportsSeasonId ?? "ss-1",
sportName: overrides.sportName ?? "Football",
sportSeasonName: overrides.sportSeasonName ?? "UCL 2025",
leagueName: overrides.leagueName,
leagueId: overrides.leagueId,
sportsSeasonPageUrl: overrides.sportsSeasonPageUrl,
relevantParticipants: overrides.relevantParticipants ?? [
{ id: "p1", name: "Man City" },
],
};
}
describe("UpcomingCalendarPanel", () => {
describe("empty state", () => {
it("shows empty state message when no events", () => {
renderWithRouter();
expect(screen.getByText(/No upcoming events in the next 30 days/i)).toBeInTheDocument();
});
it("renders the panel title", () => {
renderWithRouter();
expect(screen.getByText("Upcoming Events")).toBeInTheDocument();
});
});
describe("event display", () => {
it("shows event name and formatted date", () => {
renderWithRouter(
);
expect(screen.getByText("UCL QF")).toBeInTheDocument();
expect(screen.getByText("Apr 9")).toBeInTheDocument();
});
it("shows sport name and season name", () => {
renderWithRouter(
);
expect(screen.getByText(/Football · UCL 2025/)).toBeInTheDocument();
});
it("shows participant badge for bracket events", () => {
renderWithRouter(
);
expect(screen.getByText("Man City")).toBeInTheDocument();
});
it("shows 'N of your picks' for all-compete events with multiple participants", () => {
renderWithRouter(
);
expect(screen.getByText("5 of your picks")).toBeInTheDocument();
});
it("renders TBD when both eventDate and earliestGameTime are null", () => {
renderWithRouter(
);
expect(screen.getByText("TBD")).toBeInTheDocument();
});
it("uses earliestGameTime date when eventDate is null", () => {
renderWithRouter(
);
// Should not show TBD
expect(screen.queryByText("TBD")).not.toBeInTheDocument();
});
it("shows matchLabel appended to event name when present", () => {
renderWithRouter(
);
expect(screen.getByText(/PDC World Championship — Semifinals Game #1/)).toBeInTheDocument();
});
it("shows plain event name when matchLabel is null", () => {
renderWithRouter(
);
expect(screen.getByText("UCL QF")).toBeInTheDocument();
});
});
describe("participant overflow", () => {
it("shows first 3 participants and an overflow badge for 4+", () => {
renderWithRouter(
);
expect(screen.getByText("Alpha")).toBeInTheDocument();
expect(screen.getByText("Beta")).toBeInTheDocument();
expect(screen.getByText("Gamma")).toBeInTheDocument();
expect(screen.queryByText("Delta")).not.toBeInTheDocument();
expect(screen.getByText("+2 more")).toBeInTheDocument();
});
it("shows all participants when exactly 3", () => {
renderWithRouter(
);
expect(screen.getByText("Alpha")).toBeInTheDocument();
expect(screen.getByText("Gamma")).toBeInTheDocument();
expect(screen.queryByText(/\+\d+ more/)).not.toBeInTheDocument();
});
});
describe("league display", () => {
it("does not show league name when showLeague is false (default)", () => {
renderWithRouter(
);
expect(screen.queryByText("My League")).not.toBeInTheDocument();
});
it("shows league name badge when showLeague is true", () => {
renderWithRouter(
);
expect(screen.getByText("My League")).toBeInTheDocument();
});
it("renders multiple events from different leagues", () => {
renderWithRouter(
);
expect(screen.getByText("League A")).toBeInTheDocument();
expect(screen.getByText("League B")).toBeInTheDocument();
});
});
describe("link behaviour", () => {
it("wraps event row in a link when sportsSeasonPageUrl is provided", () => {
renderWithRouter(
);
const link = screen.getByRole("link");
expect(link).toHaveAttribute("href", "/leagues/l1/sports-seasons/ss1");
});
});
});