@doist/todoist-ai 4.15.1 → 4.16.1
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 +175 -175
- package/dist/index.js +61 -81
- package/dist/main.js +15 -23
- package/dist/mcp-helpers.d.ts +4 -4
- package/dist/mcp-server-6tm7Rhyz.js +2840 -0
- package/dist/todoist-tool.d.ts +2 -2
- package/dist/tool-helpers.d.ts +1 -1
- package/dist/tools/add-comments.d.ts +1 -1
- package/dist/tools/add-comments.d.ts.map +1 -1
- package/dist/tools/add-projects.d.ts +4 -4
- package/dist/tools/add-projects.d.ts.map +1 -1
- package/dist/tools/add-sections.d.ts +1 -1
- package/dist/tools/add-sections.d.ts.map +1 -1
- package/dist/tools/add-tasks.d.ts +4 -4
- package/dist/tools/add-tasks.d.ts.map +1 -1
- package/dist/tools/complete-tasks.d.ts +1 -1
- package/dist/tools/complete-tasks.d.ts.map +1 -1
- package/dist/tools/delete-object.d.ts +3 -3
- package/dist/tools/delete-object.d.ts.map +1 -1
- package/dist/tools/fetch.d.ts +1 -1
- package/dist/tools/find-activity.d.ts +5 -5
- package/dist/tools/find-activity.d.ts.map +1 -1
- package/dist/tools/find-comments.d.ts +2 -2
- package/dist/tools/find-comments.d.ts.map +1 -1
- package/dist/tools/find-completed-tasks.d.ts +3 -3
- package/dist/tools/find-completed-tasks.d.ts.map +1 -1
- package/dist/tools/find-project-collaborators.d.ts +2 -2
- package/dist/tools/find-projects.d.ts +1 -1
- package/dist/tools/find-projects.d.ts.map +1 -1
- package/dist/tools/find-sections.d.ts +1 -1
- package/dist/tools/find-sections.d.ts.map +1 -1
- package/dist/tools/find-tasks-by-date.d.ts +1 -1
- package/dist/tools/find-tasks-by-date.d.ts.map +1 -1
- package/dist/tools/find-tasks.d.ts +3 -3
- package/dist/tools/find-tasks.d.ts.map +1 -1
- package/dist/tools/get-overview.d.ts +1 -1
- package/dist/tools/manage-assignments.d.ts +1 -1
- package/dist/tools/search.d.ts +1 -1
- package/dist/tools/update-comments.d.ts +4 -4
- package/dist/tools/update-comments.d.ts.map +1 -1
- package/dist/tools/update-projects.d.ts +1 -1
- package/dist/tools/update-projects.d.ts.map +1 -1
- package/dist/tools/update-sections.d.ts +4 -4
- package/dist/tools/update-sections.d.ts.map +1 -1
- package/dist/tools/update-tasks.d.ts +7 -7
- package/dist/tools/update-tasks.d.ts.map +1 -1
- package/dist/tools/user-info.d.ts +1 -1
- package/dist/utils/assignment-validator.d.ts +2 -2
- 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 +11 -9
- 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 -533
- 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 -324
- 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 -245
- 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 -79
- package/dist/tools/add-projects.js +0 -63
- package/dist/tools/add-sections.js +0 -61
- package/dist/tools/add-tasks.js +0 -160
- 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 -143
- package/dist/tools/find-completed-tasks.js +0 -161
- package/dist/tools/find-project-collaborators.js +0 -151
- package/dist/tools/find-projects.js +0 -101
- package/dist/tools/find-sections.js +0 -96
- 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 -170
- 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,223 +0,0 @@
|
|
|
1
|
-
import { createMoveTaskArgs, isPersonalProject, isWorkspaceProject, mapProject, mapTask, } from './tool-helpers.js';
|
|
2
|
-
describe('shared utilities', () => {
|
|
3
|
-
describe('mapTask', () => {
|
|
4
|
-
it('should map a basic task correctly', () => {
|
|
5
|
-
const mockTask = {
|
|
6
|
-
id: '123',
|
|
7
|
-
content: 'Test task',
|
|
8
|
-
description: 'Test description',
|
|
9
|
-
projectId: 'proj-1',
|
|
10
|
-
sectionId: null,
|
|
11
|
-
parentId: null,
|
|
12
|
-
labels: ['work'],
|
|
13
|
-
priority: 1,
|
|
14
|
-
due: {
|
|
15
|
-
date: '2024-01-15',
|
|
16
|
-
isRecurring: false,
|
|
17
|
-
datetime: '2024-01-15T10:00:00Z',
|
|
18
|
-
string: 'Jan 15',
|
|
19
|
-
timezone: 'UTC',
|
|
20
|
-
},
|
|
21
|
-
};
|
|
22
|
-
expect(mapTask(mockTask)).toEqual({
|
|
23
|
-
id: '123',
|
|
24
|
-
content: 'Test task',
|
|
25
|
-
description: 'Test description',
|
|
26
|
-
dueDate: '2024-01-15',
|
|
27
|
-
recurring: false,
|
|
28
|
-
priority: 1,
|
|
29
|
-
projectId: 'proj-1',
|
|
30
|
-
sectionId: null,
|
|
31
|
-
parentId: null,
|
|
32
|
-
labels: ['work'],
|
|
33
|
-
duration: null,
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
it('should handle recurring tasks', () => {
|
|
37
|
-
const mockTask = {
|
|
38
|
-
id: '456',
|
|
39
|
-
content: 'Recurring task',
|
|
40
|
-
description: '',
|
|
41
|
-
projectId: 'proj-1',
|
|
42
|
-
sectionId: null,
|
|
43
|
-
parentId: null,
|
|
44
|
-
labels: [],
|
|
45
|
-
priority: 1,
|
|
46
|
-
due: {
|
|
47
|
-
date: '2024-01-15',
|
|
48
|
-
isRecurring: true,
|
|
49
|
-
datetime: '2024-01-15T10:00:00Z',
|
|
50
|
-
string: 'every day',
|
|
51
|
-
timezone: 'UTC',
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
const result = mapTask(mockTask);
|
|
55
|
-
expect(result.recurring).toBe('every day');
|
|
56
|
-
expect(result.duration).toBe(null);
|
|
57
|
-
});
|
|
58
|
-
it('should handle task with duration', () => {
|
|
59
|
-
const mockTask = {
|
|
60
|
-
id: '789',
|
|
61
|
-
content: 'Task with duration',
|
|
62
|
-
description: '',
|
|
63
|
-
projectId: 'proj-1',
|
|
64
|
-
sectionId: null,
|
|
65
|
-
parentId: null,
|
|
66
|
-
labels: [],
|
|
67
|
-
priority: 1,
|
|
68
|
-
duration: {
|
|
69
|
-
amount: 150,
|
|
70
|
-
unit: 'minute',
|
|
71
|
-
},
|
|
72
|
-
};
|
|
73
|
-
const result = mapTask(mockTask);
|
|
74
|
-
expect(result.duration).toBe('2h30m');
|
|
75
|
-
});
|
|
76
|
-
it('should preserve markdown links and formatting in content and description', () => {
|
|
77
|
-
const mockTask = {
|
|
78
|
-
id: '123',
|
|
79
|
-
content: 'Task with **bold** and [link](https://example.com)',
|
|
80
|
-
description: `Rich markdown description:
|
|
81
|
-
|
|
82
|
-
### Links
|
|
83
|
-
[Wikipedia](https://en.wikipedia.org/wiki/Test)
|
|
84
|
-
[GitHub](https://github.com/example/repo)
|
|
85
|
-
|
|
86
|
-
### Formatting
|
|
87
|
-
**Bold text**
|
|
88
|
-
*Italic text*
|
|
89
|
-
\`code block\`
|
|
90
|
-
|
|
91
|
-
End of description.`,
|
|
92
|
-
projectId: 'proj-1',
|
|
93
|
-
sectionId: null,
|
|
94
|
-
parentId: null,
|
|
95
|
-
labels: [],
|
|
96
|
-
priority: 1,
|
|
97
|
-
};
|
|
98
|
-
const result = mapTask(mockTask);
|
|
99
|
-
// Verify exact preservation of markdown content
|
|
100
|
-
expect(result.content).toBe('Task with **bold** and [link](https://example.com)');
|
|
101
|
-
expect(result.description).toBe(`Rich markdown description:
|
|
102
|
-
|
|
103
|
-
### Links
|
|
104
|
-
[Wikipedia](https://en.wikipedia.org/wiki/Test)
|
|
105
|
-
[GitHub](https://github.com/example/repo)
|
|
106
|
-
|
|
107
|
-
### Formatting
|
|
108
|
-
**Bold text**
|
|
109
|
-
*Italic text*
|
|
110
|
-
\`code block\`
|
|
111
|
-
|
|
112
|
-
End of description.`);
|
|
113
|
-
// Verify specific URLs are preserved
|
|
114
|
-
expect(result.content).toContain('[link](https://example.com)');
|
|
115
|
-
expect(result.description).toContain('[Wikipedia](https://en.wikipedia.org/wiki/Test)');
|
|
116
|
-
expect(result.description).toContain('[GitHub](https://github.com/example/repo)');
|
|
117
|
-
// Verify other markdown formatting is preserved
|
|
118
|
-
expect(result.content).toContain('**bold**');
|
|
119
|
-
expect(result.description).toContain('**Bold text**');
|
|
120
|
-
expect(result.description).toContain('*Italic text*');
|
|
121
|
-
expect(result.description).toContain('`code block`');
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
describe('mapProject', () => {
|
|
125
|
-
it('should map a personal project correctly', () => {
|
|
126
|
-
const mockPersonalProject = {
|
|
127
|
-
id: 'proj-1',
|
|
128
|
-
name: 'Personal Project',
|
|
129
|
-
color: 'blue',
|
|
130
|
-
isFavorite: false,
|
|
131
|
-
isShared: false,
|
|
132
|
-
parentId: null,
|
|
133
|
-
inboxProject: false,
|
|
134
|
-
viewStyle: 'list',
|
|
135
|
-
};
|
|
136
|
-
expect(mapProject(mockPersonalProject)).toEqual({
|
|
137
|
-
id: 'proj-1',
|
|
138
|
-
name: 'Personal Project',
|
|
139
|
-
color: 'blue',
|
|
140
|
-
isFavorite: false,
|
|
141
|
-
isShared: false,
|
|
142
|
-
parentId: null,
|
|
143
|
-
inboxProject: false,
|
|
144
|
-
viewStyle: 'list',
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
it('should map a workspace project correctly', () => {
|
|
148
|
-
const mockWorkspaceProject = {
|
|
149
|
-
id: 'proj-2',
|
|
150
|
-
name: 'Workspace Project',
|
|
151
|
-
color: 'red',
|
|
152
|
-
isFavorite: true,
|
|
153
|
-
isShared: true,
|
|
154
|
-
viewStyle: 'board',
|
|
155
|
-
};
|
|
156
|
-
expect(mapProject(mockWorkspaceProject)).toEqual({
|
|
157
|
-
id: 'proj-2',
|
|
158
|
-
name: 'Workspace Project',
|
|
159
|
-
color: 'red',
|
|
160
|
-
isFavorite: true,
|
|
161
|
-
isShared: true,
|
|
162
|
-
parentId: null,
|
|
163
|
-
inboxProject: false,
|
|
164
|
-
viewStyle: 'board',
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
describe('type guards', () => {
|
|
169
|
-
it('should correctly identify personal projects', () => {
|
|
170
|
-
const personalProject = {
|
|
171
|
-
id: 'proj-1',
|
|
172
|
-
name: 'Personal',
|
|
173
|
-
color: 'blue',
|
|
174
|
-
isFavorite: false,
|
|
175
|
-
isShared: false,
|
|
176
|
-
parentId: null,
|
|
177
|
-
inboxProject: true,
|
|
178
|
-
viewStyle: 'list',
|
|
179
|
-
};
|
|
180
|
-
expect(isPersonalProject(personalProject)).toBe(true);
|
|
181
|
-
expect(isWorkspaceProject(personalProject)).toBe(false);
|
|
182
|
-
});
|
|
183
|
-
it('should correctly identify workspace projects', () => {
|
|
184
|
-
const workspaceProject = {
|
|
185
|
-
id: 'proj-2',
|
|
186
|
-
name: 'Workspace',
|
|
187
|
-
color: 'red',
|
|
188
|
-
isFavorite: false,
|
|
189
|
-
isShared: true,
|
|
190
|
-
viewStyle: 'board',
|
|
191
|
-
accessLevel: 'admin',
|
|
192
|
-
};
|
|
193
|
-
expect(isWorkspaceProject(workspaceProject)).toBe(true);
|
|
194
|
-
expect(isPersonalProject(workspaceProject)).toBe(false);
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
describe('createMoveTaskArgs', () => {
|
|
198
|
-
it('should create MoveTaskArgs for projectId', () => {
|
|
199
|
-
const result = createMoveTaskArgs('task-1', 'project-123');
|
|
200
|
-
expect(result).toEqual({ projectId: 'project-123' });
|
|
201
|
-
});
|
|
202
|
-
it('should create MoveTaskArgs for sectionId', () => {
|
|
203
|
-
const result = createMoveTaskArgs('task-1', undefined, 'section-456');
|
|
204
|
-
expect(result).toEqual({ sectionId: 'section-456' });
|
|
205
|
-
});
|
|
206
|
-
it('should create MoveTaskArgs for parentId', () => {
|
|
207
|
-
const result = createMoveTaskArgs('task-1', undefined, undefined, 'parent-789');
|
|
208
|
-
expect(result).toEqual({ parentId: 'parent-789' });
|
|
209
|
-
});
|
|
210
|
-
it('should throw error when multiple move parameters are provided', () => {
|
|
211
|
-
expect(() => createMoveTaskArgs('task-1', 'project-123', 'section-456')).toThrow('Task task-1: Only one of projectId, sectionId, or parentId can be specified at a time');
|
|
212
|
-
});
|
|
213
|
-
it('should throw error when all three move parameters are provided', () => {
|
|
214
|
-
expect(() => createMoveTaskArgs('task-1', 'project-123', 'section-456', 'parent-789')).toThrow('Task task-1: Only one of projectId, sectionId, or parentId can be specified at a time');
|
|
215
|
-
});
|
|
216
|
-
it('should throw error when no move parameters are provided', () => {
|
|
217
|
-
expect(() => createMoveTaskArgs('task-1')).toThrow('Task task-1: At least one of projectId, sectionId, or parentId must be provided');
|
|
218
|
-
});
|
|
219
|
-
it('should throw error when empty strings are provided', () => {
|
|
220
|
-
expect(() => createMoveTaskArgs('task-1', '', '', '')).toThrow('Task task-1: At least one of projectId, sectionId, or parentId must be provided');
|
|
221
|
-
});
|
|
222
|
-
});
|
|
223
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"add-comments.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/add-comments.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
import { jest } from '@jest/globals';
|
|
2
|
-
import { extractStructuredContent, extractTextContent } from '../../utils/test-helpers.js';
|
|
3
|
-
import { ToolNames } from '../../utils/tool-names.js';
|
|
4
|
-
import { addComments } from '../add-comments.js';
|
|
5
|
-
// Mock the Todoist API
|
|
6
|
-
const mockTodoistApi = {
|
|
7
|
-
addComment: jest.fn(),
|
|
8
|
-
};
|
|
9
|
-
const { ADD_COMMENTS } = ToolNames;
|
|
10
|
-
const createMockComment = (overrides = {}) => ({
|
|
11
|
-
id: '12345',
|
|
12
|
-
content: 'Test comment content',
|
|
13
|
-
postedAt: '2024-01-01T12:00:00Z',
|
|
14
|
-
postedUid: 'user123',
|
|
15
|
-
taskId: 'task123',
|
|
16
|
-
projectId: undefined,
|
|
17
|
-
fileAttachment: null,
|
|
18
|
-
uidsToNotify: null,
|
|
19
|
-
reactions: null,
|
|
20
|
-
isDeleted: false,
|
|
21
|
-
...overrides,
|
|
22
|
-
});
|
|
23
|
-
describe(`${ADD_COMMENTS} tool`, () => {
|
|
24
|
-
beforeEach(() => {
|
|
25
|
-
jest.clearAllMocks();
|
|
26
|
-
});
|
|
27
|
-
describe('adding comments to tasks', () => {
|
|
28
|
-
it('should add comment to task', async () => {
|
|
29
|
-
const mockComment = createMockComment({
|
|
30
|
-
id: '98765',
|
|
31
|
-
content: 'This is a task comment',
|
|
32
|
-
taskId: 'task456',
|
|
33
|
-
});
|
|
34
|
-
mockTodoistApi.addComment.mockResolvedValue(mockComment);
|
|
35
|
-
const result = await addComments.execute({ comments: [{ taskId: 'task456', content: 'This is a task comment' }] }, mockTodoistApi);
|
|
36
|
-
expect(mockTodoistApi.addComment).toHaveBeenCalledWith({
|
|
37
|
-
content: 'This is a task comment',
|
|
38
|
-
taskId: 'task456',
|
|
39
|
-
});
|
|
40
|
-
// Verify result is a concise summary
|
|
41
|
-
expect(extractTextContent(result)).toMatchSnapshot();
|
|
42
|
-
// Verify structured content
|
|
43
|
-
const structuredContent = extractStructuredContent(result);
|
|
44
|
-
expect(structuredContent).toEqual(expect.objectContaining({
|
|
45
|
-
comments: [
|
|
46
|
-
expect.objectContaining({
|
|
47
|
-
id: '98765',
|
|
48
|
-
content: 'This is a task comment',
|
|
49
|
-
taskId: 'task456',
|
|
50
|
-
}),
|
|
51
|
-
],
|
|
52
|
-
totalCount: 1,
|
|
53
|
-
addedCommentIds: ['98765'],
|
|
54
|
-
}));
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
describe('adding comments to projects', () => {
|
|
58
|
-
it('should add comment to project', async () => {
|
|
59
|
-
const mockComment = createMockComment({
|
|
60
|
-
id: '98767',
|
|
61
|
-
content: 'This is a project comment',
|
|
62
|
-
taskId: undefined,
|
|
63
|
-
projectId: 'project789',
|
|
64
|
-
});
|
|
65
|
-
mockTodoistApi.addComment.mockResolvedValue(mockComment);
|
|
66
|
-
const result = await addComments.execute({ comments: [{ projectId: 'project789', content: 'This is a project comment' }] }, mockTodoistApi);
|
|
67
|
-
expect(mockTodoistApi.addComment).toHaveBeenCalledWith({
|
|
68
|
-
content: 'This is a project comment',
|
|
69
|
-
projectId: 'project789',
|
|
70
|
-
});
|
|
71
|
-
// Verify result is a concise summary
|
|
72
|
-
expect(extractTextContent(result)).toMatchSnapshot();
|
|
73
|
-
// Verify structured content
|
|
74
|
-
const structuredContent = extractStructuredContent(result);
|
|
75
|
-
expect(structuredContent).toEqual(expect.objectContaining({
|
|
76
|
-
comments: [
|
|
77
|
-
expect.objectContaining({
|
|
78
|
-
id: '98767',
|
|
79
|
-
content: 'This is a project comment',
|
|
80
|
-
taskId: undefined,
|
|
81
|
-
projectId: 'project789',
|
|
82
|
-
}),
|
|
83
|
-
],
|
|
84
|
-
totalCount: 1,
|
|
85
|
-
addedCommentIds: ['98767'],
|
|
86
|
-
}));
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
describe('bulk operations', () => {
|
|
90
|
-
it('should add multiple comments to different entities (task + project)', async () => {
|
|
91
|
-
const mockTaskComment = createMockComment({
|
|
92
|
-
id: '11111',
|
|
93
|
-
content: 'Task comment',
|
|
94
|
-
taskId: 'task123',
|
|
95
|
-
projectId: undefined,
|
|
96
|
-
});
|
|
97
|
-
const mockProjectComment = createMockComment({
|
|
98
|
-
id: '22222',
|
|
99
|
-
content: 'Project comment',
|
|
100
|
-
taskId: undefined,
|
|
101
|
-
projectId: 'project456',
|
|
102
|
-
});
|
|
103
|
-
mockTodoistApi.addComment
|
|
104
|
-
.mockResolvedValueOnce(mockTaskComment)
|
|
105
|
-
.mockResolvedValueOnce(mockProjectComment);
|
|
106
|
-
const result = await addComments.execute({
|
|
107
|
-
comments: [
|
|
108
|
-
{ taskId: 'task123', content: 'Task comment' },
|
|
109
|
-
{ projectId: 'project456', content: 'Project comment' },
|
|
110
|
-
],
|
|
111
|
-
}, mockTodoistApi);
|
|
112
|
-
expect(mockTodoistApi.addComment).toHaveBeenCalledTimes(2);
|
|
113
|
-
expect(mockTodoistApi.addComment).toHaveBeenCalledWith({
|
|
114
|
-
content: 'Task comment',
|
|
115
|
-
taskId: 'task123',
|
|
116
|
-
});
|
|
117
|
-
expect(mockTodoistApi.addComment).toHaveBeenCalledWith({
|
|
118
|
-
content: 'Project comment',
|
|
119
|
-
projectId: 'project456',
|
|
120
|
-
});
|
|
121
|
-
// Verify result is a concise summary
|
|
122
|
-
expect(extractTextContent(result)).toMatchSnapshot();
|
|
123
|
-
const structuredContent = extractStructuredContent(result);
|
|
124
|
-
expect(structuredContent).toEqual(expect.objectContaining({
|
|
125
|
-
comments: [
|
|
126
|
-
expect.objectContaining({
|
|
127
|
-
id: '11111',
|
|
128
|
-
content: 'Task comment',
|
|
129
|
-
taskId: 'task123',
|
|
130
|
-
}),
|
|
131
|
-
expect.objectContaining({
|
|
132
|
-
id: '22222',
|
|
133
|
-
content: 'Project comment',
|
|
134
|
-
projectId: 'project456',
|
|
135
|
-
}),
|
|
136
|
-
],
|
|
137
|
-
totalCount: 2,
|
|
138
|
-
addedCommentIds: ['11111', '22222'],
|
|
139
|
-
}));
|
|
140
|
-
});
|
|
141
|
-
it('should add multiple comments to different tasks', async () => {
|
|
142
|
-
const mockComment1 = createMockComment({
|
|
143
|
-
id: '33333',
|
|
144
|
-
content: 'First task comment',
|
|
145
|
-
taskId: 'task111',
|
|
146
|
-
});
|
|
147
|
-
const mockComment2 = createMockComment({
|
|
148
|
-
id: '44444',
|
|
149
|
-
content: 'Second task comment',
|
|
150
|
-
taskId: 'task222',
|
|
151
|
-
});
|
|
152
|
-
mockTodoistApi.addComment
|
|
153
|
-
.mockResolvedValueOnce(mockComment1)
|
|
154
|
-
.mockResolvedValueOnce(mockComment2);
|
|
155
|
-
const result = await addComments.execute({
|
|
156
|
-
comments: [
|
|
157
|
-
{ taskId: 'task111', content: 'First task comment' },
|
|
158
|
-
{ taskId: 'task222', content: 'Second task comment' },
|
|
159
|
-
],
|
|
160
|
-
}, mockTodoistApi);
|
|
161
|
-
expect(mockTodoistApi.addComment).toHaveBeenCalledTimes(2);
|
|
162
|
-
// Verify result is a concise summary
|
|
163
|
-
expect(extractTextContent(result)).toMatchSnapshot();
|
|
164
|
-
const structuredContent = extractStructuredContent(result);
|
|
165
|
-
expect(structuredContent).toEqual(expect.objectContaining({
|
|
166
|
-
comments: expect.arrayContaining([
|
|
167
|
-
expect.objectContaining({
|
|
168
|
-
id: '33333',
|
|
169
|
-
content: 'First task comment',
|
|
170
|
-
taskId: 'task111',
|
|
171
|
-
}),
|
|
172
|
-
expect.objectContaining({
|
|
173
|
-
id: '44444',
|
|
174
|
-
content: 'Second task comment',
|
|
175
|
-
taskId: 'task222',
|
|
176
|
-
}),
|
|
177
|
-
]),
|
|
178
|
-
totalCount: 2,
|
|
179
|
-
addedCommentIds: ['33333', '44444'],
|
|
180
|
-
}));
|
|
181
|
-
});
|
|
182
|
-
it('should add multiple comments to the same task', async () => {
|
|
183
|
-
const mockComment1 = createMockComment({
|
|
184
|
-
id: '55555',
|
|
185
|
-
content: 'First comment on same task',
|
|
186
|
-
taskId: 'task999',
|
|
187
|
-
});
|
|
188
|
-
const mockComment2 = createMockComment({
|
|
189
|
-
id: '66666',
|
|
190
|
-
content: 'Second comment on same task',
|
|
191
|
-
taskId: 'task999',
|
|
192
|
-
});
|
|
193
|
-
mockTodoistApi.addComment
|
|
194
|
-
.mockResolvedValueOnce(mockComment1)
|
|
195
|
-
.mockResolvedValueOnce(mockComment2);
|
|
196
|
-
const result = await addComments.execute({
|
|
197
|
-
comments: [
|
|
198
|
-
{ taskId: 'task999', content: 'First comment on same task' },
|
|
199
|
-
{ taskId: 'task999', content: 'Second comment on same task' },
|
|
200
|
-
],
|
|
201
|
-
}, mockTodoistApi);
|
|
202
|
-
expect(mockTodoistApi.addComment).toHaveBeenCalledTimes(2);
|
|
203
|
-
expect(mockTodoistApi.addComment).toHaveBeenCalledWith({
|
|
204
|
-
content: 'First comment on same task',
|
|
205
|
-
taskId: 'task999',
|
|
206
|
-
});
|
|
207
|
-
expect(mockTodoistApi.addComment).toHaveBeenCalledWith({
|
|
208
|
-
content: 'Second comment on same task',
|
|
209
|
-
taskId: 'task999',
|
|
210
|
-
});
|
|
211
|
-
// Verify result is a concise summary
|
|
212
|
-
expect(extractTextContent(result)).toMatchSnapshot();
|
|
213
|
-
const structuredContent = extractStructuredContent(result);
|
|
214
|
-
expect(structuredContent).toEqual(expect.objectContaining({
|
|
215
|
-
comments: expect.arrayContaining([
|
|
216
|
-
expect.objectContaining({
|
|
217
|
-
id: '55555',
|
|
218
|
-
content: 'First comment on same task',
|
|
219
|
-
taskId: 'task999',
|
|
220
|
-
}),
|
|
221
|
-
expect.objectContaining({
|
|
222
|
-
id: '66666',
|
|
223
|
-
content: 'Second comment on same task',
|
|
224
|
-
taskId: 'task999',
|
|
225
|
-
}),
|
|
226
|
-
]),
|
|
227
|
-
totalCount: 2,
|
|
228
|
-
addedCommentIds: ['55555', '66666'],
|
|
229
|
-
}));
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
describe('validation', () => {
|
|
233
|
-
it('should throw error when neither taskId nor projectId provided', async () => {
|
|
234
|
-
await expect(addComments.execute({ comments: [{ content: 'Test comment' }] }, mockTodoistApi)).rejects.toThrow('Comment 1: Either taskId or projectId must be provided.');
|
|
235
|
-
});
|
|
236
|
-
it('should throw error when both taskId and projectId provided', async () => {
|
|
237
|
-
const comment = { taskId: 'task123', projectId: 'project456', content: 'Test comment' };
|
|
238
|
-
await expect(addComments.execute({ comments: [comment] }, mockTodoistApi)).rejects.toThrow('Comment 1: Cannot provide both taskId and projectId. Choose one.');
|
|
239
|
-
});
|
|
240
|
-
});
|
|
241
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"add-projects.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/add-projects.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { jest } from '@jest/globals';
|
|
2
|
-
import { createMockProject, extractStructuredContent, extractTextContent, TEST_IDS, } from '../../utils/test-helpers.js';
|
|
3
|
-
import { ToolNames } from '../../utils/tool-names.js';
|
|
4
|
-
import { addProjects } from '../add-projects.js';
|
|
5
|
-
// Mock the Todoist API
|
|
6
|
-
const mockTodoistApi = {
|
|
7
|
-
addProject: jest.fn(),
|
|
8
|
-
};
|
|
9
|
-
const { ADD_TASKS, ADD_PROJECTS, ADD_SECTIONS } = ToolNames;
|
|
10
|
-
describe(`${ADD_PROJECTS} tool`, () => {
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
jest.clearAllMocks();
|
|
13
|
-
});
|
|
14
|
-
describe('creating a single project', () => {
|
|
15
|
-
it('should create a project and return mapped result', async () => {
|
|
16
|
-
const mockApiResponse = createMockProject({
|
|
17
|
-
id: TEST_IDS.PROJECT_TEST,
|
|
18
|
-
name: 'test-abc123def456-project',
|
|
19
|
-
childOrder: 1,
|
|
20
|
-
createdAt: '2024-01-01T00:00:00Z',
|
|
21
|
-
});
|
|
22
|
-
mockTodoistApi.addProject.mockResolvedValue(mockApiResponse);
|
|
23
|
-
const result = await addProjects.execute({ projects: [{ name: 'test-abc123def456-project' }] }, mockTodoistApi);
|
|
24
|
-
// Verify API was called correctly
|
|
25
|
-
expect(mockTodoistApi.addProject).toHaveBeenCalledWith({
|
|
26
|
-
name: 'test-abc123def456-project',
|
|
27
|
-
});
|
|
28
|
-
const textContent = extractTextContent(result);
|
|
29
|
-
expect(textContent).toMatchSnapshot();
|
|
30
|
-
expect(textContent).toContain('Added 1 project:');
|
|
31
|
-
expect(textContent).toContain('test-abc123def456-project');
|
|
32
|
-
expect(textContent).toContain(`id=${TEST_IDS.PROJECT_TEST}`);
|
|
33
|
-
expect(textContent).toContain(`Use ${ADD_TASKS} to add your first tasks`);
|
|
34
|
-
// Verify structured content
|
|
35
|
-
const structuredContent = extractStructuredContent(result);
|
|
36
|
-
expect(structuredContent).toEqual(expect.objectContaining({
|
|
37
|
-
projects: [
|
|
38
|
-
expect.objectContaining({
|
|
39
|
-
id: TEST_IDS.PROJECT_TEST,
|
|
40
|
-
name: 'test-abc123def456-project',
|
|
41
|
-
}),
|
|
42
|
-
],
|
|
43
|
-
totalCount: 1,
|
|
44
|
-
}));
|
|
45
|
-
});
|
|
46
|
-
it('should handle different project properties from API', async () => {
|
|
47
|
-
const mockApiResponse = createMockProject({
|
|
48
|
-
id: 'project-456',
|
|
49
|
-
name: 'My Blue Project',
|
|
50
|
-
color: 'blue',
|
|
51
|
-
isFavorite: true,
|
|
52
|
-
isShared: true,
|
|
53
|
-
parentId: 'parent-123',
|
|
54
|
-
viewStyle: 'board',
|
|
55
|
-
childOrder: 2,
|
|
56
|
-
description: 'A test project',
|
|
57
|
-
createdAt: '2024-01-01T00:00:00Z',
|
|
58
|
-
});
|
|
59
|
-
mockTodoistApi.addProject.mockResolvedValue(mockApiResponse);
|
|
60
|
-
const result = await addProjects.execute({ projects: [{ name: 'My Blue Project' }] }, mockTodoistApi);
|
|
61
|
-
expect(mockTodoistApi.addProject).toHaveBeenCalledWith({
|
|
62
|
-
name: 'My Blue Project',
|
|
63
|
-
isFavorite: undefined,
|
|
64
|
-
viewStyle: undefined,
|
|
65
|
-
});
|
|
66
|
-
const textContent = extractTextContent(result);
|
|
67
|
-
expect(textContent).toMatchSnapshot();
|
|
68
|
-
expect(textContent).toContain('Added 1 project:');
|
|
69
|
-
expect(textContent).toContain('My Blue Project');
|
|
70
|
-
expect(textContent).toContain('id=project-456');
|
|
71
|
-
expect(textContent).toContain(`Use ${ADD_SECTIONS} to organize new project`);
|
|
72
|
-
});
|
|
73
|
-
it('should create project with isFavorite and viewStyle options', async () => {
|
|
74
|
-
const mockApiResponse = createMockProject({
|
|
75
|
-
id: 'project-789',
|
|
76
|
-
name: 'Board Project',
|
|
77
|
-
isFavorite: true,
|
|
78
|
-
viewStyle: 'board',
|
|
79
|
-
});
|
|
80
|
-
mockTodoistApi.addProject.mockResolvedValue(mockApiResponse);
|
|
81
|
-
const result = await addProjects.execute({ projects: [{ name: 'Board Project', isFavorite: true, viewStyle: 'board' }] }, mockTodoistApi);
|
|
82
|
-
expect(mockTodoistApi.addProject).toHaveBeenCalledWith({
|
|
83
|
-
name: 'Board Project',
|
|
84
|
-
isFavorite: true,
|
|
85
|
-
viewStyle: 'board',
|
|
86
|
-
});
|
|
87
|
-
const textContent = extractTextContent(result);
|
|
88
|
-
expect(textContent).toMatchSnapshot();
|
|
89
|
-
expect(textContent).toContain('Added 1 project:');
|
|
90
|
-
expect(textContent).toContain('Board Project');
|
|
91
|
-
expect(textContent).toContain('id=project-789');
|
|
92
|
-
});
|
|
93
|
-
it('should create project with parentId to create a sub-project', async () => {
|
|
94
|
-
const mockApiResponse = createMockProject({
|
|
95
|
-
id: 'project-child',
|
|
96
|
-
name: 'Child Project',
|
|
97
|
-
parentId: 'project-parent',
|
|
98
|
-
});
|
|
99
|
-
mockTodoistApi.addProject.mockResolvedValue(mockApiResponse);
|
|
100
|
-
const result = await addProjects.execute({ projects: [{ name: 'Child Project', parentId: 'project-parent' }] }, mockTodoistApi);
|
|
101
|
-
expect(mockTodoistApi.addProject).toHaveBeenCalledWith({
|
|
102
|
-
name: 'Child Project',
|
|
103
|
-
parentId: 'project-parent',
|
|
104
|
-
});
|
|
105
|
-
const textContent = extractTextContent(result);
|
|
106
|
-
expect(textContent).toMatchSnapshot();
|
|
107
|
-
expect(textContent).toContain('Added 1 project:');
|
|
108
|
-
expect(textContent).toContain('Child Project');
|
|
109
|
-
expect(textContent).toContain('id=project-child');
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
describe('creating multiple projects', () => {
|
|
113
|
-
it('should create multiple projects and return mapped results', async () => {
|
|
114
|
-
const mockProjects = [
|
|
115
|
-
createMockProject({ id: 'project-1', name: 'First Project' }),
|
|
116
|
-
createMockProject({ id: 'project-2', name: 'Second Project' }),
|
|
117
|
-
createMockProject({ id: 'project-3', name: 'Third Project' }),
|
|
118
|
-
];
|
|
119
|
-
const [project1, project2, project3] = mockProjects;
|
|
120
|
-
mockTodoistApi.addProject
|
|
121
|
-
.mockResolvedValueOnce(project1)
|
|
122
|
-
.mockResolvedValueOnce(project2)
|
|
123
|
-
.mockResolvedValueOnce(project3);
|
|
124
|
-
const result = await addProjects.execute({
|
|
125
|
-
projects: [
|
|
126
|
-
{ name: 'First Project' },
|
|
127
|
-
{ name: 'Second Project' },
|
|
128
|
-
{ name: 'Third Project' },
|
|
129
|
-
],
|
|
130
|
-
}, mockTodoistApi);
|
|
131
|
-
// Verify API was called correctly for each project
|
|
132
|
-
expect(mockTodoistApi.addProject).toHaveBeenCalledTimes(3);
|
|
133
|
-
expect(mockTodoistApi.addProject).toHaveBeenNthCalledWith(1, { name: 'First Project' });
|
|
134
|
-
expect(mockTodoistApi.addProject).toHaveBeenNthCalledWith(2, { name: 'Second Project' });
|
|
135
|
-
expect(mockTodoistApi.addProject).toHaveBeenNthCalledWith(3, { name: 'Third Project' });
|
|
136
|
-
const textContent = extractTextContent(result);
|
|
137
|
-
expect(textContent).toMatchSnapshot();
|
|
138
|
-
expect(textContent).toContain('Added 3 projects:');
|
|
139
|
-
expect(textContent).toContain('First Project (id=project-1)');
|
|
140
|
-
expect(textContent).toContain('Second Project (id=project-2)');
|
|
141
|
-
expect(textContent).toContain('Third Project (id=project-3)');
|
|
142
|
-
expect(textContent).toContain(`Use ${ADD_SECTIONS} to organize these projects`);
|
|
143
|
-
// Verify structured content
|
|
144
|
-
const structuredContent = extractStructuredContent(result);
|
|
145
|
-
expect(structuredContent).toEqual(expect.objectContaining({
|
|
146
|
-
projects: expect.arrayContaining([
|
|
147
|
-
expect.objectContaining({ id: 'project-1', name: 'First Project' }),
|
|
148
|
-
expect.objectContaining({ id: 'project-2', name: 'Second Project' }),
|
|
149
|
-
expect.objectContaining({ id: 'project-3', name: 'Third Project' }),
|
|
150
|
-
]),
|
|
151
|
-
totalCount: 3,
|
|
152
|
-
}));
|
|
153
|
-
});
|
|
154
|
-
});
|
|
155
|
-
describe('error handling', () => {
|
|
156
|
-
it('should propagate API errors', async () => {
|
|
157
|
-
const apiError = new Error('API Error: Project name is required');
|
|
158
|
-
mockTodoistApi.addProject.mockRejectedValue(apiError);
|
|
159
|
-
await expect(addProjects.execute({ projects: [{ name: '' }] }, mockTodoistApi)).rejects.toThrow('API Error: Project name is required');
|
|
160
|
-
});
|
|
161
|
-
it('should handle partial failures in multiple projects', async () => {
|
|
162
|
-
const mockProject = createMockProject({
|
|
163
|
-
id: 'project-1',
|
|
164
|
-
name: 'First Project',
|
|
165
|
-
});
|
|
166
|
-
mockTodoistApi.addProject
|
|
167
|
-
.mockResolvedValueOnce(mockProject)
|
|
168
|
-
.mockRejectedValueOnce(new Error('API Error: Invalid project name'));
|
|
169
|
-
await expect(addProjects.execute({
|
|
170
|
-
projects: [{ name: 'First Project' }, { name: 'Invalid' }],
|
|
171
|
-
}, mockTodoistApi)).rejects.toThrow('API Error: Invalid project name');
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"add-sections.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/add-sections.test.ts"],"names":[],"mappings":""}
|