UNPKG

@agentics.org/sparc2

Version:

SPARC 2.0 - Autonomous Vector Coding Agent + MCP. SPARC 2.0, vectorized AI code analysis, is an intelligent coding agent framework built to automate and streamline software development. It combines secure execution environments, and version control into a

306 lines (261 loc) 7.99 kB
import { assertEquals, assertRejects, assertStringIncludes, } from "https://deno.land/std@0.203.0/testing/asserts.ts"; import { createCheckpoint, createCommit, getCurrentBranch, isRepoClean, rollbackChanges, } from "./gitIntegration.ts"; import { assertSpyCalls, spy, stub } from "https://deno.land/std@0.203.0/testing/mock.ts"; // Mock for Deno.Command const originalCommand = Deno.Command; // Mock successful command execution function mockSuccessCommand(stdout: string) { return { output: () => Promise.resolve({ success: true, stdout: new TextEncoder().encode(stdout), stderr: new Uint8Array(0), code: 0, signal: null, }), }; } // Mock failed command execution function mockFailCommand(stderr: string) { return { output: () => Promise.resolve({ success: false, stdout: new Uint8Array(0), stderr: new TextEncoder().encode(stderr), code: 1, signal: null, }), }; } // Mock logger to avoid actual logging during tests import * as logger from "../logger.ts"; const logMessageSpy = spy(logger, "logMessage"); Deno.test("createCommit should create a commit and return hash", async () => { // Setup mocks const commandStub = stub( Deno, "Command", () => mockSuccessCommand("[main abc1234] Test commit\n 1 file changed"), ); try { const hash = await createCommit("main", "test.txt", "Test commit"); // Verify the result assertEquals(hash, "abc1234"); // Verify that git add and git commit were called assertSpyCalls(commandStub, 2); // Verify that the logger was called assertSpyCalls(logMessageSpy, 1); } finally { // Restore the original function commandStub.restore(); } }); Deno.test("createCommit should handle multiple files", async () => { // Setup mocks for multiple files let callCount = 0; const commandStub = stub(Deno, "Command", (_cmd: string, _options: unknown) => { callCount++; if (callCount <= 2) { // First two calls are for git add return mockSuccessCommand(""); } else { // Third call is for git commit return mockSuccessCommand("[main def5678] Test commit multiple\n 2 files changed"); } }); try { const hash = await createCommit("main", ["file1.txt", "file2.txt"], "Test commit multiple"); // Verify the result assertEquals(hash, "def5678"); // Verify that git add was called twice (once for each file) and git commit once assertSpyCalls(commandStub, 3); } finally { commandStub.restore(); } }); Deno.test("createCommit should throw on git add failure", async () => { // Setup mock to fail on git add const commandStub = stub( Deno, "Command", () => mockFailCommand("fatal: pathspec 'nonexistent.txt' did not match any files"), ); try { await assertRejects( async () => { await createCommit("main", "nonexistent.txt", "Test commit"); }, Error, "Git add failed", ); } finally { commandStub.restore(); } }); Deno.test("createCommit should throw on git commit failure", async () => { // Setup mock to succeed on git add but fail on git commit let callCount = 0; const commandStub = stub(Deno, "Command", (_cmd: string, _options: unknown) => { callCount++; if (callCount === 1) { // First call is for git add return mockSuccessCommand(""); } else { // Second call is for git commit return mockFailCommand("fatal: cannot commit with empty message"); } }); try { await assertRejects( async () => { await createCommit("main", "test.txt", ""); }, Error, "Git commit failed", ); } finally { commandStub.restore(); } }); Deno.test("createCommit should push when requested", async () => { // Setup mocks for commit with push let callCount = 0; const commandStub = stub(Deno, "Command", (_cmd: string, _options: unknown) => { callCount++; if (callCount === 1) { // First call is for git add return mockSuccessCommand(""); } else if (callCount === 2) { // Second call is for git commit return mockSuccessCommand("[main abc1234] Test commit\n 1 file changed"); } else { // Third call is for git push return mockSuccessCommand("To github.com:user/repo.git\n abc1234..def5678 main -> main"); } }); try { const hash = await createCommit("main", "test.txt", "Test commit", { push: true }); // Verify the result assertEquals(hash, "abc1234"); // Verify that git add, git commit, and git push were called assertSpyCalls(commandStub, 3); } finally { commandStub.restore(); } }); Deno.test("rollbackChanges should reset to checkpoint", async () => { // Setup mock for git reset const commandStub = stub( Deno, "Command", () => mockSuccessCommand("HEAD is now at abc1234 Test commit"), ); try { await rollbackChanges("abc1234", "checkpoint"); // Verify that git reset was called assertSpyCalls(commandStub, 1); // Verify that the logger was called assertSpyCalls(logMessageSpy, 1); } finally { commandStub.restore(); } }); Deno.test("rollbackChanges should handle temporal rollback", async () => { // Setup mocks for temporal rollback let callCount = 0; const commandStub = stub(Deno, "Command", (_cmd: string, _options: unknown) => { callCount++; if (callCount === 1) { // First call is for git log return mockSuccessCommand("abc1234\ndef5678"); } else { // Subsequent calls are for git revert return mockSuccessCommand('Revert "Test commit"\n\nThis reverts commit abc1234.'); } }); try { await rollbackChanges("2023-01-01", "temporal"); // Verify that git log and git revert were called assertSpyCalls(commandStub, 3); // git log + 2 reverts } finally { commandStub.restore(); } }); Deno.test("createCheckpoint should create a tag", async () => { // Setup mocks for creating a checkpoint let callCount = 0; const commandStub = stub(Deno, "Command", (_cmd: string, _options: unknown) => { callCount++; if (callCount === 1) { // First call is for git tag return mockSuccessCommand(""); } else { // Second call is for git rev-parse return mockSuccessCommand("abc1234"); } }); try { const hash = await createCheckpoint("checkpoint1"); // Verify the result assertEquals(hash, "abc1234"); // Verify that git tag and git rev-parse were called assertSpyCalls(commandStub, 2); } finally { commandStub.restore(); } }); Deno.test("getCurrentBranch should return the current branch", async () => { // Setup mock for git rev-parse const commandStub = stub(Deno, "Command", () => mockSuccessCommand("main")); try { const branch = await getCurrentBranch(); // Verify the result assertEquals(branch, "main"); // Verify that git rev-parse was called assertSpyCalls(commandStub, 1); } finally { commandStub.restore(); } }); Deno.test("isRepoClean should return true for clean repo", async () => { // Setup mock for git status const commandStub = stub(Deno, "Command", () => mockSuccessCommand("")); try { const isClean = await isRepoClean(); // Verify the result assertEquals(isClean, true); // Verify that git status was called assertSpyCalls(commandStub, 1); } finally { commandStub.restore(); } }); Deno.test("isRepoClean should return false for dirty repo", async () => { // Setup mock for git status const commandStub = stub( Deno, "Command", () => mockSuccessCommand(" M modified.txt\n?? untracked.txt"), ); try { const isClean = await isRepoClean(); // Verify the result assertEquals(isClean, false); // Verify that git status was called assertSpyCalls(commandStub, 1); } finally { commandStub.restore(); } });