93 lines
3.6 KiB
TypeScript
93 lines
3.6 KiB
TypeScript
|
|
import { describe, expect, it, vi } from "vitest";
|
|||
|
|
|
|||
|
|
import {
|
|||
|
|
getBracketTemplateIdForSportsSeason,
|
|||
|
|
getBracketTemplateIdsForSportsSeasons,
|
|||
|
|
} from "../bracket-template";
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* A sports season can own several scoring events — a bracket plus schedule events, or a
|
|||
|
|
* re-created bracket alongside a stale one. Resolving the template from an arbitrary row
|
|||
|
|
* is not harmless: calculateBracketPoints falls back to the flat 5th–8th average when the
|
|||
|
|
* template id is null, so losing "llws_20" makes a team locked into 5th–6th and one
|
|||
|
|
* locked into 7th–8th both score 20.
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Minimal db stub. Applies the same filter and ordering the real query does, so the
|
|||
|
|
* assertions exercise the helper's row-picking rather than re-stating the query.
|
|||
|
|
*/
|
|||
|
|
function makeDb(
|
|||
|
|
rows: Array<{ sportsSeasonId: string; bracketTemplateId: string | null; createdAt: Date }>
|
|||
|
|
) {
|
|||
|
|
const findMany = vi.fn(async () =>
|
|||
|
|
rows
|
|||
|
|
.filter((row) => row.bracketTemplateId !== null)
|
|||
|
|
.toSorted((a, b) => b.createdAt.getTime() - a.createdAt.getTime())
|
|||
|
|
);
|
|||
|
|
return { db: { query: { scoringEvents: { findMany } } } as any, findMany };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
describe("getBracketTemplateIdForSportsSeason", () => {
|
|||
|
|
it("ignores a non-bracket event and returns the bracket event's template", async () => {
|
|||
|
|
const { db } = makeDb([
|
|||
|
|
{ sportsSeasonId: "ss1", bracketTemplateId: null, createdAt: new Date("2026-08-01") },
|
|||
|
|
{ sportsSeasonId: "ss1", bracketTemplateId: "llws_20", createdAt: new Date("2026-07-01") },
|
|||
|
|
]);
|
|||
|
|
|
|||
|
|
await expect(getBracketTemplateIdForSportsSeason("ss1", db)).resolves.toBe("llws_20");
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("takes the most recent bracket event when a stale one is still around", async () => {
|
|||
|
|
const { db } = makeDb([
|
|||
|
|
{ sportsSeasonId: "ss1", bracketTemplateId: "simple_16", createdAt: new Date("2026-06-01") },
|
|||
|
|
{ sportsSeasonId: "ss1", bracketTemplateId: "llws_20", createdAt: new Date("2026-08-01") },
|
|||
|
|
]);
|
|||
|
|
|
|||
|
|
await expect(getBracketTemplateIdForSportsSeason("ss1", db)).resolves.toBe("llws_20");
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("returns null when the season has no bracket event", async () => {
|
|||
|
|
const { db } = makeDb([
|
|||
|
|
{ sportsSeasonId: "ss1", bracketTemplateId: null, createdAt: new Date("2026-08-01") },
|
|||
|
|
]);
|
|||
|
|
|
|||
|
|
await expect(getBracketTemplateIdForSportsSeason("ss1", db)).resolves.toBeNull();
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
describe("getBracketTemplateIdsForSportsSeasons", () => {
|
|||
|
|
it("resolves each season independently in one query", async () => {
|
|||
|
|
const { db, findMany } = makeDb([
|
|||
|
|
{ sportsSeasonId: "ss1", bracketTemplateId: "llws_20", createdAt: new Date("2026-08-01") },
|
|||
|
|
{ sportsSeasonId: "ss2", bracketTemplateId: "afl_10", createdAt: new Date("2026-08-02") },
|
|||
|
|
{ sportsSeasonId: "ss3", bracketTemplateId: null, createdAt: new Date("2026-08-03") },
|
|||
|
|
]);
|
|||
|
|
|
|||
|
|
const resolved = await getBracketTemplateIdsForSportsSeasons(["ss1", "ss2", "ss3"], db);
|
|||
|
|
|
|||
|
|
expect(resolved.get("ss1")).toBe("llws_20");
|
|||
|
|
expect(resolved.get("ss2")).toBe("afl_10");
|
|||
|
|
expect(resolved.get("ss3")).toBeNull();
|
|||
|
|
expect(findMany).toHaveBeenCalledTimes(1);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("gives every requested season an entry so callers can cache the miss", async () => {
|
|||
|
|
const { db } = makeDb([]);
|
|||
|
|
|
|||
|
|
const resolved = await getBracketTemplateIdsForSportsSeasons(["ss1", "ss2"], db);
|
|||
|
|
|
|||
|
|
expect([...resolved.entries()]).toEqual([
|
|||
|
|
["ss1", null],
|
|||
|
|
["ss2", null],
|
|||
|
|
]);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("does not query at all for an empty season list", async () => {
|
|||
|
|
const { db, findMany } = makeDb([]);
|
|||
|
|
|
|||
|
|
await expect(getBracketTemplateIdsForSportsSeasons([], db)).resolves.toEqual(new Map());
|
|||
|
|
expect(findMany).not.toHaveBeenCalled();
|
|||
|
|
});
|
|||
|
|
});
|