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

The OpenAPI coverage test fails on a NOT_YET_DESCRIBED entry that is now described, and the stale entries leave #5407

Merged opened this

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

Merged

scout/forge:scout/5396-the-openapi-coverage-test-fails-on-a-not → main 3 commits fork

  • Merged. scout/5396-the-openapi-coverage-test-fails-on-a-not was merged into main as 2bed5cd.

Review

Sign in to review this change.
1 file changed +8 −52
test/openapi-coverage.test.ts +8 −52
@@ -5,59 +5,11 @@ import { ROUTES } from "../src/contract/openapi.ts";
55 /**
66 * Every `/api/v1` route registered in src/http/api.ts has a row in `ROUTES`
77 * (one file each under src/contract/openapi/routes/), or is listed here. This list only shrinks: describe
8 * a route, then delete its line. An entry that is now described is ignored.
8 * a route, then delete its line: an entry that is now described fails the test
9 * until you do.
910 */
1011 const NOT_YET_DESCRIBED: readonly string[] = [
11 "DELETE /api/v1/orgs/{}/teams/{}/members/{}",
12 "DELETE /api/v1/user/keys/{}",
13 "DELETE /api/v1/user/pins/{}/{}",
14 "GET /api/v1/agents",
15 "GET /api/v1/asks",
16 "GET /api/v1/feed",
17 "GET /api/v1/feed/chips",
18 "GET /api/v1/migrate/{}/stream",
19 "GET /api/v1/openapi.json",
20 "GET /api/v1/orgs/{}",
21 "GET /api/v1/orgs/{}/teams",
22 "GET /api/v1/orgs/{}/teams/{}/members",
23 "GET /api/v1/repos/{}/{}/app/{}/open",
24 "GET /api/v1/repos/{}/{}/labels",
25 "GET /api/v1/repos/{}/{}/milestones",
26 "GET /api/v1/repos/{}/{}/milestones/{}",
27 "GET /api/v1/user",
28 "GET /api/v1/user/assigned",
29 "GET /api/v1/user/keys",
30 "GET /api/v1/user/orgs",
3112 "GET /api/v1/user/origins/{}/browse/{}/{}",
32 "GET /api/v1/user/origins/{}/browse/{}/{}/issues",
33 "GET /api/v1/user/origins/{}/browse/{}/{}/issues/{}",
34 "GET /api/v1/user/origins/{}/browse/{}/{}/pulls",
35 "GET /api/v1/user/origins/{}/browse/{}/{}/pulls/{}",
36 "GET /api/v1/user/origins/{}/mirror/{}/stream",
37 "GET /api/v1/user/pins",
38 "GET /api/v1/users/{}",
39 "GET /api/v1/users/{}/repos",
40 "PATCH /api/v1/user",
41 "POST /api/v1/asks/bulk",
42 "POST /api/v1/asks/bulk/{}/undo",
43 "POST /api/v1/asks/decide",
44 "POST /api/v1/asks/decide/{}/undo",
45 "POST /api/v1/asks/proposal/{}/{}",
46 "POST /api/v1/feed/chips",
47 "POST /api/v1/repos/{}/{}/issues/{}/dependencies/{}/confirm",
48 "POST /api/v1/repos/{}/{}/milestones/{}/limb",
49 "POST /api/v1/repos/{}/{}/prompts/{}/run",
50 "POST /api/v1/repos/{}/{}/proposal-tokens",
51 "POST /api/v1/repos/{}/{}/pulls/{}/comments",
52 "POST /api/v1/repos/{}/{}/pulls/{}/variant",
53 "POST /api/v1/repos/{}/{}/reports/{}/accept",
54 "POST /api/v1/repos/{}/{}/reports/{}/dismiss",
55 "POST /api/v1/repos/{}/{}/runs/{}/steer",
56 "POST /api/v1/user/keys",
57 "PUT /api/v1/front",
58 "PUT /api/v1/repos/{}/{}/crew/{}",
59 "PUT /api/v1/repos/{}/{}/pulls/{}/labels",
60 "PUT /api/v1/user/pins/{}/{}",
6113 ];
6214
6315 const norm = (path: string) => path.replace(/[:*]\w+/g, "{}").replace(/\{\w+\}/g, "{}");
@@ -102,11 +54,15 @@ test("every registered /api/v1 route has an OpenAPI row or is listed as not yet
10254 const described = new Set(ROUTES.map((r) => `${r.method.toUpperCase()} ${norm(r.path)}`));
10355 const all = registered();
10456 const missing = all.filter((r) => !described.has(r) && !NOT_YET_DESCRIBED.includes(r));
105 const removable = NOT_YET_DESCRIBED.filter((r) => described.has(r));
106 console.log(`openapi-coverage: ${removable.length} NOT_YET_DESCRIBED entries could be removed`);
10757 expect(missing, `routes with no OpenAPI row (add a file under src/contract/openapi/routes/, then run bun scripts/openapi-routes.ts):\n${missing.join("\n")}`).toEqual([]);
10858 });
10959
60 test("NOT_YET_DESCRIBED has no entry that is now described", () => {
61 const described = new Set(ROUTES.map((r) => `${r.method.toUpperCase()} ${norm(r.path)}`));
62 const stale = NOT_YET_DESCRIBED.filter((r) => described.has(r));
63 expect(stale, `described now; delete these lines from NOT_YET_DESCRIBED:\n${stale.join("\n")}`).toEqual([]);
64 });
65
11066 test("NOT_YET_DESCRIBED is sorted and names registered routes", () => {
11167 expect([...NOT_YET_DESCRIBED]).toEqual([...NOT_YET_DESCRIBED].sort());
11268 const all = new Set(registered());

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs