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" ); }); });