repositories / pi-ext
pi-ext
bugabingas pi extensions
owned by admin
extensions/strata/__tests__/implementation.test.ts
Rawimport { appendFile, writeFile } from "node:fs/promises";
import path from "node:path";
import { aroundEach, describe, expect, it, vi } from "vitest";
import { assertGitHubCheckout } from "../github.js";
import { collectGitHubSnapshot, formatFeedback } from "../implementation.js";
import type { Feedback, ForgeReview, Snapshot } from "../types.js";
import {
git,
nativeOperation,
nativeTest,
openFixture,
testSignal,
withFakeGh,
} from "./fixture.js";
let fixture: Awaited<ReturnType<typeof openFixture>> | undefined;
aroundEach(async (run, context) => {
try {
await nativeTest(run, context);
} finally {
fixture = undefined;
vi.restoreAllMocks();
}
});
async function connect(url: string) {
const response = await fetch(url, {
redirect: "manual",
signal: testSignal(),
});
const cookie = response.headers.get("set-cookie")?.split(";")[0] ?? "";
const origin = new URL(url).origin;
let version = await (
await fetch(`${origin}/api/state`, {
headers: { Cookie: cookie },
signal: testSignal(),
})
).json();
return (route: string, body?: unknown) =>
nativeOperation(async () => {
const response = await fetch(`${origin}/api/${route}`, {
signal: testSignal(),
method: body === undefined ? "GET" : "POST",
headers: {
Cookie: cookie,
Origin: origin,
"Content-Type": "application/json",
"If-Match": String(version.revision),
"X-Strata-Snapshot": version.snapshotId,
},
body: body === undefined ? undefined : JSON.stringify(body),
});
const payload = await response.clone().json();
if (payload.revision !== undefined) version = payload;
return response;
});
}
function ghProgram(metadata: Record<string, unknown>): string {
return `
if (args[0] === "pr") process.stdout.write(${JSON.stringify(JSON.stringify(metadata))});
else process.stdout.write("[]");
`;
}
async function excludeTestHome(root: string): Promise<void> {
await appendFile(path.join(root, ".git", "info", "exclude"), ".test-home/\n");
}
describe("forge feedback handoff", () => {
it("carries exact snapshot, checkout, PR, anchor, and source discussion identities without treating imports as findings", () => {
const snapshot: Snapshot = {
id: "snapshot-1",
repoRoot: "/work/project",
source: { kind: "base", ref: "b".repeat(40) },
base: "a".repeat(40),
head: "c".repeat(40),
hunks: [
{
id: "h-one",
path: "src/change.ts",
header: "@@ -1 +1 @@",
lines: [{ kind: "add", text: "next", newLine: 1 }],
},
],
skipped: [],
};
const forge: ForgeReview = {
provider: "github",
providerLabel: "GitHub",
repository: "acme/project",
number: 7,
url: "https://github.com/acme/project/pull/7",
title: "Change",
body: "Description",
author: "author",
baseRef: "main",
baseSha: "b".repeat(40),
headRef: "feature",
headSha: "c".repeat(40),
checkoutBranch: "strata/pr-7-feature",
comments: [
{
id: "inline:91",
url: "https://github.com/acme/project/pull/7#discussion_r91",
author: "reviewer",
body: "Imported prose must not become a finding",
kind: "inline",
path: "src/change.ts",
side: "new",
line: 1,
commit: "c".repeat(40),
outdated: false,
},
],
};
const feedback: Feedback = {
snapshotId: snapshot.id,
reviewed: ["h-one"],
findings: [
{
id: "finding-1",
hunkId: "h-one",
side: "new",
line: 1,
severity: "major",
text: "Human finding",
},
],
notes: "Human note",
};
const result = formatFeedback(snapshot, feedback, forge);
expect(result).toContain("GitHub acme/project PR #7");
expect(result).toContain("Checkout branch: strata/pr-7-feature");
expect(result).toContain(`PR base: main ${"b".repeat(40)}`);
expect(result).toContain(`PR head: feature ${"c".repeat(40)}`);
expect(result).toContain("inline:91 [inline] src/change.ts:1 (new)");
expect(result).not.toContain("Imported prose must not become a finding");
expect(result).toContain(
"[major] src/change.ts:1 (new, h-one)\nHuman finding",
);
expect(result).toContain("Ordinary local inspection and edits may proceed");
expect(result).toContain("requires separate user approval");
expect(result).toContain("is not approval to publish it");
});
});
describe.sequential("GitHub snapshot ownership", () => {
it.each([
{
scope: "PR number",
requests: [
{ host: "github.com", number: 7 },
{ host: "github.com", number: 8 },
],
},
{
scope: "forge host",
requests: [
{ host: "github.com", number: 8 },
{ host: "github.example", number: 8 },
],
},
])("isolates saved plans and drafts by $scope", async ({ requests }) => {
fixture = await openFixture();
await excludeTestHome(fixture.root);
await git(fixture.root, "add", "contract.ts", "consumer.ts");
await git(fixture.root, "commit", "--quiet", "-m", "feature");
const branch = await git(fixture.root, "branch", "--show-current");
const head = await git(fixture.root, "rev-parse", "HEAD");
const base = await git(fixture.root, "rev-parse", "HEAD^");
await git(
fixture.root,
"remote",
"add",
"origin",
"https://github.com/acme/project.git",
);
await git(
fixture.root,
"remote",
"add",
"enterprise",
"https://github.example/acme/project.git",
);
const current = fixture;
for (const [index, request] of requests.entries()) {
const url = `https://${request.host}/acme/project/pull/${request.number}`;
await withFakeGh(
ghProgram({
number: request.number,
url,
title: "Scoped review",
body: "",
author: { login: "author" },
baseRefName: "main",
baseRefOid: base,
headRefName: branch,
headRefOid: head,
headRepository: { name: "project", nameWithOwner: "acme/project" },
headRepositoryOwner: { login: "acme" },
}),
async () => {
await current.run(`--pr ${url}`);
const api = await connect(current.url);
const state = await (await api("state")).json();
expect(state.review.forge.url).toBe(url);
expect(state.review.draft).toEqual({
reviewed: [],
findings: [],
notes: "",
});
expect(current.calls).toBe(index + 1);
expect(
(
await api("draft", {
reviewed: [state.review.snapshot.hunks[0].id],
findings: [],
notes: `Notes only for ${url}`,
})
).status,
).toBe(200);
await current.run("cancel");
},
);
}
});
it("detects a same-commit branch switch across snapshot collection", async () => {
fixture = await openFixture();
await excludeTestHome(fixture.root);
await git(fixture.root, "add", "contract.ts", "consumer.ts");
await git(fixture.root, "commit", "--quiet", "-m", "feature");
expect(await git(fixture.root, "status", "--porcelain")).toBe("");
const branch = await git(fixture.root, "branch", "--show-current");
const head = await git(fixture.root, "rev-parse", "HEAD");
const forge: ForgeReview = {
provider: "github",
providerLabel: "GitHub",
repository: "acme/project",
number: 7,
url: "https://github.com/acme/project/pull/7",
title: "Pinned capture",
body: "",
author: "author",
baseRef: branch,
baseSha: head,
headRef: branch,
headSha: head,
checkoutBranch: branch,
comments: [],
};
let assertions = 0;
const github = {
assertGitHubCheckout: async (
cwd: string,
review: ForgeReview,
signal: AbortSignal,
) => {
assertions++;
await assertGitHubCheckout(cwd, review, signal);
if (assertions === 1) {
await git(cwd, "branch", "same-sha", head);
await git(cwd, "checkout", "--quiet", "same-sha");
}
},
};
await expect(
collectGitHubSnapshot(
fixture.root,
{ kind: "base", ref: head },
forge,
github,
testSignal(),
),
).rejects.toThrow(/checkout branch, commit, or working tree changed/);
expect(assertions).toBe(2);
});
it("rejects a captured HEAD that differs from the pinned PR head", async () => {
fixture = await openFixture();
await excludeTestHome(fixture.root);
await git(fixture.root, "add", "contract.ts", "consumer.ts");
await git(fixture.root, "commit", "--quiet", "-m", "feature");
const branch = await git(fixture.root, "branch", "--show-current");
const head = await git(fixture.root, "rev-parse", "HEAD");
const forge: ForgeReview = {
provider: "github",
providerLabel: "GitHub",
repository: "acme/project",
number: 7,
url: "https://github.com/acme/project/pull/7",
title: "Pinned capture",
body: "",
author: "author",
baseRef: branch,
baseSha: head,
headRef: branch,
headSha: "f".repeat(40),
checkoutBranch: branch,
comments: [],
};
const assertCheckout = vi.fn(async () => {});
await expect(
collectGitHubSnapshot(
fixture.root,
{ kind: "base", ref: head },
forge,
{ assertGitHubCheckout: assertCheckout },
testSignal(),
),
).rejects.toThrow(
/captured Git HEAD does not match the pinned GitHub PR head/,
);
expect(assertCheckout).toHaveBeenCalledOnce();
});
it("keeps the active forge snapshot after a failed staged refresh", async () => {
fixture = await openFixture();
await excludeTestHome(fixture.root);
const baseBranch = await git(fixture.root, "branch", "--show-current");
const base = await git(fixture.root, "rev-parse", "HEAD");
await git(fixture.root, "checkout", "--quiet", "-b", "feature");
await git(fixture.root, "add", "contract.ts", "consumer.ts");
await git(fixture.root, "commit", "--quiet", "-m", "feature");
expect(await git(fixture.root, "status", "--porcelain")).toBe("");
const head = await git(fixture.root, "rev-parse", "HEAD");
await git(
fixture.root,
"checkout",
"--quiet",
"-b",
"alternate-base",
base,
);
await writeFile(path.join(fixture.root, "alternate.ts"), "export {};\n");
await git(fixture.root, "add", "alternate.ts");
await git(fixture.root, "commit", "--quiet", "-m", "alternate base");
const alternateBase = await git(fixture.root, "rev-parse", "HEAD");
await git(fixture.root, "checkout", "--quiet", "feature");
await git(
fixture.root,
"remote",
"add",
"origin",
"https://github.com/acme/project.git",
);
const metadata = {
number: 7,
url: "https://github.com/acme/project/pull/7",
title: "Stable review",
body: "",
author: { login: "author" },
baseRefName: baseBranch,
baseRefOid: base,
headRefName: "feature",
headRefOid: head,
headRepository: { name: "project", nameWithOwner: "acme/project" },
headRepositoryOwner: { login: "acme" },
};
await withFakeGh(ghProgram(metadata), async () => {
await fixture?.run("--pr");
});
const api = await connect(fixture.url);
const initial = await (await api("state")).json();
const changedMetadata = {
...metadata,
baseRefName: "alternate-base",
baseRefOid: alternateBase,
};
vi.spyOn(fixture.ctx.modelRegistry, "complete").mockRejectedValueOnce(
new Error("refresh planning failed"),
);
await withFakeGh(ghProgram(changedMetadata), async () => {
expect((await api("refresh", { confirm: true })).status).toBe(500);
});
const afterFailure = await (await api("state")).json();
expect(afterFailure.review).toEqual(initial.review);
const send = vi
.spyOn(fixture.t.session, "prompt")
.mockResolvedValue(undefined);
await withFakeGh(ghProgram(metadata), async () => {
expect(
(
await api("submit", {
draft: {
reviewed: [],
findings: [],
notes: "Keep the original refresh state.",
},
})
).status,
).toBe(200);
});
await vi.waitFor(() => expect(send).toHaveBeenCalled());
expect(send.mock.calls[0]?.[0]).toContain(`PR base: ${baseBranch} ${base}`);
expect(send.mock.calls[0]?.[0]).not.toContain(alternateBase);
});
});