235 lines
7.1 KiB
TypeScript
235 lines
7.1 KiB
TypeScript
|
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||
|
|
|
||
|
|
vi.mock("~/database/context", () => ({
|
||
|
|
database: vi.fn(),
|
||
|
|
}));
|
||
|
|
|
||
|
|
import {
|
||
|
|
upsertSeasonMatch,
|
||
|
|
upsertSeasonMatchBulk,
|
||
|
|
upsertMatchSubGame,
|
||
|
|
} from "../season-match";
|
||
|
|
import { database } from "~/database/context";
|
||
|
|
|
||
|
|
const SPORTS_SEASON_ID = "ss-1";
|
||
|
|
const SCORING_EVENT_ID = "evt-1";
|
||
|
|
const P1_ID = "p1";
|
||
|
|
const P2_ID = "p2";
|
||
|
|
const WINNER_ID = "p1";
|
||
|
|
const EXTERNAL_ID = "panda_123";
|
||
|
|
|
||
|
|
function makeUpsertDb(returnValue: object) {
|
||
|
|
const returningFn = vi.fn().mockResolvedValue([returnValue]);
|
||
|
|
const onConflictFn = vi.fn().mockReturnValue({ returning: returningFn });
|
||
|
|
const valuesFn = vi.fn().mockReturnValue({ onConflictDoUpdate: onConflictFn });
|
||
|
|
return {
|
||
|
|
insert: vi.fn().mockReturnValue({ values: valuesFn }),
|
||
|
|
_returning: returningFn,
|
||
|
|
_onConflict: onConflictFn,
|
||
|
|
_values: valuesFn,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
function makeBulkUpsertDb(returnValues: object[]) {
|
||
|
|
const returningFn = vi.fn().mockResolvedValue(returnValues);
|
||
|
|
const onConflictFn = vi.fn().mockReturnValue({ returning: returningFn });
|
||
|
|
const valuesFn = vi.fn().mockReturnValue({ onConflictDoUpdate: onConflictFn });
|
||
|
|
return {
|
||
|
|
insert: vi.fn().mockReturnValue({ values: valuesFn }),
|
||
|
|
_returning: returningFn,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
const SAMPLE_MATCH = {
|
||
|
|
id: "match-1",
|
||
|
|
sportsSeasonId: SPORTS_SEASON_ID,
|
||
|
|
scoringEventId: SCORING_EVENT_ID,
|
||
|
|
participant1Id: P1_ID,
|
||
|
|
participant2Id: P2_ID,
|
||
|
|
winnerId: WINNER_ID,
|
||
|
|
participant1Score: 2,
|
||
|
|
participant2Score: 1,
|
||
|
|
matchStage: 1,
|
||
|
|
matchRound: 3,
|
||
|
|
matchday: null,
|
||
|
|
isSeries: true,
|
||
|
|
status: "complete" as const,
|
||
|
|
scheduledAt: null,
|
||
|
|
startedAt: null,
|
||
|
|
completedAt: new Date("2025-01-15T14:00:00Z"),
|
||
|
|
externalMatchId: EXTERNAL_ID,
|
||
|
|
createdAt: new Date(),
|
||
|
|
updatedAt: new Date(),
|
||
|
|
};
|
||
|
|
|
||
|
|
describe("upsertSeasonMatch", () => {
|
||
|
|
beforeEach(() => {
|
||
|
|
vi.clearAllMocks();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("inserts a match and returns it", async () => {
|
||
|
|
const mockDb = makeUpsertDb(SAMPLE_MATCH);
|
||
|
|
vi.mocked(database).mockReturnValue(mockDb as unknown as ReturnType<typeof database>);
|
||
|
|
|
||
|
|
const result = await upsertSeasonMatch({
|
||
|
|
sportsSeasonId: SPORTS_SEASON_ID,
|
||
|
|
scoringEventId: SCORING_EVENT_ID,
|
||
|
|
participant1Id: P1_ID,
|
||
|
|
participant2Id: P2_ID,
|
||
|
|
winnerId: WINNER_ID,
|
||
|
|
participant1Score: 2,
|
||
|
|
participant2Score: 1,
|
||
|
|
matchStage: 1,
|
||
|
|
matchRound: 3,
|
||
|
|
isSeries: true,
|
||
|
|
status: "complete",
|
||
|
|
completedAt: new Date("2025-01-15T14:00:00Z"),
|
||
|
|
externalMatchId: EXTERNAL_ID,
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(result.id).toBe("match-1");
|
||
|
|
expect(result.matchStage).toBe(1);
|
||
|
|
expect(result.matchRound).toBe(3);
|
||
|
|
expect(result.status).toBe("complete");
|
||
|
|
expect(mockDb.insert).toHaveBeenCalledOnce();
|
||
|
|
expect(mockDb._values).toHaveBeenCalledOnce();
|
||
|
|
expect(mockDb._onConflict).toHaveBeenCalledOnce();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("defaults isSeries to false when not provided", async () => {
|
||
|
|
const expectedMatch = { ...SAMPLE_MATCH, isSeries: false };
|
||
|
|
const mockDb = makeUpsertDb(expectedMatch);
|
||
|
|
vi.mocked(database).mockReturnValue(mockDb as unknown as ReturnType<typeof database>);
|
||
|
|
|
||
|
|
const result = await upsertSeasonMatch({
|
||
|
|
sportsSeasonId: SPORTS_SEASON_ID,
|
||
|
|
externalMatchId: "ext_1",
|
||
|
|
status: "scheduled",
|
||
|
|
});
|
||
|
|
|
||
|
|
const valuesCall = mockDb._values.mock.calls[0][0];
|
||
|
|
expect(valuesCall.isSeries).toBe(false);
|
||
|
|
expect(result.isSeries).toBe(false);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("allows null matchStage and matchRound for non-CS2 sports", async () => {
|
||
|
|
const mlbMatch = { ...SAMPLE_MATCH, matchStage: null, matchRound: null, matchday: null, isSeries: false };
|
||
|
|
const mockDb = makeUpsertDb(mlbMatch);
|
||
|
|
vi.mocked(database).mockReturnValue(mockDb as unknown as ReturnType<typeof database>);
|
||
|
|
|
||
|
|
const result = await upsertSeasonMatch({
|
||
|
|
sportsSeasonId: SPORTS_SEASON_ID,
|
||
|
|
externalMatchId: "mlb_game_456",
|
||
|
|
status: "complete",
|
||
|
|
participant1Score: 5,
|
||
|
|
participant2Score: 3,
|
||
|
|
});
|
||
|
|
|
||
|
|
const valuesCall = mockDb._values.mock.calls[0][0];
|
||
|
|
expect(valuesCall.matchStage).toBeUndefined();
|
||
|
|
expect(valuesCall.matchRound).toBeUndefined();
|
||
|
|
expect(result.matchStage).toBeNull();
|
||
|
|
expect(result.matchRound).toBeNull();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("upsertSeasonMatchBulk", () => {
|
||
|
|
beforeEach(() => {
|
||
|
|
vi.clearAllMocks();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("returns empty array for empty input", async () => {
|
||
|
|
vi.mocked(database).mockReturnValue({} as ReturnType<typeof database>);
|
||
|
|
const result = await upsertSeasonMatchBulk([]);
|
||
|
|
expect(result).toEqual([]);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("bulk upserts multiple matches", async () => {
|
||
|
|
const match2 = { ...SAMPLE_MATCH, id: "match-2", matchRound: 4, externalMatchId: "panda_456" };
|
||
|
|
const mockDb = makeBulkUpsertDb([SAMPLE_MATCH, match2]);
|
||
|
|
vi.mocked(database).mockReturnValue(mockDb as unknown as ReturnType<typeof database>);
|
||
|
|
|
||
|
|
const result = await upsertSeasonMatchBulk([
|
||
|
|
{ sportsSeasonId: SPORTS_SEASON_ID, externalMatchId: EXTERNAL_ID, status: "complete", matchStage: 1, matchRound: 3 },
|
||
|
|
{ sportsSeasonId: SPORTS_SEASON_ID, externalMatchId: "panda_456", status: "complete", matchStage: 1, matchRound: 4 },
|
||
|
|
]);
|
||
|
|
|
||
|
|
expect(result).toHaveLength(2);
|
||
|
|
expect(mockDb.insert).toHaveBeenCalledOnce();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("upsertMatchSubGame", () => {
|
||
|
|
beforeEach(() => {
|
||
|
|
vi.clearAllMocks();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("upserts a map sub-game", async () => {
|
||
|
|
const subGame = {
|
||
|
|
id: "sg-1",
|
||
|
|
seasonMatchId: "match-1",
|
||
|
|
gameNumber: 1,
|
||
|
|
gameLabel: "Mirage",
|
||
|
|
participant1Score: 16,
|
||
|
|
participant2Score: 14,
|
||
|
|
winnerId: P1_ID,
|
||
|
|
status: "complete" as const,
|
||
|
|
startedAt: null,
|
||
|
|
completedAt: new Date(),
|
||
|
|
externalGameId: "map_1",
|
||
|
|
createdAt: new Date(),
|
||
|
|
updatedAt: new Date(),
|
||
|
|
};
|
||
|
|
const mockDb = makeUpsertDb(subGame);
|
||
|
|
vi.mocked(database).mockReturnValue(mockDb as unknown as ReturnType<typeof database>);
|
||
|
|
|
||
|
|
const result = await upsertMatchSubGame({
|
||
|
|
seasonMatchId: "match-1",
|
||
|
|
gameNumber: 1,
|
||
|
|
gameLabel: "Mirage",
|
||
|
|
participant1Score: 16,
|
||
|
|
participant2Score: 14,
|
||
|
|
winnerId: P1_ID,
|
||
|
|
status: "complete",
|
||
|
|
externalGameId: "map_1",
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(result.gameLabel).toBe("Mirage");
|
||
|
|
expect(result.participant1Score).toBe(16);
|
||
|
|
expect(result.gameNumber).toBe(1);
|
||
|
|
expect(mockDb.insert).toHaveBeenCalledOnce();
|
||
|
|
expect(mockDb._onConflict).toHaveBeenCalledOnce();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("allows null gameLabel for non-named sub-games", async () => {
|
||
|
|
const subGame = {
|
||
|
|
id: "sg-2",
|
||
|
|
seasonMatchId: "match-1",
|
||
|
|
gameNumber: 2,
|
||
|
|
gameLabel: null,
|
||
|
|
participant1Score: 3,
|
||
|
|
participant2Score: 1,
|
||
|
|
winnerId: P1_ID,
|
||
|
|
status: "complete" as const,
|
||
|
|
startedAt: null,
|
||
|
|
completedAt: new Date(),
|
||
|
|
externalGameId: null,
|
||
|
|
createdAt: new Date(),
|
||
|
|
updatedAt: new Date(),
|
||
|
|
};
|
||
|
|
const mockDb = makeUpsertDb(subGame);
|
||
|
|
vi.mocked(database).mockReturnValue(mockDb as unknown as ReturnType<typeof database>);
|
||
|
|
|
||
|
|
const result = await upsertMatchSubGame({
|
||
|
|
seasonMatchId: "match-1",
|
||
|
|
gameNumber: 2,
|
||
|
|
participant1Score: 3,
|
||
|
|
participant2Score: 1,
|
||
|
|
status: "complete",
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(result.gameLabel).toBeNull();
|
||
|
|
expect(result.gameNumber).toBe(2);
|
||
|
|
});
|
||
|
|
});
|