test(contract): classify the last 21 endpoints and cover the new reads - #188
Merged
Merged
Conversation
Final pass over the contract suite now that all 47 parity PRs are on main. The inventory test had been failing since the merge pass began, because it re-derives the endpoint set from the client on every run and the client kept growing. That is the feature working; this makes it green. Three fixes: 1. Two more files had to leave the portable subset. The glob introduced in #185 picks up new Services/ files automatically, which is what makes it safe — and it correctly failed on two that are NOT portable: AiAvailabilityService.cs -> CommunityToolkit.Mvvm GitHubListIndex.cs -> uses AppServices and AppLog Both now excluded, with the reason recorded next to the others. 2. The scanner could not resolve one more call shape: ReadTagsAsync, a private read helper whose name does not start with "Get". GetHelper now matches (Get|Read)[A-Za-z]*Async. Extending the convention rather than renaming production code to suit the scanner — both prefixes unambiguously denote a GET, and HttpMethod still wins when present. 3. Classified the remaining 21 endpoints: blog, list folders, list/document invites, tags, link metadata, weather/location, and the GitHub-backed list refresh. Six read, fifteen skip. The skips are where the judgement is. Every one of them would touch something real: POST /api/blog/subscribe and the two invite POSTs send actual emails to actual addresses; PUT /api/folders/{id} moves a folder and the server does NOT reject a cycle, so a careless move corrupts the tree; DELETE /api/folders/{id} cascades to subfolders; /api/weather and /api/location need coordinates and would assert against a real user's stored profile location; and the invite GETs are owner-only against a list the suite does not own. Added the six read probes the inventory then demanded. Two are deliberately narrow: link-metadata unfurls example.com so it asserts the unfurler answers rather than that some third-party site is up, and tags/autocomplete queries a single letter because an empty q is a 400 and anything longer assumes content. GET api/documents/{documentId} is worth having: the tree payload omits `content` with no opt-in, so this is the only bulk source of a document body and the editor breaks silently if it stops carrying one. Verified: live run: 95/95 passed (was 71 before the merge pass) gated off: 4 passed, 91 skipped, exit 0 app: Debug and Release both clean tray: builds clean Sync.Core: 38/38 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Final pass over the contract suite now that all 47 parity PRs are on
main.The inventory test had been failing since the merge pass began — it re-derives the endpoint set from the client on every run, and the client kept growing. That's the feature working as designed; this makes it green.
1. Two more files left the portable subset
The glob introduced in #185 picks up new
Services/files automatically, which is exactly what makes it safe. It correctly failed on two that are not portable:AiAvailabilityService.csCommunityToolkit.MvvmGitHubListIndex.csAppServicesandAppLogBoth excluded, reasons recorded alongside the others. Worth noting this is the glob paying off — under the old enumeration these would have been silently missing rather than loudly failing.
2. One more call shape
ReadTagsAsync— a private read helper whose name doesn't start withGet.GetHelpernow matches(Get|Read)[A-Za-z]*Async.Extending the convention rather than renaming production code to suit the scanner: both prefixes unambiguously denote a GET, and
HttpMethodstill matches first so this can't override an explicit verb.3. The last 21 endpoints classified
Blog, list folders, list/document invites, tags, link metadata, weather/location, and the GitHub-backed list refresh. Six read, fifteen skip.
The skips are where the judgement is — every one would touch something real:
POST /api/blog/subscribeand the two invitePOSTs send actual emails to actual addressesPUT /api/folders/{id}moves a folder, and the server does not reject a cycle (feat(lists): list folders (/api/folders) with a client-side cycle guard #180), so a careless move corrupts the treeDELETE /api/folders/{id}cascades to subfolders/api/weatherand/api/locationneed coordinates, and would assert against a real user's stored profile locationGETs are owner-only against a list the suite doesn't ownThe six new probes
Two are deliberately narrow:
link-metadataunfurlsexample.com, so it asserts the unfurler answers rather than that some third-party site is uptags/autocompletequeries a single letter — an emptyqis a400, and anything longer assumes the account has particular contentGET /api/documents/{documentId}is the one worth having. The tree payload omitscontentwith no opt-in (#139), so this is the only bulk source of a document body — the editor breaks silently if it stops carrying one.Verification
🤖 Generated with Claude Code