brackt/app/models/__tests__/tournament-result.test.ts
Chris Parsons 5a47300110
feat(models): add canonical tournament, participant, result, surface-elo models
Adds CRUD modules for the canonical tables created in commit 775b905.
Each module mirrors existing app/models conventions (database() from
~/database/context, schema from ~/database/schema, mock-based tests).

Key implementation notes:
- participant.ts exports use "Canonical" prefix (CanonicalParticipant,
  createCanonicalParticipant, etc.) to avoid collision with existing
  season-participant.ts exports
- All four models include comprehensive unit tests following the
  audit-log.test.ts pattern
- Tests use mocked db responses (no real database access)
- Upsert functions use onConflictDoUpdate for appropriate unique constraints

Part of Phase 1b of canonical tournament layer migration.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 20:16:53 +00:00

114 lines
3 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from "vitest";
vi.mock("~/database/context", () => ({
database: vi.fn(),
}));
import {
upsertTournamentResult,
getTournamentResults,
getTournamentResultByParticipant,
} from "../tournament-result";
import { database } from "~/database/context";
const TOURNAMENT_ID = "tournament-1";
const PARTICIPANT_ID = "participant-1";
const SAMPLE_RESULT = {
id: "result-1",
tournamentId: TOURNAMENT_ID,
participantId: PARTICIPANT_ID,
placement: 1,
rawScore: "7500.00",
createdAt: new Date("2026-01-28T00:00:00Z"),
updatedAt: new Date("2026-01-28T00:00:00Z"),
};
function makeUpsertDb(returnValue: object) {
return {
insert: vi.fn().mockReturnValue({
values: vi.fn().mockReturnValue({
onConflictDoUpdate: vi.fn().mockReturnValue({
returning: vi.fn().mockResolvedValue([returnValue]),
}),
}),
}),
};
}
function makeSelectDb(rows: object[]) {
return {
select: vi.fn().mockReturnValue({
from: vi.fn().mockReturnValue({
where: vi.fn().mockReturnValue({
limit: vi.fn().mockResolvedValue(rows),
orderBy: vi.fn().mockResolvedValue(rows),
}),
}),
}),
};
}
beforeEach(() => {
vi.clearAllMocks();
});
describe("upsertTournamentResult", () => {
it("inserts or updates a result", async () => {
vi.mocked(database).mockReturnValue(makeUpsertDb(SAMPLE_RESULT) as never);
const result = await upsertTournamentResult({
tournamentId: TOURNAMENT_ID,
participantId: PARTICIPANT_ID,
placement: 1,
rawScore: "7500.00",
});
expect(result).toEqual(SAMPLE_RESULT);
});
it("uses onConflictDoUpdate on tournamentId and participantId", async () => {
const mockDb = makeUpsertDb(SAMPLE_RESULT);
vi.mocked(database).mockReturnValue(mockDb as never);
await upsertTournamentResult({
tournamentId: TOURNAMENT_ID,
participantId: PARTICIPANT_ID,
placement: 1,
});
const onConflictCall = (mockDb.insert as ReturnType<typeof vi.fn>)
.mock.results[0].value.values.mock.results[0].value.onConflictDoUpdate;
expect(onConflictCall).toHaveBeenCalled();
});
});
describe("getTournamentResults", () => {
it("returns results ordered by placement", async () => {
const results = [SAMPLE_RESULT];
vi.mocked(database).mockReturnValue(makeSelectDb(results) as never);
const result = await getTournamentResults(TOURNAMENT_ID);
expect(result).toEqual(results);
});
});
describe("getTournamentResultByParticipant", () => {
it("returns the result when found", async () => {
vi.mocked(database).mockReturnValue(makeSelectDb([SAMPLE_RESULT]) as never);
const result = await getTournamentResultByParticipant(TOURNAMENT_ID, PARTICIPANT_ID);
expect(result).toEqual(SAMPLE_RESULT);
});
it("returns null when not found", async () => {
vi.mocked(database).mockReturnValue(makeSelectDb([]) as never);
const result = await getTournamentResultByParticipant(TOURNAMENT_ID, "nonexistent");
expect(result).toBeNull();
});
});