Skip to main content
Glama
hunk-halo-selection.spec.tsβ€’5.9 kB
import { describe, expect, it, vi } from "vitest"; import { createChangedLines, filterContentByHunks, selectHunksWithHalo } from "../../src/utils/diff"; // Mock the Guardian class to test that it receives the correct metadata const mockAnalyze = vi.fn().mockResolvedValue({ score: 0.5, factors: ["test factor"], recommendations: ["test recommendation"], severity: "medium", }); vi.mock("@snapback/core", async () => { const actual = await vi.importActual("@snapback/core"); return { ...actual, Guardian: vi.fn().mockImplementation(() => ({ addPlugin: vi.fn(), analyze: mockAnalyze, })), }; }); describe("Hunk + Halo Selection", () => { it("mcp-001: should create changed lines from diff changes", async () => { // Test data with added and removed lines const changes = [ { added: false, removed: false, value: "const a = 1;\n" }, { added: true, removed: false, value: "const b = 2;\n" }, { added: false, removed: false, value: "const c = 3;\n" }, { added: false, removed: true, value: "const d = 4;\n" }, { added: false, removed: false, value: "const e = 5;" }, ]; const changedLines = createChangedLines(changes); // Verify that only added/removed lines are included expect(changedLines).toHaveLength(2); expect(changedLines[0]).toEqual({ lineNumber: 2, content: "const b = 2;", type: "added", }); expect(changedLines[1]).toEqual({ lineNumber: 4, content: "const d = 4;", type: "removed", }); }); it("mcp-002: should select hunks with halo (context lines)", async () => { // Test data with changed lines const changedLines = [ { lineNumber: 5, content: "const newFeature = true;", type: "added" }, { lineNumber: 10, content: "oldFunction();", type: "removed" }, { lineNumber: 25, content: "anotherNewFeature();", type: "added" }, ]; const hunks = selectHunksWithHalo(changedLines, 2); // 2 lines of context // Verify that hunks are created correctly // Lines 5 and 10 should be in separate hunks since they're more than 4 lines apart (2*2) // Line 25 should be in its own hunk expect(hunks).toHaveLength(3); // First hunk for line 5 (range 3-7) expect(hunks[0].startLine).toBe(3); expect(hunks[0].endLine).toBe(7); expect(hunks[0].lines).toHaveLength(1); expect(hunks[0].lines[0].lineNumber).toBe(5); // Second hunk for line 10 (range 8-12) expect(hunks[1].startLine).toBe(8); expect(hunks[1].endLine).toBe(12); expect(hunks[1].lines).toHaveLength(1); expect(hunks[1].lines[0].lineNumber).toBe(10); // Third hunk for line 25 (range 23-27) expect(hunks[2].startLine).toBe(23); expect(hunks[2].endLine).toBe(27); expect(hunks[2].lines).toHaveLength(1); expect(hunks[2].lines[0].lineNumber).toBe(25); }); it("mcp-003: should filter content by hunks", async () => { // Test content const content = `line 1 line 2 line 3 line 4 line 5 line 6 line 7 line 8 line 9 line 10`; // Test hunks const hunks = [ { startLine: 3, endLine: 7, lines: [{ lineNumber: 5, content: "line 5", type: "added" }], }, ]; const filteredContent = filterContentByHunks(content, hunks); // Verify that only lines within the hunk range are included const expectedContent = `line 3 line 4 line 5 line 6 line 7`; expect(filteredContent).toBe(expectedContent); }); it("mcp-004: should handle empty changed lines", async () => { const changedLines = []; const hunks = selectHunksWithHalo(changedLines, 3); // Verify that no hunks are created for empty input expect(hunks).toHaveLength(0); }); it("mcp-005: should handle single changed line", async () => { const changedLines = [{ lineNumber: 10, content: "const feature = true;", type: "added" }]; const hunks = selectHunksWithHalo(changedLines, 3); // Verify that a single hunk is created expect(hunks).toHaveLength(1); expect(hunks[0].startLine).toBe(7); // 10 - 3 expect(hunks[0].endLine).toBe(13); // 10 + 3 expect(hunks[0].lines).toHaveLength(1); }); it("mcp-006: should pass metadata.changedLines to plugins", async () => { // This test verifies that the MCP server passes the correct metadata to the Guardian // We'll simulate calling the analyze_risk tool and check that the metadata is passed correctly // Reset the mock mockAnalyze.mockClear(); // Create test changes const changes = [ { added: true, removed: false, value: "const newFeature = true;\n" }, { added: false, removed: true, value: "const oldFeature = false;\n" }, ]; // In a real implementation, this would call the actual MCP server // For now, we'll simulate what the server does // Create changed lines metadata for diff-aware analysis const changedLines = createChangedLines(changes); const hunks = selectHunksWithHalo(changedLines, 3); // 3 lines of context (halo) const metadata = { changedLines, hunks, timestamp: Date.now(), }; // Simulate calling guardian.analyze with the metadata await mockAnalyze(changes, undefined, metadata); // Verify that the metadata was passed correctly expect(mockAnalyze).toHaveBeenCalledWith(changes, undefined, metadata); expect(mockAnalyze).toHaveBeenCalledTimes(1); // Verify the structure of the metadata expect(metadata.changedLines).toBeDefined(); expect(metadata.hunks).toBeDefined(); expect(metadata.timestamp).toBeDefined(); // Verify that changedLines contains the expected data expect(metadata.changedLines).toHaveLength(2); expect(metadata.changedLines[0]).toEqual({ lineNumber: 1, content: "const newFeature = true;", type: "added", }); expect(metadata.changedLines[1]).toEqual({ lineNumber: 2, content: "const oldFeature = false;", type: "removed", }); // Verify that hunks contains the expected data expect(metadata.hunks).toHaveLength(1); // Should be merged into one hunk expect(metadata.hunks[0].lines).toHaveLength(2); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/snapback-dev/mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server