/ index.test.ts
index.test.ts
1 import { describe, it, expect, vi, beforeEach } from "bun:test"; 2 import orgStyleguideReminder, { isOrgFile } from "./index"; 3 import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent"; 4 5 describe("orgStyleguideReminder filter", () => { 6 it("should return true for .org files", () => { 7 expect(isOrgFile("test.org")).toBe(true); 8 }); 9 10 it("should return true for .org_archive files", () => { 11 expect(isOrgFile("test.org_archive")).toBe(true); 12 }); 13 14 it("should return true for .org.gpg files", () => { 15 expect(isOrgFile("test.org.gpg")).toBe(true); 16 }); 17 18 it("should return false for non-org files", () => { 19 expect(isOrgFile("test.txt")).toBe(false); 20 expect(isOrgFile("test.ts")).toBe(false); 21 expect(isOrgFile(undefined)).toBe(false); 22 }); 23 }); 24 25 describe("orgStyleguideReminder logic", () => { 26 let mockPi: any; 27 let mockCtx: any; 28 let handlers: Record<string, Array<(event: any, ctx: any) => any>>; 29 30 beforeEach(() => { 31 handlers = {}; 32 mockPi = { 33 on: (event: string, handler: (event: any, ctx: any) => any) => { 34 if (!handlers[event]) handlers[event] = []; 35 handlers[event].push(handler); 36 }, 37 sendUserMessage: vi.fn(), 38 }; 39 mockCtx = { 40 hasUI: true, 41 ui: { 42 notify: vi.fn(), 43 }, 44 }; 45 }); 46 47 function triggerEvent(event: string, eventData: any) { 48 const eventHandlers = handlers[event]; 49 if (eventHandlers) { 50 eventHandlers.forEach((h) => h(eventData, mockCtx)); 51 } 52 } 53 54 it("should notify and steer on first org file edit", () => { 55 orgStyleguideReminder(mockPi); 56 57 triggerEvent("tool_call", { 58 toolName: "edit", 59 input: { path: "test.org" }, 60 }); 61 62 expect(mockPi.sendUserMessage).toHaveBeenCalledTimes(1); 63 expect(mockCtx.ui.notify).toHaveBeenCalledTimes(1); 64 }); 65 66 it("should not notify on second org file edit in same session", () => { 67 orgStyleguideReminder(mockPi); 68 69 triggerEvent("tool_call", { 70 toolName: "edit", 71 input: { path: "test.org" }, 72 }); 73 triggerEvent("tool_call", { 74 toolName: "edit", 75 input: { path: "another.org" }, 76 }); 77 78 expect(mockPi.sendUserMessage).toHaveBeenCalledTimes(1); 79 expect(mockCtx.ui.notify).toHaveBeenCalledTimes(1); 80 }); 81 82 it("should notify again after session_start", () => { 83 orgStyleguideReminder(mockPi); 84 85 triggerEvent("tool_call", { 86 toolName: "edit", 87 input: { path: "test.org" }, 88 }); 89 triggerEvent("session_start", {}); 90 triggerEvent("tool_call", { 91 toolName: "edit", 92 input: { path: "test.org" }, 93 }); 94 95 expect(mockPi.sendUserMessage).toHaveBeenCalledTimes(2); 96 expect(mockCtx.ui.notify).toHaveBeenCalledTimes(2); 97 }); 98 99 it("should not notify for non-org tools", () => { 100 orgStyleguideReminder(mockPi); 101 102 triggerEvent("tool_call", { 103 toolName: "bash", 104 input: { command: "ls" }, 105 }); 106 107 expect(mockPi.sendUserMessage).not.toHaveBeenCalled(); 108 expect(mockCtx.ui.notify).not.toHaveBeenCalled(); 109 }); 110 111 it("should not notify for non-org files", () => { 112 orgStyleguideReminder(mockPi); 113 114 triggerEvent("tool_call", { 115 toolName: "edit", 116 input: { path: "test.txt" }, 117 }); 118 119 expect(mockPi.sendUserMessage).not.toHaveBeenCalled(); 120 expect(mockCtx.ui.notify).not.toHaveBeenCalled(); 121 }); 122 });