Initial commit

This commit is contained in:
Lina Tawfik
2025-05-19 08:32:32 -07:00
commit f66f337f4e
58 changed files with 8913 additions and 0 deletions

149
test/branch-cleanup.test.ts Normal file
View File

@@ -0,0 +1,149 @@
import { describe, test, expect, beforeEach, afterEach, spyOn } from "bun:test";
import { checkAndDeleteEmptyBranch } from "../src/github/operations/branch-cleanup";
import type { Octokits } from "../src/github/api/client";
import { GITHUB_SERVER_URL } from "../src/github/api/config";
describe("checkAndDeleteEmptyBranch", () => {
let consoleLogSpy: any;
let consoleErrorSpy: any;
beforeEach(() => {
// Spy on console methods
consoleLogSpy = spyOn(console, "log").mockImplementation(() => {});
consoleErrorSpy = spyOn(console, "error").mockImplementation(() => {});
});
afterEach(() => {
consoleLogSpy.mockRestore();
consoleErrorSpy.mockRestore();
});
const createMockOctokit = (
compareResponse?: any,
deleteRefError?: Error,
): Octokits => {
return {
rest: {
repos: {
compareCommitsWithBasehead: async () => ({
data: compareResponse || { total_commits: 0 },
}),
},
git: {
deleteRef: async () => {
if (deleteRefError) {
throw deleteRefError;
}
return { data: {} };
},
},
},
} as any as Octokits;
};
test("should return no branch link and not delete when branch is undefined", async () => {
const mockOctokit = createMockOctokit();
const result = await checkAndDeleteEmptyBranch(
mockOctokit,
"owner",
"repo",
undefined,
"main",
);
expect(result.shouldDeleteBranch).toBe(false);
expect(result.branchLink).toBe("");
expect(consoleLogSpy).not.toHaveBeenCalled();
});
test("should delete branch and return no link when branch has no commits", async () => {
const mockOctokit = createMockOctokit({ total_commits: 0 });
const result = await checkAndDeleteEmptyBranch(
mockOctokit,
"owner",
"repo",
"claude/issue-123-20240101_123456",
"main",
);
expect(result.shouldDeleteBranch).toBe(true);
expect(result.branchLink).toBe("");
expect(consoleLogSpy).toHaveBeenCalledWith(
"Branch claude/issue-123-20240101_123456 has no commits from Claude, will delete it",
);
expect(consoleLogSpy).toHaveBeenCalledWith(
"✅ Deleted empty branch: claude/issue-123-20240101_123456",
);
});
test("should not delete branch and return link when branch has commits", async () => {
const mockOctokit = createMockOctokit({ total_commits: 3 });
const result = await checkAndDeleteEmptyBranch(
mockOctokit,
"owner",
"repo",
"claude/issue-123-20240101_123456",
"main",
);
expect(result.shouldDeleteBranch).toBe(false);
expect(result.branchLink).toBe(
`\n[View branch](${GITHUB_SERVER_URL}/owner/repo/tree/claude/issue-123-20240101_123456)`,
);
expect(consoleLogSpy).not.toHaveBeenCalledWith(
expect.stringContaining("has no commits"),
);
});
test("should handle branch comparison errors gracefully", async () => {
const mockOctokit = {
rest: {
repos: {
compareCommitsWithBasehead: async () => {
throw new Error("API error");
},
},
git: {
deleteRef: async () => ({ data: {} }),
},
},
} as any as Octokits;
const result = await checkAndDeleteEmptyBranch(
mockOctokit,
"owner",
"repo",
"claude/issue-123-20240101_123456",
"main",
);
expect(result.shouldDeleteBranch).toBe(false);
expect(result.branchLink).toBe(
`\n[View branch](${GITHUB_SERVER_URL}/owner/repo/tree/claude/issue-123-20240101_123456)`,
);
expect(consoleErrorSpy).toHaveBeenCalledWith(
"Error checking for commits on Claude branch:",
expect.any(Error),
);
});
test("should handle branch deletion errors gracefully", async () => {
const deleteError = new Error("Delete failed");
const mockOctokit = createMockOctokit({ total_commits: 0 }, deleteError);
const result = await checkAndDeleteEmptyBranch(
mockOctokit,
"owner",
"repo",
"claude/issue-123-20240101_123456",
"main",
);
expect(result.shouldDeleteBranch).toBe(true);
expect(result.branchLink).toBe("");
expect(consoleErrorSpy).toHaveBeenCalledWith(
"Failed to delete branch claude/issue-123-20240101_123456:",
deleteError,
);
});
});