Skip to main content
Glama

Task Trellis MCP

appendLog.e2e.test.ts7.19 kB
import { McpTestClient, TestEnvironment, createObjectContent, createObjectFile, readObjectFile, type ObjectData, } from "../utils"; describe("E2E Workflow - appendObjectLog", () => { let testEnv: TestEnvironment; let client: McpTestClient; beforeEach(async () => { testEnv = new TestEnvironment(); testEnv.setup(); client = new McpTestClient(testEnv.projectRoot); await client.connect(); await client.callTool("activate", { mode: "local", projectRoot: testEnv.projectRoot, }); }, 30000); afterEach(async () => { await client?.disconnect(); testEnv?.cleanup(); }); describe("Appending to Different Object Types", () => { it("should append log to task", async () => { const taskData: ObjectData = { id: "T-log-test", title: "Log Test Task", status: "in-progress", priority: "medium", log: ["Initial log entry"], }; await createObjectFile( testEnv.projectRoot, "task", "T-log-test", createObjectContent(taskData), ); const result = await client.callTool("append_issue_log", { id: "T-log-test", contents: "Progress update: 50% complete", }); expect(result.content[0].text).toContain("Successfully appended"); expect(result.content[0].text).toContain('"totalLogEntries": 2'); const file = await readObjectFile( testEnv.projectRoot, "t/open/T-log-test.md", ); expect(file.yaml.log).toHaveLength(2); expect(file.yaml.log[1]).toBe("Progress update: 50% complete"); }); it("should append log to project", async () => { const result = await client.callTool("create_issue", { type: "project", title: "Log Test Project", }); const projectId = result.content[0].text.match(/ID: (P-[a-z-]+)/)![1]; const logResult = await client.callTool("append_issue_log", { id: projectId, contents: "Project milestone reached", }); expect(logResult.content[0].text).toContain("Successfully appended"); const file = await readObjectFile( testEnv.projectRoot, `p/${projectId}/${projectId}.md`, ); expect(file.yaml.log).toContain("Project milestone reached"); }); it("should append log to epic", async () => { // Create project first const projectResult = await client.callTool("create_issue", { type: "project", title: "Parent Project", }); const projectId = projectResult.content[0].text.match(/ID: (P-[a-z-]+)/)![1]; // Create epic const epicResult = await client.callTool("create_issue", { type: "epic", title: "Log Test Epic", parent: projectId, }); const epicId = epicResult.content[0].text.match(/ID: (E-[a-z-]+)/)![1]; const logResult = await client.callTool("append_issue_log", { id: epicId, contents: "Epic progress note", }); expect(logResult.content[0].text).toContain("Successfully appended"); const file = await readObjectFile( testEnv.projectRoot, `p/${projectId}/e/${epicId}/${epicId}.md`, ); expect(file.yaml.log).toContain("Epic progress note"); }); it("should append log to feature", async () => { const result = await client.callTool("create_issue", { type: "feature", title: "Log Test Feature", }); const featureId = result.content[0].text.match(/ID: (F-[a-z-]+)/)![1]; const logResult = await client.callTool("append_issue_log", { id: featureId, contents: "Feature implementation note", }); expect(logResult.content[0].text).toContain("Successfully appended"); const file = await readObjectFile( testEnv.projectRoot, `f/${featureId}/${featureId}.md`, ); expect(file.yaml.log).toContain("Feature implementation note"); }); }); describe("Log Entry Formatting", () => { it("should preserve log entry format and special characters", async () => { const taskData: ObjectData = { id: "T-format-test", title: "Format Test Task", status: "open", priority: "low", log: [], }; await createObjectFile( testEnv.projectRoot, "task", "T-format-test", createObjectContent(taskData), ); const specialContent = `Multi-line log entry: - Bullet point 1 - Bullet point 2 "Quoted text" and 'single quotes' Special chars: @#$%^&*()`; await client.callTool("append_issue_log", { id: "T-format-test", contents: specialContent, }); const file = await readObjectFile( testEnv.projectRoot, "t/open/T-format-test.md", ); expect(file.yaml.log[0]).toBe(specialContent); }); it("should handle empty log entries", async () => { const taskData: ObjectData = { id: "T-empty-log", title: "Empty Log Task", status: "open", priority: "medium", }; await createObjectFile( testEnv.projectRoot, "task", "T-empty-log", createObjectContent(taskData), ); const result = await client.callTool("append_issue_log", { id: "T-empty-log", contents: "", }); expect(result.content[0].text).toContain("Successfully appended"); const file = await readObjectFile( testEnv.projectRoot, "t/open/T-empty-log.md", ); expect(file.yaml.log).toContain(""); }); }); describe("Error Handling", () => { it("should fail to append log to non-existent object", async () => { const result = await client.callTool("append_issue_log", { id: "T-nonexistent", contents: "This should fail", }); expect(result.content[0].text).toContain("not found"); }); it("should handle invalid object IDs", async () => { const result = await client.callTool("append_issue_log", { id: "invalid-id-format", contents: "Invalid ID test", }); expect(result.content[0].text).toContain("Error"); }); }); describe("Multiple Log Entries", () => { it("should maintain chronological order of log entries", async () => { const taskData: ObjectData = { id: "T-chronological", title: "Chronological Task", status: "in-progress", priority: "high", log: ["Entry 1", "Entry 2"], }; await createObjectFile( testEnv.projectRoot, "task", "T-chronological", createObjectContent(taskData), ); await client.callTool("append_issue_log", { id: "T-chronological", contents: "Entry 3", }); await client.callTool("append_issue_log", { id: "T-chronological", contents: "Entry 4", }); const file = await readObjectFile( testEnv.projectRoot, "t/open/T-chronological.md", ); expect(file.yaml.log).toEqual([ "Entry 1", "Entry 2", "Entry 3", "Entry 4", ]); }); }); });

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/langadventurellc/task-trellis-mcp'

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