@doist/todoist-ai 4.16.0 → 4.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/filter-helpers.d.ts +1 -1
- package/dist/index.d.ts +1044 -196
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +61 -81
- package/dist/main.js +15 -23
- package/dist/mcp-helpers.d.ts +5 -5
- package/dist/mcp-helpers.d.ts.map +1 -1
- package/dist/mcp-server-BADReNAy.js +3092 -0
- package/dist/todoist-tool.d.ts +9 -3
- package/dist/todoist-tool.d.ts.map +1 -1
- package/dist/tool-helpers.d.ts +1 -1
- package/dist/tools/add-comments.d.ts +69 -3
- package/dist/tools/add-comments.d.ts.map +1 -1
- package/dist/tools/add-projects.d.ts +34 -3
- package/dist/tools/add-projects.d.ts.map +1 -1
- package/dist/tools/add-sections.d.ts +14 -1
- package/dist/tools/add-sections.d.ts.map +1 -1
- package/dist/tools/add-tasks.d.ts +65 -10
- package/dist/tools/add-tasks.d.ts.map +1 -1
- package/dist/tools/complete-tasks.d.ts +20 -1
- package/dist/tools/complete-tasks.d.ts.map +1 -1
- package/dist/tools/delete-object.d.ts +16 -3
- package/dist/tools/delete-object.d.ts.map +1 -1
- package/dist/tools/fetch.d.ts +8 -1
- package/dist/tools/fetch.d.ts.map +1 -1
- package/dist/tools/find-activity.d.ts +44 -7
- package/dist/tools/find-activity.d.ts.map +1 -1
- package/dist/tools/find-comments.d.ts +69 -3
- package/dist/tools/find-comments.d.ts.map +1 -1
- package/dist/tools/find-completed-tasks.d.ts +63 -5
- package/dist/tools/find-completed-tasks.d.ts.map +1 -1
- package/dist/tools/find-project-collaborators.d.ts +33 -2
- package/dist/tools/find-project-collaborators.d.ts.map +1 -1
- package/dist/tools/find-projects.d.ts +35 -1
- package/dist/tools/find-projects.d.ts.map +1 -1
- package/dist/tools/find-sections.d.ts +15 -1
- package/dist/tools/find-sections.d.ts.map +1 -1
- package/dist/tools/find-tasks-by-date.d.ts +61 -3
- package/dist/tools/find-tasks-by-date.d.ts.map +1 -1
- package/dist/tools/find-tasks.d.ts +63 -5
- package/dist/tools/find-tasks.d.ts.map +1 -1
- package/dist/tools/get-overview.d.ts +24 -1
- package/dist/tools/get-overview.d.ts.map +1 -1
- package/dist/tools/manage-assignments.d.ts +39 -2
- package/dist/tools/manage-assignments.d.ts.map +1 -1
- package/dist/tools/search.d.ts +17 -1
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/update-comments.d.ts +76 -3
- package/dist/tools/update-comments.d.ts.map +1 -1
- package/dist/tools/update-projects.d.ts +43 -1
- package/dist/tools/update-projects.d.ts.map +1 -1
- package/dist/tools/update-sections.d.ts +17 -3
- package/dist/tools/update-sections.d.ts.map +1 -1
- package/dist/tools/update-tasks.d.ts +79 -13
- package/dist/tools/update-tasks.d.ts.map +1 -1
- package/dist/tools/user-info.d.ts +19 -1
- package/dist/tools/user-info.d.ts.map +1 -1
- package/dist/utils/assignment-validator.d.ts +2 -2
- package/dist/utils/output-schemas.d.ts +233 -0
- package/dist/utils/output-schemas.d.ts.map +1 -0
- package/dist/utils/response-builders.d.ts +1 -3
- package/dist/utils/response-builders.d.ts.map +1 -1
- package/dist/utils/test-helpers.d.ts +1 -1
- package/dist/utils/user-resolver.d.ts +1 -1
- package/package.json +10 -8
- package/dist/filter-helpers.js +0 -79
- package/dist/mcp-helpers.js +0 -71
- package/dist/mcp-server.js +0 -142
- package/dist/todoist-tool.js +0 -1
- package/dist/tool-helpers.js +0 -125
- package/dist/tool-helpers.test.d.ts +0 -2
- package/dist/tool-helpers.test.d.ts.map +0 -1
- package/dist/tool-helpers.test.js +0 -223
- package/dist/tools/__tests__/add-comments.test.d.ts +0 -2
- package/dist/tools/__tests__/add-comments.test.d.ts.map +0 -1
- package/dist/tools/__tests__/add-comments.test.js +0 -241
- package/dist/tools/__tests__/add-projects.test.d.ts +0 -2
- package/dist/tools/__tests__/add-projects.test.d.ts.map +0 -1
- package/dist/tools/__tests__/add-projects.test.js +0 -174
- package/dist/tools/__tests__/add-sections.test.d.ts +0 -2
- package/dist/tools/__tests__/add-sections.test.d.ts.map +0 -1
- package/dist/tools/__tests__/add-sections.test.js +0 -185
- package/dist/tools/__tests__/add-tasks.test.d.ts +0 -2
- package/dist/tools/__tests__/add-tasks.test.d.ts.map +0 -1
- package/dist/tools/__tests__/add-tasks.test.js +0 -606
- package/dist/tools/__tests__/assignment-integration.test.d.ts +0 -2
- package/dist/tools/__tests__/assignment-integration.test.d.ts.map +0 -1
- package/dist/tools/__tests__/assignment-integration.test.js +0 -428
- package/dist/tools/__tests__/complete-tasks.test.d.ts +0 -2
- package/dist/tools/__tests__/complete-tasks.test.d.ts.map +0 -1
- package/dist/tools/__tests__/complete-tasks.test.js +0 -206
- package/dist/tools/__tests__/delete-object.test.d.ts +0 -2
- package/dist/tools/__tests__/delete-object.test.d.ts.map +0 -1
- package/dist/tools/__tests__/delete-object.test.js +0 -110
- package/dist/tools/__tests__/fetch.test.d.ts +0 -2
- package/dist/tools/__tests__/fetch.test.d.ts.map +0 -1
- package/dist/tools/__tests__/fetch.test.js +0 -279
- package/dist/tools/__tests__/find-activity.test.d.ts +0 -2
- package/dist/tools/__tests__/find-activity.test.d.ts.map +0 -1
- package/dist/tools/__tests__/find-activity.test.js +0 -229
- package/dist/tools/__tests__/find-comments.test.d.ts +0 -2
- package/dist/tools/__tests__/find-comments.test.d.ts.map +0 -1
- package/dist/tools/__tests__/find-comments.test.js +0 -236
- package/dist/tools/__tests__/find-completed-tasks.test.d.ts +0 -2
- package/dist/tools/__tests__/find-completed-tasks.test.d.ts.map +0 -1
- package/dist/tools/__tests__/find-completed-tasks.test.js +0 -423
- package/dist/tools/__tests__/find-projects.test.d.ts +0 -2
- package/dist/tools/__tests__/find-projects.test.d.ts.map +0 -1
- package/dist/tools/__tests__/find-projects.test.js +0 -154
- package/dist/tools/__tests__/find-sections.test.d.ts +0 -2
- package/dist/tools/__tests__/find-sections.test.d.ts.map +0 -1
- package/dist/tools/__tests__/find-sections.test.js +0 -313
- package/dist/tools/__tests__/find-tasks-by-date.test.d.ts +0 -2
- package/dist/tools/__tests__/find-tasks-by-date.test.d.ts.map +0 -1
- package/dist/tools/__tests__/find-tasks-by-date.test.js +0 -528
- package/dist/tools/__tests__/find-tasks.test.d.ts +0 -2
- package/dist/tools/__tests__/find-tasks.test.d.ts.map +0 -1
- package/dist/tools/__tests__/find-tasks.test.js +0 -771
- package/dist/tools/__tests__/get-overview.test.d.ts +0 -2
- package/dist/tools/__tests__/get-overview.test.d.ts.map +0 -1
- package/dist/tools/__tests__/get-overview.test.js +0 -225
- package/dist/tools/__tests__/search.test.d.ts +0 -2
- package/dist/tools/__tests__/search.test.d.ts.map +0 -1
- package/dist/tools/__tests__/search.test.js +0 -206
- package/dist/tools/__tests__/update-comments.test.d.ts +0 -2
- package/dist/tools/__tests__/update-comments.test.d.ts.map +0 -1
- package/dist/tools/__tests__/update-comments.test.js +0 -294
- package/dist/tools/__tests__/update-projects.test.d.ts +0 -2
- package/dist/tools/__tests__/update-projects.test.d.ts.map +0 -1
- package/dist/tools/__tests__/update-projects.test.js +0 -217
- package/dist/tools/__tests__/update-sections.test.d.ts +0 -2
- package/dist/tools/__tests__/update-sections.test.d.ts.map +0 -1
- package/dist/tools/__tests__/update-sections.test.js +0 -169
- package/dist/tools/__tests__/update-tasks.test.d.ts +0 -2
- package/dist/tools/__tests__/update-tasks.test.d.ts.map +0 -1
- package/dist/tools/__tests__/update-tasks.test.js +0 -788
- package/dist/tools/__tests__/user-info.test.d.ts +0 -2
- package/dist/tools/__tests__/user-info.test.d.ts.map +0 -1
- package/dist/tools/__tests__/user-info.test.js +0 -139
- package/dist/tools/add-comments.js +0 -89
- package/dist/tools/add-projects.js +0 -63
- package/dist/tools/add-sections.js +0 -74
- package/dist/tools/add-tasks.js +0 -169
- package/dist/tools/complete-tasks.js +0 -68
- package/dist/tools/delete-object.js +0 -79
- package/dist/tools/fetch.js +0 -102
- package/dist/tools/find-activity.js +0 -221
- package/dist/tools/find-comments.js +0 -148
- package/dist/tools/find-completed-tasks.js +0 -168
- package/dist/tools/find-project-collaborators.js +0 -151
- package/dist/tools/find-projects.js +0 -101
- package/dist/tools/find-sections.js +0 -101
- package/dist/tools/find-tasks-by-date.js +0 -198
- package/dist/tools/find-tasks.js +0 -329
- package/dist/tools/get-overview.js +0 -249
- package/dist/tools/manage-assignments.js +0 -337
- package/dist/tools/search.js +0 -65
- package/dist/tools/update-comments.js +0 -82
- package/dist/tools/update-projects.js +0 -84
- package/dist/tools/update-sections.js +0 -70
- package/dist/tools/update-tasks.js +0 -179
- package/dist/tools/user-info.js +0 -142
- package/dist/utils/assignment-validator.js +0 -253
- package/dist/utils/constants.js +0 -45
- package/dist/utils/duration-parser.js +0 -96
- package/dist/utils/duration-parser.test.d.ts +0 -2
- package/dist/utils/duration-parser.test.d.ts.map +0 -1
- package/dist/utils/duration-parser.test.js +0 -147
- package/dist/utils/labels.js +0 -18
- package/dist/utils/priorities.js +0 -20
- package/dist/utils/response-builders.js +0 -210
- package/dist/utils/sanitize-data.js +0 -37
- package/dist/utils/sanitize-data.test.d.ts +0 -2
- package/dist/utils/sanitize-data.test.d.ts.map +0 -1
- package/dist/utils/sanitize-data.test.js +0 -93
- package/dist/utils/test-helpers.js +0 -237
- package/dist/utils/tool-names.js +0 -40
- package/dist/utils/user-resolver.js +0 -179
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { jest } from '@jest/globals';
|
|
2
|
-
import { extractTextContent } from '../../utils/test-helpers.js';
|
|
3
|
-
import { ToolNames } from '../../utils/tool-names.js';
|
|
4
|
-
import { deleteObject } from '../delete-object.js';
|
|
5
|
-
// Mock the Todoist API
|
|
6
|
-
const mockTodoistApi = {
|
|
7
|
-
deleteProject: jest.fn(),
|
|
8
|
-
deleteSection: jest.fn(),
|
|
9
|
-
deleteTask: jest.fn(),
|
|
10
|
-
};
|
|
11
|
-
const { FIND_PROJECTS, FIND_TASKS_BY_DATE, DELETE_OBJECT } = ToolNames;
|
|
12
|
-
describe(`${DELETE_OBJECT} tool`, () => {
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
jest.clearAllMocks();
|
|
15
|
-
});
|
|
16
|
-
describe('deleting projects', () => {
|
|
17
|
-
it('should delete a project by ID', async () => {
|
|
18
|
-
mockTodoistApi.deleteProject.mockResolvedValue(true);
|
|
19
|
-
const result = await deleteObject.execute({ type: 'project', id: '6cfCcrrCFg2xP94Q' }, mockTodoistApi);
|
|
20
|
-
expect(mockTodoistApi.deleteProject).toHaveBeenCalledWith('6cfCcrrCFg2xP94Q');
|
|
21
|
-
expect(mockTodoistApi.deleteSection).not.toHaveBeenCalled();
|
|
22
|
-
expect(mockTodoistApi.deleteTask).not.toHaveBeenCalled();
|
|
23
|
-
const textContent = extractTextContent(result);
|
|
24
|
-
expect(textContent).toMatchSnapshot();
|
|
25
|
-
expect(textContent).toContain('Deleted project: id=6cfCcrrCFg2xP94Q');
|
|
26
|
-
expect(textContent).toContain(`Use ${FIND_PROJECTS} to see remaining projects`);
|
|
27
|
-
expect(result.structuredContent).toEqual({
|
|
28
|
-
deletedEntity: {
|
|
29
|
-
type: 'project',
|
|
30
|
-
id: '6cfCcrrCFg2xP94Q',
|
|
31
|
-
},
|
|
32
|
-
success: true,
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
it('should propagate project deletion errors', async () => {
|
|
36
|
-
const apiError = new Error('API Error: Cannot delete project with tasks');
|
|
37
|
-
mockTodoistApi.deleteProject.mockRejectedValue(apiError);
|
|
38
|
-
await expect(deleteObject.execute({ type: 'project', id: 'project-with-tasks' }, mockTodoistApi)).rejects.toThrow('API Error: Cannot delete project with tasks');
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
describe('deleting sections', () => {
|
|
42
|
-
it('should delete a section by ID', async () => {
|
|
43
|
-
mockTodoistApi.deleteSection.mockResolvedValue(true);
|
|
44
|
-
const result = await deleteObject.execute({ type: 'section', id: 'section-123' }, mockTodoistApi);
|
|
45
|
-
expect(mockTodoistApi.deleteSection).toHaveBeenCalledWith('section-123');
|
|
46
|
-
expect(mockTodoistApi.deleteProject).not.toHaveBeenCalled();
|
|
47
|
-
expect(mockTodoistApi.deleteTask).not.toHaveBeenCalled();
|
|
48
|
-
const textContent = extractTextContent(result);
|
|
49
|
-
expect(textContent).toMatchSnapshot();
|
|
50
|
-
expect(textContent).toContain('Deleted section: id=section-123');
|
|
51
|
-
expect(textContent).toContain(`Use ${ToolNames.FIND_SECTIONS} to see remaining sections`);
|
|
52
|
-
expect(result.structuredContent).toEqual({
|
|
53
|
-
deletedEntity: { type: 'section', id: 'section-123' },
|
|
54
|
-
success: true,
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
it('should propagate section deletion errors', async () => {
|
|
58
|
-
const apiError = new Error('API Error: Section not found');
|
|
59
|
-
mockTodoistApi.deleteSection.mockRejectedValue(apiError);
|
|
60
|
-
await expect(deleteObject.execute({ type: 'section', id: 'non-existent-section' }, mockTodoistApi)).rejects.toThrow('API Error: Section not found');
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
describe('deleting tasks', () => {
|
|
64
|
-
it('should delete a task by ID', async () => {
|
|
65
|
-
mockTodoistApi.deleteTask.mockResolvedValue(true);
|
|
66
|
-
const result = await deleteObject.execute({ type: 'task', id: '8485093748' }, mockTodoistApi);
|
|
67
|
-
expect(mockTodoistApi.deleteTask).toHaveBeenCalledWith('8485093748');
|
|
68
|
-
expect(mockTodoistApi.deleteProject).not.toHaveBeenCalled();
|
|
69
|
-
expect(mockTodoistApi.deleteSection).not.toHaveBeenCalled();
|
|
70
|
-
const textContent = extractTextContent(result);
|
|
71
|
-
expect(textContent).toMatchSnapshot();
|
|
72
|
-
expect(textContent).toContain('Deleted task: id=8485093748');
|
|
73
|
-
expect(textContent).toContain(`Use ${FIND_TASKS_BY_DATE} to see remaining tasks`);
|
|
74
|
-
expect(result.structuredContent).toEqual({
|
|
75
|
-
deletedEntity: { type: 'task', id: '8485093748' },
|
|
76
|
-
success: true,
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
it('should propagate task deletion errors', async () => {
|
|
80
|
-
const apiError = new Error('API Error: Task not found');
|
|
81
|
-
mockTodoistApi.deleteTask.mockRejectedValue(apiError);
|
|
82
|
-
await expect(deleteObject.execute({ type: 'task', id: 'non-existent-task' }, mockTodoistApi)).rejects.toThrow('API Error: Task not found');
|
|
83
|
-
});
|
|
84
|
-
it('should handle permission errors', async () => {
|
|
85
|
-
const apiError = new Error('API Error: Insufficient permissions to delete task');
|
|
86
|
-
mockTodoistApi.deleteTask.mockRejectedValue(apiError);
|
|
87
|
-
await expect(deleteObject.execute({ type: 'task', id: 'restricted-task' }, mockTodoistApi)).rejects.toThrow('API Error: Insufficient permissions to delete task');
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
describe('type validation', () => {
|
|
91
|
-
it('should handle all supported entity types', async () => {
|
|
92
|
-
mockTodoistApi.deleteProject.mockResolvedValue(true);
|
|
93
|
-
mockTodoistApi.deleteSection.mockResolvedValue(true);
|
|
94
|
-
mockTodoistApi.deleteTask.mockResolvedValue(true);
|
|
95
|
-
// Delete project
|
|
96
|
-
await deleteObject.execute({ type: 'project', id: 'proj-1' }, mockTodoistApi);
|
|
97
|
-
expect(mockTodoistApi.deleteProject).toHaveBeenCalledWith('proj-1');
|
|
98
|
-
// Delete section
|
|
99
|
-
await deleteObject.execute({ type: 'section', id: 'sect-1' }, mockTodoistApi);
|
|
100
|
-
expect(mockTodoistApi.deleteSection).toHaveBeenCalledWith('sect-1');
|
|
101
|
-
// Delete task
|
|
102
|
-
await deleteObject.execute({ type: 'task', id: 'task-1' }, mockTodoistApi);
|
|
103
|
-
expect(mockTodoistApi.deleteTask).toHaveBeenCalledWith('task-1');
|
|
104
|
-
// Verify each API method was called exactly once
|
|
105
|
-
expect(mockTodoistApi.deleteProject).toHaveBeenCalledTimes(1);
|
|
106
|
-
expect(mockTodoistApi.deleteSection).toHaveBeenCalledTimes(1);
|
|
107
|
-
expect(mockTodoistApi.deleteTask).toHaveBeenCalledTimes(1);
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/fetch.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
import { jest } from '@jest/globals';
|
|
2
|
-
import { createMockProject, createMockTask, TEST_IDS } from '../../utils/test-helpers.js';
|
|
3
|
-
import { ToolNames } from '../../utils/tool-names.js';
|
|
4
|
-
import { fetch } from '../fetch.js';
|
|
5
|
-
// Mock the Todoist API
|
|
6
|
-
const mockTodoistApi = {
|
|
7
|
-
getTask: jest.fn(),
|
|
8
|
-
getProject: jest.fn(),
|
|
9
|
-
};
|
|
10
|
-
const { FETCH } = ToolNames;
|
|
11
|
-
describe(`${FETCH} tool`, () => {
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
jest.clearAllMocks();
|
|
14
|
-
});
|
|
15
|
-
describe('fetching tasks', () => {
|
|
16
|
-
it('should fetch a task by composite ID and return full content', async () => {
|
|
17
|
-
const mockTask = createMockTask({
|
|
18
|
-
id: TEST_IDS.TASK_1,
|
|
19
|
-
content: 'Important meeting with team',
|
|
20
|
-
description: 'Discuss project roadmap and timeline',
|
|
21
|
-
labels: ['work', 'urgent'],
|
|
22
|
-
priority: 2,
|
|
23
|
-
projectId: TEST_IDS.PROJECT_WORK,
|
|
24
|
-
sectionId: TEST_IDS.SECTION_1,
|
|
25
|
-
due: {
|
|
26
|
-
date: '2025-10-15',
|
|
27
|
-
isRecurring: false,
|
|
28
|
-
datetime: null,
|
|
29
|
-
string: '2025-10-15',
|
|
30
|
-
timezone: null,
|
|
31
|
-
lang: 'en',
|
|
32
|
-
},
|
|
33
|
-
});
|
|
34
|
-
mockTodoistApi.getTask.mockResolvedValue(mockTask);
|
|
35
|
-
const result = await fetch.execute({ id: `task:${TEST_IDS.TASK_1}` }, mockTodoistApi);
|
|
36
|
-
// Verify API was called correctly
|
|
37
|
-
expect(mockTodoistApi.getTask).toHaveBeenCalledWith(TEST_IDS.TASK_1);
|
|
38
|
-
// Verify result structure
|
|
39
|
-
expect(result.content).toHaveLength(1);
|
|
40
|
-
expect(result.content[0]?.type).toBe('text');
|
|
41
|
-
// Parse the JSON response
|
|
42
|
-
const jsonResponse = JSON.parse(result.content[0]?.text ?? '{}');
|
|
43
|
-
expect(jsonResponse).toEqual({
|
|
44
|
-
id: `task:${TEST_IDS.TASK_1}`,
|
|
45
|
-
title: 'Important meeting with team',
|
|
46
|
-
text: 'Important meeting with team\n\nDescription: Discuss project roadmap and timeline\nDue: 2025-10-15\nLabels: work, urgent',
|
|
47
|
-
url: `https://app.todoist.com/app/task/${TEST_IDS.TASK_1}`,
|
|
48
|
-
metadata: {
|
|
49
|
-
priority: 2,
|
|
50
|
-
projectId: TEST_IDS.PROJECT_WORK,
|
|
51
|
-
sectionId: TEST_IDS.SECTION_1,
|
|
52
|
-
parentId: null,
|
|
53
|
-
recurring: false,
|
|
54
|
-
duration: null,
|
|
55
|
-
responsibleUid: null,
|
|
56
|
-
assignedByUid: null,
|
|
57
|
-
checked: false,
|
|
58
|
-
completedAt: null,
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
it('should fetch a task without optional fields', async () => {
|
|
63
|
-
const mockTask = createMockTask({
|
|
64
|
-
id: TEST_IDS.TASK_2,
|
|
65
|
-
content: 'Simple task',
|
|
66
|
-
description: '',
|
|
67
|
-
labels: [],
|
|
68
|
-
due: null,
|
|
69
|
-
});
|
|
70
|
-
mockTodoistApi.getTask.mockResolvedValue(mockTask);
|
|
71
|
-
const result = await fetch.execute({ id: `task:${TEST_IDS.TASK_2}` }, mockTodoistApi);
|
|
72
|
-
const jsonResponse = JSON.parse(result.content[0]?.text ?? '{}');
|
|
73
|
-
expect(jsonResponse.title).toBe('Simple task');
|
|
74
|
-
expect(jsonResponse.text).toBe('Simple task');
|
|
75
|
-
expect(jsonResponse.metadata).toEqual({
|
|
76
|
-
priority: 1,
|
|
77
|
-
projectId: TEST_IDS.PROJECT_TEST,
|
|
78
|
-
sectionId: null,
|
|
79
|
-
parentId: null,
|
|
80
|
-
recurring: false,
|
|
81
|
-
duration: null,
|
|
82
|
-
responsibleUid: null,
|
|
83
|
-
assignedByUid: null,
|
|
84
|
-
checked: false,
|
|
85
|
-
completedAt: null,
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
it('should handle tasks with recurring due dates', async () => {
|
|
89
|
-
const mockTask = createMockTask({
|
|
90
|
-
id: TEST_IDS.TASK_3,
|
|
91
|
-
content: 'Weekly meeting',
|
|
92
|
-
due: {
|
|
93
|
-
date: '2025-10-15',
|
|
94
|
-
isRecurring: true,
|
|
95
|
-
datetime: null,
|
|
96
|
-
string: 'every monday',
|
|
97
|
-
timezone: null,
|
|
98
|
-
lang: 'en',
|
|
99
|
-
},
|
|
100
|
-
});
|
|
101
|
-
mockTodoistApi.getTask.mockResolvedValue(mockTask);
|
|
102
|
-
const result = await fetch.execute({ id: `task:${TEST_IDS.TASK_3}` }, mockTodoistApi);
|
|
103
|
-
const jsonResponse = JSON.parse(result.content[0]?.text ?? '{}');
|
|
104
|
-
expect(jsonResponse.metadata.recurring).toBe('every monday');
|
|
105
|
-
});
|
|
106
|
-
it('should handle tasks with duration', async () => {
|
|
107
|
-
const mockTask = createMockTask({
|
|
108
|
-
id: TEST_IDS.TASK_1,
|
|
109
|
-
content: 'Task with duration',
|
|
110
|
-
duration: {
|
|
111
|
-
amount: 90,
|
|
112
|
-
unit: 'minute',
|
|
113
|
-
},
|
|
114
|
-
});
|
|
115
|
-
mockTodoistApi.getTask.mockResolvedValue(mockTask);
|
|
116
|
-
const result = await fetch.execute({ id: `task:${TEST_IDS.TASK_1}` }, mockTodoistApi);
|
|
117
|
-
const jsonResponse = JSON.parse(result.content[0]?.text ?? '{}');
|
|
118
|
-
expect(jsonResponse.metadata.duration).toBe('1h30m');
|
|
119
|
-
});
|
|
120
|
-
it('should handle tasks with assignments', async () => {
|
|
121
|
-
const mockTask = createMockTask({
|
|
122
|
-
id: TEST_IDS.TASK_1,
|
|
123
|
-
content: 'Assigned task',
|
|
124
|
-
responsibleUid: 'user-123',
|
|
125
|
-
assignedByUid: 'user-456',
|
|
126
|
-
});
|
|
127
|
-
mockTodoistApi.getTask.mockResolvedValue(mockTask);
|
|
128
|
-
const result = await fetch.execute({ id: `task:${TEST_IDS.TASK_1}` }, mockTodoistApi);
|
|
129
|
-
const jsonResponse = JSON.parse(result.content[0]?.text ?? '{}');
|
|
130
|
-
expect(jsonResponse.metadata.responsibleUid).toBe('user-123');
|
|
131
|
-
expect(jsonResponse.metadata.assignedByUid).toBe('user-456');
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
describe('fetching projects', () => {
|
|
135
|
-
it('should fetch a project by composite ID and return full content', async () => {
|
|
136
|
-
const mockProject = createMockProject({
|
|
137
|
-
id: TEST_IDS.PROJECT_WORK,
|
|
138
|
-
name: 'Work Project',
|
|
139
|
-
color: 'blue',
|
|
140
|
-
isFavorite: true,
|
|
141
|
-
isShared: true,
|
|
142
|
-
viewStyle: 'board',
|
|
143
|
-
parentId: null,
|
|
144
|
-
inboxProject: false,
|
|
145
|
-
});
|
|
146
|
-
mockTodoistApi.getProject.mockResolvedValue(mockProject);
|
|
147
|
-
const result = await fetch.execute({ id: `project:${TEST_IDS.PROJECT_WORK}` }, mockTodoistApi);
|
|
148
|
-
// Verify API was called correctly
|
|
149
|
-
expect(mockTodoistApi.getProject).toHaveBeenCalledWith(TEST_IDS.PROJECT_WORK);
|
|
150
|
-
// Verify result structure
|
|
151
|
-
expect(result.content).toHaveLength(1);
|
|
152
|
-
expect(result.content[0]?.type).toBe('text');
|
|
153
|
-
// Parse the JSON response
|
|
154
|
-
const jsonResponse = JSON.parse(result.content[0]?.text ?? '{}');
|
|
155
|
-
expect(jsonResponse).toEqual({
|
|
156
|
-
id: `project:${TEST_IDS.PROJECT_WORK}`,
|
|
157
|
-
title: 'Work Project',
|
|
158
|
-
text: 'Work Project\n\nShared project\nFavorite: Yes',
|
|
159
|
-
url: `https://app.todoist.com/app/project/${TEST_IDS.PROJECT_WORK}`,
|
|
160
|
-
metadata: {
|
|
161
|
-
color: 'blue',
|
|
162
|
-
isFavorite: true,
|
|
163
|
-
isShared: true,
|
|
164
|
-
parentId: null,
|
|
165
|
-
inboxProject: false,
|
|
166
|
-
viewStyle: 'board',
|
|
167
|
-
},
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
it('should fetch a project without optional flags', async () => {
|
|
171
|
-
const mockProject = createMockProject({
|
|
172
|
-
id: TEST_IDS.PROJECT_TEST,
|
|
173
|
-
name: 'Simple Project',
|
|
174
|
-
isFavorite: false,
|
|
175
|
-
isShared: false,
|
|
176
|
-
});
|
|
177
|
-
mockTodoistApi.getProject.mockResolvedValue(mockProject);
|
|
178
|
-
const result = await fetch.execute({ id: `project:${TEST_IDS.PROJECT_TEST}` }, mockTodoistApi);
|
|
179
|
-
const jsonResponse = JSON.parse(result.content[0]?.text ?? '{}');
|
|
180
|
-
expect(jsonResponse.title).toBe('Simple Project');
|
|
181
|
-
expect(jsonResponse.text).toBe('Simple Project');
|
|
182
|
-
expect(jsonResponse.metadata.isFavorite).toBe(false);
|
|
183
|
-
expect(jsonResponse.metadata.isShared).toBe(false);
|
|
184
|
-
});
|
|
185
|
-
it('should fetch inbox project', async () => {
|
|
186
|
-
const mockProject = createMockProject({
|
|
187
|
-
id: TEST_IDS.PROJECT_INBOX,
|
|
188
|
-
name: 'Inbox',
|
|
189
|
-
inboxProject: true,
|
|
190
|
-
});
|
|
191
|
-
mockTodoistApi.getProject.mockResolvedValue(mockProject);
|
|
192
|
-
const result = await fetch.execute({ id: `project:${TEST_IDS.PROJECT_INBOX}` }, mockTodoistApi);
|
|
193
|
-
const jsonResponse = JSON.parse(result.content[0]?.text ?? '{}');
|
|
194
|
-
expect(jsonResponse.metadata.inboxProject).toBe(true);
|
|
195
|
-
});
|
|
196
|
-
it('should fetch project with parent ID', async () => {
|
|
197
|
-
const mockProject = createMockProject({
|
|
198
|
-
id: 'sub-project-id',
|
|
199
|
-
name: 'Sub Project',
|
|
200
|
-
parentId: TEST_IDS.PROJECT_WORK,
|
|
201
|
-
});
|
|
202
|
-
mockTodoistApi.getProject.mockResolvedValue(mockProject);
|
|
203
|
-
const result = await fetch.execute({ id: 'project:sub-project-id' }, mockTodoistApi);
|
|
204
|
-
const jsonResponse = JSON.parse(result.content[0]?.text ?? '{}');
|
|
205
|
-
expect(jsonResponse.metadata.parentId).toBe(TEST_IDS.PROJECT_WORK);
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
describe('error handling', () => {
|
|
209
|
-
it('should return error response for invalid ID format (missing colon)', async () => {
|
|
210
|
-
const result = await fetch.execute({ id: 'invalid-id' }, mockTodoistApi);
|
|
211
|
-
expect(result.isError).toBe(true);
|
|
212
|
-
expect(result.content[0]?.text).toContain('Invalid ID format');
|
|
213
|
-
});
|
|
214
|
-
it('should return error response for invalid ID format (missing type)', async () => {
|
|
215
|
-
const result = await fetch.execute({ id: ':8485093748' }, mockTodoistApi);
|
|
216
|
-
expect(result.isError).toBe(true);
|
|
217
|
-
expect(result.content[0]?.text).toContain('Invalid ID format');
|
|
218
|
-
});
|
|
219
|
-
it('should return error response for invalid ID format (missing object ID)', async () => {
|
|
220
|
-
const result = await fetch.execute({ id: 'task:' }, mockTodoistApi);
|
|
221
|
-
expect(result.isError).toBe(true);
|
|
222
|
-
expect(result.content[0]?.text).toContain('Invalid ID format');
|
|
223
|
-
});
|
|
224
|
-
it('should return error response for invalid type', async () => {
|
|
225
|
-
const result = await fetch.execute({ id: 'section:123' }, mockTodoistApi);
|
|
226
|
-
expect(result.isError).toBe(true);
|
|
227
|
-
expect(result.content[0]?.text).toContain('Invalid ID format');
|
|
228
|
-
});
|
|
229
|
-
it('should return error response for task fetch failure', async () => {
|
|
230
|
-
mockTodoistApi.getTask.mockRejectedValue(new Error('Task not found'));
|
|
231
|
-
const result = await fetch.execute({ id: `task:${TEST_IDS.TASK_1}` }, mockTodoistApi);
|
|
232
|
-
expect(result.isError).toBe(true);
|
|
233
|
-
expect(result.content[0]?.text).toBe('Task not found');
|
|
234
|
-
});
|
|
235
|
-
it('should return error response for project fetch failure', async () => {
|
|
236
|
-
mockTodoistApi.getProject.mockRejectedValue(new Error('Project not found'));
|
|
237
|
-
const result = await fetch.execute({ id: `project:${TEST_IDS.PROJECT_WORK}` }, mockTodoistApi);
|
|
238
|
-
expect(result.isError).toBe(true);
|
|
239
|
-
expect(result.content[0]?.text).toBe('Project not found');
|
|
240
|
-
});
|
|
241
|
-
});
|
|
242
|
-
describe('OpenAI MCP spec compliance', () => {
|
|
243
|
-
it('should return exactly one content item with type "text"', async () => {
|
|
244
|
-
const mockTask = createMockTask({ id: TEST_IDS.TASK_1, content: 'Test' });
|
|
245
|
-
mockTodoistApi.getTask.mockResolvedValue(mockTask);
|
|
246
|
-
const result = await fetch.execute({ id: `task:${TEST_IDS.TASK_1}` }, mockTodoistApi);
|
|
247
|
-
expect(result.content).toHaveLength(1);
|
|
248
|
-
expect(result.content[0]?.type).toBe('text');
|
|
249
|
-
});
|
|
250
|
-
it('should return valid JSON string in text field', async () => {
|
|
251
|
-
const mockTask = createMockTask({ id: TEST_IDS.TASK_1, content: 'Test' });
|
|
252
|
-
mockTodoistApi.getTask.mockResolvedValue(mockTask);
|
|
253
|
-
const result = await fetch.execute({ id: `task:${TEST_IDS.TASK_1}` }, mockTodoistApi);
|
|
254
|
-
expect(() => JSON.parse(result.content[0]?.text ?? '{}')).not.toThrow();
|
|
255
|
-
});
|
|
256
|
-
it('should include all required fields (id, title, text, url)', async () => {
|
|
257
|
-
const mockTask = createMockTask({ id: TEST_IDS.TASK_1, content: 'Test' });
|
|
258
|
-
mockTodoistApi.getTask.mockResolvedValue(mockTask);
|
|
259
|
-
const result = await fetch.execute({ id: `task:${TEST_IDS.TASK_1}` }, mockTodoistApi);
|
|
260
|
-
const jsonResponse = JSON.parse(result.content[0]?.text ?? '{}');
|
|
261
|
-
expect(jsonResponse).toHaveProperty('id');
|
|
262
|
-
expect(jsonResponse).toHaveProperty('title');
|
|
263
|
-
expect(jsonResponse).toHaveProperty('text');
|
|
264
|
-
expect(jsonResponse).toHaveProperty('url');
|
|
265
|
-
expect(typeof jsonResponse.id).toBe('string');
|
|
266
|
-
expect(typeof jsonResponse.title).toBe('string');
|
|
267
|
-
expect(typeof jsonResponse.text).toBe('string');
|
|
268
|
-
expect(typeof jsonResponse.url).toBe('string');
|
|
269
|
-
});
|
|
270
|
-
it('should include optional metadata field', async () => {
|
|
271
|
-
const mockTask = createMockTask({ id: TEST_IDS.TASK_1, content: 'Test' });
|
|
272
|
-
mockTodoistApi.getTask.mockResolvedValue(mockTask);
|
|
273
|
-
const result = await fetch.execute({ id: `task:${TEST_IDS.TASK_1}` }, mockTodoistApi);
|
|
274
|
-
const jsonResponse = JSON.parse(result.content[0]?.text ?? '{}');
|
|
275
|
-
expect(jsonResponse).toHaveProperty('metadata');
|
|
276
|
-
expect(typeof jsonResponse.metadata).toBe('object');
|
|
277
|
-
});
|
|
278
|
-
});
|
|
279
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"find-activity.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/find-activity.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
import { jest } from '@jest/globals';
|
|
2
|
-
import { extractTextContent } from '../../utils/test-helpers.js';
|
|
3
|
-
import { ToolNames } from '../../utils/tool-names.js';
|
|
4
|
-
import { findActivity } from '../find-activity.js';
|
|
5
|
-
// Mock the Todoist API
|
|
6
|
-
const mockTodoistApi = {
|
|
7
|
-
getActivityLogs: jest.fn(),
|
|
8
|
-
};
|
|
9
|
-
const { FIND_ACTIVITY } = ToolNames;
|
|
10
|
-
/**
|
|
11
|
-
* Helper to create a mock activity event
|
|
12
|
-
*/
|
|
13
|
-
function createMockActivityEvent(overrides = {}) {
|
|
14
|
-
return {
|
|
15
|
-
id: 'event-123',
|
|
16
|
-
objectType: 'task',
|
|
17
|
-
objectId: 'task-456',
|
|
18
|
-
eventType: 'added',
|
|
19
|
-
eventDate: '2024-10-23T10:30:00Z',
|
|
20
|
-
parentProjectId: 'project-789',
|
|
21
|
-
parentItemId: null,
|
|
22
|
-
initiatorId: 'user-001',
|
|
23
|
-
extraData: null,
|
|
24
|
-
...overrides,
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
describe(`${FIND_ACTIVITY} tool`, () => {
|
|
28
|
-
beforeEach(() => {
|
|
29
|
-
jest.clearAllMocks();
|
|
30
|
-
});
|
|
31
|
-
describe('basic functionality', () => {
|
|
32
|
-
it('should retrieve activity events with default parameters', async () => {
|
|
33
|
-
const mockEvents = [
|
|
34
|
-
createMockActivityEvent({
|
|
35
|
-
id: 'event-1',
|
|
36
|
-
eventType: 'added',
|
|
37
|
-
eventDate: '2024-10-23T10:00:00Z',
|
|
38
|
-
}),
|
|
39
|
-
createMockActivityEvent({
|
|
40
|
-
id: 'event-2',
|
|
41
|
-
eventType: 'completed',
|
|
42
|
-
eventDate: '2024-10-23T11:00:00Z',
|
|
43
|
-
}),
|
|
44
|
-
];
|
|
45
|
-
mockTodoistApi.getActivityLogs.mockResolvedValue({
|
|
46
|
-
results: mockEvents,
|
|
47
|
-
nextCursor: null,
|
|
48
|
-
});
|
|
49
|
-
const result = await findActivity.execute({ limit: 20 }, mockTodoistApi);
|
|
50
|
-
expect(mockTodoistApi.getActivityLogs).toHaveBeenCalledWith({
|
|
51
|
-
limit: 20,
|
|
52
|
-
cursor: null,
|
|
53
|
-
});
|
|
54
|
-
expect(extractTextContent(result)).toMatchSnapshot();
|
|
55
|
-
});
|
|
56
|
-
it('should handle empty results', async () => {
|
|
57
|
-
mockTodoistApi.getActivityLogs.mockResolvedValue({
|
|
58
|
-
results: [],
|
|
59
|
-
nextCursor: null,
|
|
60
|
-
});
|
|
61
|
-
const result = await findActivity.execute({ limit: 20 }, mockTodoistApi);
|
|
62
|
-
expect(extractTextContent(result)).toMatchSnapshot();
|
|
63
|
-
});
|
|
64
|
-
it('should handle pagination with cursor', async () => {
|
|
65
|
-
const mockEvents = Array.from({ length: 20 }, (_, i) => createMockActivityEvent({
|
|
66
|
-
id: `event-${i}`,
|
|
67
|
-
objectId: `task-${i}`,
|
|
68
|
-
}));
|
|
69
|
-
mockTodoistApi.getActivityLogs.mockResolvedValue({
|
|
70
|
-
results: mockEvents,
|
|
71
|
-
nextCursor: 'next-page-cursor',
|
|
72
|
-
});
|
|
73
|
-
const result = await findActivity.execute({ limit: 20, cursor: 'current-cursor' }, mockTodoistApi);
|
|
74
|
-
expect(mockTodoistApi.getActivityLogs).toHaveBeenCalledWith({
|
|
75
|
-
limit: 20,
|
|
76
|
-
cursor: 'current-cursor',
|
|
77
|
-
});
|
|
78
|
-
expect(extractTextContent(result)).toContain('Pass cursor');
|
|
79
|
-
expect(extractTextContent(result)).toContain('next-page-cursor');
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
describe('filtering', () => {
|
|
83
|
-
it.each([
|
|
84
|
-
['task', 'added'],
|
|
85
|
-
['project', 'updated'],
|
|
86
|
-
['comment', 'deleted'],
|
|
87
|
-
])('should filter by object type: %s', async (objectType, eventType) => {
|
|
88
|
-
const mockEvents = [
|
|
89
|
-
createMockActivityEvent({
|
|
90
|
-
objectType: objectType,
|
|
91
|
-
eventType: eventType,
|
|
92
|
-
}),
|
|
93
|
-
];
|
|
94
|
-
mockTodoistApi.getActivityLogs.mockResolvedValue({
|
|
95
|
-
results: mockEvents,
|
|
96
|
-
nextCursor: null,
|
|
97
|
-
});
|
|
98
|
-
const result = await findActivity.execute({ objectType: objectType, limit: 20 }, mockTodoistApi);
|
|
99
|
-
expect(mockTodoistApi.getActivityLogs).toHaveBeenCalledWith({
|
|
100
|
-
objectType,
|
|
101
|
-
limit: 20,
|
|
102
|
-
cursor: null,
|
|
103
|
-
});
|
|
104
|
-
expect(extractTextContent(result)).toContain(objectType);
|
|
105
|
-
});
|
|
106
|
-
it.each([
|
|
107
|
-
['added', 'task-1'],
|
|
108
|
-
['completed', 'task-2'],
|
|
109
|
-
['updated', 'task-3'],
|
|
110
|
-
['deleted', 'task-4'],
|
|
111
|
-
])('should filter by event type: %s', async (eventType, objectId) => {
|
|
112
|
-
const mockEvents = [
|
|
113
|
-
createMockActivityEvent({
|
|
114
|
-
eventType: eventType,
|
|
115
|
-
objectId,
|
|
116
|
-
}),
|
|
117
|
-
];
|
|
118
|
-
mockTodoistApi.getActivityLogs.mockResolvedValue({
|
|
119
|
-
results: mockEvents,
|
|
120
|
-
nextCursor: null,
|
|
121
|
-
});
|
|
122
|
-
const result = await findActivity.execute({
|
|
123
|
-
eventType: eventType,
|
|
124
|
-
limit: 20,
|
|
125
|
-
}, mockTodoistApi);
|
|
126
|
-
expect(mockTodoistApi.getActivityLogs).toHaveBeenCalledWith({
|
|
127
|
-
eventType,
|
|
128
|
-
limit: 20,
|
|
129
|
-
cursor: null,
|
|
130
|
-
});
|
|
131
|
-
expect(extractTextContent(result)).toContain(eventType);
|
|
132
|
-
});
|
|
133
|
-
it.each([
|
|
134
|
-
['objectId', 'task-123', { objectId: 'task-123' }],
|
|
135
|
-
['projectId', 'project-abc', { parentProjectId: 'project-abc' }],
|
|
136
|
-
['taskId', 'parent-task-789', { parentItemId: 'parent-task-789' }],
|
|
137
|
-
['initiatorId', 'user-alice', { initiatorId: 'user-alice' }],
|
|
138
|
-
])('should filter by %s', async (filterName, filterId, expectedApiCall) => {
|
|
139
|
-
const mockEvents = [createMockActivityEvent()];
|
|
140
|
-
mockTodoistApi.getActivityLogs.mockResolvedValue({
|
|
141
|
-
results: mockEvents,
|
|
142
|
-
nextCursor: null,
|
|
143
|
-
});
|
|
144
|
-
const args = { limit: 20 };
|
|
145
|
-
args[filterName] = filterId;
|
|
146
|
-
await findActivity.execute(args, mockTodoistApi);
|
|
147
|
-
expect(mockTodoistApi.getActivityLogs).toHaveBeenCalledWith({
|
|
148
|
-
...expectedApiCall,
|
|
149
|
-
limit: 20,
|
|
150
|
-
cursor: null,
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
it('should support multiple filters simultaneously', async () => {
|
|
154
|
-
const mockEvents = [
|
|
155
|
-
createMockActivityEvent({
|
|
156
|
-
objectType: 'task',
|
|
157
|
-
eventType: 'completed',
|
|
158
|
-
parentProjectId: 'project-work',
|
|
159
|
-
initiatorId: 'user-bob',
|
|
160
|
-
}),
|
|
161
|
-
];
|
|
162
|
-
mockTodoistApi.getActivityLogs.mockResolvedValue({
|
|
163
|
-
results: mockEvents,
|
|
164
|
-
nextCursor: null,
|
|
165
|
-
});
|
|
166
|
-
const result = await findActivity.execute({
|
|
167
|
-
objectType: 'task',
|
|
168
|
-
eventType: 'completed',
|
|
169
|
-
projectId: 'project-work',
|
|
170
|
-
initiatorId: 'user-bob',
|
|
171
|
-
limit: 50,
|
|
172
|
-
}, mockTodoistApi);
|
|
173
|
-
expect(mockTodoistApi.getActivityLogs).toHaveBeenCalledWith({
|
|
174
|
-
objectType: 'task',
|
|
175
|
-
eventType: 'completed',
|
|
176
|
-
parentProjectId: 'project-work',
|
|
177
|
-
initiatorId: 'user-bob',
|
|
178
|
-
limit: 50,
|
|
179
|
-
cursor: null,
|
|
180
|
-
});
|
|
181
|
-
expect(extractTextContent(result)).toMatchSnapshot();
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
describe('content extraction', () => {
|
|
185
|
-
it('should extract task content from extraData', async () => {
|
|
186
|
-
const mockEvents = [
|
|
187
|
-
createMockActivityEvent({
|
|
188
|
-
eventType: 'added',
|
|
189
|
-
extraData: { content: 'Buy groceries' },
|
|
190
|
-
}),
|
|
191
|
-
];
|
|
192
|
-
mockTodoistApi.getActivityLogs.mockResolvedValue({
|
|
193
|
-
results: mockEvents,
|
|
194
|
-
nextCursor: null,
|
|
195
|
-
});
|
|
196
|
-
const result = await findActivity.execute({ limit: 20 }, mockTodoistApi);
|
|
197
|
-
expect(extractTextContent(result)).toContain('Buy groceries');
|
|
198
|
-
});
|
|
199
|
-
it('should handle system-generated events with no initiator', async () => {
|
|
200
|
-
const mockEvents = [
|
|
201
|
-
createMockActivityEvent({
|
|
202
|
-
initiatorId: null,
|
|
203
|
-
eventType: 'completed',
|
|
204
|
-
}),
|
|
205
|
-
];
|
|
206
|
-
mockTodoistApi.getActivityLogs.mockResolvedValue({
|
|
207
|
-
results: mockEvents,
|
|
208
|
-
nextCursor: null,
|
|
209
|
-
});
|
|
210
|
-
const result = await findActivity.execute({ limit: 20 }, mockTodoistApi);
|
|
211
|
-
expect(extractTextContent(result)).toContain('system');
|
|
212
|
-
});
|
|
213
|
-
it('should truncate long content', async () => {
|
|
214
|
-
const longContent = 'A'.repeat(100);
|
|
215
|
-
const mockEvents = [
|
|
216
|
-
createMockActivityEvent({
|
|
217
|
-
extraData: { content: longContent },
|
|
218
|
-
}),
|
|
219
|
-
];
|
|
220
|
-
mockTodoistApi.getActivityLogs.mockResolvedValue({
|
|
221
|
-
results: mockEvents,
|
|
222
|
-
nextCursor: null,
|
|
223
|
-
});
|
|
224
|
-
const result = await findActivity.execute({ limit: 20 }, mockTodoistApi);
|
|
225
|
-
expect(extractTextContent(result)).toContain('...');
|
|
226
|
-
expect(extractTextContent(result)).not.toContain(longContent);
|
|
227
|
-
});
|
|
228
|
-
});
|
|
229
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"find-comments.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/find-comments.test.ts"],"names":[],"mappings":""}
|