# Testing Twungeon ## Automated gates From a clean checkout: ```bash npm install npm run lint npm run typecheck npm test npm run test:integration npm run build ``` `npm test` covers deterministic domain rules and 500 generated floors. `npm run test:integration` covers the HTTP/session boundary and independent viewer authority. Tests use injected clocks, IDs, random rolls, and synthetic Twitch identities; they do not require credentials. ## Local gameplay verification 1. Run `npm run dev` and open `http://localhost:3000`. 2. Confirm the exact dormant banner appears and no timer runs. 3. Use **Local viewer login** to spawn and bind a viewer. 4. Confirm 3 HP, 2 AP, no Guard, a ready heal, and a 25-second phase. 5. Exercise movement, invalid walls, Attack, Heal, and Pass. Invalid actions must not consume AP. 6. Open a second browser/private window with a different ID. Confirm both characters share the dungeon but each controller spends only its own AP. 7. Refresh during a phase. Confirm a snapshot restores the map/log and no command replays. 8. Run `npm run build && npm start` and repeat the smoke test against the built server. The local-only endpoints `/api/dev/spawn` and `/api/dev/redemption` exist only while `TWITCH_ENABLED` is false. ## Local video-overlay verification The production viewer path is `/extension`. It is safe to open directly, but it waits for Twitch authorization when it is not inside Twitch. While running the synthetic local backend, open: ```text http://localhost:3000/extension?dev=1&debug=1 ``` `dev=1` exposes the existing **Local viewer login** inside the overlay so the same controller and API flow can be exercised without Twitch. `debug=1` draws a cyan control-region boundary and a pink controller boundary. Both switches are accepted only on `localhost`, `127.0.0.1`, or `[::1]`, so the diagnostics cannot be enabled on the deployed Extension origin. Verify at 1920×1080, 1280×720, and a narrower or 4:3 viewport: - the document and empty overlay canvas remain transparent; - controls stay within the upper-left debug boundary and remain readable; - the dungeon, log, branding, and status tiles are absent from `/extension`; - only buttons (and the local-only login form) accept pointer events; - Up, Down, Left, Right, Attack, Heal, and Pass reach the same backend routes; - missing character, dead character, non-player phase, and zero-AP states still disable the controls; and - loading `/` still presents the full local game and controller. Remove the query string for the production-shaped local view. Twitch-hosted testing still must cover identity sharing, player ownership, theater mode, fullscreen, embeds, ads/pauses, and Twitch player-control safe zones. ## Live-channel campaign After completing `docs/twitch-setup.md`, use two follower accounts and one non-follower account. Capture redacted evidence for: - eligible, ineligible, and duplicate `!spawn` attempts; - matching and mismatched Extension identities; - independent commands from two viewers; - phase expiry and AutoGuard while one viewer is disconnected; - death and a configured Channel Points reward redemption from the same user; - escape with the Goblin alive, floor revival, and a total-party wipe; - refresh/reconnect during a phase and transition; and - repeated floors and a short soak session. Do not record tokens, JWTs, secrets, or complete authorization headers. Use the acceptance matrix in `Twungeon_MVP_Acceptance_Test_and_Build_Checklist.md` for AT-001 through AT-033 evidence. Automated passing tests do not substitute for the clean-operator, live Twitch, first-time-viewer, or concept-validation gates. ## Fault injection Test each failure separately: expired Extension JWT, wrong channel claim, unlinked identity, invalid broadcaster token, missing follower scope, Twitch chat disconnect, wrong/duplicate Channel Points redemption, WebSocket interruption, and stale run/floor/phase command. Expected behavior is a stable rejection or a fresh snapshot without partial game-state mutation.