Skip to main content
Glama
tasks.spec.ts6 kB
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { Task } from '../src/tasks/schemas.js'; import { TaskStorage } from '../src/tasks/storage.js'; import { v4 as uuidv4 } from 'uuid'; // Fix the fs mock to match Node.js ESM module structure vi.mock('fs', async () => { return { existsSync: vi.fn(() => false), writeFileSync: vi.fn(), readFileSync: vi.fn(), appendFileSync: vi.fn(), mkdirSync: vi.fn(), createWriteStream: vi.fn(() => ({ write: vi.fn(), end: vi.fn(), on: vi.fn((event, callback) => callback()) })), renameSync: vi.fn(), default: { existsSync: vi.fn(() => false), writeFileSync: vi.fn(), readFileSync: vi.fn(), appendFileSync: vi.fn(), mkdirSync: vi.fn(), createWriteStream: vi.fn(() => ({ write: vi.fn(), end: vi.fn(), on: vi.fn((event, callback) => callback()) })), renameSync: vi.fn() }, promises: { readFile: vi.fn().mockResolvedValue(''), writeFile: vi.fn().mockResolvedValue(undefined), mkdir: vi.fn().mockResolvedValue(undefined) } }; }); vi.mock('../src/utils/fs.js', () => ({ createDirectory: vi.fn() })); vi.mock('../src/utils/logger.js', () => ({ createLogger: () => ({ info: vi.fn(), error: vi.fn(), debug: vi.fn(), warn: vi.fn() }) })); vi.mock('fastmcp', () => ({ FastMCP: class { addTool = vi.fn(); callTool = vi.fn(); start = vi.fn(); } })); // Add a helper to clear all tasks for testing declare module '../src/tasks/storage.js' { interface TaskStorage { clearAllTasks(): void; } } TaskStorage.prototype.clearAllTasks = function () { (this as unknown as { tasks: Map<string, Task> }).tasks.clear(); }; describe('Task Management', () => { let taskStorage: TaskStorage; beforeEach(() => { vi.resetAllMocks(); // Create a new instance for each test taskStorage = new TaskStorage(); // Use the public helper to clear tasks taskStorage.clearAllTasks(); }); afterEach(() => { vi.useRealTimers(); vi.restoreAllMocks(); }); it('should create a new task', async () => { const task: Task = { id: uuidv4(), description: 'Test task', status: 'todo', priority: 'medium', created: new Date().toISOString(), tags: [], dependsOn: [] }; const result = await taskStorage.addTask(task); expect(result).toMatchObject({ description: task.description, status: task.status, priority: task.priority }); const allTasks = await taskStorage.getAllTasks(); expect(allTasks.length).toBe(1); expect(allTasks[0].description).toBe(task.description); }); it('should update an existing task', async () => { // Create a task const task: Task = { id: uuidv4(), description: 'Test task', status: 'todo', priority: 'medium', created: new Date().toISOString(), tags: [], dependsOn: [] }; const addedTask = await taskStorage.addTask(task); // Update the task const updatedTask = await taskStorage.updateTask(addedTask.id, { description: 'Updated task', priority: 'high' }); expect(updatedTask.description).toBe('Updated task'); expect(updatedTask.priority).toBe('high'); expect(updatedTask.id).toBe(addedTask.id); }); it('should throw error when updating a non-existent task', async () => { await expect(taskStorage.updateTask('non-existent-id', { description: 'This should fail' })).rejects.toThrow(); }); it('should delete a task', async () => { // Create a task const task: Task = { id: uuidv4(), description: 'Task to delete', status: 'todo', priority: 'low', created: new Date().toISOString(), tags: [], dependsOn: [] }; const addedTask = await taskStorage.addTask(task); const deleteResult = await taskStorage.deleteTask(addedTask.id); expect(deleteResult).toBe(true); const allTasks = await taskStorage.getAllTasks(); expect(allTasks.length).toBe(0); }); it('should filter tasks by status', async () => { // Create a todo task const todoTask: Task = { id: uuidv4(), description: 'Todo task', status: 'todo', priority: 'medium', created: new Date().toISOString(), tags: [], dependsOn: [] }; // Create a done task const doneTask: Task = { id: uuidv4(), description: 'Done task', status: 'done', priority: 'medium', created: new Date().toISOString(), tags: [], dependsOn: [] }; await taskStorage.addTask(todoTask); await taskStorage.addTask(doneTask); const todoTasks = await taskStorage.getTasksBy({ status: 'todo' }); expect(todoTasks).toHaveLength(1); expect(todoTasks[0].description).toBe('Todo task'); const doneTasks = await taskStorage.getTasksBy({ status: 'done' }); expect(doneTasks).toHaveLength(1); expect(doneTasks[0].description).toBe('Done task'); }); it('should filter tasks by priority', async () => { // Create a high priority task const highTask: Task = { id: uuidv4(), description: 'High priority task', status: 'todo', priority: 'high', created: new Date().toISOString(), tags: [], dependsOn: [] }; // Create a low priority task const lowTask: Task = { id: uuidv4(), description: 'Low priority task', status: 'todo', priority: 'low', created: new Date().toISOString(), tags: [], dependsOn: [] }; await taskStorage.addTask(highTask); await taskStorage.addTask(lowTask); const highTasks = await taskStorage.getTasksBy({ priority: 'high' }); expect(highTasks).toHaveLength(1); expect(highTasks[0].description).toBe('High priority task'); }); });

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/flight505/mcp-think-tank'

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