import { describe, it, expect } from "vitest"; import { debateReducer, createInitialDebateState } from "./engine"; import type { DebateConfig, DebateTopic, RoundData, DebateVerdict } from "./types"; const mockConfig: DebateConfig = { durationMinutes: 3, rounds: 4, timePerTurn: 45 }; const mockTopic: DebateTopic = { id: "t1", topic: "Climate Policy", question: "Should carbon taxes be mandatory?", category: "environment", heatLevel: 4, }; describe("debateReducer", () => { it("starts in idle phase", () => { const state = createInitialDebateState(); expect(state.phase).toBe("idle"); expect(state.rounds).toEqual([]); expect(state.currentRound).toBe(0); }); it("transitions to config phase on SET_CONFIG", () => { let state = createInitialDebateState(); state = debateReducer(state, { type: "SET_CONFIG", config: mockConfig }); expect(state.phase).toBe("config"); expect(state.config).toEqual(mockConfig); }); it("transitions to topic-select on SET_TOPICS", () => { let state = createInitialDebateState(); state = debateReducer(state, { type: "SET_CONFIG", config: mockConfig }); state = debateReducer(state, { type: "SET_TOPICS", topics: [mockTopic] }); expect(state.phase).toBe("topic-select"); expect(state.topicOptions).toHaveLength(1); }); it("records vote on VOTE_TOPIC", () => { let state = createInitialDebateState(); state = debateReducer(state, { type: "SET_CONFIG", config: mockConfig }); state = debateReducer(state, { type: "SET_TOPICS", topics: [mockTopic] }); state = debateReducer(state, { type: "VOTE_TOPIC", topicId: "t1" }); expect(state.myVote).toBe("t1"); }); it("transitions to round phase on SELECT_TOPIC", () => { let state = createInitialDebateState(); state = debateReducer(state, { type: "SET_CONFIG", config: mockConfig }); state = debateReducer(state, { type: "SET_TOPICS", topics: [mockTopic] }); state = debateReducer(state, { type: "SELECT_TOPIC", topic: mockTopic }); expect(state.phase).toBe("round-open"); expect(state.selectedTopic).toEqual(mockTopic); expect(state.currentRound).toBe(1); }); it("tracks argument text on UPDATE_ARGUMENT", () => { let state = createInitialDebateState(); state = debateReducer(state, { type: "SET_CONFIG", config: mockConfig }); state = debateReducer(state, { type: "SET_TOPICS", topics: [mockTopic] }); state = debateReducer(state, { type: "SELECT_TOPIC", topic: mockTopic }); state = debateReducer(state, { type: "UPDATE_ARGUMENT", text: "My argument" }); expect(state.myArgument).toBe("My argument"); }); it("transitions to commentary on COMPLETE_ROUND", () => { let state = createInitialDebateState(); state = debateReducer(state, { type: "SET_CONFIG", config: mockConfig }); state = debateReducer(state, { type: "SET_TOPICS", topics: [mockTopic] }); state = debateReducer(state, { type: "SELECT_TOPIC", topic: mockTopic }); const round: RoundData = { roundNumber: 1, openerId: "p1", openerArgument: "arg1", rebuttalArgument: "arg2", openerFactCheck: [], rebuttalFactCheck: [], commentary: null, }; state = debateReducer(state, { type: "COMPLETE_ROUND", round }); expect(state.phase).toBe("commentary"); expect(state.rounds).toHaveLength(1); }); it("advances round on START_ROUND after complete", () => { let state = createInitialDebateState(); state = debateReducer(state, { type: "SET_CONFIG", config: mockConfig }); state = debateReducer(state, { type: "SET_TOPICS", topics: [mockTopic] }); state = debateReducer(state, { type: "SELECT_TOPIC", topic: mockTopic }); const round: RoundData = { roundNumber: 1, openerId: "p1", openerArgument: "arg1", rebuttalArgument: "arg2", openerFactCheck: [], rebuttalFactCheck: [], commentary: null, }; state = debateReducer(state, { type: "COMPLETE_ROUND", round }); state = debateReducer(state, { type: "START_ROUND" }); expect(state.phase).toBe("round-open"); expect(state.currentRound).toBe(2); expect(state.myArgument).toBe(""); }); it("transitions to results on SET_VERDICT", () => { let state = createInitialDebateState(); state = debateReducer(state, { type: "SET_CONFIG", config: mockConfig }); const verdict: DebateVerdict = { winnerId: "p1", margin: "clear", player1Score: 78, player2Score: 55, roundVerdicts: [ { round: 1, edge: "player1", highlight: "Player 1 framed the issue effectively." }, ], turningPoint: "Player 1's rebuttal in round 1 shifted the debate.", analysis: "Player 1 presented stronger logical arguments.", }; state = debateReducer(state, { type: "SET_VERDICT", verdict, eloChange: 16 }); expect(state.phase).toBe("verdict"); expect(state.verdict).toEqual(verdict); expect(state.eloChange).toBe(16); }); it("resets to idle on RESET", () => { let state = createInitialDebateState(); state = debateReducer(state, { type: "SET_CONFIG", config: mockConfig }); state = debateReducer(state, { type: "RESET" }); expect(state.phase).toBe("idle"); expect(state.config).toBeNull(); expect(state.rounds).toEqual([]); }); });