Test the raid flow for real, and fix what that turned up - #202
Merged
Conversation
Owner asked why I was not testing this myself with Playwright. Fair question — the repo already has the pattern (test-bunker-floor-reset.js boots the app in headless Chromium and reads the saved draft back), and everything I had verified about raids so far came from reading code and exercising logic in isolation. So this drives the real map: seeds a player midway through Bunker 3 on floor 3, waits for the world map, checks the daily status chips render with live numbers, checks bunkers 1 and 2 carry a ✓, taps Treeline, asserts the button reads RAID and the subline names the energy cost, taps it, and asserts the campaign's act AND floor come back afterwards with everything the raid earned kept. It immediately earned its keep twice. First, it caught a real leak. takeCampaignResume was called INSIDE the `if (raw)` guard, so any path where the engine had no snapshot to give — never mounted, already torn down, getSaveSnapshot threw — left the stash on disk. A leaked stash is not inert: the next raid to finish would read it and restore a campaign position from two raids ago. The stash is now consumed first and unconditionally, which is also the right outcome on that path, since no snapshot written means the draft still holds the position the stash was insurance for. Second, and worth writing down: its own first run was a FALSE GREEN. With no engine mounted the whole write block was skipped, so three assertions about the campaign being "restored" passed against the untouched seeded draft. A tracer on the resume key showed one write and no removal, which is what exposed both the leak and the vacuous pass. The engine stub and the "raid keeps what it earned" assertion are there so that cannot repeat: that one can only pass if the raid's own snapshot really was written. Kept as npm run test:raid rather than thrown away. It does not prove the engine half — playing five floors of real-time combat headlessly is not practical — but the shell owns every hazard in this flow, and the shell is what it drives.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You asked why I wasn't testing this myself with Playwright. Fair question — the repo already has the pattern (
scripts/test-bunker-floor-reset.jsboots the app in headless Chromium and reads the saved draft back), and everything I'd verified about raids so far came from reading code and exercising logic in isolation.So this drives the real map in a real browser.
What the test does
Seeds a player midway through Bunker 3 on floor 3, then:
Kept as
npm run test:raid.It earned its keep twice
1. A real leak.
takeCampaignResumewas called inside theif (raw)guard, so any path where the engine had no snapshot to give — never mounted, already torn down,getSaveSnapshotthrew — left the stash on disk. A leaked stash is not inert: the next raid to finish would read it and restore a campaign position from two raids ago.It is now consumed first and unconditionally, which is also the correct outcome on that path — no snapshot written means the draft still holds the position the stash was insurance for.
2. Its own first run was a false green. With no engine mounted the whole write block was skipped, so three assertions about the campaign being "restored" passed against the untouched seeded draft. A tracer on the resume key showed one write and no removal — which is what exposed both the leak and the vacuous pass.
The engine stub and the
raid KEEPS what it earnedassertion exist so that cannot repeat: that one can only pass if the raid's own snapshot really was written.I'm flagging this because I reported those three assertions as passing in a previous message before spotting it. They weren't proving anything then. They are now.
Limits, stated plainly
This drives the shell half. Playing five floors of real-time combat headlessly is not practical, so the engine's snapshot is stubbed — same technique as the existing
test-bunker-floor-reset.js, which says the same thing about itself.That is the right seam here: every one of the four hazards in this flow lives in the shell (
GameFlowManager,WorldMapHub,campaignProgress), not the engine.Still unproven and wanting a human: the engine actually reaching
onActBunkerClearedin raid mode, and how the chips look on a real phone with the game's own fonts.Verification
tsc --noEmitclean · lint 34 errors, unchanged frommain·check:copy,auditpass ·npm run test:raid16/16.Generated by Claude Code