import { describe, expect, it } from 'vitest'; import { allowedGameplayEvents, deriveGameplayPhase, transitionGameplayPhase, type GameplayPhase } from '../src/spa/gameplay-phase-machine'; describe('gameplay phase machine skeleton', () => { it('supports canonical phase progression lie -> guess -> reveal -> scoreboard -> lie', () => { let phase: GameplayPhase = 'lie'; phase = transitionGameplayPhase(phase, 'LIES_LOCKED').phase; expect(phase).toBe('guess'); phase = transitionGameplayPhase(phase, 'GUESSES_LOCKED').phase; expect(phase).toBe('reveal'); phase = transitionGameplayPhase(phase, 'SCOREBOARD_READY').phase; expect(phase).toBe('scoreboard'); phase = transitionGameplayPhase(phase, 'NEXT_ROUND').phase; expect(phase).toBe('lie'); }); it('keeps state unchanged for invalid transition events', () => { const transition = transitionGameplayPhase('lie', 'NEXT_ROUND'); expect(transition.phase).toBe('lie'); expect(transition.changed).toBe(false); }); it('exposes allowed events per phase', () => { expect(allowedGameplayEvents('guess')).toEqual(['GUESSES_LOCKED']); expect(allowedGameplayEvents('scoreboard')).toEqual(['NEXT_ROUND']); }); it('derives gameplay phase from session detail status', () => { expect( deriveGameplayPhase({ session: { code: 'ABCD12', status: 'lie', host_id: 1, current_round: 1, players_count: 3 }, players: [], round_question: null, phase_view_model: { status: 'lie', round_number: 1, players_count: 3, constraints: { min_players_to_start: 3, max_players_mvp: 5, min_players_reached: true, max_players_allowed: true }, host: { can_start_round: false, can_show_question: true, can_mix_answers: true, can_calculate_scores: false, can_reveal_scoreboard: false, can_start_next_round: false, can_finish_game: false }, player: { can_join: false, can_submit_lie: true, can_submit_guess: false, can_view_final_result: false } } }) ).toBe('lie'); expect( deriveGameplayPhase({ session: { code: 'ABCD12', status: 'finished', host_id: 1, current_round: 1, players_count: 3 }, players: [], round_question: null, phase_view_model: { status: 'finished', round_number: 1, players_count: 3, constraints: { min_players_to_start: 3, max_players_mvp: 5, min_players_reached: true, max_players_allowed: true }, host: { can_start_round: false, can_show_question: false, can_mix_answers: false, can_calculate_scores: false, can_reveal_scoreboard: false, can_start_next_round: false, can_finish_game: false }, player: { can_join: false, can_submit_lie: false, can_submit_guess: false, can_view_final_result: true } } }) ).toBe('scoreboard'); }); });