/** * Tests for getEventsForDates — the admin dashboard "Games to Score" query. */ import { describe, it, expect, vi, beforeEach } from "vitest"; // ── DB mock ───────────────────────────────────────────────────────────────── const mockFindMany = vi.fn(); const mockDb = { query: { scoringEvents: { findMany: mockFindMany }, }, }; vi.mock("~/database/context", () => ({ database: () => mockDb, })); vi.mock("~/database/schema", () => ({ scoringEvents: { eventDate: "se.event_date", eventType: "se.event_type", eventStartsAt: "se.event_starts_at", createdAt: "se.created_at", }, })); vi.mock("drizzle-orm", () => ({ eq: (col: unknown, val: unknown) => ({ type: "eq", col, val }), and: (...args: unknown[]) => ({ type: "and", args }), asc: (col: unknown) => ({ type: "asc", col }), desc: (col: unknown) => ({ type: "desc", col }), gte: (col: unknown, val: unknown) => ({ type: "gte", col, val }), lte: (col: unknown, val: unknown) => ({ type: "lte", col, val }), or: (...args: unknown[]) => ({ type: "or", args }), inArray: (col: unknown, arr: unknown) => ({ type: "inArray", col, arr }), isNotNull: (col: unknown) => ({ type: "isNotNull", col }), })); // Must be imported after mocks are registered import { getEventsForDates } from "../scoring-event"; // ── Helpers ────────────────────────────────────────────────────────────────── function makeScoringEventRow(overrides: Partial<{ id: string; name: string; eventDate: string | null; eventStartsAt: Date | null; eventType: string; isComplete: boolean; completedAt: Date | null; sportsSeasonId: string; sportsSeason: { name: string; sport: { name: string; slug: string | null } }; }> = {}) { return { id: overrides.id ?? "event-1", name: overrides.name ?? "Test Event", eventDate: overrides.eventDate ?? "2026-03-20", eventStartsAt: overrides.eventStartsAt ?? null, eventType: overrides.eventType ?? "playoff_game", isComplete: overrides.isComplete ?? false, completedAt: overrides.completedAt ?? null, sportsSeasonId: overrides.sportsSeasonId ?? "season-1", sportsSeason: overrides.sportsSeason ?? { name: "2026 NFL Playoffs", sport: { name: "NFL", slug: "nfl" }, }, }; } // ── Tests ──────────────────────────────────────────────────────────────────── describe("getEventsForDates", () => { beforeEach(() => { mockFindMany.mockReset(); }); it("returns an empty array when no dates are provided", async () => { const result = await getEventsForDates([]); expect(result).toEqual([]); expect(mockFindMany).not.toHaveBeenCalled(); }); it("maps database rows to DashboardScoringEvent shape", async () => { const row = makeScoringEventRow({ id: "e1", name: "Conference Finals", eventDate: "2026-03-20", eventType: "playoff_game", isComplete: false, sportsSeasonId: "ss-1", sportsSeason: { name: "2026 NBA Playoffs", sport: { name: "NBA", slug: "nba" }, }, }); mockFindMany.mockResolvedValueOnce([row]); const result = await getEventsForDates(["2026-03-20"]); expect(result).toHaveLength(1); expect(result[0]).toMatchObject({ id: "e1", name: "Conference Finals", eventDate: "2026-03-20", eventType: "playoff_game", isComplete: false, sportsSeasonId: "ss-1", sportsSeasonName: "2026 NBA Playoffs", sportName: "NBA", sportSlug: "nba", }); }); it("returns events for multiple dates", async () => { const todayRow = makeScoringEventRow({ id: "e1", eventDate: "2026-03-20" }); const tomorrowRow = makeScoringEventRow({ id: "e2", eventDate: "2026-03-21" }); mockFindMany.mockResolvedValueOnce([todayRow, tomorrowRow]); const result = await getEventsForDates(["2026-03-20", "2026-03-21"]); expect(result).toHaveLength(2); expect(result.map((e) => e.id)).toEqual(["e1", "e2"]); }); it("includes completed events with isComplete: true", async () => { const completedRow = makeScoringEventRow({ id: "e-done", isComplete: true, completedAt: new Date("2026-03-20T18:00:00Z"), }); mockFindMany.mockResolvedValueOnce([completedRow]); const result = await getEventsForDates(["2026-03-20"]); expect(result[0].isComplete).toBe(true); expect(result[0].completedAt).toBeInstanceOf(Date); }); it("includes eventStartsAt when present", async () => { const starts = new Date("2026-03-20T19:30:00Z"); const row = makeScoringEventRow({ id: "e1", eventStartsAt: starts }); mockFindMany.mockResolvedValueOnce([row]); const result = await getEventsForDates(["2026-03-20"]); expect(result[0].eventStartsAt).toEqual(starts); }); it("passes both dates as an inArray condition to the query", async () => { mockFindMany.mockResolvedValueOnce([]); await getEventsForDates(["2026-03-20", "2026-03-21"]); const callArgs = mockFindMany.mock.calls[0][0]; // The where clause should contain an inArray condition with both dates const whereStr = JSON.stringify(callArgs.where); expect(whereStr).toContain("2026-03-20"); expect(whereStr).toContain("2026-03-21"); }); it("excludes schedule_event types via inArray condition", async () => { mockFindMany.mockResolvedValueOnce([]); await getEventsForDates(["2026-03-20"]); const callArgs = mockFindMany.mock.calls[0][0]; const whereStr = JSON.stringify(callArgs.where); // The allowed event types should be present expect(whereStr).toContain("playoff_game"); expect(whereStr).toContain("major_tournament"); expect(whereStr).toContain("final_standings"); // schedule_event should not appear expect(whereStr).not.toContain("schedule_event"); }); it("returns empty array when DB returns no rows", async () => { mockFindMany.mockResolvedValueOnce([]); const result = await getEventsForDates(["2026-03-20"]); expect(result).toEqual([]); }); });