74 lines
3.0 KiB
TypeScript
74 lines
3.0 KiB
TypeScript
|
|
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);
|
||
|
|
});
|
||
|
|
});
|