Repository navigation
feat(params, collections): practical query-parameter testing and stronger GET collection checks - #16
Merged
Merged
Conversation
…nger GET collection checks Query parameters: - confirmed: an integer parameter gets a decimal inside its bounds (only the type is broken); every query case checks the value really went over HTTP; accepted values check the response contract; values over the limits are CASE_LIMIT_REACHED gaps; Python sends query booleans as true / false. - exploratory probes (empty, text, decimal, zero, negative, large, special, boolean / enum spelling, missing): GET / HEAD only, deduplicated against confirmed cases and the documented range, never failing on the API's behavior, recorded in the run report (exploratory.jsonl). GET collections (on the PR #14 engine): - "match": "search" (case-insensitive substring), "total" consistency, sort-reverse (descending = ascending reversed), several mappings per resource ("collections": [...]). Case ID vocabulary v5: sort-reverse, total, probe, decimal type case. CI gate: a Python test that reassigns its own fixture fails (a generated test shadowed the "items" fixture; its cleanup would not have run). Demo API: GET /items/search and 8 more faults; fault injection 17/17 in TypeScript and Python (base generator: 14/17 on the same spec). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
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.
Audit (before the changes)
Already in place, reused:
param-cases.tsalready gives one-rule-at-a-time constraint cases for query / header / cookie / path through the body-case engine:minimum − step,maximum + step, the exclusive bound itself, the nearest non-multiple;boundaryValues/queryVariants: the valid limits and enum values, asaccepted-value.collection.ts,collection-tests.ts,collection-render.ts): strategies A / B / C, membership, filter, sort, pagination, uniqueness, lifecycle. Thecollection-cases.tsfile named in the task does not exist; these three files are its role.Gaps found:
What changed
request.<in>#/<name>/decimal, ruletype;multipleOf> 1 or anenum→CANNOT_ISOLATE_RULE);expectSentQuery/expect_sent_queryon every query case; accepted values also check the response contract; dropped values →CASE_LIMIT_REACHEDsrc/generate/probes.ts)requiredRequest, IDs, the contract validatormissing,empty,text,decimal,zero,negative,large,special,numeric,case. They are deduplicated against confirmed rules and against values the documented range makes valid. A probe asserts only that its value was sent; the API's answer (status, documented, 5xx, contract) is recorded and never asserted.--runcollects the answers intoexploratory.jsonland a report section"match": "search"(case-insensitive: query in upper case, data in lower case);total(the same on every page, equal to the number listed);sort-reverse(descending = ascending reversed);"collections": [...](several list operations per resource;collectionstill works)true/false, like TypeScript (requests sentTrue)sort-reverse,total,probe, the decimaltypecaseitems,items/search,me, 17 faultsFound and fixed during verification:
totaltest wroteitems, totals, _ = …inside a test whose resource fixture isitems. Itsfinallythen calledlist.remove, so the cleanup would not have run. Generated names were fixed, and the new gate rejects that output, now verified on the real generated code.expectSentQuerywithout importing it. The check is now emitted only when needed.Metrics (demo API, same spec for both columns)
wrong-total,broken-search,truncate-decimalWhich test catches each fault (
mutation-check.ts --show, TS; Python identical):ignore-max/loose-types/ignore-enummaximum/type/enumcasesignore-requiredmissing required query "q"truncate-decimallimit=20.5wrong-total/total equals the number of resources…broken-searchtotaldrop-updateignore-filter,wrong-sort,hide-created,duplicate,wrong-field,bad-paginationtotalfor filter / duplicatesrequire-optional,accept-expired,ignore-suspensionsort-reversecatches no fault on its own here: wherever it fails, the individual sort tests fail too. It stays because the task asks for asc / desc consistency, and it is the read-only check of that on APIs where the individual order cannot be verified.Gaps
CANNOT_ISOLATE_RULE GET /items/search lifecycle. The update renames the item, and the search needs a requiredq, so the updated item cannot be found reliably. It is recorded in the baseline.CASE_LIMIT_REACHED/UNSAFE_LIVE_CHECK/MISSING_RESOURCE_SOURCEwith ruleprobewhere they apply; none on the demo.Commands run (local, CI-equivalent)
npx tsc --noEmit,npm run build: ok.npx vitest run: 233 passed, 2 skipped (oasdiff-only).generate --run(TS and Python):stats/get/contractdefect fails;scripts/coverage-summary.tsagainst the previous baseline: cases +35 / lost 0, gaps +1 (the one above). The baseline was then updated. Kitchen sink: cases +10 / lost 0.tscandpy_compilepass, registry valid, parity holds.scripts/mutation-check.ts, TS and Python,items+items/search+me: 17 / 17, clean without a fault.maintainon a changed spec: regenerated, validated, the stale mapping reported.Limitations
UNSAFE_LIVE_CHECK.totalis skipped when the collection has more thanmaxPagespages. Read-onlysort-reverseandtotalre-read once on a mismatch, but heavy concurrent writes can still make them flaky.sort-reversecompares values, not ids, in read-only mode (ties have no defined order).between=price,10,30) and default-scoped boolean flags (is_rental) are still not mapped.