Files
zopu-code/packages/agents/src/git/gitea.test.ts
2026-07-24 02:05:30 +05:30

156 lines
4.7 KiB
TypeScript

import { describe, expect, test } from "vitest";
import { createGiteaHttpTransport, runPostRunGiteaLifecycle } from "./gitea";
import type { GitCommandRunner, GiteaTransport } from "./gitea";
const repository = {
cloneUrl: "https://git.openputer.com/puter/zopu-code.git",
defaultBranch: "main",
htmlUrl: "https://git.openputer.com/puter/zopu-code",
name: "zopu-code",
sshUrl: "ssh://git@git.openputer.com:2222/puter/zopu-code.git",
};
const makeRunner = (): GitCommandRunner & { readonly commands: string[] } => {
const commands: string[] = [];
let statusCalls = 0;
return {
commands,
run(command) {
commands.push(command);
if (command === "git branch --show-current") {
return Promise.resolve({
exitCode: 0,
stderr: "",
stdout: "work/issue-5\n",
});
}
if (command === "git status --porcelain=v1") {
statusCalls += 1;
return Promise.resolve({
exitCode: 0,
stderr: "",
stdout: statusCalls === 1 ? " M src/gitea.ts\n" : "",
});
}
if (command === "git diff --no-ext-diff --binary") {
return Promise.resolve({
exitCode: 0,
stderr: "",
stdout: "diff --git ...",
});
}
if (command === "git rev-parse HEAD") {
return Promise.resolve({
exitCode: 0,
stderr: "",
stdout: "abc123\n",
});
}
if (command.includes("git status --porcelain=v1")) {
return Promise.resolve({ exitCode: 0, stderr: "", stdout: "" });
}
return Promise.resolve({ exitCode: 0, stderr: "", stdout: "" });
},
};
};
describe("Gitea lifecycle adapter", () => {
test("inspects, commits, pushes, and creates an open PR through mocked boundaries", async () => {
const runner = makeRunner();
const pullRequests: unknown[] = [];
const transport: GiteaTransport = {
createPullRequest(input) {
pullRequests.push(input);
return Promise.resolve({
base: { ref: input.base },
head: { ref: input.head },
htmlUrl: "https://git.openputer.com/puter/zopu-code/pulls/5",
number: 5,
state: "open",
});
},
getRepository() {
return Promise.resolve(repository);
},
};
const result = await runPostRunGiteaLifecycle({
baseBranch: "main",
body: "Generated by the verified project run.",
issueNumber: 5,
issueTitle: "Publish verified changes",
repositoryPath: "puter/zopu-code",
runner,
transport,
verification: "passed",
workspace: "/workspace",
});
expect(result).toMatchObject({
branch: "work/issue-5",
commitSha: "abc123",
pullRequest: {
baseBranch: "main",
branch: "work/issue-5",
number: 5,
status: "open",
},
status: "pull_request_open",
});
expect(runner.commands).toEqual([
"git branch --show-current",
"git status --porcelain=v1",
"git diff --no-ext-diff --binary",
"git add --all && git commit -m 'feat(issue-5): Publish verified changes'",
"git rev-parse HEAD",
"git status --porcelain=v1",
"git push 'ssh://git@git.openputer.com:2222/puter/zopu-code.git' HEAD:'work/issue-5'",
]);
expect(pullRequests).toHaveLength(1);
});
test("mocks the HTTP Gitea boundary without calling the network", async () => {
const requests: Request[] = [];
const transport = createGiteaHttpTransport({
baseUrl: "https://git.openputer.com",
fetch: (input, init) => {
const request = new Request(String(input), init);
requests.push(request);
return Promise.resolve(
new Response(
request.method === "GET"
? JSON.stringify(repository)
: JSON.stringify({
base: { ref: "main" },
head: { ref: "work/issue-5" },
html_url: "https://git.openputer.com/puter/zopu-code/pulls/5",
number: 5,
state: "open",
}),
{ headers: { "content-type": "application/json" } }
)
);
},
token: "scoped-test-token",
});
await transport.getRepository("puter/zopu-code");
await transport.createPullRequest({
base: "main",
body: "body",
head: "work/issue-5",
repositoryPath: "puter/zopu-code",
title: "title",
});
expect(requests).toHaveLength(2);
expect(requests[0]?.url).toBe(
"https://git.openputer.com/api/v1/repos/puter/zopu-code"
);
expect(requests[1]?.headers.get("authorization")).toBe(
"token scoped-test-token"
);
});
});