215 lines
7.5 KiB
TypeScript
215 lines
7.5 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { render, screen } from "@testing-library/react";
|
|
import { BrowserRouter } from "react-router";
|
|
import { SportSeasonCard } from "../SportSeasonCard";
|
|
import type { UpcomingParticipantEvent } from "~/models/scoring-event";
|
|
|
|
function renderWithRouter(ui: React.ReactElement) {
|
|
return render(<BrowserRouter>{ui}</BrowserRouter>);
|
|
}
|
|
|
|
function makeEvent(overrides: Partial<UpcomingParticipantEvent> = {}): UpcomingParticipantEvent {
|
|
return {
|
|
id: overrides.id ?? "event-1",
|
|
name: overrides.name ?? "UCL Quarterfinals",
|
|
eventDate: overrides.eventDate ?? "2025-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",
|
|
relevantParticipants: overrides.relevantParticipants ?? [
|
|
{ id: "p1", name: "Man City" },
|
|
],
|
|
};
|
|
}
|
|
|
|
const BASE_PROPS = {
|
|
leagueId: "league-1",
|
|
sportSeasonId: "ss-1",
|
|
sportName: "Football",
|
|
seasonName: "UCL 2025",
|
|
status: "active" as const,
|
|
};
|
|
|
|
describe("SportSeasonCard", () => {
|
|
describe("base rendering", () => {
|
|
it("shows sport name and season name", () => {
|
|
renderWithRouter(<SportSeasonCard {...BASE_PROPS} />);
|
|
expect(screen.getByText("Football")).toBeInTheDocument();
|
|
expect(screen.getByText("UCL 2025")).toBeInTheDocument();
|
|
});
|
|
|
|
it("links to the sports season page", () => {
|
|
renderWithRouter(<SportSeasonCard {...BASE_PROPS} />);
|
|
expect(screen.getByRole("link")).toHaveAttribute(
|
|
"href",
|
|
"/leagues/league-1/sports-seasons/ss-1"
|
|
);
|
|
});
|
|
|
|
it("shows Active badge for active status", () => {
|
|
renderWithRouter(<SportSeasonCard {...BASE_PROPS} status="active" />);
|
|
expect(screen.getByText("Active")).toBeInTheDocument();
|
|
});
|
|
|
|
it("shows Upcoming badge for upcoming status", () => {
|
|
renderWithRouter(<SportSeasonCard {...BASE_PROPS} status="upcoming" />);
|
|
expect(screen.getByText("Upcoming")).toBeInTheDocument();
|
|
});
|
|
|
|
it("shows Completed badge for completed status", () => {
|
|
renderWithRouter(<SportSeasonCard {...BASE_PROPS} status="completed" />);
|
|
expect(screen.getByText("Completed")).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe("no upcoming events", () => {
|
|
it("renders without error when upcomingParticipantEvents is empty", () => {
|
|
renderWithRouter(<SportSeasonCard {...BASE_PROPS} upcomingParticipantEvents={[]} />);
|
|
expect(screen.getByText("Football")).toBeInTheDocument();
|
|
});
|
|
|
|
it("renders without error when upcomingParticipantEvents is omitted (pre-draft)", () => {
|
|
renderWithRouter(<SportSeasonCard {...BASE_PROPS} />);
|
|
expect(screen.getByText("Football")).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe("bracket event display", () => {
|
|
it("shows event name and date for a bracket event", () => {
|
|
renderWithRouter(
|
|
<SportSeasonCard
|
|
{...BASE_PROPS}
|
|
upcomingParticipantEvents={[
|
|
makeEvent({ name: "UCL QF", eventDate: "2025-04-09", eventType: "playoff_game" }),
|
|
]}
|
|
/>
|
|
);
|
|
expect(screen.getByText("UCL QF")).toBeInTheDocument();
|
|
expect(screen.getByText("— Apr 9")).toBeInTheDocument();
|
|
});
|
|
|
|
it("shows participant badge for bracket events with one pick", () => {
|
|
renderWithRouter(
|
|
<SportSeasonCard
|
|
{...BASE_PROPS}
|
|
upcomingParticipantEvents={[
|
|
makeEvent({
|
|
eventType: "playoff_game",
|
|
relevantParticipants: [{ id: "p1", name: "Man City" }],
|
|
}),
|
|
]}
|
|
/>
|
|
);
|
|
expect(screen.getByText("Man City")).toBeInTheDocument();
|
|
});
|
|
|
|
it("shows participant badges for two picks in same bracket event", () => {
|
|
renderWithRouter(
|
|
<SportSeasonCard
|
|
{...BASE_PROPS}
|
|
upcomingParticipantEvents={[
|
|
makeEvent({
|
|
eventType: "playoff_game",
|
|
relevantParticipants: [
|
|
{ id: "p1", name: "Man City" },
|
|
{ id: "p2", name: "Arsenal" },
|
|
],
|
|
}),
|
|
]}
|
|
/>
|
|
);
|
|
expect(screen.getByText("Man City")).toBeInTheDocument();
|
|
expect(screen.getByText("Arsenal")).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe("all-compete event display", () => {
|
|
it("shows participant count badge for schedule_event with multiple picks", () => {
|
|
renderWithRouter(
|
|
<SportSeasonCard
|
|
{...BASE_PROPS}
|
|
upcomingParticipantEvents={[
|
|
makeEvent({
|
|
eventType: "schedule_event",
|
|
name: "Australian GP",
|
|
relevantParticipants: [
|
|
{ id: "p1", name: "Verstappen" },
|
|
{ id: "p2", name: "Hamilton" },
|
|
{ id: "p3", name: "Leclerc" },
|
|
{ id: "p4", name: "Norris" },
|
|
{ id: "p5", name: "Russell" },
|
|
],
|
|
}),
|
|
]}
|
|
/>
|
|
);
|
|
// Shows count badge, not individual names
|
|
expect(screen.getByText("5")).toBeInTheDocument();
|
|
expect(screen.queryByText("Verstappen")).not.toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe("event overflow", () => {
|
|
it("shows up to 3 events without overflow message", () => {
|
|
renderWithRouter(
|
|
<SportSeasonCard
|
|
{...BASE_PROPS}
|
|
upcomingParticipantEvents={[
|
|
makeEvent({ id: "e1", name: "Event One" }),
|
|
makeEvent({ id: "e2", name: "Event Two" }),
|
|
makeEvent({ id: "e3", name: "Event Three" }),
|
|
]}
|
|
/>
|
|
);
|
|
expect(screen.getByText("Event One")).toBeInTheDocument();
|
|
expect(screen.getByText("Event Three")).toBeInTheDocument();
|
|
expect(screen.queryByText(/more event/i)).not.toBeInTheDocument();
|
|
});
|
|
|
|
it("shows overflow count when more than 3 events", () => {
|
|
renderWithRouter(
|
|
<SportSeasonCard
|
|
{...BASE_PROPS}
|
|
upcomingParticipantEvents={[
|
|
makeEvent({ id: "e1", name: "Event One" }),
|
|
makeEvent({ id: "e2", name: "Event Two" }),
|
|
makeEvent({ id: "e3", name: "Event Three" }),
|
|
makeEvent({ id: "e4", name: "Event Four" }),
|
|
makeEvent({ id: "e5", name: "Event Five" }),
|
|
]}
|
|
/>
|
|
);
|
|
expect(screen.getByText("Event One")).toBeInTheDocument();
|
|
expect(screen.queryByText("Event Four")).not.toBeInTheDocument();
|
|
expect(screen.getByText("+2 more events")).toBeInTheDocument();
|
|
});
|
|
|
|
it("uses singular 'event' when overflow is 1", () => {
|
|
renderWithRouter(
|
|
<SportSeasonCard
|
|
{...BASE_PROPS}
|
|
upcomingParticipantEvents={[
|
|
makeEvent({ id: "e1", name: "Event One" }),
|
|
makeEvent({ id: "e2", name: "Event Two" }),
|
|
makeEvent({ id: "e3", name: "Event Three" }),
|
|
makeEvent({ id: "e4", name: "Event Four" }),
|
|
]}
|
|
/>
|
|
);
|
|
expect(screen.getByText("+1 more event")).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe("scoring pattern label", () => {
|
|
it("shows Playoff Bracket label", () => {
|
|
renderWithRouter(<SportSeasonCard {...BASE_PROPS} scoringPattern="playoff_bracket" />);
|
|
expect(screen.getByText("Playoff Bracket")).toBeInTheDocument();
|
|
});
|
|
|
|
it("shows Season Standings label", () => {
|
|
renderWithRouter(<SportSeasonCard {...BASE_PROPS} scoringPattern="season_standings" />);
|
|
expect(screen.getByText("Season Standings")).toBeInTheDocument();
|
|
});
|
|
});
|
|
});
|