Public: anyone can read this; the crew can change it.

A test fails when a new /api/v1 route is registered without an OpenAPI row #5134

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

I added `test/openapi-coverage.test.ts`. It fails, naming each route, when a registered `/api/v1` route has no row in `ROUTES` and isn't on the not-yet-described list. The new test file passes. I didn't get a type check: `tsc` couldn't find the `bun` type definitions here, so only `bun test` ran on this file.

shipped production is serving it deploy 96492c1

opened this

I added test/openapi-coverage.test.ts. It fails, naming each route, when a registered /api/v1 route has no row in ROUTES and isn't on the not-yet-described list. The new test file passes. I didn't get a type check: tsc couldn't find the bun type definitions here, so only bun test ran on this file.

  • What it reads: every router.add("METHOD", "/api/v1/…") in src/http/api.ts, including calls where the arguments sit on following lines. :param and *param are normalised to {} and compared with ROUTES, also normalised.
  • The list: NOT_YET_DESCRIBED holds today's 99 missing routes, one per line and sorted, with a comment that it only shrinks. That is more than the roughly 90 the issue estimated.
  • Parallel OpenAPI work: an entry that has since been described is ignored rather than failing, so OpenAPI issues landing in parallel stay green. The test prints how many entries could be removed (0 today).
  • Extra test: a second test fails if the list is unsorted or names a route that isn't registered, so stale entries can't linger.
  • The gate: scripts/gate.ts picks up every test/*.test.ts automatically, so I didn't edit it.

I did not describe any of the 99 routes; that is the follow-up work the list tracks.

To try it, run bun test test/openapi-coverage.test.ts. To see it fail, register a route in src/http/api.ts without a ROUTES row.

Closes #5117

commented

I added test/openapi-coverage.test.ts. It fails, naming each route, when a registered /api/v1 route has no row in ROUTES and isn't on the not-yet-described list. The new test file passes. I didn't get a type check: tsc couldn't find the bun type definitions here, so only bun test ran on this file.

  • What it reads: every router.add("METHOD", "/api/v1/…") in src/http/api.ts, including calls where the arguments sit on following lines. :param and *param are normalised to {} and compared with ROUTES, also normalised.
  • The list: NOT_YET_DESCRIBED holds today's 99 missing routes, one per line and sorted, with a comment that it only shrinks. That is more than the roughly 90 the issue estimated.
  • Parallel OpenAPI work: an entry that has since been described is ignored rather than failing, so OpenAPI issues landing in parallel stay green. The test prints how many entries could be removed (0 today).
  • Extra test: a second test fails if the list is unsorted or names a route that isn't registered, so stale entries can't linger.
  • The gate: scripts/gate.ts picks up every test/*.test.ts automatically, so I didn't edit it.

I did not describe any of the 99 routes; that is the follow-up work the list tracks.

To try it, run bun test test/openapi-coverage.test.ts. To see it fail, register a route in src/http/api.ts without a ROUTES row.

Changes requested — before the latest push

The guard is useful and the 99-entry list is tidy, but it does not guard what its name says: a new /api/v1 route can still be registered without an OpenAPI row and the test stays green.

First fix: registered() only reads src/http/api.ts, and only calls whose path is a plain string literal. Missed today: 12 /api/v1 routes in src/http/feed.ts (feed, feed/chips, asks, asks/bulk, asks/decide, ...), 1 in src/http/passport_edge.ts, and the 14 api.ts routes built from a template literal such as ${BROWSE}/branches. Scan every file under src/http that calls router.add, and resolve the literal prefixes (BROWSE, and any like it) before normalising, or fail loudly when a router.add call in the scanned files has a path the regex cannot read. A count check that compares regex matches against the number of router.add( occurrences would catch both gaps. Then add the newly visible routes to NOT_YET_DESCRIBED, or describe them.

Second: expect(all.length).toBeGreaterThan(100) is a weak floor. Use the exact count check above so a changed call style cannot silently shrink coverage.

The author also says no type check ran (tsc could not find bun types); please run bun x tsc --noEmit after bun install.

No user-facing surface changes, so the tty, README and preview checks do not apply. Nothing here touches the arm-stability work, and the pull stays test-only, which is right.

commented

The test in test/openapi-coverage.test.ts now covers routes it used to miss, and it throws if it can't read a router.add call. The new test file passes and bun x tsc --noEmit is clean after bun install. I did not run the whole check, which the forge runs.

  • Every route file: it scans every file under src/http that calls router.add. That adds the routes in feed.ts and passport_edge.ts, plus api.ts paths built with ${BROWSE} or with the kind loop (${kind} expands to issues and pulls). It also expands the method loop (PUT and DELETE) for the milestone watch route.
  • Loud on unreadable calls: for each file it requires the number of readable router.add( calls to equal the number of occurrences. It also throws when an /api/v1 path still contains an unresolved ${…}. That replaces the old > 100 floor, so a changed call style can no longer shrink coverage quietly.
  • The list: NOT_YET_DESCRIBED grows from 99 to 132 entries, all of them newly visible routes, still sorted. I did not describe them. A second test fails if the list is unsorted or names a route that isn't registered.

The kind and method expansions are hard-coded in the test. If a new loop appears, the test throws at that call instead of skipping it.

Approved

Test-only, does what #5117 asked, and addresses the earlier round. I rebuilt the scanner from the diff and ran it against the current tree: it reads every router.add( in all four route files under src/http (api, feed, passport_edge, server), and the read count matches the call count in each one. It resolves ${BROWSE}, and the kind loop (api.ts:6289, issues/pulls) and method loop (api.ts:3626, PUT/DELETE) expand to what the source does. It finds 270 routes. 131 have no row against main today. Main gained rows in #5051 since this branch's base, so one list entry is now described: this test ignores it, and it can be deleted later. No /api/v1 route is registered outside src/http (mcp/oauth/passport/feed helpers all live there and all register via router.add), so the scan scope is complete. A new route with no row fails with its name; an unreadable call style throws instead of quietly reducing coverage; stale or unsorted list entries fail the second test. No security surface, no runtime change, no dependency. The tty, README and preview checks don't apply. One small non-blocking note is inline.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs