Add OpenAPI parity guard for pull-number routes
swadhinbiswas committed 8 months ago
f8e3815
1 parent d817506
commit f8e3815
2 files changed
+47 -1
Showing 2 changed files+47-1
▼doc/feature_audit.md
+1-1
| @@ -200,7 +200,7 @@ | ||
200 | 200 | | CLI | ✅ | `cli/` package - 21+ commands | |
201 | 201 | | Plugin/extension system | ⚠️ | `plugins.ts` infrastructure exists, but basic | |
202 | 202 | | Webhook events | ✅ | Full implementation | |
203 | -| API documentation | ⚠️ | OpenAPI coverage now includes AI callback and AI review trigger/read routes, PR detail/update routes, review/comment flows (including path-scoped comment visibility metadata), stack approvals/rebase/auto-update/merge routes, PR bulk-merge/auto-merge/checks/merge/impact/rewrite routes, PR issue-links and file-approvals routes, merge-gate reporting metadata, notifications/email test endpoints, and analytics merge-frequency/workload routes; broader endpoint parity still incomplete | | |
203 | +| API documentation | ⚠️ | OpenAPI coverage now includes AI callback and AI review trigger/read routes, PR detail/update routes, review/comment flows (including path-scoped comment visibility metadata), stack approvals/rebase/auto-update/merge routes, PR bulk-merge/auto-merge/checks/merge/impact/rewrite routes, PR issue-links and file-approvals routes, merge-gate reporting metadata, notifications/email test endpoints, and analytics merge-frequency/workload routes, plus parity guard tests for `pulls/{number}` route documentation; broader endpoint parity still incomplete | | |
204 | 204 | |
205 | 205 | ## 12. Self-Hosted & Deployment |
206 | 206 | | Feature | Status | Implementation Notes | |
207 | 207 | |
▼tests/unit/openapi-pulls-parity.test.ts
+46-0
| @@ -0,0 +1,46 @@ | ||
1 | +import { describe, expect, it } from "vitest"; | |
2 | +import { readdirSync, statSync } from "node:fs"; | |
3 | +import { join, relative } from "node:path"; | |
4 | +import { openApiSpec } from "@/lib/openapi"; | |
5 | + | |
6 | +function collectRouteFiles(root: string): string[] { | |
7 | + const files: string[] = []; | |
8 | + const stack = [root]; | |
9 | + | |
10 | + while (stack.length > 0) { | |
11 | + const dir = stack.pop()!; | |
12 | + for (const entry of readdirSync(dir)) { | |
13 | + const fullPath = join(dir, entry); | |
14 | + const stats = statSync(fullPath); | |
15 | + if (stats.isDirectory()) { | |
16 | + stack.push(fullPath); | |
17 | + } else if (entry.endsWith(".ts")) { | |
18 | + files.push(relative(root, fullPath).replaceAll("\\", "/")); | |
19 | + } | |
20 | + } | |
21 | + } | |
22 | + | |
23 | + return files; | |
24 | +} | |
25 | + | |
26 | +function toOpenApiPath(routeFile: string): string { | |
27 | + const withoutTs = routeFile.replace(/\.ts$/, ""); | |
28 | + if (withoutTs === "index") { | |
29 | + return "/repos/{owner}/{repo}/pulls/{number}"; | |
30 | + } | |
31 | + const normalized = withoutTs.replace(/\[([^\]]+)\]/g, "{$1}"); | |
32 | + return `/repos/{owner}/{repo}/pulls/{number}/${normalized}`; | |
33 | +} | |
34 | + | |
35 | +describe("openapi pulls[number] parity", () => { | |
36 | + it("documents all implemented pull-number routes", () => { | |
37 | + const routeRoot = "src/pages/api/repos/[owner]/[repo]/pulls/[number]"; | |
38 | + const routeFiles = collectRouteFiles(routeRoot); | |
39 | + const expectedPaths = routeFiles.map(toOpenApiPath); | |
40 | + | |
41 | + const openApiPaths = new Set(Object.keys(openApiSpec.paths)); | |
42 | + const missing = expectedPaths.filter((path) => !openApiPaths.has(path)); | |
43 | + | |
44 | + expect(missing).toEqual([]); | |
45 | + }); | |
46 | +}); | |
0 | 47 | |