114 lines
3.3 KiB
TypeScript
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([]);
|
|
});
|
|
});
|