@doist/todoist-ai 2.2.2 → 3.0.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/README.md +11 -3
- package/dist/index.d.ts +496 -255
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +41 -29
- package/dist/mcp-helpers.d.ts +25 -3
- package/dist/mcp-helpers.d.ts.map +1 -1
- package/dist/mcp-helpers.js +37 -19
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +32 -28
- package/dist/tools/__tests__/add-tasks.test.d.ts +2 -0
- package/dist/tools/__tests__/add-tasks.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{tasks-add-multiple.test.js → add-tasks.test.js} +85 -81
- package/dist/tools/__tests__/complete-tasks.test.d.ts +2 -0
- package/dist/tools/__tests__/complete-tasks.test.d.ts.map +1 -0
- package/dist/tools/__tests__/complete-tasks.test.js +206 -0
- package/dist/tools/__tests__/delete-object.test.d.ts +2 -0
- package/dist/tools/__tests__/delete-object.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{delete-one.test.js → delete-object.test.js} +42 -22
- package/dist/tools/__tests__/find-completed-tasks.test.d.ts +2 -0
- package/dist/tools/__tests__/find-completed-tasks.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{tasks-list-completed.test.js → find-completed-tasks.test.js} +13 -36
- package/dist/tools/__tests__/find-projects.test.d.ts +2 -0
- package/dist/tools/__tests__/find-projects.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{projects-list.test.js → find-projects.test.js} +55 -39
- package/dist/tools/__tests__/find-sections.test.d.ts +2 -0
- package/dist/tools/__tests__/find-sections.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{sections-search.test.js → find-sections.test.js} +64 -50
- package/dist/tools/__tests__/find-tasks-by-date.test.d.ts +2 -0
- package/dist/tools/__tests__/find-tasks-by-date.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{tasks-list-by-date.test.js → find-tasks-by-date.test.js} +96 -14
- package/dist/tools/__tests__/find-tasks.test.d.ts +2 -0
- package/dist/tools/__tests__/find-tasks.test.d.ts.map +1 -0
- package/dist/tools/__tests__/find-tasks.test.js +334 -0
- package/dist/tools/__tests__/get-overview.test.d.ts +2 -0
- package/dist/tools/__tests__/get-overview.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{overview.test.js → get-overview.test.js} +77 -13
- package/dist/tools/__tests__/manage-projects.test.d.ts +2 -0
- package/dist/tools/__tests__/manage-projects.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{projects-manage.test.js → manage-projects.test.js} +33 -30
- package/dist/tools/__tests__/manage-sections.test.d.ts +2 -0
- package/dist/tools/__tests__/manage-sections.test.d.ts.map +1 -0
- package/dist/tools/__tests__/manage-sections.test.js +162 -0
- package/dist/tools/__tests__/update-tasks.test.d.ts +2 -0
- package/dist/tools/__tests__/update-tasks.test.d.ts.map +1 -0
- package/dist/tools/__tests__/update-tasks.test.js +645 -0
- package/dist/tools/{tasks-add-multiple.d.ts → add-tasks.d.ts} +36 -16
- package/dist/tools/add-tasks.d.ts.map +1 -0
- package/dist/tools/{tasks-add-multiple.js → add-tasks.js} +39 -4
- package/dist/tools/complete-tasks.d.ts +40 -0
- package/dist/tools/complete-tasks.d.ts.map +1 -0
- package/dist/tools/complete-tasks.js +68 -0
- package/dist/tools/delete-object.d.ts +38 -0
- package/dist/tools/delete-object.d.ts.map +1 -0
- package/dist/tools/delete-object.js +69 -0
- package/dist/tools/find-completed-tasks.d.ts +74 -0
- package/dist/tools/find-completed-tasks.d.ts.map +1 -0
- package/dist/tools/find-completed-tasks.js +112 -0
- package/dist/tools/find-projects.d.ts +53 -0
- package/dist/tools/find-projects.d.ts.map +1 -0
- package/dist/tools/find-projects.js +101 -0
- package/dist/tools/find-sections.d.ts +42 -0
- package/dist/tools/find-sections.d.ts.map +1 -0
- package/dist/tools/find-sections.js +96 -0
- package/dist/tools/find-tasks-by-date.d.ts +59 -0
- package/dist/tools/find-tasks-by-date.d.ts.map +1 -0
- package/dist/tools/find-tasks-by-date.js +121 -0
- package/dist/tools/find-tasks.d.ts +65 -0
- package/dist/tools/find-tasks.d.ts.map +1 -0
- package/dist/tools/find-tasks.js +182 -0
- package/dist/tools/get-overview.d.ts +67 -0
- package/dist/tools/get-overview.d.ts.map +1 -0
- package/dist/tools/{overview.js → get-overview.js} +66 -19
- package/dist/tools/manage-projects.d.ts +35 -0
- package/dist/tools/manage-projects.d.ts.map +1 -0
- package/dist/tools/manage-projects.js +63 -0
- package/dist/tools/manage-sections.d.ts +38 -0
- package/dist/tools/manage-sections.d.ts.map +1 -0
- package/dist/tools/manage-sections.js +78 -0
- package/dist/tools/update-tasks.d.ts +94 -0
- package/dist/tools/update-tasks.d.ts.map +1 -0
- package/dist/tools/update-tasks.js +120 -0
- package/dist/utils/constants.d.ts +35 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +37 -0
- package/dist/utils/response-builders.d.ts +88 -0
- package/dist/utils/response-builders.d.ts.map +1 -0
- package/dist/utils/response-builders.js +202 -0
- package/dist/{tools → utils}/test-helpers.d.ts +16 -0
- package/dist/utils/test-helpers.d.ts.map +1 -0
- package/dist/{tools → utils}/test-helpers.js +51 -0
- package/dist/utils/tool-names.d.ts +23 -0
- package/dist/utils/tool-names.d.ts.map +1 -0
- package/dist/utils/tool-names.js +25 -0
- package/package.json +1 -1
- package/dist/tools/__tests__/delete-one.test.d.ts +0 -2
- package/dist/tools/__tests__/delete-one.test.d.ts.map +0 -1
- package/dist/tools/__tests__/overview.test.d.ts +0 -2
- package/dist/tools/__tests__/overview.test.d.ts.map +0 -1
- package/dist/tools/__tests__/projects-list.test.d.ts +0 -2
- package/dist/tools/__tests__/projects-list.test.d.ts.map +0 -1
- package/dist/tools/__tests__/projects-manage.test.d.ts +0 -2
- package/dist/tools/__tests__/projects-manage.test.d.ts.map +0 -1
- package/dist/tools/__tests__/sections-manage.test.d.ts +0 -2
- package/dist/tools/__tests__/sections-manage.test.d.ts.map +0 -1
- package/dist/tools/__tests__/sections-manage.test.js +0 -138
- package/dist/tools/__tests__/sections-search.test.d.ts +0 -2
- package/dist/tools/__tests__/sections-search.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-add-multiple.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-add-multiple.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-complete-multiple.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-complete-multiple.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-complete-multiple.test.js +0 -146
- package/dist/tools/__tests__/tasks-list-by-date.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-list-by-date.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-list-completed.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-list-completed.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-list-for-container.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-list-for-container.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-list-for-container.test.js +0 -232
- package/dist/tools/__tests__/tasks-organize-multiple.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-organize-multiple.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-organize-multiple.test.js +0 -245
- package/dist/tools/__tests__/tasks-search.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-search.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-search.test.js +0 -106
- package/dist/tools/__tests__/tasks-update-one.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-update-one.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-update-one.test.js +0 -251
- package/dist/tools/delete-one.d.ts +0 -17
- package/dist/tools/delete-one.d.ts.map +0 -1
- package/dist/tools/delete-one.js +0 -25
- package/dist/tools/overview.d.ts +0 -14
- package/dist/tools/overview.d.ts.map +0 -1
- package/dist/tools/projects-list.d.ts +0 -29
- package/dist/tools/projects-list.d.ts.map +0 -1
- package/dist/tools/projects-list.js +0 -39
- package/dist/tools/projects-manage.d.ts +0 -24
- package/dist/tools/projects-manage.d.ts.map +0 -1
- package/dist/tools/projects-manage.js +0 -26
- package/dist/tools/sections-manage.d.ts +0 -23
- package/dist/tools/sections-manage.d.ts.map +0 -1
- package/dist/tools/sections-manage.js +0 -37
- package/dist/tools/sections-search.d.ts +0 -18
- package/dist/tools/sections-search.d.ts.map +0 -1
- package/dist/tools/sections-search.js +0 -27
- package/dist/tools/tasks-add-multiple.d.ts.map +0 -1
- package/dist/tools/tasks-complete-multiple.d.ts +0 -16
- package/dist/tools/tasks-complete-multiple.d.ts.map +0 -1
- package/dist/tools/tasks-complete-multiple.js +0 -23
- package/dist/tools/tasks-list-by-date.d.ts +0 -34
- package/dist/tools/tasks-list-by-date.d.ts.map +0 -1
- package/dist/tools/tasks-list-by-date.js +0 -53
- package/dist/tools/tasks-list-completed.d.ts +0 -44
- package/dist/tools/tasks-list-completed.d.ts.map +0 -1
- package/dist/tools/tasks-list-completed.js +0 -49
- package/dist/tools/tasks-list-for-container.d.ts +0 -34
- package/dist/tools/tasks-list-for-container.d.ts.map +0 -1
- package/dist/tools/tasks-list-for-container.js +0 -48
- package/dist/tools/tasks-organize-multiple.d.ts +0 -37
- package/dist/tools/tasks-organize-multiple.d.ts.map +0 -1
- package/dist/tools/tasks-organize-multiple.js +0 -34
- package/dist/tools/tasks-search.d.ts +0 -32
- package/dist/tools/tasks-search.d.ts.map +0 -1
- package/dist/tools/tasks-search.js +0 -30
- package/dist/tools/tasks-update-one.d.ts +0 -29
- package/dist/tools/tasks-update-one.d.ts.map +0 -1
- package/dist/tools/tasks-update-one.js +0 -63
- package/dist/tools/test-helpers.d.ts.map +0 -1
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { jest } from '@jest/globals';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { TEST_ERRORS, TEST_IDS, createMockSection, extractStructuredContent, extractTextContent, } from '../../utils/test-helpers.js';
|
|
3
|
+
import { ToolNames } from '../../utils/tool-names.js';
|
|
4
|
+
import { findSections } from '../find-sections.js';
|
|
4
5
|
// Mock the Todoist API
|
|
5
6
|
const mockTodoistApi = {
|
|
6
7
|
getSections: jest.fn(),
|
|
7
8
|
};
|
|
8
|
-
|
|
9
|
+
const { FIND_SECTIONS, MANAGE_SECTIONS } = ToolNames;
|
|
10
|
+
describe(`${FIND_SECTIONS} tool`, () => {
|
|
9
11
|
beforeEach(() => {
|
|
10
12
|
jest.clearAllMocks();
|
|
11
13
|
});
|
|
@@ -40,29 +42,47 @@ describe('sections-search tool', () => {
|
|
|
40
42
|
results: mockSections,
|
|
41
43
|
nextCursor: null,
|
|
42
44
|
});
|
|
43
|
-
const result = await
|
|
44
|
-
// Verify API was called correctly
|
|
45
|
+
const result = await findSections.execute({ projectId: TEST_IDS.PROJECT_TEST }, mockTodoistApi);
|
|
45
46
|
expect(mockTodoistApi.getSections).toHaveBeenCalledWith({
|
|
46
47
|
projectId: TEST_IDS.PROJECT_TEST,
|
|
47
48
|
});
|
|
48
|
-
|
|
49
|
-
expect(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
const textContent = extractTextContent(result);
|
|
50
|
+
expect(textContent).toMatchSnapshot();
|
|
51
|
+
expect(textContent).toContain('Sections in project');
|
|
52
|
+
expect(textContent).toContain('To Do • id=');
|
|
53
|
+
expect(textContent).toContain('In Progress • id=');
|
|
54
|
+
expect(textContent).toContain('Done • id=');
|
|
55
|
+
expect(textContent).toContain('Backlog Items • id=');
|
|
56
|
+
// Verify structured content
|
|
57
|
+
const structuredContent = extractStructuredContent(result);
|
|
58
|
+
expect(structuredContent.sections).toHaveLength(4);
|
|
59
|
+
expect(structuredContent.totalCount).toBe(4);
|
|
60
|
+
expect(structuredContent.appliedFilters).toEqual({
|
|
61
|
+
projectId: TEST_IDS.PROJECT_TEST,
|
|
62
|
+
search: undefined,
|
|
63
|
+
});
|
|
55
64
|
});
|
|
56
65
|
it('should handle project with no sections', async () => {
|
|
57
66
|
mockTodoistApi.getSections.mockResolvedValue({
|
|
58
67
|
results: [],
|
|
59
68
|
nextCursor: null,
|
|
60
69
|
});
|
|
61
|
-
const result = await
|
|
70
|
+
const result = await findSections.execute({ projectId: 'empty-project-id' }, mockTodoistApi);
|
|
62
71
|
expect(mockTodoistApi.getSections).toHaveBeenCalledWith({
|
|
63
72
|
projectId: 'empty-project-id',
|
|
64
73
|
});
|
|
65
|
-
|
|
74
|
+
const textContent = extractTextContent(result);
|
|
75
|
+
expect(textContent).toMatchSnapshot();
|
|
76
|
+
expect(textContent).toContain('Project has no sections yet');
|
|
77
|
+
expect(textContent).toContain(`Use ${MANAGE_SECTIONS} to create sections`);
|
|
78
|
+
// Verify structured content
|
|
79
|
+
const structuredContent = extractStructuredContent(result);
|
|
80
|
+
expect(structuredContent.sections).toHaveLength(0);
|
|
81
|
+
expect(structuredContent.totalCount).toBe(0);
|
|
82
|
+
expect(structuredContent.appliedFilters).toEqual({
|
|
83
|
+
projectId: 'empty-project-id',
|
|
84
|
+
search: undefined,
|
|
85
|
+
});
|
|
66
86
|
});
|
|
67
87
|
});
|
|
68
88
|
describe('searching sections by name', () => {
|
|
@@ -96,18 +116,16 @@ describe('sections-search tool', () => {
|
|
|
96
116
|
results: mockSections,
|
|
97
117
|
nextCursor: null,
|
|
98
118
|
});
|
|
99
|
-
const result = await
|
|
100
|
-
projectId: TEST_IDS.PROJECT_TEST,
|
|
101
|
-
search: 'progress',
|
|
102
|
-
}, mockTodoistApi);
|
|
119
|
+
const result = await findSections.execute({ projectId: TEST_IDS.PROJECT_TEST, search: 'progress' }, mockTodoistApi);
|
|
103
120
|
expect(mockTodoistApi.getSections).toHaveBeenCalledWith({
|
|
104
121
|
projectId: TEST_IDS.PROJECT_TEST,
|
|
105
122
|
});
|
|
106
123
|
// Should return both "In Progress" and "Progress Review" (case insensitive partial match)
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
124
|
+
const textContent = extractTextContent(result);
|
|
125
|
+
expect(textContent).toMatchSnapshot();
|
|
126
|
+
expect(textContent).toContain('matching "progress"');
|
|
127
|
+
expect(textContent).toContain('In Progress • id=');
|
|
128
|
+
expect(textContent).toContain('Progress Review • id=');
|
|
111
129
|
});
|
|
112
130
|
it('should handle search with no matches', async () => {
|
|
113
131
|
const mockSections = [
|
|
@@ -127,11 +145,12 @@ describe('sections-search tool', () => {
|
|
|
127
145
|
results: mockSections,
|
|
128
146
|
nextCursor: null,
|
|
129
147
|
});
|
|
130
|
-
const result = await
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
expect(
|
|
148
|
+
const result = await findSections.execute({ projectId: TEST_IDS.PROJECT_TEST, search: 'nonexistent' }, mockTodoistApi);
|
|
149
|
+
const textContent = extractTextContent(result);
|
|
150
|
+
expect(textContent).toMatchSnapshot();
|
|
151
|
+
expect(textContent).toContain('Try broader search terms');
|
|
152
|
+
expect(textContent).toContain('Check spelling');
|
|
153
|
+
expect(textContent).toContain('Remove search to see all sections');
|
|
135
154
|
});
|
|
136
155
|
it('should handle case sensitive search correctly', async () => {
|
|
137
156
|
const mockSections = [
|
|
@@ -151,13 +170,12 @@ describe('sections-search tool', () => {
|
|
|
151
170
|
results: mockSections,
|
|
152
171
|
nextCursor: null,
|
|
153
172
|
});
|
|
154
|
-
const result = await
|
|
155
|
-
projectId: TEST_IDS.PROJECT_TEST,
|
|
156
|
-
search: 'IMPORTANT',
|
|
157
|
-
}, mockTodoistApi);
|
|
173
|
+
const result = await findSections.execute({ projectId: TEST_IDS.PROJECT_TEST, search: 'IMPORTANT' }, mockTodoistApi);
|
|
158
174
|
// Should match despite different case
|
|
159
|
-
|
|
160
|
-
expect(
|
|
175
|
+
const textContent = extractTextContent(result);
|
|
176
|
+
expect(textContent).toMatchSnapshot();
|
|
177
|
+
expect(textContent).toContain('matching "IMPORTANT"');
|
|
178
|
+
expect(textContent).toContain('Important Tasks • id=');
|
|
161
179
|
});
|
|
162
180
|
it('should handle partial matches correctly', async () => {
|
|
163
181
|
const mockSections = [
|
|
@@ -183,15 +201,13 @@ describe('sections-search tool', () => {
|
|
|
183
201
|
results: mockSections,
|
|
184
202
|
nextCursor: null,
|
|
185
203
|
});
|
|
186
|
-
const result = await
|
|
187
|
-
projectId: TEST_IDS.PROJECT_TEST,
|
|
188
|
-
search: 'task',
|
|
189
|
-
}, mockTodoistApi);
|
|
204
|
+
const result = await findSections.execute({ projectId: TEST_IDS.PROJECT_TEST, search: 'task' }, mockTodoistApi);
|
|
190
205
|
// Should match both sections with "task" in the name
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
206
|
+
const textContent = extractTextContent(result);
|
|
207
|
+
expect(textContent).toMatchSnapshot();
|
|
208
|
+
expect(textContent).toContain('matching "task"');
|
|
209
|
+
expect(textContent).toContain('Development Tasks • id=');
|
|
210
|
+
expect(textContent).toContain('Testing Tasks • id=');
|
|
195
211
|
});
|
|
196
212
|
it('should handle exact matches', async () => {
|
|
197
213
|
const mockSections = [
|
|
@@ -211,15 +227,13 @@ describe('sections-search tool', () => {
|
|
|
211
227
|
results: mockSections,
|
|
212
228
|
nextCursor: null,
|
|
213
229
|
});
|
|
214
|
-
const result = await
|
|
215
|
-
projectId: TEST_IDS.PROJECT_TEST,
|
|
216
|
-
search: 'done',
|
|
217
|
-
}, mockTodoistApi);
|
|
230
|
+
const result = await findSections.execute({ projectId: TEST_IDS.PROJECT_TEST, search: 'done' }, mockTodoistApi);
|
|
218
231
|
// Should match both sections containing "done"
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
232
|
+
const textContent = extractTextContent(result);
|
|
233
|
+
expect(textContent).toMatchSnapshot();
|
|
234
|
+
expect(textContent).toContain('matching "done"');
|
|
235
|
+
expect(textContent).toContain('Done • id=');
|
|
236
|
+
expect(textContent).toContain('Done Soon • id=');
|
|
223
237
|
});
|
|
224
238
|
});
|
|
225
239
|
describe('error handling', () => {
|
|
@@ -229,7 +243,7 @@ describe('sections-search tool', () => {
|
|
|
229
243
|
{ error: 'API Error: Invalid project ID format', projectId: 'invalid-id-format' },
|
|
230
244
|
])('should propagate $error', async ({ error, projectId }) => {
|
|
231
245
|
mockTodoistApi.getSections.mockRejectedValue(new Error(error));
|
|
232
|
-
await expect(
|
|
246
|
+
await expect(findSections.execute({ projectId }, mockTodoistApi)).rejects.toThrow(error);
|
|
233
247
|
});
|
|
234
248
|
});
|
|
235
249
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-tasks-by-date.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/find-tasks-by-date.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { jest } from '@jest/globals';
|
|
2
2
|
import { getTasksByFilter } from '../../tool-helpers.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { TEST_ERRORS, TEST_IDS, createMappedTask, extractStructuredContent, extractTextContent, } from '../../utils/test-helpers.js';
|
|
4
|
+
import { ToolNames } from '../../utils/tool-names.js';
|
|
5
|
+
import { findTasksByDate } from '../find-tasks-by-date.js';
|
|
5
6
|
// Mock the tool helpers
|
|
6
7
|
jest.mock('../../tool-helpers', () => ({
|
|
7
8
|
getTasksByFilter: jest.fn(),
|
|
8
9
|
}));
|
|
9
10
|
const mockGetTasksByFilter = getTasksByFilter;
|
|
10
|
-
// Mock the Todoist API (not directly used by tasks-
|
|
11
|
+
// Mock the Todoist API (not directly used by find-tasks-by-date, but needed for type)
|
|
11
12
|
const mockTodoistApi = {};
|
|
12
13
|
// Mock date-fns functions to make tests deterministic
|
|
13
14
|
jest.mock('date-fns', () => ({
|
|
@@ -25,7 +26,8 @@ jest.mock('date-fns', () => ({
|
|
|
25
26
|
return '2025-08-16'; // Return predictable end date
|
|
26
27
|
}),
|
|
27
28
|
}));
|
|
28
|
-
|
|
29
|
+
const { FIND_TASKS_BY_DATE, UPDATE_TASKS } = ToolNames;
|
|
30
|
+
describe(`${FIND_TASKS_BY_DATE} tool`, () => {
|
|
29
31
|
beforeEach(() => {
|
|
30
32
|
jest.clearAllMocks();
|
|
31
33
|
// Mock current date to make tests deterministic
|
|
@@ -52,14 +54,26 @@ describe('tasks-list-by-date tool', () => {
|
|
|
52
54
|
: [];
|
|
53
55
|
const mockResponse = { tasks: mockTasks, nextCursor: null };
|
|
54
56
|
mockGetTasksByFilter.mockResolvedValue(mockResponse);
|
|
55
|
-
const result = await
|
|
57
|
+
const result = await findTasksByDate.execute({ startDate: 'overdue', limit: 50, daysCount }, mockTodoistApi);
|
|
56
58
|
expect(mockGetTasksByFilter).toHaveBeenCalledWith({
|
|
57
59
|
client: mockTodoistApi,
|
|
58
60
|
query: 'overdue',
|
|
59
61
|
cursor: undefined,
|
|
60
62
|
limit: 50,
|
|
61
63
|
});
|
|
62
|
-
|
|
64
|
+
// Verify result is a concise summary
|
|
65
|
+
expect(extractTextContent(result)).toMatchSnapshot();
|
|
66
|
+
// Verify structured content
|
|
67
|
+
const structuredContent = extractStructuredContent(result);
|
|
68
|
+
expect(structuredContent.tasks).toHaveLength(hasTasks ? 1 : 0);
|
|
69
|
+
expect(structuredContent).toEqual(expect.objectContaining({
|
|
70
|
+
totalCount: hasTasks ? 1 : 0,
|
|
71
|
+
hasMore: false,
|
|
72
|
+
nextCursor: null,
|
|
73
|
+
appliedFilters: expect.objectContaining({
|
|
74
|
+
startDate: 'overdue',
|
|
75
|
+
}),
|
|
76
|
+
}));
|
|
63
77
|
});
|
|
64
78
|
});
|
|
65
79
|
describe('listing tasks by date range', () => {
|
|
@@ -67,14 +81,15 @@ describe('tasks-list-by-date tool', () => {
|
|
|
67
81
|
const mockTasks = [createMappedTask({ content: 'Today task', dueDate: '2025-08-15' })];
|
|
68
82
|
const mockResponse = { tasks: mockTasks, nextCursor: null };
|
|
69
83
|
mockGetTasksByFilter.mockResolvedValue(mockResponse);
|
|
70
|
-
const result = await
|
|
84
|
+
const result = await findTasksByDate.execute({ startDate: 'today', limit: 50, daysCount: 7 }, mockTodoistApi);
|
|
71
85
|
expect(mockGetTasksByFilter).toHaveBeenCalledWith({
|
|
72
86
|
client: mockTodoistApi,
|
|
73
87
|
query: expect.stringContaining('due after:') && expect.stringContaining('due before:'),
|
|
74
88
|
cursor: undefined,
|
|
75
89
|
limit: 50,
|
|
76
90
|
});
|
|
77
|
-
|
|
91
|
+
// Verify result is a concise summary
|
|
92
|
+
expect(extractTextContent(result)).toMatchSnapshot();
|
|
78
93
|
});
|
|
79
94
|
it.each([
|
|
80
95
|
{
|
|
@@ -108,14 +123,15 @@ describe('tasks-list-by-date tool', () => {
|
|
|
108
123
|
])('should handle $name', async ({ params, tasks, cursor }) => {
|
|
109
124
|
const mockResponse = { tasks, nextCursor: cursor };
|
|
110
125
|
mockGetTasksByFilter.mockResolvedValue(mockResponse);
|
|
111
|
-
const result = await
|
|
126
|
+
const result = await findTasksByDate.execute(params, mockTodoistApi);
|
|
112
127
|
expect(mockGetTasksByFilter).toHaveBeenCalledWith({
|
|
113
128
|
client: mockTodoistApi,
|
|
114
129
|
query: expect.stringContaining('2025-08-20'),
|
|
115
130
|
cursor: params.cursor || undefined,
|
|
116
131
|
limit: params.limit,
|
|
117
132
|
});
|
|
118
|
-
|
|
133
|
+
// Verify result is a concise summary
|
|
134
|
+
expect(extractTextContent(result)).toMatchSnapshot();
|
|
119
135
|
});
|
|
120
136
|
});
|
|
121
137
|
describe('pagination and limits', () => {
|
|
@@ -140,7 +156,7 @@ describe('tasks-list-by-date tool', () => {
|
|
|
140
156
|
])('should handle $name', async ({ params, expectedCursor, expectedLimit }) => {
|
|
141
157
|
const mockResponse = { tasks: [], nextCursor: null };
|
|
142
158
|
mockGetTasksByFilter.mockResolvedValue(mockResponse);
|
|
143
|
-
await
|
|
159
|
+
await findTasksByDate.execute(params, mockTodoistApi);
|
|
144
160
|
expect(mockGetTasksByFilter).toHaveBeenCalledWith({
|
|
145
161
|
client: mockTodoistApi,
|
|
146
162
|
query: expect.any(String),
|
|
@@ -158,13 +174,79 @@ describe('tasks-list-by-date tool', () => {
|
|
|
158
174
|
const mockResponse = { tasks: [], nextCursor: null };
|
|
159
175
|
mockGetTasksByFilter.mockResolvedValue(mockResponse);
|
|
160
176
|
const startDate = daysCount === 7 ? 'today' : '2025-08-15';
|
|
161
|
-
const result = await
|
|
177
|
+
const result = await findTasksByDate.execute({ startDate, limit: 50, daysCount }, mockTodoistApi);
|
|
162
178
|
expect(mockGetTasksByFilter).toHaveBeenCalledTimes(1);
|
|
163
179
|
if (shouldReturnResult) {
|
|
164
|
-
|
|
180
|
+
// Verify result is a concise summary
|
|
181
|
+
expect(extractTextContent(result)).toMatchSnapshot();
|
|
165
182
|
}
|
|
166
183
|
});
|
|
167
184
|
});
|
|
185
|
+
describe('next steps logic', () => {
|
|
186
|
+
it('should suggest appropriate actions when hasOverdue is true', async () => {
|
|
187
|
+
const mockTasks = [
|
|
188
|
+
createMappedTask({
|
|
189
|
+
id: TEST_IDS.TASK_1,
|
|
190
|
+
content: 'Overdue task from list',
|
|
191
|
+
dueDate: '2025-08-10', // Past date - creates hasOverdue context
|
|
192
|
+
}),
|
|
193
|
+
];
|
|
194
|
+
const mockResponse = { tasks: mockTasks, nextCursor: null };
|
|
195
|
+
mockGetTasksByFilter.mockResolvedValue(mockResponse);
|
|
196
|
+
const result = await findTasksByDate.execute({ startDate: '2025-08-15', limit: 10, daysCount: 1 }, mockTodoistApi);
|
|
197
|
+
const textContent = extractTextContent(result);
|
|
198
|
+
expect(textContent).toMatchSnapshot();
|
|
199
|
+
expect(textContent).toContain(`Use ${UPDATE_TASKS} to modify priorities or due dates`);
|
|
200
|
+
});
|
|
201
|
+
it('should suggest today-focused actions when startDate is today', async () => {
|
|
202
|
+
const mockTasks = [
|
|
203
|
+
createMappedTask({
|
|
204
|
+
id: TEST_IDS.TASK_1,
|
|
205
|
+
content: "Today's task",
|
|
206
|
+
dueDate: '2025-08-15', // Today's date based on our mock
|
|
207
|
+
}),
|
|
208
|
+
];
|
|
209
|
+
const mockResponse = { tasks: mockTasks, nextCursor: null };
|
|
210
|
+
mockGetTasksByFilter.mockResolvedValue(mockResponse);
|
|
211
|
+
const result = await findTasksByDate.execute({ startDate: 'today', limit: 10, daysCount: 1 }, mockTodoistApi);
|
|
212
|
+
const textContent = extractTextContent(result);
|
|
213
|
+
expect(textContent).toMatchSnapshot();
|
|
214
|
+
expect(textContent).toContain(`Use ${UPDATE_TASKS} to modify priorities or due dates`);
|
|
215
|
+
});
|
|
216
|
+
it('should suggest appropriate actions when startDate is overdue', async () => {
|
|
217
|
+
const mockTasks = [
|
|
218
|
+
createMappedTask({
|
|
219
|
+
id: TEST_IDS.TASK_1,
|
|
220
|
+
content: 'Overdue task',
|
|
221
|
+
dueDate: '2025-08-10',
|
|
222
|
+
}),
|
|
223
|
+
];
|
|
224
|
+
const mockResponse = { tasks: mockTasks, nextCursor: null };
|
|
225
|
+
mockGetTasksByFilter.mockResolvedValue(mockResponse);
|
|
226
|
+
const result = await findTasksByDate.execute({ startDate: 'overdue', limit: 10, daysCount: 1 }, mockTodoistApi);
|
|
227
|
+
const textContent = extractTextContent(result);
|
|
228
|
+
expect(textContent).toMatchSnapshot();
|
|
229
|
+
expect(textContent).toContain(`Use ${UPDATE_TASKS} to modify priorities or due dates`);
|
|
230
|
+
});
|
|
231
|
+
it('should provide helpful suggestions for empty overdue results', async () => {
|
|
232
|
+
const mockResponse = { tasks: [], nextCursor: null };
|
|
233
|
+
mockGetTasksByFilter.mockResolvedValue(mockResponse);
|
|
234
|
+
const result = await findTasksByDate.execute({ startDate: 'overdue', limit: 10, daysCount: 1 }, mockTodoistApi);
|
|
235
|
+
const textContent = extractTextContent(result);
|
|
236
|
+
expect(textContent).toMatchSnapshot();
|
|
237
|
+
expect(textContent).toContain('Great job! No overdue tasks');
|
|
238
|
+
expect(textContent).toContain("Check today's tasks with startDate='today'");
|
|
239
|
+
});
|
|
240
|
+
it('should provide helpful suggestions for empty date range results', async () => {
|
|
241
|
+
const mockResponse = { tasks: [], nextCursor: null };
|
|
242
|
+
mockGetTasksByFilter.mockResolvedValue(mockResponse);
|
|
243
|
+
const result = await findTasksByDate.execute({ startDate: '2025-08-20', limit: 10, daysCount: 1 }, mockTodoistApi);
|
|
244
|
+
const textContent = extractTextContent(result);
|
|
245
|
+
expect(textContent).toMatchSnapshot();
|
|
246
|
+
expect(textContent).toContain("Expand date range with larger 'daysCount'");
|
|
247
|
+
expect(textContent).toContain("Check 'overdue' for past-due items");
|
|
248
|
+
});
|
|
249
|
+
});
|
|
168
250
|
describe('error handling', () => {
|
|
169
251
|
it.each([
|
|
170
252
|
{
|
|
@@ -186,7 +268,7 @@ describe('tasks-list-by-date tool', () => {
|
|
|
186
268
|
},
|
|
187
269
|
])('should propagate $error', async ({ error, params }) => {
|
|
188
270
|
mockGetTasksByFilter.mockRejectedValue(new Error(error));
|
|
189
|
-
await expect(
|
|
271
|
+
await expect(findTasksByDate.execute(params, mockTodoistApi)).rejects.toThrow(error);
|
|
190
272
|
});
|
|
191
273
|
});
|
|
192
274
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-tasks.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/find-tasks.test.ts"],"names":[],"mappings":""}
|