Skip to main content
Glama

Task Trellis MCP

deserializeTrellisObject.test.ts11.5 kB
import { TrellisObject, TrellisObjectPriority, TrellisObjectStatus, TrellisObjectType, } from "../../models"; import { deserializeTrellisObject } from "../deserializeTrellisObject"; import { serializeTrellisObject } from "../serializeTrellisObject"; describe("deserializeTrellisObject", () => { it("should deserialize a basic markdown string with YAML frontmatter", () => { const markdownString = `--- id: T-test-id-123 title: Test Task status: in-progress priority: high parent: F-parent-feature-456 prerequisites: - prereq-1 - prereq-2 affectedFiles: src/file1.ts: modified src/file2.ts: created log: - Initial commit - Updated implementation schema: v1.0 childrenIds: - child-1 - child-2 created: "2025-01-15T10:00:00Z" updated: "2025-01-15T10:00:00Z" --- This is the main content of the task.`; const result = deserializeTrellisObject(markdownString); expect(result).toEqual({ id: "T-test-id-123", type: TrellisObjectType.TASK, title: "Test Task", status: TrellisObjectStatus.IN_PROGRESS, priority: TrellisObjectPriority.HIGH, parent: "F-parent-feature-456", prerequisites: ["prereq-1", "prereq-2"], affectedFiles: new Map([ ["src/file1.ts", "modified"], ["src/file2.ts", "created"], ]), log: ["Initial commit", "Updated implementation"], schema: "v1.0", childrenIds: ["child-1", "child-2"], body: "This is the main content of the task.", created: "2025-01-15T10:00:00Z", updated: "2025-01-15T10:00:00Z", }); }); it("should handle multi-line log entries correctly", () => { const markdownString = `--- id: T-multiline-test title: Multi-line Log Test status: open priority: medium prerequisites: [] affectedFiles: {} log: - Single line entry - |- Multi-line entry: This spans multiple lines With various details And even more information - Another single line - |- Complex multi-line: - Bullet point 1 - Bullet point 2 - Nested point - Final point schema: v1.0 childrenIds: [] created: "2025-01-15T10:00:00Z" updated: "2025-01-15T10:00:00Z" --- Test body content`; const result = deserializeTrellisObject(markdownString); expect(result.log).toHaveLength(4); expect(result.log[0]).toBe("Single line entry"); expect(result.log[1]).toBe( "Multi-line entry:\nThis spans multiple lines\nWith various details\nAnd even more information", ); expect(result.log[2]).toBe("Another single line"); expect(result.log[3]).toBe( "Complex multi-line:\n- Bullet point 1\n- Bullet point 2\n - Nested point\n- Final point", ); }); it("should handle empty arrays and objects correctly", () => { const markdownString = `--- id: T-empty-test title: Empty Collections Test status: draft priority: low prerequisites: [] affectedFiles: {} log: [] schema: v1.0 childrenIds: [] created: "2025-01-15T10:00:00Z" updated: "2025-01-15T10:00:00Z" --- `; const result = deserializeTrellisObject(markdownString); expect(result.prerequisites).toEqual([]); expect(result.affectedFiles).toEqual(new Map()); expect(result.log).toEqual([]); expect(result.childrenIds).toEqual([]); expect(result.body).toBe(""); }); it("should handle special characters in strings", () => { const markdownString = `--- id: T-special-chars-test title: 'Title with "quotes" and symbols: @#$%' status: in-progress priority: high prerequisites: - prereq with spaces - prereq-with-dashes affectedFiles: 'src/file with spaces.ts': 'status with "quotes"' 'src/file-with-dashes.ts': 'status: with: colons' log: - 'Log entry with "double quotes"' - "Log entry with 'single quotes'" - 'Log entry with: colons and @symbols' schema: v2.0-beta childrenIds: - child-with-dashes - child with spaces created: "2025-01-15T10:00:00Z" updated: "2025-01-15T10:00:00Z" --- Body with "quotes", symbols: @#$%, and other special characters!`; const result = deserializeTrellisObject(markdownString); expect(result.title).toBe('Title with "quotes" and symbols: @#$%'); expect(result.affectedFiles.get("src/file with spaces.ts")).toBe( 'status with "quotes"', ); expect(result.log[0]).toBe('Log entry with "double quotes"'); expect(result.body).toBe( 'Body with "quotes", symbols: @#$%, and other special characters!', ); }); it("should throw error for invalid format without frontmatter delimiters", () => { const invalidString = `id: test title: Test body content`; expect(() => deserializeTrellisObject(invalidString)).toThrow( "Invalid format: Expected YAML frontmatter delimited by --- markers", ); }); it("should throw error for invalid YAML syntax", () => { const invalidYamlString = `--- id: test title: Test invalid: [unclosed array --- body content`; expect(() => deserializeTrellisObject(invalidYamlString)).toThrow( /Invalid YAML frontmatter:/, ); }); it("should throw error for missing required fields", () => { const missingFieldString = `--- id: test title: Test Task status: open # priority is missing schema: v1.0 created: "2025-01-15T10:00:00Z" updated: "2025-01-15T10:00:00Z" --- body content`; expect(() => deserializeTrellisObject(missingFieldString)).toThrow( "Missing required field: priority", ); }); it("should throw error for invalid field types", () => { const invalidTypeString = `--- id: test title: Test Task status: open priority: 123 # should be string, not number schema: v1.0 created: "2025-01-15T10:00:00Z" updated: "2025-01-15T10:00:00Z" --- body content`; expect(() => deserializeTrellisObject(invalidTypeString)).toThrow( "Invalid type for field priority: Expected string", ); }); it("should handle non-string values in arrays by filtering them out", () => { const mixedArrayString = `--- id: T-test title: Test Task status: open priority: high prerequisites: - valid string - 123 - another string - true - null log: - valid log entry - 456 - another valid entry schema: v1.0 childrenIds: - valid-child - 789 created: "2025-01-15T10:00:00Z" updated: "2025-01-15T10:00:00Z" --- body content`; const result = deserializeTrellisObject(mixedArrayString); expect(result.prerequisites).toEqual(["valid string", "another string"]); expect(result.log).toEqual(["valid log entry", "another valid entry"]); expect(result.childrenIds).toEqual(["valid-child"]); }); it("should handle non-string values in affectedFiles by filtering them out", () => { const mixedObjectString = `--- id: T-test title: Test Task status: open priority: high prerequisites: [] affectedFiles: 'valid-file.ts': modified 'another-file.js': created 'invalid-number': 123 'invalid-boolean': true log: [] schema: v1.0 childrenIds: [] created: "2025-01-15T10:00:00Z" updated: "2025-01-15T10:00:00Z" --- body content`; const result = deserializeTrellisObject(mixedObjectString); expect(result.affectedFiles.size).toBe(2); expect(result.affectedFiles.get("valid-file.ts")).toBe("modified"); expect(result.affectedFiles.get("another-file.js")).toBe("created"); expect(result.affectedFiles.has("invalid-number")).toBe(false); expect(result.affectedFiles.has("invalid-boolean")).toBe(false); }); it("should handle complex markdown body content", () => { const complexBodyString = `--- id: T-complex-body-test title: Complex Body Test status: open priority: medium prerequisites: [] affectedFiles: {} log: [] schema: v1.0 childrenIds: [] created: "2025-01-15T10:00:00Z" updated: "2025-01-15T10:00:00Z" --- # Main Task Description This is a detailed description of the task. ## Steps to Complete 1. First step 2. Second step 3. Final step > Important note about the implementation \`\`\`typescript const example = "code block"; \`\`\` ### Additional Notes - Bullet point 1 - Bullet point 2 - Nested point - Final point`; const result = deserializeTrellisObject(complexBodyString); expect(result.body).toContain("# Main Task Description"); expect(result.body).toContain("## Steps to Complete"); expect(result.body).toContain("```typescript"); expect(result.body).toContain("- Bullet point 1"); }); it("should perform round-trip serialization/deserialization correctly", () => { const originalObject: TrellisObject = { id: "T-round-trip-test", title: "Round Trip Test", status: TrellisObjectStatus.IN_PROGRESS, priority: TrellisObjectPriority.HIGH, parent: "F-parent-feature-789", prerequisites: ["prereq-1", "prereq-2"], affectedFiles: new Map([ ["src/file1.ts", "modified"], ["src/file2.ts", "created"], ["config/settings.json", "deleted"], ]), log: [ "Initial implementation", "Multi-line log entry:\nWith multiple lines\nAnd details", "Final commit", ], schema: "v1.0", childrenIds: ["child-1", "child-2"], body: "# Task Description\n\nThis is the task body with **markdown** formatting.", type: TrellisObjectType.TASK, created: "2025-01-15T10:00:00Z", updated: "2025-01-15T10:00:00Z", }; // Serialize then deserialize const serialized = serializeTrellisObject(originalObject); const deserialized = deserializeTrellisObject(serialized); // Should be identical expect(deserialized).toEqual(originalObject); }); it("should handle frontmatter that is not an object", () => { const nonObjectString = `--- "just a string" --- body content`; expect(() => deserializeTrellisObject(nonObjectString)).toThrow( "Invalid frontmatter: Expected an object", ); }); it("should handle body content with --- markers", () => { const bodyWithDelimitersString = `--- id: T-delim-test title: Delimiter Test status: open priority: medium prerequisites: [] affectedFiles: {} log: [] schema: v1.0 childrenIds: [] created: "2025-01-15T10:00:00Z" updated: "2025-01-15T10:00:00Z" --- This body contains --- markers and should handle them correctly. --- Even multiple --- sections should work.`; const result = deserializeTrellisObject(bodyWithDelimitersString); expect(result.body).toBe(`This body contains --- markers and should handle them correctly. --- Even multiple --- sections should work.`); }); it("should handle markdown without parent field", () => { const markdownString = `--- id: P-no-parent-test title: No Parent Test status: open priority: medium prerequisites: [] affectedFiles: {} log: [] schema: v1.0 childrenIds: [] created: "2025-01-15T10:00:00Z" updated: "2025-01-15T10:00:00Z" --- Test body content`; const result = deserializeTrellisObject(markdownString); expect(result.parent).toBeNull(); expect(result.id).toBe("P-no-parent-test"); expect(result.title).toBe("No Parent Test"); }); it("should handle markdown with parent set to 'none'", () => { const markdownString = `--- id: P-none-parent-test title: None Parent Test status: open priority: medium parent: none prerequisites: [] affectedFiles: {} log: [] schema: v1.0 childrenIds: [] created: "2025-01-15T10:00:00Z" updated: "2025-01-15T10:00:00Z" --- Test body content with parent set to 'none'`; const result = deserializeTrellisObject(markdownString); expect(result.parent).toBeNull(); expect(result.id).toBe("P-none-parent-test"); expect(result.title).toBe("None Parent Test"); }); });

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