brackt/app/models/__tests__/participant.test.ts

153 lines
4.3 KiB
TypeScript
Raw Normal View History

import { describe, it, expect, vi, beforeEach } from "vitest";
vi.mock("~/database/context", () => ({
database: vi.fn(),
}));
import {
createCanonicalParticipant,
getCanonicalParticipantById,
findCanonicalParticipantsBySport,
findCanonicalParticipantBySportName,
upsertCanonicalParticipantBySportName,
} from "../participant";
import { database } from "~/database/context";
const SPORT_ID = "sport-1";
const PARTICIPANT_ID = "participant-1";
const SAMPLE_PARTICIPANT = {
id: PARTICIPANT_ID,
sportId: SPORT_ID,
name: "Novak Djokovic",
externalKey: "djokovic-n",
metadata: { atp_id: "12345" },
createdAt: new Date("2026-01-01T00:00:00Z"),
updatedAt: new Date("2026-01-01T00:00:00Z"),
};
function makeInsertDb(returnValue: object) {
return {
insert: vi.fn().mockReturnValue({
values: 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("createCanonicalParticipant", () => {
it("inserts a participant and returns it", async () => {
vi.mocked(database).mockReturnValue(makeInsertDb(SAMPLE_PARTICIPANT) as never);
const result = await createCanonicalParticipant({
sportId: SPORT_ID,
name: "Novak Djokovic",
});
expect(result).toEqual(SAMPLE_PARTICIPANT);
});
});
describe("getCanonicalParticipantById", () => {
it("returns the participant when found", async () => {
vi.mocked(database).mockReturnValue(makeSelectDb([SAMPLE_PARTICIPANT]) as never);
const result = await getCanonicalParticipantById(PARTICIPANT_ID);
expect(result).toEqual(SAMPLE_PARTICIPANT);
});
it("returns null when not found", async () => {
vi.mocked(database).mockReturnValue(makeSelectDb([]) as never);
const result = await getCanonicalParticipantById("nonexistent");
expect(result).toBeNull();
});
});
describe("findCanonicalParticipantsBySport", () => {
it("returns participants ordered by name", async () => {
const participants = [SAMPLE_PARTICIPANT];
vi.mocked(database).mockReturnValue(makeSelectDb(participants) as never);
const result = await findCanonicalParticipantsBySport(SPORT_ID);
expect(result).toEqual(participants);
});
});
describe("findCanonicalParticipantBySportName", () => {
it("returns the participant when found", async () => {
vi.mocked(database).mockReturnValue(makeSelectDb([SAMPLE_PARTICIPANT]) as never);
const result = await findCanonicalParticipantBySportName(SPORT_ID, "Novak Djokovic");
expect(result).toEqual(SAMPLE_PARTICIPANT);
});
it("returns null when not found", async () => {
vi.mocked(database).mockReturnValue(makeSelectDb([]) as never);
const result = await findCanonicalParticipantBySportName(SPORT_ID, "Roger Federer");
expect(result).toBeNull();
});
});
describe("upsertCanonicalParticipantBySportName", () => {
it("returns existing participant if found", async () => {
vi.mocked(database).mockReturnValue(makeSelectDb([SAMPLE_PARTICIPANT]) as never);
const result = await upsertCanonicalParticipantBySportName(SPORT_ID, "Novak Djokovic");
expect(result).toEqual(SAMPLE_PARTICIPANT);
});
it("creates new participant if not found", async () => {
let callCount = 0;
vi.mocked(database).mockImplementation(() => {
callCount++;
return (callCount === 1 ? makeSelectDb([]) : makeInsertDb(SAMPLE_PARTICIPANT)) as never;
});
const result = await upsertCanonicalParticipantBySportName(SPORT_ID, "Novak Djokovic");
expect(result).toEqual(SAMPLE_PARTICIPANT);
});
it("passes extra fields when creating", async () => {
let callCount = 0;
vi.mocked(database).mockImplementation(() => {
callCount++;
return (callCount === 1 ? makeSelectDb([]) : makeInsertDb(SAMPLE_PARTICIPANT)) as never;
});
const result = await upsertCanonicalParticipantBySportName(
SPORT_ID,
"Novak Djokovic",
{ externalKey: "djokovic-n" }
);
expect(result).toEqual(SAMPLE_PARTICIPANT);
});
});