ignored.test.ts

3.9 KB · raw

1// Covers names ignored in every repo (June, 2026-10-01): a file or folder with that exact name, at2// any depth, is gone from every repo at once, stays gone in later saves, and comes back when the3// name is taken off the list.45import { beforeAll, describe, expect, test } from "bun:test";6import { mkdir, writeFile } from "node:fs/promises";7import { join } from "node:path";8import { openBucket } from "../src/bucket/reader.ts";9import { syncAll } from "../src/bucket/sync.ts";10import { Browser, type Instance, instance } from "./browser.ts";11import { makeRepos } from "./fixture.ts";1213describe("names ignored in every repo", () => {14	let inst: Instance;15	let browser: Browser;16	let repos: Awaited<ReturnType<typeof makeRepos>>;17	const status = async (path: string) => `${path} ${(await inst.app.request(path)).status}`;18	const ignore = (ignored: string) => browser.post("/admin/site", { section: "site", ignored });19	const sync = () =>20		syncAll({21			bucket: openBucket({ kind: "folder", path: repos.bucketDir }),22			kepr: inst.kepr,23			mirrorDir: join(inst.dataDir, "mirror"),24		});25	// The console applies a change after its response, once any sync under way has finished.26	const settled = async (path: string, want: number) => {27		for (let i = 0; i < 100 && (await inst.app.request(path)).status !== want; i++) {28			await Bun.sleep(50);29		}30	};31	const gone = ["/app/raw/AGENTS.md", "/app/raw/.agent/notes.md", "/lib/raw/src/AGENTS.md"];32	const kept = ["/app/raw/AGENTS.md.bak", "/app/raw/.agents/x.md", "/lib/raw/src/main.ts"];3334	beforeAll(async () => {35		repos = await makeRepos(["app", "lib"]);36		const files: [string, string][] = [37			["app/AGENTS.md", "rules\n"],38			["app/AGENTS.md.bak", "old rules\n"],39			["app/.agent/notes.md", "notes\n"],40			["app/.agents/x.md", "not the same name\n"],41			["lib/src/AGENTS.md", "nested rules\n"],42			["lib/src/main.ts", "export const a = 1;\n"],43		];44		for (const [path, text] of files) {45			const full = join(repos.bucketDir, "..", "work", path);46			await mkdir(join(full, ".."), { recursive: true });47			await writeFile(full, text);48		}49		for (const repo of ["app", "lib"]) {50			repos.koh(repo, "save", "add agent files");51			repos.koh(repo, "offer");52		}53		inst = await instance(repos.bucketDir);54		browser = new Browser(inst.app);55		await browser.signIn();56		for (const repo of ["app", "lib"]) {57			await browser.post(`/admin/repos/${repo}`, { public: "1", hidden_paths: "" });58		}59	});6061	test("refuses anything but a plain name", async () => {62		for (const name of ["src/AGENTS.md", "..", "a\u0000b", "x".repeat(256)]) {63			expect((await ignore(name)).status).toBe(400);64		}65		expect(await status(gone[0] as string)).toBe(`${gone[0]} 200`);66	});6768	test("an ignored name is gone from every repo at any depth, and only that name", async () => {69		expect((await ignore(".agent\r\nAGENTS.md\n")).status).toBe(303);70		await settled(gone[2] as string, 404);71		for (const path of gone) expect(await status(path)).toBe(`${path} 404`);72		for (const path of kept) expect(await status(path)).toBe(`${path} 200`);73		expect(await (await browser.get("/admin/site")).text()).toContain(74			">.agent\nAGENTS.md</textarea>",75		);76	});7778	test("stays ignored in saves that arrive later", async () => {79		await writeFile(join(repos.bucketDir, "..", "work", "app", "AGENTS.md"), "new rules\n");80		repos.koh("app", "save", "change the rules");81		repos.koh("app", "offer");82		await sync();83		expect(await status("/app/raw/AGENTS.md")).toBe("/app/raw/AGENTS.md 404");84		expect(await (await inst.app.request("/app")).text()).toContain("change the rules");85	});8687	test("taking a name off the list brings its files back", async () => {88		expect((await ignore(".agent")).status).toBe(303);89		await settled("/lib/raw/src/AGENTS.md", 200);90		expect(await status("/lib/raw/src/AGENTS.md")).toBe("/lib/raw/src/AGENTS.md 200");91		expect(await (await inst.app.request("/app/raw/AGENTS.md")).text()).toBe("new rules\n");92		expect(await status("/app/raw/.agent/notes.md")).toBe("/app/raw/.agent/notes.md 404");93	});94});