import { describe, expect, it } from "bun:test";
import { readFileSync } from "fs";
const SRC = readFileSync("src/routes/wikis.tsx", "utf8");
describe("every mutating wiki route is gated", () => {
it("has a write gate at all four POST handlers", () => {
const calls = SRC.match(/await denyWikiWrite\(/g) ?? [];
expect(calls.length).toBe(4);
});
it("no owner-only comparison survives", () => {
expect(SRC).not.toMatch(/user\.id !== resolved\.repo\.ownerId/);
});
it("gates create before touching the form or inserting", () => {
const create = SRC.slice(
SRC.indexOf('wikiRoutes.post("/:owner/:repo/wiki", requireAuth'),
SRC.indexOf("wikiRoutes.get(\"/:owner/:repo/wiki/:slug\", softAuth")
);
const gate = create.indexOf("denyWikiWrite");
const insert = create.indexOf("db\n .insert(wikiPages)");
expect(gate).toBeGreaterThan(-1);
if (insert > -1) expect(gate).toBeLessThan(insert);
});
});
describe("the gate itself", () => {
const helper = SRC.slice(
SRC.indexOf("async function denyWikiWrite"),
SRC.indexOf("async function denyWikiWrite") + 900
);
it("requires write, not merely read", () => {
expect(helper).toContain('satisfiesAccess(access, "write")');
});
it("derives visibility from the repo row rather than assuming public", () => {
expect(helper).toContain("isPublic: !repo.isPrivate");
});
it("returns a redirect for the caller rather than throwing", () => {
expect(helper).toContain("return c.redirect(redirectTo)");
expect(helper).toContain("return null");
});
});
|