Public: anyone can read this; the crew can change it.
The OpenAPI waves reads list the query parameters their handlers read, and a test compares them #11370
Check · Review · Land · Live done — Landed and live in production.
mason/forge:mason/11359-the-openapi-waves-reads-list-the-query-p → main 2 commits fork 2 threads · 2 unresolved
3 files
changed +17
−2
src/contract/openapi/routes/getApiV1ReposOwnerNameWaves.ts +1 −1
| @@ -1,3 +1,3 @@ | ||
| 1 | 1 | import { REPO, type Route } from "../shared.ts"; |
| 2 | 2 | |
| 3 | export const route: Route = { method: "get", path: `${REPO}/waves`, summary: "List what shipped, newest first, as { items: [{ version, date, headline }], next_cursor: null }; a file that is not a wave is left out; a private repository needs a token", auth: false, role: "anonymous", reply: { items: "array", next_cursor: "null" }, refusals: { not_found: "404: no such repository, or it is not readable" } }; | |
| 3 | export const route: Route = { method: "get", path: `${REPO}/waves`, summary: "Takes no query parameters (the list is not paged: next_cursor is always null). List what shipped, newest first, as { items: [{ version, date, headline }], next_cursor: null }; a file that is not a wave is left out; a private repository needs a token", auth: false, role: "anonymous", reply: { items: "array", next_cursor: "null" }, refusals: { not_found: "404: no such repository, or it is not readable" } }; |
src/contract/openapi/routes/getApiV1ReposOwnerNameWavesVersion.ts +1 −1
| @@ -1,3 +1,3 @@ | ||
| 1 | 1 | import { REPO, type Route } from "../shared.ts"; |
| 2 | 2 | |
| 3 | export const route: Route = { method: "get", path: `${REPO}/waves/{version}`, summary: "Read one wave as { version, date, headline, highlights, pulls: [{ number, title, url }] }; number is null when the line names no pull; a private repository needs a token", auth: false, role: "anonymous", reply: { version: "string", date: "string", headline: "string", highlights: "array", pulls: "array" }, refusals: { not_found: "404: no such repository, or it is not readable, or no such wave" } }; | |
| 3 | export const route: Route = { method: "get", path: `${REPO}/waves/{version}`, summary: "Takes no query parameters. Read one wave as { version, date, headline, highlights, pulls: [{ number, title, url }] }; number is null when the line names no pull; a private repository needs a token", auth: false, role: "anonymous", reply: { version: "string", date: "string", headline: "string", highlights: "array", pulls: "array" }, refusals: { not_found: "404: no such repository, or it is not readable, or no such wave" } }; |
test/openapi-oa-waves.test.ts +15
| @@ -50,9 +50,24 @@ test("GET /api/v1/changelog lists each query parameter its handler reads", () => | ||
| 50 | 50 | |
| 51 | 51 | test("the waves list lists each query parameter its handler reads", () => { |
| 52 | 52 | const code = slice("src/http/api.ts", '"/api/v1/repos/:owner/:name/waves", async', '"/api/v1/repos/:owner/:name/waves/:version"'); |
| 53 | expect(reads(code)).toEqual([]); | |
| 53 | 54 | expect(described(`${R}/waves`)).toEqual(reads(code)); |
| 54 | 55 | }); |
| 55 | 56 | |
| 57 | test("one wave lists each query parameter its handler reads", () => { | |
| 58 | const code = slice("src/http/api.ts", '"/api/v1/repos/:owner/:name/waves/:version", async', "router.add("); | |
| 59 | expect(reads(code)).toEqual([]); | |
| 60 | expect(described(`${R}/waves/{version}`)).toEqual(reads(code)); | |
| 61 | }); | |
| 62 | ||
outdated
Wrong path: this checks the list route, not |
||
| 63 | test("the waves summaries say they take no query parameters", () => { | |
| 64 | const doc = openapi("https://f.test", "1", "admin") as any; | |
| 65 | const list = doc.paths[`${R}/waves`].get; | |
| 66 | const one = doc.paths[`${R}/waves/{version}`].get; | |
| 67 | expect(list.summary).toContain("Takes no query parameters (the list is not paged: next_cursor is always null)"); | |
| 68 | expect(one.summary).toContain("Takes no query parameters"); | |
| 69 | }); | |
| 70 | ||
| 56 | 71 | test("the comparison fails on a parameter the description lacks", () => { |
| 57 | 72 | expect(reads('ctx.url.searchParams.get("limit")')).toEqual(["limit"]); |
| 58 | 73 | expect(described("/api/v1/changelog")).not.toEqual(reads('ctx.url.searchParams.get("repo"); ctx.url.searchParams.get("limit")')); |
End marker is an unrelated comment in api.ts; use the next
router.add(so the slice is the handler and nothing else.