brackt/app/components/league/settings/__tests__/SportsSection.test.tsx
2026-05-07 23:06:49 -07:00

114 lines
3.3 KiB
TypeScript

import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { useState, type FormEvent } from "react";
import { describe, expect, it, vi } from "vitest";
import { SportsSection } from "../SportsSection";
type SportsSeason = {
id: string;
name: string;
year: number;
scoringType: string;
sport: { id: string; name: string; slug: string; type: string; iconUrl: string | null };
};
const displaySportsSeasons: SportsSeason[] = [
{
id: "nba-2025",
name: "2025 Season",
year: 2025,
scoringType: "standings",
sport: { id: "sport-1", name: "NBA", slug: "nba", type: "team", iconUrl: "/sports-icons/nba.svg" },
},
{
id: "mlb-2025",
name: "2025 Season",
year: 2025,
scoringType: "playoffs",
sport: { id: "sport-2", name: "MLB", slug: "mlb", type: "team", iconUrl: "/sports-icons/mlb.svg" },
},
];
function SportsSectionHarness({
initialSelected = ["nba-2025"],
canEditSports = true,
onSubmit,
}: {
initialSelected?: string[];
canEditSports?: boolean;
onSubmit?: (selectedSports: string[]) => void;
}) {
const [selectedSports, setSelectedSports] = useState(new Set(initialSelected));
const handleSportToggle = (id: string) => {
setSelectedSports((prev) => {
const next = new Set(prev);
if (next.has(id)) {
next.delete(id);
} else {
next.add(id);
}
return next;
});
};
const handleClearAll = () => {
setSelectedSports(new Set());
};
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
const formData = new FormData(event.currentTarget);
onSubmit?.(formData.getAll("sportsSeasons").map(String));
};
return (
<form onSubmit={handleSubmit}>
<SportsSection
active
canEditSports={canEditSports}
selectedSports={selectedSports}
displaySportsSeasons={displaySportsSeasons}
onSportToggle={handleSportToggle}
onClearAll={handleClearAll}
/>
<button type="submit">Save</button>
</form>
);
}
describe("SportsSection", () => {
it("keeps native checkbox semantics while using the row as the visible control", async () => {
const user = userEvent.setup();
render(<SportsSectionHarness />);
const mlbCheckbox = screen.getByRole("checkbox", { name: /mlb - 2025 season \(2025\)/i });
expect(mlbCheckbox).not.toBeChecked();
await user.click(screen.getByText("MLB - 2025 Season (2025)"));
expect(mlbCheckbox).toBeChecked();
});
it("submits the currently selected sports seasons after toggling", async () => {
const user = userEvent.setup();
const handleSubmit = vi.fn();
render(<SportsSectionHarness onSubmit={handleSubmit} />);
await user.click(screen.getByText("MLB - 2025 Season (2025)"));
await user.click(screen.getByRole("button", { name: "Save" }));
expect(handleSubmit).toHaveBeenCalledWith(["nba-2025", "mlb-2025"]);
});
it("submits an empty sports selection after clearing all", async () => {
const user = userEvent.setup();
const handleSubmit = vi.fn();
render(<SportsSectionHarness onSubmit={handleSubmit} />);
await user.click(screen.getByRole("button", { name: /clear all/i }));
await user.click(screen.getByRole("button", { name: "Save" }));
expect(handleSubmit).toHaveBeenCalledWith([]);
});
});