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

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