import { describe, expect, it } from 'vitest'; import { createState, currentReport, reportsForDay, nextShift, routeReport, startGame } from './engine.ts'; import { REPORTS } from './data/content.ts'; describe('routing engine', () => { it('starts on the first report of shift one', () => { const state = startGame(createState()); expect(state.phase).toBe('playing'); expect(currentReport(state)?.id).toBe('d01'); }); it('advances and records a correct route', () => { const state = routeReport(startGame(createState()), 'avfarda'); expect(state.reportIndex).toBe(1); expect(state.decisions[0].correct).toBe(true); expect(state.trust).toBe(3); }); it('penalizes an incorrect route', () => { const state = routeReport(startGame(createState()), 'arkivera'); expect(state.decisions[0].correct).toBe(false); expect(state.trust).toBe(2); expect(state.insight).toBe(1); }); it('escalating costs insight even when it is the correct route', () => { // d04 (Turning Torso rotating) is correctly routed eskalera. let state = startGame(createState()); for (const route of ['avfarda', 'arkivera', 'utred'] as const) state = routeReport(state, route); expect(currentReport(state)?.id).toBe('d04'); state = routeReport(state, 'eskalera'); expect(state.lastDecision?.correct).toBe(true); expect(state.lastDecision?.trustCost).toBe(0); expect(state.lastDecision?.insightCost).toBe(1); }); it('escalating a wrong report stacks the escalation cost on top of the wrong-route cost', () => { let state = startGame(createState()); // d01's correct route is avfarda; eskalera is wrong here. state = routeReport(state, 'eskalera'); expect(state.lastDecision?.correct).toBe(false); expect(state.lastDecision?.insightCost).toBe(2); // 1 for wrong + 1 for escalating }); it('ends a shift and restores one trust point for the next', () => { let state = startGame(createState()); const routes = reportsForDay(1).map((report) => report.correctRoute); state = routeReport(state, 'arkivera'); // deliberately wrong on d01 for (const route of routes.slice(1)) state = routeReport(state, route); expect(state.phase).toBe('shift-end'); state = nextShift(state); expect(state.day).toBe(2); expect(state.trust).toBe(3); }); it('has five authored reports in every shift', () => { for (let day = 1; day <= 5; day += 1) expect(reportsForDay(day)).toHaveLength(5); }); it('every report has its own correct-route consequence', () => { for (const report of REPORTS) { expect(report.correctConsequence, `${report.id} is missing a correctConsequence`).toBeTruthy(); } }); it('loses on insight reaching the cap even with trust intact', () => { let state = startGame(createState()); // Escalate every report regardless of correctness to ramp insight fast. for (let i = 0; i < 10 && state.phase === 'playing'; i++) state = routeReport(state, 'eskalera'); expect(state.phase).toBe('lost'); expect(state.insight).toBeGreaterThanOrEqual(5); }); });