brackt/app/routes/__tests__/admin.sports-seasons.bracket.reseed-afl.test.ts
Claude 95acc6fcba
All checks were successful
🚀 Deploy / 🧪 Test (pull_request) Successful in 3m7s
🚀 Deploy / ʦ🔍 Typecheck & Lint (pull_request) Successful in 1m17s
🚀 Deploy / 🐳 Build (pull_request) Has been skipped
🚀 Deploy / 🚀 Deploy (pull_request) Has been skipped
Add a Re-seed Wildcard Winners button to the bracket admin
Repairing a bracket advanced before the re-seeding rule needed a script and
a shell. Add the same repair as an admin action on the event's bracket page,
shown for afl_10 brackets: it runs reseedAflEliminationFinals and reports
which team each Elimination Final now hosts, or says the pairings were
already right.

Only the qualifier slots move, so no scoring runs and nothing is announced —
a test asserts the action calls neither the scoring path nor Discord. A
bracket whose Elimination Final has already been played still refuses, with
the model's message surfaced to the admin.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDbHrCce1UhahbkwKkc7hK
2026-09-04 21:40:08 +00:00

133 lines
4.5 KiB
TypeScript

/**
* The Re-seed Wildcard Winners admin action.
*
* Advancement pairs the Wildcard winners with 5th and 6th by ladder position on every
* result, so this action exists for brackets advanced before that rule: their winners sit
* in the wrong Elimination Finals and nothing re-runs advancement, because 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 { reseedAflEliminationFinals } 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<object>()),
getScoringEventById: vi.fn(),
isReadOnlySibling: vi.fn(() => false),
}));
vi.mock("~/models/playoff-match", async (importOriginal) => ({
...(await importOriginal<object>()),
reseedAflEliminationFinals: vi.fn(),
}));
vi.mock("~/models/season-participant", async (importOriginal) => ({
...(await importOriginal<object>()),
findParticipantsBySportsSeasonId: vi.fn(),
}));
vi.mock("~/models/scoring-calculator", async (importOriginal) => ({
...(await importOriginal<object>()),
processMatchResult: vi.fn(),
recalculateAffectedLeagues: vi.fn(),
}));
vi.mock("~/services/discord", async (importOriginal) => ({
...(await importOriginal<object>()),
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-wildcard");
return new Request("http://localhost/bracket", { method: "POST", body });
}
const run = () => action({ request: request(), params } as never);
describe("reseed-afl-wildcard", () => {
beforeEach(() => {
vi.clearAllMocks();
vi.mocked(getScoringEventById).mockResolvedValue(EVENT as never);
vi.mocked(findParticipantsBySportsSeasonId).mockResolvedValue([
{ id: "carlton", name: "Carlton Blues" },
{ id: "bulldogs", name: "Western Bulldogs" },
] as never);
});
it("names the teams that moved", async () => {
vi.mocked(reseedAflEliminationFinals).mockResolvedValue({
vacated: [1, 2],
filled: [
{ matchNumber: 2, participantId: "bulldogs" },
{ matchNumber: 1, participantId: "carlton" },
],
});
const result = await run();
expect(reseedAflEliminationFinals).toHaveBeenCalledWith("event-1");
expect(result).toEqual({
success:
"Re-seeded the Elimination Finals: match 1 now hosts Carlton Blues, " +
"match 2 now hosts Western Bulldogs.",
});
});
it("says so when the pairings are already right", async () => {
vi.mocked(reseedAflEliminationFinals).mockResolvedValue({ vacated: [], filled: [] });
expect(await run()).toEqual({
success: "Elimination Finals already match the Wildcard results — nothing to re-seed.",
});
});
it("scores nothing and announces nothing", async () => {
vi.mocked(reseedAflEliminationFinals).mockResolvedValue({
vacated: [1, 2],
filled: [{ matchNumber: 1, participantId: "carlton" }],
});
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(reseedAflEliminationFinals).not.toHaveBeenCalled();
});
it("surfaces a refusal to re-seed a game that has been played", async () => {
vi.mocked(reseedAflEliminationFinals).mockRejectedValue(
new Error("Elimination Finals match 1 already has a recorded result")
);
expect(await run()).toEqual({
error: "Elimination Finals match 1 already has a recorded result",
});
});
});