/** * The Fix Semi-Final Pairings admin action. * * Elimination Final n feeds Semi-Final n, but brackets advanced before that was fixed * crossed the two winners, and nothing re-runs advancement — a completed match cannot be * re-submitted from the UI. * * It moves qualifier slots only — no scoring runs, so nothing reaches Discord. */ import { beforeEach, describe, expect, it, vi } from "vitest"; import { reseedAflSemiFinals } from "~/models/playoff-match"; import { findParticipantsBySportsSeasonId } from "~/models/season-participant"; import { getScoringEventById } from "~/models/scoring-event"; import { processMatchResult, recalculateAffectedLeagues } from "~/models/scoring-calculator"; import { sendDiscordWebhook } from "~/services/discord"; import { action } from "../admin.sports-seasons.$id.events.$eventId.bracket.server"; vi.mock("~/database/context", () => ({ database: vi.fn(() => ({})) })); vi.mock("~/models/scoring-event", async (importOriginal) => ({ ...(await importOriginal()), getScoringEventById: vi.fn(), isReadOnlySibling: vi.fn(() => false), })); vi.mock("~/models/playoff-match", async (importOriginal) => ({ ...(await importOriginal()), reseedAflSemiFinals: vi.fn(), })); vi.mock("~/models/season-participant", async (importOriginal) => ({ ...(await importOriginal()), findParticipantsBySportsSeasonId: vi.fn(), })); vi.mock("~/models/scoring-calculator", async (importOriginal) => ({ ...(await importOriginal()), processMatchResult: vi.fn(), recalculateAffectedLeagues: vi.fn(), })); vi.mock("~/services/discord", async (importOriginal) => ({ ...(await importOriginal()), sendDiscordWebhook: vi.fn(), })); const params = { id: "season-1", eventId: "event-1" }; const EVENT = { id: "event-1", name: "AFL Finals", sportsSeasonId: "season-1", isQualifyingEvent: false, bracketTemplateId: "afl_10", }; function request() { const body = new FormData(); body.set("intent", "reseed-afl-semifinals"); return new Request("http://localhost/bracket", { method: "POST", body }); } const run = () => action({ request: request(), params } as never); describe("reseed-afl-semifinals", () => { beforeEach(() => { vi.clearAllMocks(); vi.mocked(getScoringEventById).mockResolvedValue(EVENT as never); vi.mocked(findParticipantsBySportsSeasonId).mockResolvedValue([ { id: "geelong", name: "Geelong Cats" }, { id: "adelaide", name: "Adelaide Crows" }, ] as never); }); it("names the teams that moved", async () => { vi.mocked(reseedAflSemiFinals).mockResolvedValue({ vacated: [1, 2], filled: [ { matchNumber: 2, participantId: "adelaide" }, { matchNumber: 1, participantId: "geelong" }, ], }); const result = await run(); expect(reseedAflSemiFinals).toHaveBeenCalledWith("event-1"); expect(result).toEqual({ success: "Re-seeded the Semi-Finals: match 1 now hosts Geelong Cats, " + "match 2 now hosts Adelaide Crows.", }); }); it("reports a slot that was emptied without being refilled", async () => { // Un-recording an Elimination Final result takes its winner back out of the semi. vi.mocked(reseedAflSemiFinals).mockResolvedValue({ vacated: [1, 2], filled: [{ matchNumber: 2, participantId: "adelaide" }], }); expect(await run()).toEqual({ success: "Re-seeded the Semi-Finals: match 1 is back to TBD, " + "match 2 now hosts Adelaide Crows.", }); }); it("says so when the pairings are already right", async () => { vi.mocked(reseedAflSemiFinals).mockResolvedValue({ vacated: [], filled: [] }); expect(await run()).toEqual({ success: "Semi-Finals already match the Elimination Finals results — nothing to re-seed.", }); }); it("scores nothing and announces nothing", async () => { vi.mocked(reseedAflSemiFinals).mockResolvedValue({ vacated: [1, 2], filled: [{ matchNumber: 1, participantId: "geelong" }], }); await run(); expect(processMatchResult).not.toHaveBeenCalled(); expect(recalculateAffectedLeagues).not.toHaveBeenCalled(); expect(sendDiscordWebhook).not.toHaveBeenCalled(); }); it("refuses a bracket that is not an AFL finals bracket", async () => { vi.mocked(getScoringEventById).mockResolvedValue({ ...EVENT, bracketTemplateId: "nfl_14", } as never); expect(await run()).toEqual({ error: "This action only applies to AFL finals brackets", }); expect(reseedAflSemiFinals).not.toHaveBeenCalled(); }); it("surfaces a refusal to re-seed a game that has been played", async () => { vi.mocked(reseedAflSemiFinals).mockRejectedValue( new Error("Semi-Finals match 1 already has a recorded result") ); expect(await run()).toEqual({ error: "Semi-Finals match 1 already has a recorded result", }); }); });