import { beforeAll, describe, expect, it } from "vitest"; import { fetchSchedule, type ScheduleGame, } from "../../src/kbo/schedule"; // 실제 KBO `fetchSchedule` (cli `npx tsx src/kbo/cli.ts schedule 2026 4 --json`이 쓰는 동일 경로)을 // 호출하여, 알려진 회귀 케이스가 정확히 파싱되는지 검증한다. 과거 경기는 결과가 불변이라 결정론적. const TIMEOUT_MS = 30_000; describe("fetchSchedule (실제 KBO 호출) — 케이스별 회귀", () => { let april: ScheduleGame[]; let may: ScheduleGame[]; beforeAll(async () => { [april, may] = await Promise.all([ fetchSchedule({ year: 2026, month: 4 }).then((r) => r.games), fetchSchedule({ year: 2026, month: 5 }).then((r) => r.games), ]); }, TIMEOUT_MS); function find(games: ScheduleGame[], gameId: string): ScheduleGame { const g = games.find((x) => x.gameId === gameId); if (!g) throw new Error(`gameId ${gameId} not found in fetched schedule`); return g; } it("win/lose: 20260401LTNC0 (LT 4 @ NC 5) → completed, score 정확", () => { const g = find(april, "20260401LTNC0"); expect(g.status).toBe("completed"); expect(g.awayTeamCode).toBe("LT"); expect(g.homeTeamCode).toBe("NC"); expect(g.awayScore).toBe(4); expect(g.homeScore).toBe(5); expect(g.note).toBe("-"); }); it("draw(4월): 20260426LTHT0 (LT 5 @ HT 5) → completed, 동점 score 파싱 (parsePlayCell 회귀)", () => { const g = find(april, "20260426LTHT0"); expect(g.status).toBe("completed"); expect(g.awayTeamCode).toBe("LT"); expect(g.homeTeamCode).toBe("HT"); expect(g.awayScore).toBe(5); expect(g.homeScore).toBe(5); }); it("draw(5월): 20260505NCSK0 (NC 7 @ SSG 7) → completed, 동점 score 파싱", () => { const g = find(may, "20260505NCSK0"); expect(g.status).toBe("completed"); expect(g.awayTeamCode).toBe("NC"); expect(g.homeTeamCode).toBe("SK"); expect(g.awayScore).toBe(7); expect(g.homeScore).toBe(7); }); it("cancelled: 20260409WOOB0 (우천취소) → status=cancelled, score=null", () => { const g = find(april, "20260409WOOB0"); expect(g.status).toBe("cancelled"); expect(g.awayTeamCode).toBe("WO"); expect(g.homeTeamCode).toBe("OB"); expect(g.awayScore).toBeNull(); expect(g.homeScore).toBeNull(); expect(g.note).toContain("우천"); }); it("scheduled(미래): 20260507OBLG0 → status=scheduled, score=null", () => { const g = find(may, "20260507OBLG0"); expect(g.status).toBe("scheduled"); expect(g.awayScore).toBeNull(); expect(g.homeScore).toBeNull(); }); it("4월 모든 completed 경기: score는 null 아님 (무승부 포함 회귀)", () => { const completed = april.filter((g) => g.status === "completed"); expect(completed.length).toBeGreaterThan(0); for (const g of completed) { expect(g.awayScore, `${g.gameId} awayScore`).not.toBeNull(); expect(g.homeScore, `${g.gameId} homeScore`).not.toBeNull(); } }); it("4월 모든 cancelled 경기: score는 null이어야 함", () => { const cancelled = april.filter((g) => g.status === "cancelled"); expect(cancelled.length).toBeGreaterThan(0); for (const g of cancelled) { expect(g.awayScore, `${g.gameId} awayScore`).toBeNull(); expect(g.homeScore, `${g.gameId} homeScore`).toBeNull(); } }); });