import { describe, it, expect, vi, beforeEach } from "vitest"; vi.mock("~/database/context", () => ({ database: vi.fn(), })); import { database } from "~/database/context"; import { getGolfSkillsForSeason, getGolfSkillsMap, batchUpsertGolfSkills } from "../golf-skills"; const mockDb = { select: vi.fn().mockReturnThis(), from: vi.fn().mockReturnThis(), where: vi.fn().mockReturnThis(), innerJoin: vi.fn().mockReturnThis(), leftJoin: vi.fn().mockReturnThis(), orderBy: vi.fn().mockReturnThis(), insert: vi.fn().mockReturnThis(), values: vi.fn().mockReturnThis(), onConflictDoUpdate: vi.fn().mockReturnThis(), }; beforeEach(() => { vi.clearAllMocks(); (database as ReturnType).mockReturnValue(mockDb); mockDb.select.mockReturnValue(mockDb); mockDb.from.mockReturnValue(mockDb); mockDb.where.mockReturnValue(mockDb); mockDb.innerJoin.mockReturnValue(mockDb); mockDb.leftJoin.mockReturnValue(mockDb); mockDb.orderBy.mockReturnValue(mockDb); mockDb.insert.mockReturnValue(mockDb); mockDb.values.mockReturnValue(mockDb); mockDb.onConflictDoUpdate.mockResolvedValue(undefined); }); describe("getGolfSkillsMap", () => { it("returns an empty Map when no records exist", async () => { mockDb.where.mockResolvedValue([]); const result = await getGolfSkillsMap("season-1"); expect(result).toBeInstanceOf(Map); expect(result.size).toBe(0); }); it("returns a Map keyed by seasonParticipantId with sgTotal converted to number", async () => { mockDb.where.mockResolvedValue([ { seasonParticipantId: "sp-1", sportsSeasonId: "season-1", id: "skill-1", sgTotal: "2.50", datagolfRank: 3, mastersOdds: 800, usOpenOdds: null, openChampionshipOdds: null, pgaChampionshipOdds: null, updatedAt: new Date("2026-01-01"), }, ]); const result = await getGolfSkillsMap("season-1"); expect(result.size).toBe(1); const record = result.get("sp-1"); expect(record).toBeDefined(); expect(record?.sgTotal).toBe(2.5); expect(record?.participantId).toBe("sp-1"); expect(record?.mastersOdds).toBe(800); }); it("preserves null sgTotal", async () => { mockDb.where.mockResolvedValue([ { seasonParticipantId: "sp-1", sportsSeasonId: "season-1", id: "skill-1", sgTotal: null, datagolfRank: null, mastersOdds: null, usOpenOdds: null, openChampionshipOdds: null, pgaChampionshipOdds: null, updatedAt: new Date("2026-01-01"), }, ]); const result = await getGolfSkillsMap("season-1"); expect(result.get("sp-1")?.sgTotal).toBeNull(); }); }); describe("getGolfSkillsForSeason", () => { it("returns records joined with participant names and converts sgTotal", async () => { mockDb.orderBy.mockResolvedValue([ { id: "skill-1", participantId: "sp-1", sportsSeasonId: "season-1", sgTotal: "1.24", datagolfRank: 10, mastersOdds: 400, usOpenOdds: null, openChampionshipOdds: null, pgaChampionshipOdds: null, updatedAt: new Date("2026-01-01"), participantName: "Rory McIlroy", }, ]); const result = await getGolfSkillsForSeason("season-1"); expect(result).toHaveLength(1); expect(result[0].participantName).toBe("Rory McIlroy"); expect(result[0].sgTotal).toBe(1.24); expect(result[0].mastersOdds).toBe(400); }); it("returns empty array when no records exist", async () => { mockDb.orderBy.mockResolvedValue([]); const result = await getGolfSkillsForSeason("season-1"); expect(result).toEqual([]); }); }); describe("batchUpsertGolfSkills", () => { it("does nothing when given an empty array", async () => { await batchUpsertGolfSkills([]); expect(mockDb.insert).not.toHaveBeenCalled(); }); it("writes canonical rows using resolved canonical participant ids", async () => { mockDb.where.mockResolvedValueOnce([ { id: "sp-1", canonicalId: "canon-1" }, { id: "sp-2", canonicalId: "canon-2" }, ]); await batchUpsertGolfSkills([ { participantId: "sp-1", sgTotal: 2.5, mastersOdds: 400 }, { participantId: "sp-2", sgTotal: null, usOpenOdds: 800 }, ]); expect(mockDb.insert).toHaveBeenCalledOnce(); expect(mockDb.values).toHaveBeenCalledOnce(); expect(mockDb.onConflictDoUpdate).toHaveBeenCalledOnce(); const passedValues = mockDb.values.mock.calls[0][0] as Array<{ participantId: string; sgTotal: string | null; mastersOdds: number | null; usOpenOdds: number | null; }>; expect(passedValues).toHaveLength(2); expect(passedValues[0].participantId).toBe("canon-1"); expect(passedValues[0].sgTotal).toBe("2.5"); expect(passedValues[0].mastersOdds).toBe(400); expect(passedValues[1].participantId).toBe("canon-2"); expect(passedValues[1].sgTotal).toBeNull(); expect(passedValues[1].usOpenOdds).toBe(800); }); it("skips season_participants that have no canonical link", async () => { mockDb.where.mockResolvedValueOnce([]); await batchUpsertGolfSkills([ { participantId: "sp-1", sgTotal: 2.5 }, ]); expect(mockDb.insert).not.toHaveBeenCalled(); }); });