Repository navigation
test(downgrader): cover mixed literal union edge cases, note boolean-ish flags with coercing validators - #136
Conversation
Three cases close the Stryker gaps in mergeEnumsByType: a described branch stops the merge, typeless multi-value enums stay as written, and a lone described typed enum stays as written. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018XRYDXpPjZLwYYLKH7PZWd
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — test-only follow-up adding 3 assertions to packages/downgrader/tests/v3.1-to-v3.0.test.ts inside the existing const-union it block; no source change.
- Described branch blocks a same-type merge —
anyOf [const a, const b+description, const c, {type:null}]keeps all four branches, guardingmergeEnums'srepeats-false path. - Described typed enum beside another type —
{description:'D', anyOf:[{type:'string',enum:['a'],description:'D'}, {type:'boolean'}]}becomes aoneOfretainingdescription, guardingmergeEnumsByType'srepeats-true path and itsresult.length < branches.lengthfalse guard. - Typeless mixed enums stay put —
[{enum:['a',1]},{enum:['b',2]},{type:'boolean'}]is returned as written, guarding thetypeof branch.type !== 'string'check and type-grouping.
I verified both mutations the body claims: with the new cases removed, mutating typeof branch.type !== 'string' to false, or result.length < branches.length to true, passes the full 280-test suite; with the new cases present each fails (at the new lines 1248 and 1244 respectively). The new tests pass (108 in file, 280 full suite) and uncheck is clean, so the cases are genuine, non-redundant coverage rather than theatre. One cosmetic note: the body attributes all three cases to mergeEnumsByType, but the first exercises mergeEnums's same-type branch (it returns before reaching mergeEnumsByType) — wording only, not a code concern.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
… flag A union of "true", "false" and a boolean, as GrowthBook writes for query flags, becomes a oneOf in 3.0, and a validator that coerces matches "true" to both branches. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018XRYDXpPjZLwYYLKH7PZWd
There was a problem hiding this comment.
ℹ️ No critical issues — the core claim in the new sentence is correct; one attribution gap noted inline.
Reviewed changes — incremental delta since the prior pullfrog review (ecd10b2): one sentence added to the "Validators that coerce" limitation bullet in packages/downgrader/README.md; no source change.
- GrowthBook coercion example — the bullet now says a GrowthBook-style query flag that takes
"true","false"or a boolean rejects?flag=true, since"true"matches the string branch and, coerced, the boolean branch.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
|
ℹ️ One minor note to supplement the review above (it could not be anchored inline — a second review submission is blocked as a duplicate in this session). The new sentence says a query flag "takes The claim itself is unaffected: I confirmed the converted
|
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018XRYDXpPjZLwYYLKH7PZWd
|
Agreed, fixed in the next commit: the sentence now lists Generated by Claude Code |

Requested by dinwwwh · project thread
Follow-up to #135, tests and one README sentence, no source change.
Tests
Three cases in
v3.1-to-v3.0.test.tsclose the Stryker survivor gaps in the enum merge of a literal union:mergeEnums(anyOf [const a, const b + description, const c, null]keeps every branch)mergeEnumsByType)mergeEnumsByType)README
The "Validators that coerce" limitation now says that a query flag of
"true","false","0","1"or a boolean, as GrowthBook writes (itsmineparameter in REST API 5.1.0), rejects?flag=trueafter #135: it becomesoneOf [string enum ["true", "false", "0", "1"], boolean], and"true"matches the string and, coerced, the boolean. Checked with AjvcoerceTypes: true: theoneOfrejects{ flag: "true" }, the oldanyOfaccepts it.Checks
pnpm test:coverage: 280 tests pass, coverage stays at 100% statements, branches, functions and linespnpm checkpassestypeof branch.type !== 'string'tofalse, or the finalresult.length < branches.lengthguard totrue, passes every test on main and fails with these cases. Stryker on the merge code with these tests kills 125 of 127 mutants; the two left are equivalent.🤖 Generated with Claude Code
https://claude.ai/code/session_018XRYDXpPjZLwYYLKH7PZWd