Skip to main content
Glama
workflows-tasks.spec.ts13.4 kB
import { getChoresDueTodayTool, getShoppingListTool, getTicklerTasksTool, getRecentMediaTool, getAreasOfFocusTool, listNextActionsTool, } from './workflows-tasks'; import type { MockedFunction } from 'vitest'; import { getChoresDueToday, getShoppingList, getTicklerTasks, getRecentMedia, getAreasOfFocus, listNextActions, } from '../services/tasks/task-retrieval'; vi.mock('../services/tasks/task-retrieval'); const mockGetChoresDueToday = getChoresDueToday as MockedFunction< typeof getChoresDueToday >; const mockGetShoppingList = getShoppingList as MockedFunction< typeof getShoppingList >; const mockGetTicklerTasks = getTicklerTasks as MockedFunction< typeof getTicklerTasks >; const mockGetRecentMedia = getRecentMedia as MockedFunction< typeof getRecentMedia >; const mockGetAreasOfFocus = getAreasOfFocus as MockedFunction< typeof getAreasOfFocus >; const mockListNextActions = listNextActions as MockedFunction< typeof listNextActions >; describe('Workflows Tasks', () => { beforeEach(() => { vi.clearAllMocks(); }); describe('getChoresDueTodayTool', () => { it('should return chores due today or overdue', async () => { // arrange const mockTasks = [ { id: '1', content: 'Do laundry', description: '', is_completed: false, labels: ['chore'], 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: '123', }, { id: '2', content: 'Clean kitchen', description: '', is_completed: false, labels: ['chore'], priority: 1, due: { date: '2024-01-14', string: 'yesterday', lang: 'en', is_recurring: false, }, url: 'https://todoist.com/showTask?id=2', comment_count: 0, created_at: '2024-01-14T00:00:00Z', updated_at: '2024-01-14T00:00:00Z', project_id: '123', }, ]; mockGetChoresDueToday.mockResolvedValue(mockTasks); // act const result = await getChoresDueTodayTool.handler(); // assert expect(result.content[0].text).toBe(JSON.stringify(mockTasks, null, 2)); expect(mockGetChoresDueToday).toHaveBeenCalledWith(); }); it('should return empty array when no chores are due', async () => { // arrange mockGetChoresDueToday.mockResolvedValue([]); // act const result = await getChoresDueTodayTool.handler(); // assert expect(result.content[0].text).toBe('[]'); expect(mockGetChoresDueToday).toHaveBeenCalledWith(); }); it('should handle service errors gracefully', async () => { // arrange mockGetChoresDueToday.mockRejectedValue(new Error('Service Error')); // act const promise = getChoresDueTodayTool.handler(); // assert await expect(promise).rejects.toThrow('Service Error'); }); }); describe('getShoppingListTool', () => { it('should return shopping list tasks successfully', async () => { // arrange const mockTasks = [ { id: 1, content: 'Milk', description: 'Organic whole milk', is_completed: false, labels: ['dairy'], priority: 1, due_date: '2024-01-15', url: 'https://todoist.com/task/1', comment_count: 0, }, { id: 2, content: 'Bread', description: 'Whole grain bread', is_completed: false, labels: ['bakery'], priority: 2, due_date: '2024-01-15', url: 'https://todoist.com/task/2', comment_count: 0, }, ]; mockGetShoppingList.mockResolvedValue({ tasks: mockTasks, total_count: 2, }); // act const result = await getShoppingListTool.handler(); // assert expect(result).toEqual({ content: [ { type: 'text', text: JSON.stringify( { tasks: mockTasks, total_count: 2, }, null, 2 ), }, ], }); expect(mockGetShoppingList).toHaveBeenCalled(); }); it('should handle empty response', async () => { // arrange mockGetShoppingList.mockResolvedValue({ tasks: [], total_count: 0, }); // act const result = await getShoppingListTool.handler(); // assert expect(result).toEqual({ content: [ { type: 'text', text: JSON.stringify( { tasks: [], total_count: 0, }, null, 2 ), }, ], }); expect(mockGetShoppingList).toHaveBeenCalled(); }); it('should handle errors from service', async () => { // arrange mockGetShoppingList.mockRejectedValue(new Error('Service error')); // act const promise = getShoppingListTool.handler(); // assert await expect(promise).rejects.toThrow('Service error'); expect(mockGetShoppingList).toHaveBeenCalled(); }); }); describe('getTicklerTasksTool', () => { it('should return tickler tasks in MCP format', async () => { // arrange const mockTicklerTasks = [ { id: '1', project_id: '123', content: 'Review insurance policies', description: '', is_completed: false, labels: ['Tickler'], priority: 1, due: { date: '2024-01-15', string: '2024-01-15', lang: 'en', is_recurring: false, }, url: 'https://todoist.com/task/1', comment_count: 0, created_at: '2024-01-01T00:00:00Z', updated_at: '2024-01-01T00:00:00Z', }, ]; mockGetTicklerTasks.mockResolvedValue(mockTicklerTasks); // act const result = await getTicklerTasksTool.handler(); // assert expect(result).toEqual({ content: [ { type: 'text', text: JSON.stringify(mockTicklerTasks, null, 2), }, ], }); expect(mockGetTicklerTasks).toHaveBeenCalledOnce(); }); it('should handle empty results', async () => { // arrange mockGetTicklerTasks.mockResolvedValue([]); // act const result = await getTicklerTasksTool.handler(); // assert expect(result).toEqual({ content: [ { type: 'text', text: JSON.stringify([], null, 2), }, ], }); }); }); describe('getRecentMediaTool', () => { it('should return formatted JSON response', async () => { // arrange const mockTasks = [ { id: '1', content: 'Watch The Matrix', project_id: '123', labels: ['Media', 'Movie'], created_at: '2024-01-15T10:00:00Z', due: null, parent_id: null, description: '', is_completed: false, priority: 1, url: 'https://todoist.com/task/1', comment_count: 0, updated_at: '2024-01-15T10:00:00Z', }, ]; mockGetRecentMedia.mockResolvedValue(mockTasks); // act const result = await getRecentMediaTool.handler(); // assert expect(result).toEqual({ content: [ { type: 'text', text: JSON.stringify(mockTasks, null, 2), }, ], }); expect(mockGetRecentMedia).toHaveBeenCalled(); }); it('should handle empty results', async () => { // arrange mockGetRecentMedia.mockResolvedValue([]); // act const result = await getRecentMediaTool.handler(); // assert expect(result).toEqual({ content: [ { type: 'text', text: '[]', }, ], }); expect(mockGetRecentMedia).toHaveBeenCalled(); }); it('should handle service errors', async () => { // arrange mockGetRecentMedia.mockRejectedValue(new Error('Service Error')); // act const promise = getRecentMediaTool.handler(); // assert await expect(promise).rejects.toThrow('Service Error'); expect(mockGetRecentMedia).toHaveBeenCalled(); }); }); describe('getAreasOfFocusTool', () => { it('should return areas of focus tasks successfully', async () => { // arrange const mockTasks = [ { id: 1, content: 'Review quarterly goals', description: 'Strategic planning task', is_completed: false, labels: ['focus'], priority: 1, due_date: '2024-01-15', url: 'https://todoist.com/task/1', comment_count: 0, }, { id: 2, content: 'Plan strategic initiatives', description: 'Long-term planning', is_completed: false, labels: ['planning'], priority: 2, due_date: '2024-01-20', url: 'https://todoist.com/task/2', comment_count: 1, }, ]; mockGetAreasOfFocus.mockResolvedValue({ tasks: mockTasks, total_count: 2, }); // act const result = await getAreasOfFocusTool.handler(); // assert expect(result).toEqual({ content: [ { type: 'text', text: JSON.stringify( { tasks: mockTasks, total_count: 2, }, null, 2 ), }, ], }); expect(mockGetAreasOfFocus).toHaveBeenCalled(); }); it('should handle empty response', async () => { // arrange mockGetAreasOfFocus.mockResolvedValue({ tasks: [], total_count: 0, }); // act const result = await getAreasOfFocusTool.handler(); // assert expect(result).toEqual({ content: [ { type: 'text', text: JSON.stringify( { tasks: [], total_count: 0, }, null, 2 ), }, ], }); expect(mockGetAreasOfFocus).toHaveBeenCalled(); }); it('should handle errors from service', async () => { // arrange mockGetAreasOfFocus.mockRejectedValue(new Error('Service error')); // act const promise = getAreasOfFocusTool.handler(); // assert await expect(promise).rejects.toThrow('Service error'); expect(mockGetAreasOfFocus).toHaveBeenCalled(); }); }); describe('listNextActionsTool', () => { it('should return JSON formatted next actions when API call succeeds', async () => { // arrange const mockTasks = [ { id: 1, content: 'Test next action task 1', description: 'Test description 1', is_completed: false, labels: ['label1'], priority: 1, due_date: '2024-01-01', url: 'https://todoist.com/task/1', comment_count: 2, }, { id: 2, content: 'Test next action task 2', description: 'Test description 2', is_completed: false, labels: ['label2'], priority: 2, due_date: null, url: 'https://todoist.com/task/2', comment_count: 0, }, ]; const mockResponse = { tasks: mockTasks, total_count: 2, }; mockListNextActions.mockResolvedValue(mockResponse); // act const result = await listNextActionsTool.handler(); // 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(mockListNextActions).toHaveBeenCalledTimes(1); }); it('should handle empty response', async () => { // arrange const mockResponse = { tasks: [], total_count: 0, }; mockListNextActions.mockResolvedValue(mockResponse); // act const result = await listNextActionsTool.handler(); // 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(mockListNextActions).toHaveBeenCalledTimes(1); }); it('should handle API errors', async () => { // arrange mockListNextActions.mockRejectedValue(new Error('API Error')); // act const promise = listNextActionsTool.handler(); // assert await expect(promise).rejects.toThrow('API Error'); expect(mockListNextActions).toHaveBeenCalledTimes(1); }); }); });

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