@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.
Files changed (167) hide show
  1. package/dist/filter-helpers.d.ts +1 -1
  2. package/dist/index.d.ts +175 -175
  3. package/dist/index.js +61 -81
  4. package/dist/main.js +15 -23
  5. package/dist/mcp-helpers.d.ts +4 -4
  6. package/dist/mcp-server-6tm7Rhyz.js +2840 -0
  7. package/dist/todoist-tool.d.ts +2 -2
  8. package/dist/tool-helpers.d.ts +1 -1
  9. package/dist/tools/add-comments.d.ts +1 -1
  10. package/dist/tools/add-comments.d.ts.map +1 -1
  11. package/dist/tools/add-projects.d.ts +4 -4
  12. package/dist/tools/add-projects.d.ts.map +1 -1
  13. package/dist/tools/add-sections.d.ts +1 -1
  14. package/dist/tools/add-sections.d.ts.map +1 -1
  15. package/dist/tools/add-tasks.d.ts +4 -4
  16. package/dist/tools/add-tasks.d.ts.map +1 -1
  17. package/dist/tools/complete-tasks.d.ts +1 -1
  18. package/dist/tools/complete-tasks.d.ts.map +1 -1
  19. package/dist/tools/delete-object.d.ts +3 -3
  20. package/dist/tools/delete-object.d.ts.map +1 -1
  21. package/dist/tools/fetch.d.ts +1 -1
  22. package/dist/tools/find-activity.d.ts +5 -5
  23. package/dist/tools/find-activity.d.ts.map +1 -1
  24. package/dist/tools/find-comments.d.ts +2 -2
  25. package/dist/tools/find-comments.d.ts.map +1 -1
  26. package/dist/tools/find-completed-tasks.d.ts +3 -3
  27. package/dist/tools/find-completed-tasks.d.ts.map +1 -1
  28. package/dist/tools/find-project-collaborators.d.ts +2 -2
  29. package/dist/tools/find-projects.d.ts +1 -1
  30. package/dist/tools/find-projects.d.ts.map +1 -1
  31. package/dist/tools/find-sections.d.ts +1 -1
  32. package/dist/tools/find-sections.d.ts.map +1 -1
  33. package/dist/tools/find-tasks-by-date.d.ts +1 -1
  34. package/dist/tools/find-tasks-by-date.d.ts.map +1 -1
  35. package/dist/tools/find-tasks.d.ts +3 -3
  36. package/dist/tools/find-tasks.d.ts.map +1 -1
  37. package/dist/tools/get-overview.d.ts +1 -1
  38. package/dist/tools/manage-assignments.d.ts +1 -1
  39. package/dist/tools/search.d.ts +1 -1
  40. package/dist/tools/update-comments.d.ts +4 -4
  41. package/dist/tools/update-comments.d.ts.map +1 -1
  42. package/dist/tools/update-projects.d.ts +1 -1
  43. package/dist/tools/update-projects.d.ts.map +1 -1
  44. package/dist/tools/update-sections.d.ts +4 -4
  45. package/dist/tools/update-sections.d.ts.map +1 -1
  46. package/dist/tools/update-tasks.d.ts +7 -7
  47. package/dist/tools/update-tasks.d.ts.map +1 -1
  48. package/dist/tools/user-info.d.ts +1 -1
  49. package/dist/utils/assignment-validator.d.ts +2 -2
  50. package/dist/utils/response-builders.d.ts +1 -3
  51. package/dist/utils/response-builders.d.ts.map +1 -1
  52. package/dist/utils/test-helpers.d.ts +1 -1
  53. package/dist/utils/user-resolver.d.ts +1 -1
  54. package/package.json +11 -9
  55. package/dist/filter-helpers.js +0 -79
  56. package/dist/mcp-helpers.js +0 -71
  57. package/dist/mcp-server.js +0 -142
  58. package/dist/todoist-tool.js +0 -1
  59. package/dist/tool-helpers.js +0 -125
  60. package/dist/tool-helpers.test.d.ts +0 -2
  61. package/dist/tool-helpers.test.d.ts.map +0 -1
  62. package/dist/tool-helpers.test.js +0 -223
  63. package/dist/tools/__tests__/add-comments.test.d.ts +0 -2
  64. package/dist/tools/__tests__/add-comments.test.d.ts.map +0 -1
  65. package/dist/tools/__tests__/add-comments.test.js +0 -241
  66. package/dist/tools/__tests__/add-projects.test.d.ts +0 -2
  67. package/dist/tools/__tests__/add-projects.test.d.ts.map +0 -1
  68. package/dist/tools/__tests__/add-projects.test.js +0 -174
  69. package/dist/tools/__tests__/add-sections.test.d.ts +0 -2
  70. package/dist/tools/__tests__/add-sections.test.d.ts.map +0 -1
  71. package/dist/tools/__tests__/add-sections.test.js +0 -185
  72. package/dist/tools/__tests__/add-tasks.test.d.ts +0 -2
  73. package/dist/tools/__tests__/add-tasks.test.d.ts.map +0 -1
  74. package/dist/tools/__tests__/add-tasks.test.js +0 -533
  75. package/dist/tools/__tests__/assignment-integration.test.d.ts +0 -2
  76. package/dist/tools/__tests__/assignment-integration.test.d.ts.map +0 -1
  77. package/dist/tools/__tests__/assignment-integration.test.js +0 -428
  78. package/dist/tools/__tests__/complete-tasks.test.d.ts +0 -2
  79. package/dist/tools/__tests__/complete-tasks.test.d.ts.map +0 -1
  80. package/dist/tools/__tests__/complete-tasks.test.js +0 -206
  81. package/dist/tools/__tests__/delete-object.test.d.ts +0 -2
  82. package/dist/tools/__tests__/delete-object.test.d.ts.map +0 -1
  83. package/dist/tools/__tests__/delete-object.test.js +0 -110
  84. package/dist/tools/__tests__/fetch.test.d.ts +0 -2
  85. package/dist/tools/__tests__/fetch.test.d.ts.map +0 -1
  86. package/dist/tools/__tests__/fetch.test.js +0 -279
  87. package/dist/tools/__tests__/find-activity.test.d.ts +0 -2
  88. package/dist/tools/__tests__/find-activity.test.d.ts.map +0 -1
  89. package/dist/tools/__tests__/find-activity.test.js +0 -229
  90. package/dist/tools/__tests__/find-comments.test.d.ts +0 -2
  91. package/dist/tools/__tests__/find-comments.test.d.ts.map +0 -1
  92. package/dist/tools/__tests__/find-comments.test.js +0 -236
  93. package/dist/tools/__tests__/find-completed-tasks.test.d.ts +0 -2
  94. package/dist/tools/__tests__/find-completed-tasks.test.d.ts.map +0 -1
  95. package/dist/tools/__tests__/find-completed-tasks.test.js +0 -324
  96. package/dist/tools/__tests__/find-projects.test.d.ts +0 -2
  97. package/dist/tools/__tests__/find-projects.test.d.ts.map +0 -1
  98. package/dist/tools/__tests__/find-projects.test.js +0 -154
  99. package/dist/tools/__tests__/find-sections.test.d.ts +0 -2
  100. package/dist/tools/__tests__/find-sections.test.d.ts.map +0 -1
  101. package/dist/tools/__tests__/find-sections.test.js +0 -245
  102. package/dist/tools/__tests__/find-tasks-by-date.test.d.ts +0 -2
  103. package/dist/tools/__tests__/find-tasks-by-date.test.d.ts.map +0 -1
  104. package/dist/tools/__tests__/find-tasks-by-date.test.js +0 -528
  105. package/dist/tools/__tests__/find-tasks.test.d.ts +0 -2
  106. package/dist/tools/__tests__/find-tasks.test.d.ts.map +0 -1
  107. package/dist/tools/__tests__/find-tasks.test.js +0 -771
  108. package/dist/tools/__tests__/get-overview.test.d.ts +0 -2
  109. package/dist/tools/__tests__/get-overview.test.d.ts.map +0 -1
  110. package/dist/tools/__tests__/get-overview.test.js +0 -225
  111. package/dist/tools/__tests__/search.test.d.ts +0 -2
  112. package/dist/tools/__tests__/search.test.d.ts.map +0 -1
  113. package/dist/tools/__tests__/search.test.js +0 -206
  114. package/dist/tools/__tests__/update-comments.test.d.ts +0 -2
  115. package/dist/tools/__tests__/update-comments.test.d.ts.map +0 -1
  116. package/dist/tools/__tests__/update-comments.test.js +0 -294
  117. package/dist/tools/__tests__/update-projects.test.d.ts +0 -2
  118. package/dist/tools/__tests__/update-projects.test.d.ts.map +0 -1
  119. package/dist/tools/__tests__/update-projects.test.js +0 -217
  120. package/dist/tools/__tests__/update-sections.test.d.ts +0 -2
  121. package/dist/tools/__tests__/update-sections.test.d.ts.map +0 -1
  122. package/dist/tools/__tests__/update-sections.test.js +0 -169
  123. package/dist/tools/__tests__/update-tasks.test.d.ts +0 -2
  124. package/dist/tools/__tests__/update-tasks.test.d.ts.map +0 -1
  125. package/dist/tools/__tests__/update-tasks.test.js +0 -788
  126. package/dist/tools/__tests__/user-info.test.d.ts +0 -2
  127. package/dist/tools/__tests__/user-info.test.d.ts.map +0 -1
  128. package/dist/tools/__tests__/user-info.test.js +0 -139
  129. package/dist/tools/add-comments.js +0 -79
  130. package/dist/tools/add-projects.js +0 -63
  131. package/dist/tools/add-sections.js +0 -61
  132. package/dist/tools/add-tasks.js +0 -160
  133. package/dist/tools/complete-tasks.js +0 -68
  134. package/dist/tools/delete-object.js +0 -79
  135. package/dist/tools/fetch.js +0 -102
  136. package/dist/tools/find-activity.js +0 -221
  137. package/dist/tools/find-comments.js +0 -143
  138. package/dist/tools/find-completed-tasks.js +0 -161
  139. package/dist/tools/find-project-collaborators.js +0 -151
  140. package/dist/tools/find-projects.js +0 -101
  141. package/dist/tools/find-sections.js +0 -96
  142. package/dist/tools/find-tasks-by-date.js +0 -198
  143. package/dist/tools/find-tasks.js +0 -329
  144. package/dist/tools/get-overview.js +0 -249
  145. package/dist/tools/manage-assignments.js +0 -337
  146. package/dist/tools/search.js +0 -65
  147. package/dist/tools/update-comments.js +0 -82
  148. package/dist/tools/update-projects.js +0 -84
  149. package/dist/tools/update-sections.js +0 -70
  150. package/dist/tools/update-tasks.js +0 -170
  151. package/dist/tools/user-info.js +0 -142
  152. package/dist/utils/assignment-validator.js +0 -253
  153. package/dist/utils/constants.js +0 -45
  154. package/dist/utils/duration-parser.js +0 -96
  155. package/dist/utils/duration-parser.test.d.ts +0 -2
  156. package/dist/utils/duration-parser.test.d.ts.map +0 -1
  157. package/dist/utils/duration-parser.test.js +0 -147
  158. package/dist/utils/labels.js +0 -18
  159. package/dist/utils/priorities.js +0 -20
  160. package/dist/utils/response-builders.js +0 -210
  161. package/dist/utils/sanitize-data.js +0 -37
  162. package/dist/utils/sanitize-data.test.d.ts +0 -2
  163. package/dist/utils/sanitize-data.test.d.ts.map +0 -1
  164. package/dist/utils/sanitize-data.test.js +0 -93
  165. package/dist/utils/test-helpers.js +0 -237
  166. package/dist/utils/tool-names.js +0 -40
  167. package/dist/utils/user-resolver.js +0 -179
@@ -1,533 +0,0 @@
1
- import { jest } from '@jest/globals';
2
- import { createMockTask, extractStructuredContent, extractTextContent, TODAY, } from '../../utils/test-helpers.js';
3
- import { ToolNames } from '../../utils/tool-names.js';
4
- import { addTasks } from '../add-tasks.js';
5
- // Mock the Todoist API
6
- const mockTodoistApi = {
7
- addTask: jest.fn(),
8
- };
9
- const { ADD_TASKS, GET_OVERVIEW } = ToolNames;
10
- describe(`${ADD_TASKS} tool`, () => {
11
- beforeEach(() => {
12
- jest.clearAllMocks();
13
- });
14
- describe('adding multiple tasks', () => {
15
- it('should add multiple tasks and return mapped results', async () => {
16
- // Mock API responses extracted from recordings (Task type)
17
- const mockApiResponse1 = createMockTask({
18
- id: '8485093748',
19
- content: 'First task content',
20
- url: 'https://todoist.com/showTask?id=8485093748',
21
- addedAt: '2025-08-13T22:09:56.123456Z',
22
- });
23
- const mockApiResponse2 = createMockTask({
24
- id: '8485093749',
25
- content: 'Second task content',
26
- description: 'Task description',
27
- labels: ['work', 'urgent'],
28
- childOrder: 2,
29
- priority: 2,
30
- url: 'https://todoist.com/showTask?id=8485093749',
31
- addedAt: '2025-08-13T22:09:57.123456Z',
32
- due: {
33
- date: '2025-08-15',
34
- isRecurring: false,
35
- lang: 'en',
36
- string: 'Aug 15',
37
- timezone: null,
38
- },
39
- });
40
- mockTodoistApi.addTask
41
- .mockResolvedValueOnce(mockApiResponse1)
42
- .mockResolvedValueOnce(mockApiResponse2);
43
- const result = await addTasks.execute({
44
- tasks: [
45
- {
46
- content: 'First task content',
47
- projectId: '6cfCcrrCFg2xP94Q',
48
- },
49
- {
50
- content: 'Second task content',
51
- description: 'Task description',
52
- priority: 'p2',
53
- dueString: 'Aug 15',
54
- projectId: '6cfCcrrCFg2xP94Q',
55
- },
56
- ],
57
- }, mockTodoistApi);
58
- // Verify API was called correctly for each task
59
- expect(mockTodoistApi.addTask).toHaveBeenCalledTimes(2);
60
- expect(mockTodoistApi.addTask).toHaveBeenNthCalledWith(1, {
61
- content: 'First task content',
62
- projectId: '6cfCcrrCFg2xP94Q',
63
- sectionId: undefined,
64
- parentId: undefined,
65
- });
66
- expect(mockTodoistApi.addTask).toHaveBeenNthCalledWith(2, {
67
- content: 'Second task content',
68
- description: 'Task description',
69
- priority: 3,
70
- dueString: 'Aug 15',
71
- projectId: '6cfCcrrCFg2xP94Q',
72
- sectionId: undefined,
73
- parentId: undefined,
74
- });
75
- // Verify result is a concise summary
76
- expect(extractTextContent(result)).toMatchSnapshot();
77
- // Verify structured content
78
- const structuredContent = extractStructuredContent(result);
79
- expect(structuredContent.tasks).toHaveLength(2);
80
- expect(structuredContent).toEqual(expect.objectContaining({
81
- totalCount: 2,
82
- tasks: expect.arrayContaining([
83
- expect.objectContaining({ id: '8485093748' }),
84
- expect.objectContaining({ id: '8485093749' }),
85
- ]),
86
- }));
87
- });
88
- it('should handle tasks with section and parent IDs', async () => {
89
- const mockApiResponse = createMockTask({
90
- id: '8485093750',
91
- content: 'Subtask content',
92
- description: 'Subtask description',
93
- priority: 3,
94
- sectionId: 'section-123',
95
- parentId: 'parent-task-456',
96
- url: 'https://todoist.com/showTask?id=8485093750',
97
- addedAt: '2025-08-13T22:09:58.123456Z',
98
- });
99
- mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
100
- const result = await addTasks.execute({
101
- tasks: [
102
- {
103
- content: 'Subtask content',
104
- description: 'Subtask description',
105
- priority: 'p3',
106
- projectId: '6cfCcrrCFg2xP94Q',
107
- sectionId: 'section-123',
108
- parentId: 'parent-task-456',
109
- },
110
- ],
111
- }, mockTodoistApi);
112
- expect(mockTodoistApi.addTask).toHaveBeenCalledWith({
113
- content: 'Subtask content',
114
- description: 'Subtask description',
115
- priority: 2,
116
- projectId: '6cfCcrrCFg2xP94Q',
117
- sectionId: 'section-123',
118
- parentId: 'parent-task-456',
119
- });
120
- // Verify result is a concise summary
121
- expect(extractTextContent(result)).toMatchSnapshot();
122
- // Verify structured content
123
- const structuredContent = extractStructuredContent(result);
124
- expect(structuredContent).toEqual(expect.objectContaining({
125
- totalCount: 1,
126
- tasks: expect.arrayContaining([expect.objectContaining({ id: '8485093750' })]),
127
- }));
128
- });
129
- it('should add tasks with duration', async () => {
130
- const mockApiResponse1 = createMockTask({
131
- id: '8485093752',
132
- content: 'Task with 2 hour duration',
133
- duration: { amount: 120, unit: 'minute' },
134
- url: 'https://todoist.com/showTask?id=8485093752',
135
- addedAt: '2025-08-13T22:09:56.123456Z',
136
- });
137
- const mockApiResponse2 = createMockTask({
138
- id: '8485093753',
139
- content: 'Task with 45 minute duration',
140
- duration: { amount: 45, unit: 'minute' },
141
- url: 'https://todoist.com/showTask?id=8485093753',
142
- addedAt: '2025-08-13T22:09:57.123456Z',
143
- });
144
- mockTodoistApi.addTask
145
- .mockResolvedValueOnce(mockApiResponse1)
146
- .mockResolvedValueOnce(mockApiResponse2);
147
- const result = await addTasks.execute({
148
- tasks: [
149
- {
150
- content: 'Task with 2 hour duration',
151
- duration: '2h',
152
- projectId: '6cfCcrrCFg2xP94Q',
153
- },
154
- {
155
- content: 'Task with 45 minute duration',
156
- duration: '45m',
157
- projectId: '6cfCcrrCFg2xP94Q',
158
- },
159
- ],
160
- }, mockTodoistApi);
161
- // Verify API was called with parsed duration
162
- expect(mockTodoistApi.addTask).toHaveBeenNthCalledWith(1, {
163
- content: 'Task with 2 hour duration',
164
- projectId: '6cfCcrrCFg2xP94Q',
165
- sectionId: undefined,
166
- parentId: undefined,
167
- duration: 120,
168
- durationUnit: 'minute',
169
- });
170
- expect(mockTodoistApi.addTask).toHaveBeenNthCalledWith(2, {
171
- content: 'Task with 45 minute duration',
172
- projectId: '6cfCcrrCFg2xP94Q',
173
- sectionId: undefined,
174
- parentId: undefined,
175
- duration: 45,
176
- durationUnit: 'minute',
177
- });
178
- // Verify result is a concise summary
179
- expect(extractTextContent(result)).toMatchSnapshot();
180
- // Verify structured content
181
- const structuredContent = extractStructuredContent(result);
182
- expect(structuredContent.tasks).toHaveLength(2);
183
- expect(structuredContent).toEqual(expect.objectContaining({
184
- totalCount: 2,
185
- tasks: expect.arrayContaining([
186
- expect.objectContaining({ id: '8485093752' }),
187
- expect.objectContaining({ id: '8485093753' }),
188
- ]),
189
- }));
190
- });
191
- it('should handle various duration formats', async () => {
192
- const mockApiResponse = createMockTask({
193
- id: '8485093754',
194
- content: 'Task with combined duration',
195
- duration: { amount: 150, unit: 'minute' },
196
- url: 'https://todoist.com/showTask?id=8485093754',
197
- addedAt: '2025-08-13T22:09:56.123456Z',
198
- });
199
- mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
200
- // Test different duration formats
201
- const testCases = [
202
- { input: '2h30m', expectedMinutes: 150 },
203
- { input: '1.5h', expectedMinutes: 90 },
204
- { input: ' 90m ', expectedMinutes: 90 },
205
- { input: '2H30M', expectedMinutes: 150 },
206
- ];
207
- for (const testCase of testCases) {
208
- mockTodoistApi.addTask.mockClear();
209
- await addTasks.execute({
210
- tasks: [
211
- {
212
- content: 'Test task',
213
- duration: testCase.input,
214
- projectId: '6cfCcrrCFg2xP94Q',
215
- },
216
- ],
217
- }, mockTodoistApi);
218
- expect(mockTodoistApi.addTask).toHaveBeenCalledWith(expect.objectContaining({
219
- duration: testCase.expectedMinutes,
220
- durationUnit: 'minute',
221
- }));
222
- }
223
- });
224
- it('should add task with deadline', async () => {
225
- const mockApiResponse = createMockTask({
226
- id: '8485093756',
227
- content: 'Task with deadline',
228
- deadline: {
229
- date: '2025-12-31',
230
- lang: 'en',
231
- },
232
- url: 'https://todoist.com/showTask?id=8485093756',
233
- addedAt: '2025-08-13T22:09:56.123456Z',
234
- });
235
- mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
236
- const result = await addTasks.execute({
237
- tasks: [
238
- {
239
- content: 'Task with deadline',
240
- projectId: '6cfCcrrCFg2xP94Q',
241
- deadlineDate: '2025-12-31',
242
- },
243
- ],
244
- }, mockTodoistApi);
245
- // Verify API was called with deadline
246
- expect(mockTodoistApi.addTask).toHaveBeenCalledWith({
247
- content: 'Task with deadline',
248
- projectId: '6cfCcrrCFg2xP94Q',
249
- sectionId: undefined,
250
- parentId: undefined,
251
- deadlineDate: '2025-12-31',
252
- });
253
- // Verify result is a concise summary
254
- expect(extractTextContent(result)).toMatchSnapshot();
255
- // Verify structured content includes deadline
256
- const structuredContent = extractStructuredContent(result);
257
- expect(structuredContent.tasks).toHaveLength(1);
258
- expect(structuredContent).toEqual(expect.objectContaining({
259
- totalCount: 1,
260
- tasks: expect.arrayContaining([
261
- expect.objectContaining({
262
- id: '8485093756',
263
- deadlineDate: '2025-12-31',
264
- }),
265
- ]),
266
- }));
267
- });
268
- it('should add task with labels', async () => {
269
- const mockApiResponse = createMockTask({
270
- id: '8485093755',
271
- content: 'Task with labels',
272
- labels: ['urgent', 'work'],
273
- url: 'https://todoist.com/showTask?id=8485093755',
274
- addedAt: '2025-08-13T22:09:56.123456Z',
275
- });
276
- mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
277
- const result = await addTasks.execute({
278
- tasks: [
279
- {
280
- content: 'Task with labels',
281
- labels: ['urgent', 'work'],
282
- projectId: '6cfCcrrCFg2xP94Q',
283
- },
284
- ],
285
- }, mockTodoistApi);
286
- expect(mockTodoistApi.addTask).toHaveBeenCalledWith({
287
- content: 'Task with labels',
288
- labels: ['urgent', 'work'],
289
- projectId: '6cfCcrrCFg2xP94Q',
290
- sectionId: undefined,
291
- parentId: undefined,
292
- });
293
- // Verify structured content includes labels
294
- const structuredContent = extractStructuredContent(result);
295
- expect(structuredContent.tasks).toHaveLength(1);
296
- expect(structuredContent.tasks).toEqual(expect.arrayContaining([expect.objectContaining({ labels: ['urgent', 'work'] })]));
297
- });
298
- it('should add task with empty labels array', async () => {
299
- const mockApiResponse = createMockTask({
300
- id: '8485093756',
301
- content: 'Task with empty labels',
302
- labels: [],
303
- url: 'https://todoist.com/showTask?id=8485093756',
304
- addedAt: '2025-08-13T22:09:56.123456Z',
305
- });
306
- mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
307
- await addTasks.execute({
308
- tasks: [
309
- {
310
- content: 'Task with empty labels',
311
- labels: [],
312
- projectId: '6cfCcrrCFg2xP94Q',
313
- },
314
- ],
315
- }, mockTodoistApi);
316
- expect(mockTodoistApi.addTask).toHaveBeenCalledWith({
317
- content: 'Task with empty labels',
318
- labels: [],
319
- projectId: '6cfCcrrCFg2xP94Q',
320
- sectionId: undefined,
321
- parentId: undefined,
322
- });
323
- });
324
- it('should add task without labels field', async () => {
325
- const mockApiResponse = createMockTask({
326
- id: '8485093757',
327
- content: 'Task without labels',
328
- url: 'https://todoist.com/showTask?id=8485093757',
329
- addedAt: '2025-08-13T22:09:56.123456Z',
330
- });
331
- mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
332
- await addTasks.execute({
333
- tasks: [
334
- {
335
- content: 'Task without labels',
336
- projectId: '6cfCcrrCFg2xP94Q',
337
- },
338
- ],
339
- }, mockTodoistApi);
340
- expect(mockTodoistApi.addTask).toHaveBeenCalledWith({
341
- content: 'Task without labels',
342
- labels: undefined,
343
- projectId: '6cfCcrrCFg2xP94Q',
344
- sectionId: undefined,
345
- parentId: undefined,
346
- });
347
- });
348
- it('should add multiple tasks with different label configurations', async () => {
349
- const mockApiResponse1 = createMockTask({
350
- id: '8485093758',
351
- content: 'Task with labels',
352
- labels: ['personal'],
353
- });
354
- const mockApiResponse2 = createMockTask({
355
- id: '8485093759',
356
- content: 'Task without labels',
357
- });
358
- const mockApiResponse3 = createMockTask({
359
- id: '8485093760',
360
- content: 'Task with multiple labels',
361
- labels: ['work', 'urgent', 'review'],
362
- });
363
- mockTodoistApi.addTask
364
- .mockResolvedValueOnce(mockApiResponse1)
365
- .mockResolvedValueOnce(mockApiResponse2)
366
- .mockResolvedValueOnce(mockApiResponse3);
367
- await addTasks.execute({
368
- tasks: [
369
- {
370
- content: 'Task with labels',
371
- labels: ['personal'],
372
- projectId: '6cfCcrrCFg2xP94Q',
373
- },
374
- {
375
- content: 'Task without labels',
376
- projectId: '6cfCcrrCFg2xP94Q',
377
- },
378
- {
379
- content: 'Task with multiple labels',
380
- labels: ['work', 'urgent', 'review'],
381
- projectId: '6cfCcrrCFg2xP94Q',
382
- },
383
- ],
384
- }, mockTodoistApi);
385
- expect(mockTodoistApi.addTask).toHaveBeenCalledTimes(3);
386
- expect(mockTodoistApi.addTask).toHaveBeenNthCalledWith(1, expect.objectContaining({
387
- labels: ['personal'],
388
- }));
389
- expect(mockTodoistApi.addTask).toHaveBeenNthCalledWith(2, expect.objectContaining({
390
- labels: undefined,
391
- }));
392
- expect(mockTodoistApi.addTask).toHaveBeenNthCalledWith(3, expect.objectContaining({
393
- labels: ['work', 'urgent', 'review'],
394
- }));
395
- });
396
- });
397
- describe('error handling', () => {
398
- it('should throw error for invalid duration format', async () => {
399
- await expect(addTasks.execute({
400
- tasks: [
401
- {
402
- content: 'Task with invalid duration',
403
- duration: 'invalid',
404
- projectId: '6cfCcrrCFg2xP94Q',
405
- },
406
- ],
407
- }, mockTodoistApi)).rejects.toThrow('Task "Task with invalid duration": Invalid duration format "invalid"');
408
- });
409
- it('should throw error for duration exceeding 24 hours', async () => {
410
- await expect(addTasks.execute({
411
- tasks: [
412
- {
413
- content: 'Task with too long duration',
414
- duration: '25h',
415
- projectId: '6cfCcrrCFg2xP94Q',
416
- },
417
- ],
418
- }, mockTodoistApi)).rejects.toThrow('Task "Task with too long duration": Invalid duration format "25h": Duration cannot exceed 24 hours (1440 minutes)');
419
- });
420
- it('should propagate API errors', async () => {
421
- const apiError = new Error('API Error: Task content is required');
422
- mockTodoistApi.addTask.mockRejectedValue(apiError);
423
- await expect(addTasks.execute({ tasks: [{ content: '', projectId: '6cfCcrrCFg2xP94Q' }] }, mockTodoistApi)).rejects.toThrow(apiError.message);
424
- });
425
- it('should handle partial failures when adding multiple tasks', async () => {
426
- const mockApiResponse = createMockTask({
427
- id: '8485093751',
428
- content: 'First task content',
429
- url: 'https://todoist.com/showTask?id=8485093751',
430
- addedAt: '2025-08-13T22:09:59.123456Z',
431
- });
432
- const apiError = new Error('API Error: Second task failed');
433
- mockTodoistApi.addTask
434
- .mockResolvedValueOnce(mockApiResponse)
435
- .mockRejectedValueOnce(apiError);
436
- await expect(addTasks.execute({
437
- tasks: [
438
- { content: 'First task content', projectId: '6cfCcrrCFg2xP94Q' },
439
- { content: 'Second task content', projectId: '6cfCcrrCFg2xP94Q' },
440
- ],
441
- }, mockTodoistApi)).rejects.toThrow('API Error: Second task failed');
442
- // Verify first task was attempted
443
- expect(mockTodoistApi.addTask).toHaveBeenCalledTimes(2);
444
- });
445
- });
446
- describe('next steps logic', () => {
447
- it('should suggest find-tasks-by-date for today when hasToday is true', async () => {
448
- // Clear any leftover mocks from previous tests
449
- mockTodoistApi.addTask.mockClear();
450
- const mockApiResponse = createMockTask({
451
- id: '8485093755',
452
- content: 'Task due today',
453
- url: 'https://todoist.com/showTask?id=8485093755',
454
- addedAt: '2025-08-13T22:09:56.123456Z',
455
- due: {
456
- date: TODAY,
457
- isRecurring: false,
458
- lang: 'en',
459
- string: 'today',
460
- timezone: null,
461
- },
462
- });
463
- mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
464
- const result = await addTasks.execute({
465
- tasks: [
466
- {
467
- content: 'Task due today',
468
- dueString: 'today',
469
- projectId: '6cfCcrrCFg2xP94Q',
470
- },
471
- ],
472
- }, mockTodoistApi);
473
- const textContent = extractTextContent(result);
474
- expect(textContent).toMatchSnapshot();
475
- expect(textContent).toContain(`Use ${GET_OVERVIEW} to see your updated project organization`);
476
- });
477
- it('should suggest overview tool when no hasToday context', async () => {
478
- // Clear any leftover mocks from previous tests
479
- mockTodoistApi.addTask.mockClear();
480
- const mockApiResponse = createMockTask({
481
- id: '8485093756',
482
- content: 'Regular task',
483
- url: 'https://todoist.com/showTask?id=8485093756',
484
- addedAt: '2025-08-13T22:09:56.123456Z',
485
- });
486
- mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
487
- const result = await addTasks.execute({
488
- tasks: [{ content: 'Regular task', projectId: '6cfCcrrCFg2xP94Q' }],
489
- }, mockTodoistApi);
490
- const textContent = extractTextContent(result);
491
- expect(textContent).toMatchSnapshot();
492
- expect(textContent).toContain(`Use ${GET_OVERVIEW} to see your updated project organization`);
493
- });
494
- });
495
- describe('tasks without project context', () => {
496
- it('should allow creating tasks with only content (goes to Inbox)', async () => {
497
- const mockApiResponse = createMockTask({
498
- id: '8485093758',
499
- content: 'Simple inbox task',
500
- url: 'https://todoist.com/showTask?id=8485093758',
501
- addedAt: '2025-08-13T22:09:56.123456Z',
502
- });
503
- mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
504
- const result = await addTasks.execute({
505
- tasks: [
506
- {
507
- content: 'Simple inbox task',
508
- },
509
- ],
510
- }, mockTodoistApi);
511
- expect(mockTodoistApi.addTask).toHaveBeenCalledWith({
512
- content: 'Simple inbox task',
513
- labels: undefined,
514
- projectId: undefined,
515
- sectionId: undefined,
516
- parentId: undefined,
517
- });
518
- const textContent = extractTextContent(result);
519
- expect(textContent).toContain('Added 1 task');
520
- expect(textContent).toContain('Simple inbox task');
521
- });
522
- it('should prevent assignment without project context', async () => {
523
- await expect(addTasks.execute({
524
- tasks: [
525
- {
526
- content: 'Task with assignment but no project',
527
- responsibleUser: 'user@example.com',
528
- },
529
- ],
530
- }, mockTodoistApi)).rejects.toThrow('Task "Task with assignment but no project": Cannot assign tasks without specifying project context. Please specify a projectId, sectionId, or parentId.');
531
- });
532
- });
533
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=assignment-integration.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"assignment-integration.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/assignment-integration.test.ts"],"names":[],"mappings":""}