Track HiveGrid Cloud planning reference
This commit is contained in:
1 parent
b3d5ea6764
commit
e341c5938a
5784 files changed
+1104929
-3
No files matched your search
@@ -0,0 +1,108 @@
|
||||
import { execFile } from "node:child_process";
|
||||
import { mkdtemp, mkdir, writeFile } from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { promisify } from "node:util";
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import { renderApiInventoryGuardResult, validateApiInventory } from "./check-api-inventory.js";
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
|
||||
async function makeFixture() {
|
||||
const root = await mkdtemp(path.join(os.tmpdir(), "api-inventory-"));
|
||||
const appSourcePath = path.join(root, "app.ts");
|
||||
const removedWebApiRoutesRoot = path.join(root, "routes", "api");
|
||||
await writeFile(appSourcePath, 'import { Hono } from "hono";\nconst app = new Hono();\napp.get("/healthz", (c) => c.json({ ok: true }));\n', "utf8");
|
||||
return { root, appSourcePath, removedWebApiRoutesRoot };
|
||||
}
|
||||
|
||||
describe("api inventory guard", () => {
|
||||
test("passes when current inventory has no deprecated route keys", async () => {
|
||||
const result = await validateApiInventory();
|
||||
|
||||
expect(result).toEqual({ ok: true, violations: [], missingRoots: [] });
|
||||
expect(renderApiInventoryGuardResult(result)).toMatch(/^PASS api-inventory/);
|
||||
});
|
||||
|
||||
test("fails on denylisted Hono route keys without printing handler source", async () => {
|
||||
const fixture = await makeFixture();
|
||||
await writeFile(
|
||||
fixture.appSourcePath,
|
||||
'import { Hono } from "hono";\nconst app = new Hono();\napp.get("/v1/auth/me", () => {\n const token = "SECRET_TOKEN_SHOULD_NOT_PRINT";\n return token;\n});\n',
|
||||
"utf8",
|
||||
);
|
||||
|
||||
const result = await validateApiInventory({ appSourcePath: fixture.appSourcePath, removedWebApiRoutesRoot: fixture.removedWebApiRoutesRoot });
|
||||
const output = renderApiInventoryGuardResult(result);
|
||||
|
||||
expect(result.ok).toBe(false);
|
||||
expect(output).toContain("GET /v1/auth/me");
|
||||
expect(output).toContain(fixture.appSourcePath);
|
||||
expect(output).toContain(":3:1");
|
||||
expect(output).not.toContain("SECRET_TOKEN_SHOULD_NOT_PRINT");
|
||||
});
|
||||
|
||||
test("fails when removed React Router API route files are present", async () => {
|
||||
const fixture = await makeFixture();
|
||||
await mkdir(path.join(fixture.removedWebApiRoutesRoot, "auth"), { recursive: true });
|
||||
await writeFile(path.join(fixture.removedWebApiRoutesRoot, "auth", "verify-token.tsx"), "export async function loader() {}\n", "utf8");
|
||||
|
||||
const result = await validateApiInventory({ appSourcePath: fixture.appSourcePath, removedWebApiRoutesRoot: fixture.removedWebApiRoutesRoot });
|
||||
const output = renderApiInventoryGuardResult(result);
|
||||
|
||||
expect(result.ok).toBe(false);
|
||||
expect(output).toContain("GET /v1/auth/verify-token");
|
||||
expect(output).toContain("removed-react-router-api");
|
||||
expect(output).toContain(path.join(fixture.removedWebApiRoutesRoot, "auth", "verify-token.tsx"));
|
||||
});
|
||||
|
||||
test("blocks unrelated removed web API runtime routes too", async () => {
|
||||
const fixture = await makeFixture();
|
||||
await mkdir(path.join(fixture.removedWebApiRoutesRoot, "entities"), { recursive: true });
|
||||
await writeFile(path.join(fixture.removedWebApiRoutesRoot, "entities", "index.tsx"), "export async function loader() {}\n", "utf8");
|
||||
|
||||
const result = await validateApiInventory({ appSourcePath: fixture.appSourcePath, removedWebApiRoutesRoot: fixture.removedWebApiRoutesRoot });
|
||||
|
||||
expect(result.ok).toBe(false);
|
||||
expect(result.violations).toEqual([
|
||||
expect.objectContaining({
|
||||
routeKey: "REMOVED /api web route",
|
||||
surface: "removed-react-router-api",
|
||||
sourcePath: path.join(fixture.removedWebApiRoutesRoot, "entities", "index.tsx"),
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
test("passes when the removed web API route root is absent", async () => {
|
||||
const fixture = await makeFixture();
|
||||
const missingRemovedRoutesRoot = path.join(fixture.root, "missing", "api");
|
||||
|
||||
const result = await validateApiInventory({ appSourcePath: fixture.appSourcePath, removedWebApiRoutesRoot: missingRemovedRoutesRoot });
|
||||
|
||||
expect(result).toEqual({ ok: true, violations: [], missingRoots: [] });
|
||||
});
|
||||
|
||||
test("CLI fails on unknown flags", async () => {
|
||||
await expect(execFileAsync("pnpm", ["exec", "tsx", "scripts/check-api-inventory.ts", "--unknown"])).rejects.toMatchObject({
|
||||
code: 1,
|
||||
stderr: expect.stringContaining("FAIL api-inventory: unknown arguments"),
|
||||
});
|
||||
});
|
||||
|
||||
test("diagnostics are route-key and location based", async () => {
|
||||
const fixture = await makeFixture();
|
||||
await writeFile(
|
||||
fixture.appSourcePath,
|
||||
'const app = { get() {} };\napp.get("/v1/auth/me", () => "PASSWORD=never-print");\n',
|
||||
"utf8",
|
||||
);
|
||||
|
||||
const result = await validateApiInventory({ appSourcePath: fixture.appSourcePath, removedWebApiRoutesRoot: fixture.removedWebApiRoutesRoot });
|
||||
const output = renderApiInventoryGuardResult(result);
|
||||
|
||||
expect(output).toMatch(/GET \/v1\/auth\/me \[hono\] .+app\.ts:2:1/);
|
||||
expect(output).not.toContain("PASSWORD=never-print");
|
||||
expect(output).not.toContain("handler");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user