feat(assert): Accept a status class, list or range in --assert-status - #103
Merged
Conversation
The flag took one exact code, so asking "did this succeed" meant either naming every acceptable code in separate runs or falling back to --assert-ok, which also passes on a 3xx. A class, a list and a range cover what callers actually mean, and they mix: 301,2xx,500-503 is one spec. Every form reduces to a set of inclusive ranges, so one matcher serves all of them and an exact code is a range of one. The failure quotes the spec as written -- `expected 2xx` is the question that was asked, where `expected 200-299` would be an answer to translate back. The flag changes from an int to a string, which is what lets it carry the other forms. Nothing else about it moves: it stays single-valued and command-line only, and an exact code behaves and reads exactly as before. Parsing the spec also settles #93, which asked for codes that can never match to be rejected at the flag rather than failing an assertion at exit 93. Its suggested bound was wrong, though: it named 999 as unmatchable, and a server can send 999. net/http reports 6xx-9xx faithfully and refuses only to write below 100 or above 999, so those are the bounds enforced here -- an assertion about a non-conformant status is answerable, and only a code no response can carry is a typo. 1xx and 6xx-9xx classes parse for the same reason and are deliberately not advertised: they are answerable rather than useful, and documenting them would suggest otherwise. Closes #93 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CrknafJSP5hF8u865cbnqX
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.
Problem
Asking "did this request succeed" took either one run per acceptable status code or
--assert-ok, which also passes on a 3xx.--assert-statusaccepted exactly one integer, so a caller who meant any 2xx, either 200 or 204, or anything in 401-403 had no way to say it.Separately, the flag accepted codes no response can carry.
--assert-status 1000exited93— the code that means the service answered and was wrong — when the real problem was a typo in the command line (#93).Solution
Accept a spec instead of a code: a class, an inclusive range, a comma-separated list, or any mix of them.
Every form reduces to a set of inclusive ranges, so one matcher serves all of them and an exact code is simply a range of one. The failure quotes the spec as written:
expected 2xxis the question the caller asked;expected 200-299would be an answer they have to translate back.The flag moves from
inttostring, which is what lets it carry the other forms. Nothing else about it changes — still single-valued, still command-line only, and an exact code behaves and reads exactly as it did.#93's premise was wrong, and the plan changed because of it
#93 asks to reject "codes that can never match (-1, 999)" by bounding to 100-599. A probe says otherwise:
A server can send 6xx-9xx and
net/httpreports them faithfully, so an assertion about one is answerable. Implementing the ticket as written would have made real responses unassertable. The bound enforced here is 100-999 — what a response can actually carry — so-1,1000and099exit71while999remains a legitimate assertion.1xxand6xx-9xxclasses parse for the same reason and are deliberately not documented: answerable, but not useful, and advertising them would suggest otherwise.Verification
Unit tests cover 12 accepted specs against matching and non-matching codes, and 17 rejected ones against the message each should produce. E2E covers every form end to end plus rejection before any request is made.
Mutation-checked — each of these fails the suite:
Manually verified against live endpoints:
2xx,4xx,404,410and400-499against real 200 and 404 responses, plus999still assertable and1000still rejected.Other Changes
Failure.Expectedfor a status assertion is now the spec text rather than anint. No consumer exists yet (Feature: machine-readable output (--json) #45 is unbuilt); a type that varied by form would be worse for a future JSON consumer than one that is always a string.assertions_test.gousedAssertStatusEqual(1)as its never-matching case;1is no longer expressible, so it is now599.Closes #93
🤖 Generated with Claude Code