Cover the preference upload gate with the Node test suite (#86) - #87
Conversation
Move the state machine deciding when a signed-in player's preferences may be sent to their account out of game.html's inline script and into game-logic.js as createPreferenceSync, taking the reads, writes and requests as callbacks so the orderings that carry the risk can be driven without a browser. The reads, writes, requests and the DOM work stay inline as those callbacks. The defect found by hand during the review of #85 - a preference changed while the account copy was still in flight scheduling an upload that could beat the response and put this browser's stale copy over the account's - now fails a test rather than only a reviewer. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1ad11ec to
f3215b9
Compare
The suite drives an injected clock everywhere else, leaving the setTimeout / clearTimeout the browser is actually given, and the no-op onError a caller may rely on, exercised by nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Self-review rubric, scored against the diff and against CI run
Two observations that belong to the body rather than to any changed line:
This review was posted during a Gardener session (https://github.com/Stephenson-Software/gardener). drafted by Claude on behalf of Daniel Stephenson |
|
Merge held for a human decision, not for a defect. The merge-readiness bar is otherwise met: CI run What holds it is the autonomous-merge rule against any single file losing more than 50 lines: This comment was posted during a Gardener session (https://github.com/Stephenson-Software/gardener). drafted by Claude on behalf of Daniel Stephenson |
Merge-readiness review (continued dispatch)This pull request was left open by an interrupted Gardener dispatch. Its state has been The hold. The autonomous-merge rule against any single file losing more than 50 lines was
Ordering. Anchor. CI run 31468687551 is green on head Documentation. A fresh sweep found nothing left to correct. The README API section still Backlog. #86 was the only open issue and is closed by this change. PR #42 ( Merging proceeds under the operator's explicit pre-authorization for this run, the matched path This review was posted during a Gardener session (https://github.com/Stephenson-Software/gardener). |
Summary
The per-account preference sync shipped in #85 had its reconciliation rule (
mergePreferences)covered by the Node suite while the wiring around it stayed inline in
game.html, executed by nosuite at all. The state machine has been moved into
web-client/src/main/resources/static/js/game-logic.jsascreatePreferenceSync, which takes thereads, writes and requests as callbacks. What is left inline is exactly that browser work — reading
and writing
localStorage, re-applying what is stored to the page, and the twofetchcalls.reconciled/uploadDeferred), the echo guard used while the account copy isbeing applied, and the debounce are now driven by tests through an injected clock, so the
orderings that carry the risk are exercised without a browser.
preference changed while the account copy is still in flight used to schedule an upload that
could beat the response and put this browser's stale copy over the account's. Removing the gate
makes that test fail — verified on this branch, see the self-review comment.
including the failure paths (a failed load still opens the gate, and a failed upload is still
logged rather than raised over the game).
#55CHANGELOG entry was corrected to say that the gate is covered too, not only the mergerule.
Module(s) touched
web-clientonly. No backend change, and no change to the/api/session/preferencescontract oneither side of it.
Test plan
web-client/src/test/js/game-logic.test.jsgains 10 tests forcreatePreferenceSyncBackend Build and TestandWeb Client Build and Test(the latter also runsnode --test web-client/src/test/js/)Neither Maven nor Node could be run in the environment this branch was written in, so the CI run on
this PR's head commit is the only anchor for it; local execution is recorded as UNVERIFIED.
ProxyRouteCoverageTestreadsfetch('/api/...')calls out of the rendered page in document order,and the two preference calls were reordered by this change (the
GETnow precedes thePUT); themethod:option of each is still the first one following its own call, so both are still read asGETandPUT /api/session/preferences. CI is what confirms it.Backlog deferred this cycle
#86 was the only open issue at triage, so nothing else was deferred. PR #42 (
copilot/*, draft) wasleft alone as the work of another author.
Closes #86
This PR description was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).
drafted by Claude on behalf of Daniel Stephenson