brackt/app/components/league/settings/__tests__/SportsSection.test.tsx
Chris Parsons 55828e9f42
Simplify sports season display and add local timezone hints (#434)
* Show season name instead of year/bracket format; add local timezone hint to draft time

Replace the raw year number and scoringType string in the league creation
sport picker, review step, and league settings sports section with the
human-readable season name (e.g. "2025 NBA Season"), matching how the
league homepage sports list already displays seasons.

Add a client-side local timezone label below the draft date & time fields
on both the league creation wizard and the league settings page, so users
know that draft times are in their local timezone.

https://claude.ai/code/session_01GtJowGruAc1A4jURkSDVjX

* Address code review: shared tz hook, short abbrev, sort fix, dead type cleanup, test update

- Extract timezone detection into useLocalTimezone hook to avoid duplication
  across DraftSetupSection and Step3DraftSettings
- Use Intl short timezone abbreviation (e.g. "EST") instead of raw IANA name,
  matching DraftInfoCard's existing pattern
- Sort review step sport list by season name instead of sport.name so the
  visible order matches the displayed text
- Remove unused scoringType and year fields from SportsSection's local type
- Update SportsSection tests to use realistic season names and the new
  display format

https://claude.ai/code/session_01GtJowGruAc1A4jURkSDVjX

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-05-15 16:04:07 -07:00

108 lines
3.2 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;
sport: { id: string; name: string; slug: string; type: string; iconUrl: string | null };
};
const displaySportsSeasons: SportsSeason[] = [
{
id: "nba-2025",
name: "2025 NBA Season",
sport: { id: "sport-1", name: "NBA", slug: "nba", type: "team", iconUrl: "/sports-icons/nba.svg" },
},
{
id: "mlb-2025",
name: "2025 MLB Season",
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: /2025 mlb season/i });
expect(mlbCheckbox).not.toBeChecked();
await user.click(screen.getByText("2025 MLB Season"));
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("2025 MLB Season"));
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([]);
});
});