import { describe, expect, test } from 'vitest'; import type { MiniGameDraftGenerationKind, MiniGameDraftGenerationPhase, MiniGameDraftGenerationState, } from '../../services/miniGameDraftGenerationProgress'; import type { SelectionStage } from './platformEntryTypes'; import { resolvePlatformGenerationProgressTickDecision } from './platformGenerationProgressTickModel'; function buildGenerationState( kind: MiniGameDraftGenerationKind, phase: MiniGameDraftGenerationPhase = 'compile', ): MiniGameDraftGenerationState { return { kind, phase, startedAtMs: 1000, completedAssetCount: 0, totalAssetCount: 1, error: null, }; } describe('platformGenerationProgressTickModel', () => { test('ticks while a mini-game generation stage has a running state', () => { const cases: Array< [stage: SelectionStage, kind: MiniGameDraftGenerationKind] > = [ ['puzzle-generating', 'puzzle'], ['match3d-generating', 'match3d'], ['big-fish-generating', 'big-fish'], ['square-hole-generating', 'square-hole'], ['jump-hop-generating', 'jump-hop'], ['wooden-fish-generating', 'wooden-fish'], ['baby-object-match-generating', 'baby-object-match'], ]; for (const [selectionStage, kind] of cases) { expect( resolvePlatformGenerationProgressTickDecision({ selectionStage, miniGameStates: { [kind]: buildGenerationState(kind), }, visualNovel: { startedAtMs: null, phase: 'generating', }, }), ).toEqual({ activeKind: kind, shouldTick: true, }); } }); test('does not tick mini-game generation when state is missing or terminal', () => { expect( resolvePlatformGenerationProgressTickDecision({ selectionStage: 'puzzle-generating', miniGameStates: {}, visualNovel: { startedAtMs: null, phase: 'generating', }, }), ).toEqual({ activeKind: 'puzzle', shouldTick: false, }); for (const phase of ['ready', 'failed'] as const) { expect( resolvePlatformGenerationProgressTickDecision({ selectionStage: 'puzzle-generating', miniGameStates: { puzzle: buildGenerationState('puzzle', phase), }, visualNovel: { startedAtMs: null, phase: 'generating', }, }), ).toEqual({ activeKind: 'puzzle', shouldTick: false, }); } }); test('does not tick when stage and mini-game state do not match', () => { expect( resolvePlatformGenerationProgressTickDecision({ selectionStage: 'puzzle-generating', miniGameStates: { match3d: buildGenerationState('match3d'), }, visualNovel: { startedAtMs: null, phase: 'generating', }, }), ).toEqual({ activeKind: 'puzzle', shouldTick: false, }); }); test('ticks visual novel generation only after it has started and before terminal phases', () => { expect( resolvePlatformGenerationProgressTickDecision({ selectionStage: 'visual-novel-generating', miniGameStates: {}, visualNovel: { startedAtMs: 1000, phase: 'generating', }, }), ).toEqual({ activeKind: 'visual-novel', shouldTick: true, }); expect( resolvePlatformGenerationProgressTickDecision({ selectionStage: 'visual-novel-generating', miniGameStates: {}, visualNovel: { startedAtMs: null, phase: 'generating', }, }), ).toEqual({ activeKind: 'visual-novel', shouldTick: false, }); for (const phase of ['ready', 'failed'] as const) { expect( resolvePlatformGenerationProgressTickDecision({ selectionStage: 'visual-novel-generating', miniGameStates: {}, visualNovel: { startedAtMs: 1000, phase, }, }), ).toEqual({ activeKind: 'visual-novel', shouldTick: false, }); } }); test('does not tick non-generation stages even when states are present', () => { expect( resolvePlatformGenerationProgressTickDecision({ selectionStage: 'platform', miniGameStates: { puzzle: buildGenerationState('puzzle'), }, visualNovel: { startedAtMs: 1000, phase: 'generating', }, }), ).toEqual({ activeKind: null, shouldTick: false, }); }); });