Triviaverse / src /lib /spark /engine.test.ts
Simeon Garratt
feat(spark): complete debate arena rework to conversational flow
4295c71
Raw
History Blame Contribute Delete
5.32 kB
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([]);
});
});