Skip to main content
Glama
task-queries.spec.ts15.4 kB
import { getTasksDueTodayTool, getTasksDueTomorrowTool, getTasksDueThisWeekTool, getTasksWithLabelTool, getWaitingTasksTool, searchTasksTool, searchTasksUsingAndTool, searchTasksUsingOrTool, } from './task-queries'; import type { MockedFunction } from 'vitest'; import { getTasksDueToday, getTasksDueTomorrow, getTasksDueThisWeek, getTasksWithLabel, getWaitingTasks, } from '../services/tasks/task-retrieval'; import { searchTasks, searchTasksUsingAnd, searchTasksUsingOr, } from '../services/tasks/task-search'; vi.mock('../services/tasks/task-retrieval'); vi.mock('../services/tasks/task-search'); const mockGetTasksDueToday = getTasksDueToday as MockedFunction< typeof getTasksDueToday >; const mockGetTasksDueTomorrow = getTasksDueTomorrow as MockedFunction< typeof getTasksDueTomorrow >; const mockGetTasksDueThisWeek = getTasksDueThisWeek as MockedFunction< typeof getTasksDueThisWeek >; const mockGetTasksWithLabel = getTasksWithLabel as MockedFunction< typeof getTasksWithLabel >; const mockGetWaitingTasks = getWaitingTasks as MockedFunction< typeof getWaitingTasks >; const mockSearchTasks = searchTasks as MockedFunction<typeof searchTasks>; const mockSearchTasksUsingAnd = searchTasksUsingAnd as MockedFunction< typeof searchTasksUsingAnd >; const mockSearchTasksUsingOr = searchTasksUsingOr as MockedFunction< typeof searchTasksUsingOr >; describe('Task Queries', () => { beforeEach(() => { vi.clearAllMocks(); }); describe('getTasksDueTodayTool', () => { it('should return tasks due today data', async () => { // arrange const mockTasks = [ { id: 123, content: 'Complete project report', description: 'Finish the quarterly report', is_completed: false, labels: ['work', 'priority'], priority: 3, due_date: '2024-01-15', url: 'https://todoist.com/showTask?id=123', comment_count: 0, }, { id: 456, content: 'Buy groceries', description: 'Milk, bread, eggs', is_completed: false, labels: ['personal'], priority: 2, due_date: '2024-01-15', url: 'https://todoist.com/showTask?id=456', comment_count: 1, }, ]; const mockResult = { tasks: mockTasks, total_count: 2, }; mockGetTasksDueToday.mockResolvedValue(mockResult); // act const result = await getTasksDueTodayTool.handler(); // assert expect(result.content[0].text).toBe(JSON.stringify(mockResult, null, 2)); expect(mockGetTasksDueToday).toHaveBeenCalledTimes(1); }); it('should handle error when service fails', async () => { // arrange mockGetTasksDueToday.mockRejectedValue(new Error('API Error')); // act const promise = getTasksDueTodayTool.handler(); // assert await expect(promise).rejects.toThrow('API Error'); }); }); describe('getTasksDueTomorrowTool', () => { it('should return formatted JSON response with tasks due tomorrow', async () => { // arrange const mockTasks = [ { id: '123', content: 'Review project proposal', description: '', is_completed: false, labels: ['work', 'priority'], priority: 1, due: { date: '2024-01-16', string: 'tomorrow', lang: 'en', is_recurring: false, }, url: 'https://todoist.com/showTask?id=123', comment_count: 0, created_at: '2024-01-15T00:00:00Z', updated_at: '2024-01-15T00:00:00Z', project_id: '456', }, { id: '124', content: 'Team meeting prep', description: '', is_completed: false, labels: ['work'], priority: 1, due: { date: '2024-01-16', string: 'tomorrow', lang: 'en', is_recurring: false, }, url: 'https://todoist.com/showTask?id=124', comment_count: 0, created_at: '2024-01-15T00:00:00Z', updated_at: '2024-01-15T00:00:00Z', project_id: '789', }, ]; mockGetTasksDueTomorrow.mockResolvedValue(mockTasks); // act const result = await getTasksDueTomorrowTool.handler(); // assert expect(result).toEqual({ content: [ { type: 'text', text: JSON.stringify(mockTasks, null, 2), }, ], }); expect(mockGetTasksDueTomorrow).toHaveBeenCalledOnce(); }); it('should handle empty response', async () => { // arrange mockGetTasksDueTomorrow.mockResolvedValue([]); // act const result = await getTasksDueTomorrowTool.handler(); // assert expect(result).toEqual({ content: [ { type: 'text', text: '[]', }, ], }); }); it('should handle service errors', async () => { // arrange const errorMessage = 'API Error'; mockGetTasksDueTomorrow.mockRejectedValue(new Error(errorMessage)); // act const promise = getTasksDueTomorrowTool.handler(); // assert await expect(promise).rejects.toThrow(errorMessage); }); }); describe('getTasksDueThisWeekTool', () => { it('should return tasks due this week in MCP format', async () => { // arrange const mockTasks = [ { id: '1', content: 'Task 1', description: '', is_completed: false, labels: [], priority: 1, due: { date: '2024-01-15', string: 'today', lang: 'en', is_recurring: false, }, url: 'https://todoist.com/showTask?id=1', comment_count: 0, created_at: '2024-01-15T00:00:00Z', updated_at: '2024-01-15T00:00:00Z', project_id: '456', }, { id: '2', content: 'Task 2', description: '', is_completed: false, labels: [], priority: 1, due: { date: '2024-01-16', string: 'tomorrow', lang: 'en', is_recurring: false, }, url: 'https://todoist.com/showTask?id=2', comment_count: 0, created_at: '2024-01-15T00:00:00Z', updated_at: '2024-01-15T00:00:00Z', project_id: '789', }, ]; mockGetTasksDueThisWeek.mockResolvedValue(mockTasks); // act const result = await getTasksDueThisWeekTool.handler(); // assert expect(result).toEqual({ content: [ { type: 'text', text: JSON.stringify(mockTasks, null, 2), }, ], }); expect(mockGetTasksDueThisWeek).toHaveBeenCalledOnce(); }); it('should handle empty results', async () => { // arrange const mockTasks: any[] = []; mockGetTasksDueThisWeek.mockResolvedValue(mockTasks); // act const result = await getTasksDueThisWeekTool.handler(); // assert expect(result.content[0].text).toBe('[]'); expect(mockGetTasksDueThisWeek).toHaveBeenCalledOnce(); }); }); describe('getTasksWithLabelTool', () => { it('should return JSON formatted tasks with label when API call succeeds', async () => { // arrange const mockTasks = [ { id: 1, content: 'Test task with urgent label', description: 'Test description 1', is_completed: false, labels: ['urgent'], priority: 1, due_date: '2024-01-01', url: 'https://todoist.com/task/1', comment_count: 2, }, { id: 2, content: 'Another urgent task', description: 'Test description 2', is_completed: false, labels: ['urgent', 'work'], priority: 2, due_date: null, url: 'https://todoist.com/task/2', comment_count: 0, }, ]; const mockResponse = { tasks: mockTasks, total_count: 2, }; mockGetTasksWithLabel.mockResolvedValue(mockResponse); // act const result = await getTasksWithLabelTool.handler({ label: 'urgent' }); // assert expect(result.content).toHaveLength(1); expect(result.content[0].type).toBe('text'); expect(result.content[0].text).toBe( JSON.stringify(mockResponse, null, 2) ); expect(mockGetTasksWithLabel).toHaveBeenCalledWith('urgent'); }); it('should handle empty response', async () => { // arrange const mockResponse = { tasks: [], total_count: 0, }; mockGetTasksWithLabel.mockResolvedValue(mockResponse); // act const result = await getTasksWithLabelTool.handler({ label: 'nonexistent', }); // assert expect(result.content).toHaveLength(1); expect(result.content[0].type).toBe('text'); expect(result.content[0].text).toBe( JSON.stringify(mockResponse, null, 2) ); expect(mockGetTasksWithLabel).toHaveBeenCalledWith('nonexistent'); }); it('should handle API errors', async () => { // arrange mockGetTasksWithLabel.mockRejectedValue(new Error('API Error')); // act const promise = getTasksWithLabelTool.handler({ label: 'urgent' }); // assert await expect(promise).rejects.toThrow('API Error'); expect(mockGetTasksWithLabel).toHaveBeenCalledWith('urgent'); }); }); describe('getWaitingTasksTool', () => { it('should return waiting tasks data', async () => { // arrange const mockTasks = [ { id: 123, content: 'Wait for client feedback', description: 'Project is on hold until client responds', is_completed: false, labels: ['Waiting', 'work'], priority: 2, due_date: null, url: 'https://todoist.com/showTask?id=123', comment_count: 0, }, { id: 456, content: 'Wait for vendor quote', description: 'Need pricing before proceeding', is_completed: false, labels: ['Brian waiting', 'business'], priority: 3, due_date: null, url: 'https://todoist.com/showTask?id=456', comment_count: 1, }, ]; const mockResult = { tasks: mockTasks, total_count: 2, }; mockGetWaitingTasks.mockResolvedValue(mockResult); // act const result = await getWaitingTasksTool.handler(); // assert expect(result.content[0].text).toBe(JSON.stringify(mockResult, null, 2)); expect(mockGetWaitingTasks).toHaveBeenCalledTimes(1); }); it('should handle error when service fails', async () => { // arrange mockGetWaitingTasks.mockRejectedValue(new Error('API Error')); // act const promise = getWaitingTasksTool.handler(); // assert await expect(promise).rejects.toThrow('API Error'); }); }); describe('searchTasksTool', () => { it('should return search results', async () => { // arrange const mockResults = { tasks: [ { id: 1, content: 'Meeting with team', description: 'Weekly team sync', is_completed: false, labels: ['work'], priority: 2, due_date: '2024-01-15', url: 'https://todoist.com/task/1', comment_count: 0, }, ], total_count: 1, }; mockSearchTasks.mockResolvedValue(mockResults); // act const result = await searchTasksTool.handler({ query: 'meeting' }); // assert expect(result.content[0].text).toBe(JSON.stringify(mockResults, null, 2)); expect(mockSearchTasks).toHaveBeenCalledWith('meeting'); }); it('should handle search errors', async () => { // arrange mockSearchTasks.mockRejectedValue(new Error('Search failed')); // act const promise = searchTasksTool.handler({ query: 'meeting' }); // assert await expect(promise).rejects.toThrow('Search failed'); }); }); describe('searchTasksUsingAndTool', () => { it('should return AND search results', async () => { // arrange const mockResults = { tasks: [ { id: 1, content: 'Weekly team meeting', description: 'Team sync meeting', is_completed: false, labels: ['work', 'meeting'], priority: 2, due_date: '2024-01-15', url: 'https://todoist.com/task/1', comment_count: 0, }, ], total_count: 1, }; mockSearchTasksUsingAnd.mockResolvedValue(mockResults); // act const result = await searchTasksUsingAndTool.handler({ search_terms: ['meeting', 'team'], }); // assert expect(result.content[0].text).toBe(JSON.stringify(mockResults, null, 2)); expect(mockSearchTasksUsingAnd).toHaveBeenCalledWith(['meeting', 'team']); }); it('should handle AND search errors', async () => { // arrange mockSearchTasksUsingAnd.mockRejectedValue(new Error('AND search failed')); // act const promise = searchTasksUsingAndTool.handler({ search_terms: ['meeting', 'team'], }); // assert await expect(promise).rejects.toThrow('AND search failed'); }); }); describe('searchTasksUsingOrTool', () => { it('should return OR search results', async () => { // arrange const mockResults = { tasks: [ { id: 1, content: 'Meeting with team', description: 'Team sync', is_completed: false, labels: ['work'], priority: 2, due_date: '2024-01-15', url: 'https://todoist.com/task/1', comment_count: 0, }, { id: 2, content: 'Team building event', description: 'Company team event', is_completed: false, labels: ['team'], priority: 3, due_date: '2024-01-20', url: 'https://todoist.com/task/2', comment_count: 1, }, ], total_count: 2, }; mockSearchTasksUsingOr.mockResolvedValue(mockResults); // act const result = await searchTasksUsingOrTool.handler({ search_terms: ['meeting', 'team'], }); // assert expect(result.content[0].text).toBe(JSON.stringify(mockResults, null, 2)); expect(mockSearchTasksUsingOr).toHaveBeenCalledWith(['meeting', 'team']); }); it('should handle OR search errors', async () => { // arrange mockSearchTasksUsingOr.mockRejectedValue(new Error('OR search failed')); // act const promise = searchTasksUsingOrTool.handler({ search_terms: ['meeting', 'team'], }); // assert await expect(promise).rejects.toThrow('OR search failed'); }); }); });

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/bkotos/todoist-mcp'

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