import { describe, it, expect, vi, beforeEach } from "vitest"; vi.mock("~/database/context", () => ({ database: vi.fn(), })); vi.mock("~/database/schema", () => ({ sportsSeasonTournaments: { sportsSeasonId: "sst.sports_season_id", tournamentId: "sst.tournament_id", }, })); vi.mock("drizzle-orm", () => ({ eq: (col: unknown, val: unknown) => ({ type: "eq", col, val }), and: (...args: unknown[]) => ({ type: "and", args }), })); vi.mock("~/models/tournament", () => ({ getTournamentById: vi.fn(), })); vi.mock("~/models/sports-season", () => ({ findSportsSeasonById: vi.fn(), })); import { linkTournamentToSportsSeason, unlinkTournamentFromSportsSeason, } from "../sports-season-tournament"; import { database } from "~/database/context"; import { getTournamentById } from "~/models/tournament"; import { findSportsSeasonById } from "~/models/sports-season"; const SPORT_ID = "sport-1"; const SPORTS_SEASON_ID = "ss-1"; const TOURNAMENT_ID = "t-1"; const mockSportsSeason = { id: SPORTS_SEASON_ID, sportId: SPORT_ID, name: "2026 Tennis", year: 2026, startDate: null, endDate: null, status: "active" as const, scoringType: "majors" as const, scoringPattern: "qualifying_points", totalMajors: 4, majorsCompleted: 0, qualifyingPointsFinalized: false, eloCalibrationExponent: null, eloMinRating: null, eloMaxRating: null, simulationStatus: "idle" as const, draftOn: "2026-01-01", draftOff: "2026-12-31", createdAt: new Date(), updatedAt: new Date(), }; const mockTournament = { id: TOURNAMENT_ID, sportId: SPORT_ID, name: "Wimbledon", year: 2026, startsAt: null, endsAt: null, surface: "grass", location: "London", status: "scheduled" as const, externalKey: null, createdAt: new Date(), updatedAt: new Date(), }; function makeInsertDb(returnValue: object) { return { insert: vi.fn().mockReturnValue({ values: vi.fn().mockReturnValue({ returning: vi.fn().mockResolvedValue([returnValue]), }), }), }; } function makeDeleteDb() { return { delete: vi.fn().mockReturnValue({ where: vi.fn().mockResolvedValue(undefined), }), }; } beforeEach(() => { vi.clearAllMocks(); }); describe("linkTournamentToSportsSeason", () => { it("links a tournament to a sports season when sports match", async () => { vi.mocked(findSportsSeasonById).mockResolvedValue(mockSportsSeason as never); vi.mocked(getTournamentById).mockResolvedValue(mockTournament as never); const link = { id: "link-1", sportsSeasonId: SPORTS_SEASON_ID, tournamentId: TOURNAMENT_ID, createdAt: new Date() }; vi.mocked(database).mockReturnValue(makeInsertDb(link) as never); const result = await linkTournamentToSportsSeason(SPORTS_SEASON_ID, TOURNAMENT_ID); expect(result).toEqual(link); }); it("throws when sports season not found", async () => { vi.mocked(findSportsSeasonById).mockResolvedValue(undefined as never); vi.mocked(getTournamentById).mockResolvedValue(mockTournament as never); await expect( linkTournamentToSportsSeason(SPORTS_SEASON_ID, TOURNAMENT_ID) ).rejects.toThrow("Sports season ss-1 not found"); }); it("throws when tournament not found", async () => { vi.mocked(findSportsSeasonById).mockResolvedValue(mockSportsSeason as never); vi.mocked(getTournamentById).mockResolvedValue(null as never); await expect( linkTournamentToSportsSeason(SPORTS_SEASON_ID, TOURNAMENT_ID) ).rejects.toThrow("Tournament t-1 not found"); }); it("throws when tournament and sports season belong to different sports", async () => { vi.mocked(findSportsSeasonById).mockResolvedValue(mockSportsSeason as never); vi.mocked(getTournamentById).mockResolvedValue({ ...mockTournament, sportId: "different-sport" } as never); await expect( linkTournamentToSportsSeason(SPORTS_SEASON_ID, TOURNAMENT_ID) ).rejects.toThrow("Tournament and sports season must belong to the same sport"); }); }); describe("unlinkTournamentFromSportsSeason", () => { it("deletes the link", async () => { vi.mocked(database).mockReturnValue(makeDeleteDb() as never); await unlinkTournamentFromSportsSeason(SPORTS_SEASON_ID, TOURNAMENT_ID); const db = vi.mocked(database).mock.results[0].value; expect(db.delete).toHaveBeenCalled(); }); });