import { describe, expect, it, vi } from "vitest"; vi.mock("../scoring-calculator", () => ({ recalculateAffectedLeagues: vi.fn(), })); vi.mock("../qualifying-points", async (importOriginal) => { const actual = await importOriginal(); return { ...(actual as Record), recalculateParticipantQP: vi.fn(), }; }); import { deleteScoringEvent } from "../scoring-event"; describe("deleteScoringEvent", () => { it("decrements majorsCompleted for a processed zero-QP qualifying event", async () => { const setCalls: unknown[] = []; const deleteChain = { where: vi.fn().mockResolvedValue(undefined) }; const updateChain = { set: vi.fn((values: unknown) => { setCalls.push(values); return { where: vi.fn().mockResolvedValue(undefined) }; }), }; const db = { query: { scoringEvents: { findFirst: vi.fn().mockResolvedValue({ id: "event-1", sportsSeasonId: "sports-season-1", eventType: "major_tournament", isQualifyingEvent: true, }), }, eventResults: { findMany: vi.fn().mockResolvedValue([ { seasonParticipantId: "participant-1", placement: 20, qualifyingPointsAwarded: "0.00", }, ]), }, sportsSeasons: { findFirst: vi.fn().mockResolvedValue({ id: "sports-season-1", majorsCompleted: 1, }), }, }, transaction: vi.fn(async (callback) => callback(db)), delete: vi.fn(() => deleteChain), update: vi.fn(() => updateChain), } as any; await deleteScoringEvent("event-1", db); expect(setCalls).toEqual( expect.arrayContaining([ expect.objectContaining({ majorsCompleted: 0 }), ]) ); }); describe("shared tournament handling", () => { // Builds a mock db for a non-qualifying schedule_event linked to a tournament, // so the delete skips the QP/league branches and exercises only the // shared-tournament bookkeeping. function makeSharedDb({ deletedEvent, remaining, siblingTournamentId = "tournament-1", }: { deletedEvent: { tournamentId: string | null; isPrimary: boolean }; remaining: Array<{ id: string; isPrimary: boolean }>; siblingTournamentId?: string; }) { const findFirst = vi .fn() // 1st call: the event being deleted .mockResolvedValueOnce({ id: "event-1", sportsSeasonId: "sports-season-1", eventType: "schedule_event", isQualifyingEvent: false, ...deletedEvent, }) // subsequent calls: setPrimaryEvent looking up the promoted event .mockResolvedValue({ id: "promoted", tournamentId: siblingTournamentId }); const deleteWhere = vi.fn().mockResolvedValue(undefined); const updateWhere = vi.fn().mockResolvedValue(undefined); const db = { query: { scoringEvents: { findFirst, findMany: vi.fn().mockResolvedValue(remaining), }, }, transaction: vi.fn(async (callback) => callback(db)), delete: vi.fn(() => ({ where: deleteWhere })), update: vi.fn(() => ({ set: vi.fn(() => ({ where: updateWhere })) })), } as any; return { db, deleteWhere }; } it("keeps the tournament and promotes nothing when a non-primary window is deleted", async () => { const { db } = makeSharedDb({ deletedEvent: { tournamentId: "tournament-1", isPrimary: false }, remaining: [{ id: "event-2", isPrimary: true }], }); const result = await deleteScoringEvent("event-1", db); expect(result.remainingWindows).toBe(1); expect(result.promotedPrimaryId).toBeNull(); expect(result.deletedTournament).toBe(false); }); it("does not promote a primary when a golf-style tournament (no primary) loses a window", async () => { // Golf-style shared majors intentionally have no primary window — every // linked event is isPrimary=false. Deleting one must not flip a sibling // into a primary, which would change its scoring/guard behavior. const { db } = makeSharedDb({ deletedEvent: { tournamentId: "tournament-1", isPrimary: false }, remaining: [ { id: "event-2", isPrimary: false }, { id: "event-3", isPrimary: false }, ], }); const result = await deleteScoringEvent("event-1", db); expect(result.promotedPrimaryId).toBeNull(); expect(result.remainingWindows).toBe(2); }); it("promotes the earliest remaining window when the primary window is deleted", async () => { const { db } = makeSharedDb({ deletedEvent: { tournamentId: "tournament-1", isPrimary: true }, // findMany is ordered asc(createdAt); first is the earliest. remaining: [ { id: "event-2", isPrimary: false }, { id: "event-3", isPrimary: false }, ], }); const result = await deleteScoringEvent("event-1", db); expect(result.promotedPrimaryId).toBe("event-2"); expect(result.remainingWindows).toBe(2); }); it("leaves the orphaned tournament intact when the last window is deleted without the flag", async () => { const { db } = makeSharedDb({ deletedEvent: { tournamentId: "tournament-1", isPrimary: true }, remaining: [], }); const result = await deleteScoringEvent("event-1", db); expect(result.remainingWindows).toBe(0); expect(result.deletedTournament).toBe(false); }); it("deletes the orphaned tournament when the last window is deleted with the flag", async () => { const { db } = makeSharedDb({ deletedEvent: { tournamentId: "tournament-1", isPrimary: true }, remaining: [], }); const result = await deleteScoringEvent("event-1", db, { deleteOrphanTournament: true, }); expect(result.deletedTournament).toBe(true); }); }); });