clone

a browser grid puzzle game where you push words around to rewrite the rules of each level

main
miau-is-true / tests / win-flow.test.js
win-flow.test.js 2.6K
1import test from 'node:test';2import assert from 'node:assert/strict';3import { createWinFlow, WIN_ENTRANCE_END } from '../src/stage/win-flow.js';4import { WIN_TIMING } from '../src/render/stage-win.js';56function harness(reducedMotion = false) {7 let now = 100;8 let pending = null;9 const changes = [];10 let continues = 0;11 const clock = {12 now: () => now,13 setTimeout(callback, delay) { pending = { callback, due: now + delay }; return 1; },14 clearTimeout() { pending = null; },15 };16 const flow = createWinFlow({ clock, reducedMotion, onChange: () => changes.push(now), onContinue: () => { continues += 1; } });17 return {18 flow, changes,19 setTime(value) { now = value; if (pending && now >= pending.due) { const task = pending; pending = null; task.callback(); } },20 get continues() { return continues; },21 };22}2324test('first confirmation during entrance settles Win, second exits once', () => {25 const h = harness();26 h.flow.enter();27 h.setTime(100 + WIN_ENTRANCE_END - 1);28 assert.equal(h.flow.confirm(), true);29 assert.equal(h.flow.view.winSkip, true);30 assert.equal(h.continues, 0);31 assert.equal(h.flow.confirm(), true);32 assert.equal(h.flow.exiting, true);33 assert.equal(h.flow.confirm(), true);34 h.setTime(100 + WIN_ENTRANCE_END - 1 + WIN_TIMING.exit);35 assert.equal(h.continues, 1);36});3738test('settled or initially won cards continue with one confirmation', () => {39 const h = harness();40 h.flow.enter();41 h.setTime(100 + WIN_ENTRANCE_END);42 h.flow.confirm();43 h.setTime(100 + WIN_ENTRANCE_END + WIN_TIMING.exit);44 assert.equal(h.continues, 1);45 h.flow.enter({ instant: true });46 assert.equal(h.flow.view.winSkip, true);47 h.flow.confirm();48 h.setTime(100 + WIN_ENTRANCE_END + WIN_TIMING.exit * 2);49 assert.equal(h.continues, 2);50});5152test('cancelling an exit prevents stale INDEX transition after Undo', () => {53 const h = harness();54 h.flow.enter({ instant: true });55 h.flow.confirm();56 h.flow.cancel();57 h.setTime(1000);58 assert.equal(h.continues, 0);59 assert.equal(h.flow.active, false);60});6162test('reduced motion continues immediately from its settled card', () => {63 const h = harness(true);64 h.flow.enter();65 assert.equal(h.flow.view.winSkip, true);66 h.flow.confirm();67 assert.equal(h.continues, 1);68});6970test('an exit begun at clock zero is still treated as active', () => {71 let scheduled = 0;72 const clock = {73 now: () => 0,74 setTimeout: () => { scheduled += 1; return 1; },75 clearTimeout: () => {},76 };77 const flow = createWinFlow({ clock });78 flow.enter({ instant: true });79 flow.confirm();80 flow.confirm();81 assert.equal(flow.exiting, true);82 assert.equal(scheduled, 1);83});