Files
mesh-catalog/modules/gitea/test/pages.test.ts
T
jochen f4fb0a7461
mesh/merge-gate pass: builds build-agent, gitea, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did witho…
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery delivered
Name the package each controller-repository image compiles, and say a renamed file under both names (hq ADR 0267, issue 363)
Every merge to the controller's repository rebuilt the route proxy and the
build seat's holder, because their builds read that repository whole. Named,
the build seat hands each only its program's build source and the planner
moves each only when that changes. A rename was said under its new name
alone, so a file moved out of a build source changed nothing the planner
could see.
2026-10-10 02:58:31 +02:00

92 lines
5.0 KiB
TypeScript

import assert from "node:assert/strict";
import { test } from "node:test";
import { createServer } from "node:http";
import { GiteaClient } from "../client.ts";
test("every page of a pull request's files is read, though the forge caps a page at fifty", async () => {
const total = 59;
const server = createServer((req, res) => {
const url = new URL(req.url ?? "", "http://x");
const page = Number(url.searchParams.get("page") ?? "1");
const start = (page - 1) * 50;
const files = Array.from({ length: Math.max(0, Math.min(50, total - start)) }, (_, i) => ({
filename: `modules/m${start + i}/x`, status: start + i === 3 ? "deleted" : "changed" }));
res.setHeader("content-type", "application/json");
res.end(JSON.stringify(files));
});
await new Promise<void>((r) => server.listen(0, r));
const port = (server.address() as any).port;
const client = new GiteaClient(`http://127.0.0.1:${port}`, "t");
const got = await client.listPullFiles("novox", "mesh-catalog", 60);
server.close();
assert.equal(got.paths.length, total);
assert.equal(got.truncated, false);
assert.equal(new Set(got.paths).size, total);
assert.deepEqual(got.removed, ["modules/m3/x"], "a file the merge deleted is said as deleted");
});
test("a pass asks only the repositories that moved since the last look, every one before the first", async () => {
const { movedSince } = await import("../client.ts");
const repos = [
{ full_name: "a/old", name: "old", owner: "a", private: false, html_url: "", updated_at: "2026-10-05T10:00:00Z" },
{ full_name: "a/new", name: "new", owner: "a", private: false, html_url: "", updated_at: "2026-10-05T16:10:02Z" },
{ full_name: "a/unknown", name: "unknown", owner: "a", private: false, html_url: "" },
];
assert.deepEqual(movedSince(repos, "").map((r) => r.name), ["old", "new", "unknown"]);
assert.deepEqual(movedSince(repos, "2026-10-05T16:09:00.000Z").map((r) => r.name), ["new", "unknown"]);
assert.deepEqual(movedSince(repos, "2026-10-05T18:10:02+02:00").map((r) => r.name), ["new", "unknown"], "an offset is a moment, not a string");
});
test("the directories above a merge's files that hold a module at the commit are said, the root never", async () => {
const { directoriesAbove } = await import("../client.ts");
assert.deepEqual(directoriesAbove(["modules/showcase/index.ts", "modules/showcase/daemon/x.ts", "README.md", "/modules/lib/a.go"]),
["modules", "modules/lib", "modules/showcase", "modules/showcase/daemon"]);
const asked: string[] = [];
const server = createServer((req, res) => {
const url = new URL(req.url ?? "", "http://x");
asked.push(`${url.pathname}@${url.searchParams.get("ref")}`);
const held = ["/api/v1/repos/novox/mesh-catalog/contents/modules/showcase/module.json"];
res.statusCode = held.includes(url.pathname) ? 200 : 404;
res.end(res.statusCode === 200 ? "{}" : '{"message":"not found"}');
});
await new Promise<void>((r) => server.listen(0, r));
const port = (server.address() as any).port;
const client = new GiteaClient(`http://127.0.0.1:${port}`, "t");
const got = await client.moduleDirsAt("novox", "mesh-catalog", "abc", ["modules/showcase/index.ts", "modules/lib/x.go"]);
const capped = await client.moduleDirsAt("novox", "mesh-catalog", "abc", ["a/b/c/d.ts"], 2);
server.close();
assert.deepEqual(got, ["modules/showcase"], "a directory holding a manifest is a module; one holding none is not");
assert.ok(asked.every((a) => a.endsWith("@abc")), "looked up at the merge commit");
assert.equal(capped, null, "past the bound it is not said, and the mesh keeps its old rule");
});
test("a lookup the forge refuses is thrown, not read as no module", async () => {
const server = createServer((_req, res) => {
res.statusCode = 500;
res.end("down");
});
await new Promise<void>((r) => server.listen(0, r));
const port = (server.address() as any).port;
const client = new GiteaClient(`http://127.0.0.1:${port}`, "t");
await assert.rejects(client.moduleDirsAt("novox", "mesh-catalog", "abc", ["modules/x/y.ts"]));
server.close();
});
test("a renamed file is said under its old name too, as gone (novox/hq ADR 0267)", async () => {
const server = createServer((req, res) => {
const page = Number(new URL(req.url ?? "", "http://x").searchParams.get("page") ?? "1");
res.setHeader("content-type", "application/json");
res.end(JSON.stringify(page > 1 ? [] : [
{ filename: "internal/elsewhere/moved.go", previous_filename: "internal/broker/moved.go", status: "renamed" },
{ filename: "README.md", status: "changed" },
]));
});
await new Promise<void>((r) => server.listen(0, r));
const port = (server.address() as any).port;
const client = new GiteaClient(`http://127.0.0.1:${port}`, "t");
const got = await client.listPullFiles("novox", "mesh-controller", 7);
server.close();
assert.deepEqual(got.paths, ["internal/elsewhere/moved.go", "internal/broker/moved.go", "README.md"]);
assert.deepEqual(got.removed, ["internal/broker/moved.go"], "the old name is gone from the tree");
});