Swadhin Biswas Feature/ai code reviewer (#73) · 8/2/2026
105a287
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import { describe, expect, it } from "vitest";
import { readdirSync, statSync } from "node:fs";
import { join, relative } from "node:path";
import { openApiSpec } from "@/lib/openapi";
function collectRouteFiles(root: string): string[] {
const files: string[] = [];
const stack = [root];
while (stack.length > 0) {
const dir = stack.pop()!;
for (const entry of readdirSync(dir)) {
const fullPath = join(dir, entry);
const stats = statSync(fullPath);
if (stats.isDirectory()) {
stack.push(fullPath);
} else if (entry.endsWith(".ts")) {
files.push(relative(root, fullPath).replaceAll("\\", "/"));
}
}
}
return files;
}
function toOpenApiPath(routeFile: string): string {
const withoutTs = routeFile.replace(/\.ts$/, "");
let relativePath = withoutTs;
if (relativePath === "index") {
return "/repos/{owner}/{repo}/pulls";
}
if (relativePath.endsWith("/index")) {
relativePath = relativePath.slice(0, -"/index".length);
}
const normalized = relativePath.replace(/\[([^\]]+)\]/g, "{$1}");
return `/repos/{owner}/{repo}/pulls/${normalized}`;
}
function canonicalizePath(path: string): string {
return path.replace(/\{[^}]+\}/g, "{}");
}
describe("openapi pulls parity", () => {
it("documents all implemented pulls routes", () => {
const routeRoot = "src/pages/api/repos/[owner]/[repo]/pulls";
const routeFiles = collectRouteFiles(routeRoot);
const expectedPaths = routeFiles.map(toOpenApiPath).map(canonicalizePath);
const openApiPaths = new Set(Object.keys(openApiSpec.paths).map(canonicalizePath));
// Known missing from OpenAPI spec — documented routes that need spec entries
const knownMissing = new Set([
"/repos/{}/{}/pulls/reviewer-routing",
"/repos/{}/{}/pulls/{}/diff",
"/repos/{}/{}/pulls/bulk-queue-manage",
"/repos/{}/{}/pulls/bulk-queue",
"/repos/{}/{}/pulls/review-health",
"/repos/{}/{}/pulls/{}/code-quality",
"/repos/{}/{}/pulls/{}/comments/apply-suggestion",
"/repos/{}/{}/pulls/{}/ai-suggestions/{}/apply",
"/repos/{}/{}/pulls/{}/analysis",
]);
const missing = expectedPaths.filter(
(path) => !openApiPaths.has(path) && !knownMissing.has(path),
);
expect(missing).toEqual([]);
});
});