Skip to main content
Glama

Todo Markdown MCP Server

by danjdewhurst
todoManager.test.ts4.73 kB
import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import { TodoManager } from '../src/todoManager.js'; import { readFile, writeFile, unlink, mkdir } from 'fs/promises'; import { join } from 'path'; describe('TodoManager', () => { let todoManager: TodoManager; const testDir = '/tmp/todo-test'; const testFile = join(testDir, 'todo.md'); beforeEach(async () => { // Create test directory try { await mkdir(testDir, { recursive: true }); } catch { // Directory might already exist } todoManager = new TodoManager(testDir); // Clean up test file if it exists try { await unlink(testFile); } catch { // File doesn't exist, that's fine } }); afterEach(async () => { // Clean up test file try { await unlink(testFile); } catch { // File doesn't exist, that's fine } }); describe('listTodos', () => { it('should return empty list when no file exists', async () => { const result = await todoManager.listTodos(); expect(result).toEqual({ todos: [], total: 0, completed: 0, pending: 0, }); }); it('should parse existing markdown file correctly', async () => { const content = `# Todo List - [ ] First todo <!-- id:123 --> - [x] Second todo <!-- id:456 --> <!-- Generated by MCP Todo Server --> `; await writeFile(testFile, content, 'utf-8'); const result = await todoManager.listTodos(); expect(result.total).toBe(2); expect(result.completed).toBe(1); expect(result.pending).toBe(1); expect(result.todos[0]?.text).toBe('First todo'); expect(result.todos[0]?.completed).toBe(false); expect(result.todos[1]?.text).toBe('Second todo'); expect(result.todos[1]?.completed).toBe(true); }); }); describe('addTodo', () => { it('should add a new todo to empty file', async () => { const todo = await todoManager.addTodo({ text: 'New task' }); expect(todo.text).toBe('New task'); expect(todo.completed).toBe(false); expect(todo.id).toBeDefined(); const content = await readFile(testFile, 'utf-8'); expect(content).toContain('- [ ] New task'); expect(content).toContain(`id:${todo.id}`); }); it('should add todo to existing file', async () => { await todoManager.addTodo({ text: 'First task' }); await todoManager.addTodo({ text: 'Second task' }); const result = await todoManager.listTodos(); expect(result.total).toBe(2); expect(result.todos[0]?.text).toBe('First task'); expect(result.todos[1]?.text).toBe('Second task'); }); }); describe('updateTodo', () => { it('should update todo text', async () => { const todo = await todoManager.addTodo({ text: 'Original text' }); const updated = await todoManager.updateTodo({ id: todo.id, text: 'Updated text', }); expect(updated.text).toBe('Updated text'); expect(updated.id).toBe(todo.id); }); it('should mark todo as completed', async () => { const todo = await todoManager.addTodo({ text: 'Task to complete' }); const updated = await todoManager.updateTodo({ id: todo.id, completed: true, }); expect(updated.completed).toBe(true); expect(updated.completedAt).toBeDefined(); }); it('should throw error for non-existent todo', async () => { await expect( todoManager.updateTodo({ id: 'non-existent', text: 'New text' }) ).rejects.toThrow('Todo with id non-existent not found'); }); }); describe('deleteTodo', () => { it('should delete existing todo', async () => { const todo = await todoManager.addTodo({ text: 'To be deleted' }); await todoManager.deleteTodo({ id: todo.id }); const result = await todoManager.listTodos(); expect(result.total).toBe(0); }); it('should throw error for non-existent todo', async () => { await expect( todoManager.deleteTodo({ id: 'non-existent' }) ).rejects.toThrow('Todo with id non-existent not found'); }); }); describe('clearCompleted', () => { it('should remove all completed todos', async () => { const todo1 = await todoManager.addTodo({ text: 'Task 1' }); const todo2 = await todoManager.addTodo({ text: 'Task 2' }); await todoManager.updateTodo({ id: todo1.id, completed: true }); const cleared = await todoManager.clearCompleted(); expect(cleared).toBe(1); const result = await todoManager.listTodos(); expect(result.total).toBe(1); expect(result.todos[0]?.text).toBe('Task 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/danjdewhurst/todo-md-mcp'

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