Skip to content

test: guard the pokersolver behaviours bestFive slices on - #102

Open
pip-robot[bot] wants to merge 1 commit into
mainfrom
guard-pokersolver-contract
Open

test: guard the pokersolver behaviours bestFive slices on#102
pip-robot[bot] wants to merge 1 commit into
mainfrom
guard-pokersolver-contract

Conversation

@pip-robot

@pip-robot pip-robot Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

bestFive() in src/lib/poker/handEval.ts does slice(0, 5). That line is only correct because pokersolver returns the cards that make the hand first, in its own order, and that was asserted in a doc comment rather than a test.

The failure shape if it ever stopped being true: every showdown reveal shows the wrong five cards, the recap explains hands wrongly, and the suite stays green, because every hand name is still right.

Three of the shapes were already covered in tests/handEval.test.ts (six-card flush, two trips, the low-ace '1' rewrite). Two were not:

  • A full house whose trips rank below its pair (3s 3h 3d As Ah). The one case where "first five" and "five highest" disagree, so it is the case that actually pins the slice. Sorted by rank the reveal would show two pair.
  • The royal-flush name/descr split. handPhrase() reads descr because a royal is named "Straight Flush". If descr ever stopped being exactly "Royal Flush", the recap and every drill grade would call a royal a straight flush, and no name assertion anywhere would fail. There was no test on handPhrase at all, so this adds one covering every category name it maps.

Plus one direct assertion on the raw solved.cards shape (six-card flush, two trips, six-card straight flush returning five rather than overflowing, the low ace as '1'). bestFive hides all of that from its own callers, so anything new that reads solved.cards inherits the traps with nothing to warn it.

Two fixes to that same trap while in here:

  • src/types/pokersolver.d.ts said cards was "the five cards the solver used". It is not always five, and that sentence is what leads someone to read it raw.
  • bestFiveOf in tests/learnExamples.test.ts did read it raw, through an as unknown as cast, and was safe only because no fixture is a six-card flush. It goes through bestFive now, which also drops the cast.

What I checked: every behaviour was run against the installed pokersolver@2.1.4 before being written down, not recalled. pnpm test:all green (554 tests). No production code changed, so there is nothing UI-shaped here to verify, and I have no browser on this runner either way.

Credit: the read that turned this up is the CMO's, on playpip/technology#78. Her count was five unguarded behaviours; three of them already had tests, and this adds the two that did not.

bestFive() does slice(0, 5) and that line is only correct because the solver
returns the cards that make the hand first, in its own order. That was asserted
in a doc comment. Three of the shapes were already covered; two were not.

- A full house whose trips rank below its pair (3s 3h 3d As Ah). This is the
  one case where "first five" and "five highest" disagree, so it is the case
  that pins the slice.
- The royal-flush name/descr split. handPhrase() reads descr because a royal is
  *named* "Straight Flush"; if descr ever changed, the recap and every drill
  grade would call a royal a straight flush and no name assertion would fail.
  Also covers every category name handPhrase maps, so a rename shows up as a
  failing test rather than a dropped clause.
- One direct assertion on the raw solved.cards shape (six-card flush, two
  trips, six-card straight flush returning five, the low ace as '1'), because
  anything reading solved.cards inherits those traps and bestFive hides them.

Two fixes to the same trap while here: pokersolver.d.ts said cards was always
five, which is what leads someone to read it raw; and bestFiveOf in
learnExamples.test.ts did read it raw, through an unknown cast, and was safe
only because no fixture is a six-card flush. It now goes through bestFive.

Verified against the installed pokersolver@2.1.4, which is pinned at ^2.1.4 and
last published July 2020. Refs playpip/technology#78.
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying pip-web with  Cloudflare Pages  Cloudflare Pages

Latest commit: c8aaa98
Status: ✅  Deploy successful!
Preview URL: https://83aaf76e.pip-web-9oj.pages.dev
Branch Preview URL: https://guard-pokersolver-contract.pip-web-9oj.pages.dev

View logs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants