import { describe, it, expect, vi, beforeEach } from "vitest"; // Mock the database context before importing any model vi.mock("~/database/context", () => ({ database: vi.fn(), })); import { database } from "~/database/context"; import { batchSaveFuturesOddsForSimulator } from "../simulator"; type SetPayload = Record; const conflictSetCalls: SetPayload[] = []; const onConflictDoUpdate = vi.fn((arg: { set: SetPayload }) => { conflictSetCalls.push(arg.set); return Promise.resolve(undefined); }); const mockDb = { insert: vi.fn(() => ({ values: vi.fn(() => ({ onConflictDoUpdate })), })), }; beforeEach(() => { vi.clearAllMocks(); conflictSetCalls.length = 0; (database as ReturnType).mockReturnValue(mockDb); }); describe("batchSaveFuturesOddsForSimulator", () => { it("persists odds without destroying a stored Elo/rating", async () => { await batchSaveFuturesOddsForSimulator([ { participantId: "team-1", sportsSeasonId: "season-1", sourceOdds: 550 }, ]); // The upsert writes the odds and leaves Elo/rating untouched — whether the // odds override them is now decided by the configurable source priority, // not by nulling stored values here. expect(mockDb.insert).toHaveBeenCalledTimes(1); expect(conflictSetCalls).toHaveLength(1); expect(conflictSetCalls[0]).toHaveProperty("sourceOdds"); expect(conflictSetCalls[0]).not.toHaveProperty("sourceElo"); expect(conflictSetCalls[0]).not.toHaveProperty("rating"); }); it("is a no-op when given no inputs", async () => { await batchSaveFuturesOddsForSimulator([]); expect(mockDb.insert).not.toHaveBeenCalled(); }); });