172 lines
6.2 KiB
TypeScript
172 lines
6.2 KiB
TypeScript
|
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||
|
|
import { render, screen, fireEvent } from "@testing-library/react";
|
||
|
|
import { MiniDraftGrid } from "~/components/draft/MiniDraftGrid";
|
||
|
|
|
||
|
|
const draftSlots = [
|
||
|
|
{ id: "slot-1", draftOrder: 1, team: { id: "team-1", name: "Alpha", logoUrl: null } },
|
||
|
|
{ id: "slot-2", draftOrder: 2, team: { id: "team-2", name: "Bravo", logoUrl: null } },
|
||
|
|
];
|
||
|
|
|
||
|
|
const ownerMap = { "team-1": "Alpha", "team-2": "Bravo" };
|
||
|
|
|
||
|
|
// Round 1: team-1 pick 1 (filled), team-2 pick 2 (current/empty)
|
||
|
|
// Round 2 (snake): team-2 pick 3, team-1 pick 4 — both empty
|
||
|
|
const draftGrid = [
|
||
|
|
[
|
||
|
|
{ pickNumber: 1, round: 1, pickInRound: 1, teamId: "team-1", pick: { participant: { name: "Player A" }, sport: { name: "NFL" } } },
|
||
|
|
{ pickNumber: 2, round: 1, pickInRound: 2, teamId: "team-2" },
|
||
|
|
],
|
||
|
|
[
|
||
|
|
{ pickNumber: 3, round: 2, pickInRound: 1, teamId: "team-2" },
|
||
|
|
{ pickNumber: 4, round: 2, pickInRound: 2, teamId: "team-1" },
|
||
|
|
],
|
||
|
|
];
|
||
|
|
|
||
|
|
const baseProps = {
|
||
|
|
draftSlots,
|
||
|
|
draftGrid,
|
||
|
|
currentPick: 2,
|
||
|
|
currentRound: 1,
|
||
|
|
ownerMap,
|
||
|
|
};
|
||
|
|
|
||
|
|
describe("MiniDraftGrid", () => {
|
||
|
|
beforeEach(() => vi.clearAllMocks());
|
||
|
|
|
||
|
|
describe("Team header layout", () => {
|
||
|
|
it("renders all team names", () => {
|
||
|
|
render(<MiniDraftGrid {...baseProps} />);
|
||
|
|
expect(screen.getAllByText("Alpha").length).toBeGreaterThan(0);
|
||
|
|
expect(screen.getAllByText("Bravo").length).toBeGreaterThan(0);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("non-commissioner headers carry flex sizing classes", () => {
|
||
|
|
render(<MiniDraftGrid {...baseProps} />);
|
||
|
|
const alphaHeader = screen.getAllByText("Alpha")[0].closest(".flex-1");
|
||
|
|
expect(alphaHeader).toHaveClass("flex-1", "min-w-20");
|
||
|
|
});
|
||
|
|
|
||
|
|
it("commissioner headers carry flex sizing classes", () => {
|
||
|
|
render(
|
||
|
|
<MiniDraftGrid
|
||
|
|
{...baseProps}
|
||
|
|
onAdjustTimeBankOpen={vi.fn()}
|
||
|
|
onSetAutodraftOpen={vi.fn()}
|
||
|
|
/>
|
||
|
|
);
|
||
|
|
const alphaHeader = screen.getAllByText("Alpha")[0].closest(".flex-1");
|
||
|
|
expect(alphaHeader).toHaveClass("flex-1", "min-w-20");
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("Disconnected team styling", () => {
|
||
|
|
it("applies italic + muted style to disconnected teams when connectedTeams provided", () => {
|
||
|
|
render(
|
||
|
|
<MiniDraftGrid
|
||
|
|
{...baseProps}
|
||
|
|
connectedTeams={new Set(["team-1"])}
|
||
|
|
/>
|
||
|
|
);
|
||
|
|
const bravoSpan = screen.getAllByText("Bravo")[0];
|
||
|
|
expect(bravoSpan).toHaveClass("italic", "text-muted-foreground");
|
||
|
|
const alphaSpan = screen.getAllByText("Alpha")[0];
|
||
|
|
expect(alphaSpan).not.toHaveClass("italic");
|
||
|
|
});
|
||
|
|
|
||
|
|
it("treats all teams as connected when connectedTeams is not provided", () => {
|
||
|
|
render(<MiniDraftGrid {...baseProps} />);
|
||
|
|
expect(screen.getAllByText("Alpha")[0]).not.toHaveClass("italic");
|
||
|
|
expect(screen.getAllByText("Bravo")[0]).not.toHaveClass("italic");
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("Team header context menus (commissioner)", () => {
|
||
|
|
it("shows no context menu when callbacks are absent", () => {
|
||
|
|
render(<MiniDraftGrid {...baseProps} />);
|
||
|
|
const alphaHeader = screen.getAllByText("Alpha")[0];
|
||
|
|
fireEvent.contextMenu(alphaHeader);
|
||
|
|
expect(screen.queryByText("Adjust Time Bank...")).not.toBeInTheDocument();
|
||
|
|
expect(screen.queryByText("Set Autodraft...")).not.toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("shows Adjust Time Bank and Set Autodraft on right-click when both callbacks provided", () => {
|
||
|
|
render(
|
||
|
|
<MiniDraftGrid
|
||
|
|
{...baseProps}
|
||
|
|
onAdjustTimeBankOpen={vi.fn()}
|
||
|
|
onSetAutodraftOpen={vi.fn()}
|
||
|
|
/>
|
||
|
|
);
|
||
|
|
fireEvent.contextMenu(screen.getAllByText("Alpha")[0]);
|
||
|
|
expect(screen.getByText("Adjust Time Bank...")).toBeInTheDocument();
|
||
|
|
expect(screen.getByText("Set Autodraft...")).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("shows only Adjust Time Bank when only that callback is provided", () => {
|
||
|
|
render(
|
||
|
|
<MiniDraftGrid {...baseProps} onAdjustTimeBankOpen={vi.fn()} />
|
||
|
|
);
|
||
|
|
fireEvent.contextMenu(screen.getAllByText("Alpha")[0]);
|
||
|
|
expect(screen.getByText("Adjust Time Bank...")).toBeInTheDocument();
|
||
|
|
expect(screen.queryByText("Set Autodraft...")).not.toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("Current cell context menu (commissioner)", () => {
|
||
|
|
it("shows Force Auto Pick and Force Manual Pick on right-click of current cell", () => {
|
||
|
|
render(
|
||
|
|
<MiniDraftGrid
|
||
|
|
{...baseProps}
|
||
|
|
onForceAutopick={vi.fn()}
|
||
|
|
onForceManualPickOpen={vi.fn()}
|
||
|
|
/>
|
||
|
|
);
|
||
|
|
// Pick 2 is the current cell (team-2, round 1)
|
||
|
|
const currentCell = screen.getByTitle("Overall Pick #2");
|
||
|
|
fireEvent.contextMenu(currentCell);
|
||
|
|
expect(screen.getByText("Force Auto Pick")).toBeInTheDocument();
|
||
|
|
expect(screen.getByText("Force Manual Pick")).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("shows no force-pick menu when no callbacks provided", () => {
|
||
|
|
render(<MiniDraftGrid {...baseProps} />);
|
||
|
|
fireEvent.contextMenu(screen.getByTitle("Overall Pick #2"));
|
||
|
|
expect(screen.queryByText("Force Auto Pick")).not.toBeInTheDocument();
|
||
|
|
expect(screen.queryByText("Force Manual Pick")).not.toBeInTheDocument();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("Picked cell context menu (commissioner)", () => {
|
||
|
|
it("shows Replace Pick and Roll Back on right-click of a picked cell", () => {
|
||
|
|
render(
|
||
|
|
<MiniDraftGrid
|
||
|
|
{...baseProps}
|
||
|
|
onReplacePick={vi.fn()}
|
||
|
|
onRollbackToPick={vi.fn()}
|
||
|
|
/>
|
||
|
|
);
|
||
|
|
// Pick 1 is already picked (team-1)
|
||
|
|
const pickedCell = screen.getByTitle("Overall Pick #1");
|
||
|
|
fireEvent.contextMenu(pickedCell);
|
||
|
|
expect(screen.getByText("Replace Pick")).toBeInTheDocument();
|
||
|
|
expect(screen.getByText("Roll Back to This Pick")).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("shows no menu on picked cell when no callbacks provided", () => {
|
||
|
|
render(<MiniDraftGrid {...baseProps} />);
|
||
|
|
fireEvent.contextMenu(screen.getByTitle("Overall Pick #1"));
|
||
|
|
expect(screen.queryByText("Replace Pick")).not.toBeInTheDocument();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("Empty grid", () => {
|
||
|
|
it("renders nothing when draftGrid is empty", () => {
|
||
|
|
const { container } = render(
|
||
|
|
<MiniDraftGrid {...baseProps} draftGrid={[]} />
|
||
|
|
);
|
||
|
|
expect(container.firstChild).toBeNull();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|