import { describe, it, expect, vi, beforeEach } from "vitest"; vi.mock("~/database/context", () => ({ database: vi.fn(), })); import { upsertRegularSeasonStandings, upsertManualStanding, getRegularSeasonStandings, getLastSyncedAt, deleteRegularSeasonStandings, getParticipantStanding, } from "../regular-season-standings"; import { database } from "~/database/context"; // --------------------------------------------------------------------------- // Helpers // --------------------------------------------------------------------------- function makeUpsertDb(returnedRows: object[] = []) { const returning = vi.fn().mockResolvedValue(returnedRows); const onConflictDoUpdate = vi.fn().mockReturnValue({ returning }); const values = vi.fn().mockReturnValue({ onConflictDoUpdate }); const insert = vi.fn().mockReturnValue({ values }); const db: Record = { insert, transaction: vi.fn().mockImplementation(async (fn: (tx: unknown) => unknown) => fn(db)), }; return { db, insert, values, onConflictDoUpdate, returning }; } function makeRecord(overrides: Record = {}) { return { participantId: "p-1", sportsSeasonId: "ss-1", wins: 10, losses: 5, gamesPlayed: 15, ...overrides, }; } beforeEach(() => { vi.clearAllMocks(); }); // --------------------------------------------------------------------------- // upsertRegularSeasonStandings // --------------------------------------------------------------------------- describe("upsertRegularSeasonStandings", () => { it("returns empty array immediately when given no records", async () => { const { db } = makeUpsertDb(); vi.mocked(database).mockReturnValue(db as never); const result = await upsertRegularSeasonStandings([]); expect(result).toEqual([]); expect(db.insert).not.toHaveBeenCalled(); }); it("maps winPct and gamesBack to strings", async () => { const { db, values } = makeUpsertDb([]); vi.mocked(database).mockReturnValue(db as never); await upsertRegularSeasonStandings([ makeRecord({ winPct: 0.667, gamesBack: 2.5 }), ]); const inserted = values.mock.calls[0][0]; expect(inserted[0].winPct).toBe("0.667"); expect(inserted[0].gamesBack).toBe("2.5"); }); it("maps null winPct and gamesBack to null", async () => { const { db, values } = makeUpsertDb([]); vi.mocked(database).mockReturnValue(db as never); await upsertRegularSeasonStandings([ makeRecord({ winPct: null, gamesBack: null }), ]); const inserted = values.mock.calls[0][0]; expect(inserted[0].winPct).toBeNull(); expect(inserted[0].gamesBack).toBeNull(); }); it("uses the provided db instead of calling database()", async () => { const { db } = makeUpsertDb([]); await upsertRegularSeasonStandings([makeRecord()], db as never); expect(database).not.toHaveBeenCalled(); expect(db.transaction).toHaveBeenCalled(); }); it("returns the rows from the DB", async () => { const row = { id: "row-1", wins: 10 }; const { db } = makeUpsertDb([row]); vi.mocked(database).mockReturnValue(db as never); const result = await upsertRegularSeasonStandings([makeRecord()]); expect(result).toEqual([row]); }); it("inserts multiple records in a single call", async () => { const { db, values } = makeUpsertDb([]); vi.mocked(database).mockReturnValue(db as never); await upsertRegularSeasonStandings([ makeRecord({ participantId: "p-1" }), makeRecord({ participantId: "p-2" }), ]); expect(values.mock.calls[0][0]).toHaveLength(2); }); it("sets syncedAt to now when not provided", async () => { const before = new Date(); const { db, values } = makeUpsertDb([]); vi.mocked(database).mockReturnValue(db as never); await upsertRegularSeasonStandings([makeRecord()]); const inserted = values.mock.calls[0][0]; expect(inserted[0].syncedAt).toBeInstanceOf(Date); expect(inserted[0].syncedAt.getTime()).toBeGreaterThanOrEqual(before.getTime()); }); }); // --------------------------------------------------------------------------- // upsertManualStanding // --------------------------------------------------------------------------- describe("upsertManualStanding", () => { it("sets syncedAt to null", async () => { const { db, values } = makeUpsertDb([{ id: "row-1" }]); vi.mocked(database).mockReturnValue(db as never); await upsertManualStanding("p-1", "ss-1", { wins: 10, losses: 5, gamesPlayed: 15, }); const inserted = values.mock.calls[0][0]; expect(inserted[0].syncedAt).toBeNull(); }); it("returns the first row", async () => { const row = { id: "row-1" }; const { db } = makeUpsertDb([row]); vi.mocked(database).mockReturnValue(db as never); const result = await upsertManualStanding("p-1", "ss-1", { wins: 10, losses: 5, gamesPlayed: 15, }); expect(result).toEqual(row); }); }); // --------------------------------------------------------------------------- // getRegularSeasonStandings — sorting logic // --------------------------------------------------------------------------- function makeRow(overrides: Record) { return { conference: null, division: null, divisionRank: null, leagueRank: null, participant: {}, ...overrides, }; } function makeQueryDb(rows: object[]) { return { query: { regularSeasonStandings: { findMany: vi.fn().mockResolvedValue(rows), }, }, }; } describe("getRegularSeasonStandings", () => { it("sorts by conference alphabetically", async () => { const rows = [ makeRow({ conference: "Western", leagueRank: 1 }), makeRow({ conference: "Eastern", leagueRank: 2 }), ]; vi.mocked(database).mockReturnValue(makeQueryDb(rows) as never); const result = await getRegularSeasonStandings("ss-1"); expect(result[0].conference).toBe("Eastern"); expect(result[1].conference).toBe("Western"); }); it("sorts by division within conference", async () => { const rows = [ makeRow({ conference: "East", division: "Southeast", leagueRank: 1 }), makeRow({ conference: "East", division: "Atlantic", leagueRank: 2 }), ]; vi.mocked(database).mockReturnValue(makeQueryDb(rows) as never); const result = await getRegularSeasonStandings("ss-1"); expect(result[0].division).toBe("Atlantic"); expect(result[1].division).toBe("Southeast"); }); it("sorts by divisionRank within division", async () => { const rows = [ makeRow({ conference: "East", division: "Atlantic", divisionRank: 3 }), makeRow({ conference: "East", division: "Atlantic", divisionRank: 1 }), makeRow({ conference: "East", division: "Atlantic", divisionRank: 2 }), ]; vi.mocked(database).mockReturnValue(makeQueryDb(rows) as never); const result = await getRegularSeasonStandings("ss-1"); expect(result.map((r) => r.divisionRank)).toEqual([1, 2, 3]); }); it("falls back to leagueRank when divisionRank is null", async () => { const rows = [ makeRow({ leagueRank: 3 }), makeRow({ leagueRank: 1 }), makeRow({ leagueRank: 2 }), ]; vi.mocked(database).mockReturnValue(makeQueryDb(rows) as never); const result = await getRegularSeasonStandings("ss-1"); expect(result.map((r) => r.leagueRank)).toEqual([1, 2, 3]); }); it("places null conference/division rows last", async () => { const rows = [ makeRow({ conference: null, leagueRank: 1 }), makeRow({ conference: "Eastern", leagueRank: 2 }), ]; vi.mocked(database).mockReturnValue(makeQueryDb(rows) as never); const result = await getRegularSeasonStandings("ss-1"); expect(result[0].conference).toBe("Eastern"); expect(result[1].conference).toBeNull(); }); }); // --------------------------------------------------------------------------- // getLastSyncedAt // --------------------------------------------------------------------------- describe("getLastSyncedAt", () => { function makeSelectDb(lastSync: Date | null) { return { select: vi.fn().mockReturnValue({ from: vi.fn().mockReturnValue({ where: vi.fn().mockResolvedValue([{ lastSync }]), }), }), }; } it("returns the max syncedAt date", async () => { const date = new Date("2025-03-01T00:00:00Z"); vi.mocked(database).mockReturnValue(makeSelectDb(date) as never); const result = await getLastSyncedAt("ss-1"); expect(result).toEqual(date); }); it("returns null when no synced records exist", async () => { vi.mocked(database).mockReturnValue(makeSelectDb(null) as never); const result = await getLastSyncedAt("ss-1"); expect(result).toBeNull(); }); }); // --------------------------------------------------------------------------- // deleteRegularSeasonStandings // --------------------------------------------------------------------------- describe("deleteRegularSeasonStandings", () => { it("calls delete on the DB", async () => { const where = vi.fn().mockResolvedValue(undefined); const del = vi.fn().mockReturnValue({ where }); const db = { delete: del }; vi.mocked(database).mockReturnValue(db as never); await deleteRegularSeasonStandings("ss-1"); expect(del).toHaveBeenCalled(); expect(where).toHaveBeenCalled(); }); }); // --------------------------------------------------------------------------- // getParticipantStanding // --------------------------------------------------------------------------- describe("getParticipantStanding", () => { it("returns the standing row when found", async () => { const row = { id: "row-1", participantId: "p-1" }; const db = { query: { regularSeasonStandings: { findFirst: vi.fn().mockResolvedValue(row), }, }, }; vi.mocked(database).mockReturnValue(db as never); const result = await getParticipantStanding("p-1", "ss-1"); expect(result).toEqual(row); }); it("returns undefined when not found", async () => { const db = { query: { regularSeasonStandings: { findFirst: vi.fn().mockResolvedValue(undefined), }, }, }; vi.mocked(database).mockReturnValue(db as never); const result = await getParticipantStanding("p-99", "ss-1"); expect(result).toBeUndefined(); }); });