@doist/todoist-ai 2.2.2 → 4.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 +6 -14
- package/dist/index.d.ts +619 -250
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +45 -29
- package/dist/main.js +2 -1
- 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 +44 -28
- package/dist/tools/__tests__/add-comments.test.d.ts +2 -0
- package/dist/tools/__tests__/add-comments.test.d.ts.map +1 -0
- package/dist/tools/__tests__/add-comments.test.js +241 -0
- package/dist/tools/__tests__/add-projects.test.d.ts +2 -0
- package/dist/tools/__tests__/add-projects.test.d.ts.map +1 -0
- package/dist/tools/__tests__/add-projects.test.js +152 -0
- package/dist/tools/__tests__/add-sections.test.d.ts +2 -0
- package/dist/tools/__tests__/add-sections.test.d.ts.map +1 -0
- package/dist/tools/__tests__/add-sections.test.js +181 -0
- 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} +89 -79
- 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-comments.test.d.ts +2 -0
- package/dist/tools/__tests__/find-comments.test.d.ts.map +1 -0
- package/dist/tools/__tests__/find-comments.test.js +242 -0
- 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__/update-comments.test.d.ts +2 -0
- package/dist/tools/__tests__/update-comments.test.d.ts.map +1 -0
- package/dist/tools/__tests__/update-comments.test.js +296 -0
- package/dist/tools/__tests__/update-projects.test.d.ts +2 -0
- package/dist/tools/__tests__/update-projects.test.d.ts.map +1 -0
- package/dist/tools/__tests__/update-projects.test.js +205 -0
- package/dist/tools/__tests__/update-sections.test.d.ts +2 -0
- package/dist/tools/__tests__/update-sections.test.d.ts.map +1 -0
- package/dist/tools/__tests__/update-sections.test.js +156 -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/add-comments.d.ts +51 -0
- package/dist/tools/add-comments.d.ts.map +1 -0
- package/dist/tools/add-comments.js +79 -0
- package/dist/tools/add-projects.d.ts +50 -0
- package/dist/tools/add-projects.d.ts.map +1 -0
- package/dist/tools/add-projects.js +59 -0
- package/dist/tools/add-sections.d.ts +46 -0
- package/dist/tools/add-sections.d.ts.map +1 -0
- package/dist/tools/add-sections.js +61 -0
- package/dist/tools/add-tasks.d.ts +82 -0
- package/dist/tools/add-tasks.d.ts.map +1 -0
- package/dist/tools/add-tasks.js +96 -0
- 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 +79 -0
- package/dist/tools/find-comments.d.ts +46 -0
- package/dist/tools/find-comments.d.ts.map +1 -0
- package/dist/tools/find-comments.js +143 -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/update-comments.d.ts +50 -0
- package/dist/tools/update-comments.d.ts.map +1 -0
- package/dist/tools/update-comments.js +82 -0
- package/dist/tools/update-projects.d.ts +59 -0
- package/dist/tools/update-projects.d.ts.map +1 -0
- package/dist/tools/update-projects.js +84 -0
- package/dist/tools/update-sections.d.ts +47 -0
- package/dist/tools/update-sections.d.ts.map +1 -0
- package/dist/tools/update-sections.js +70 -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 +39 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +41 -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 +28 -0
- package/dist/utils/tool-names.d.ts.map +1 -0
- package/dist/utils/tool-names.js +31 -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__/projects-manage.test.js +0 -106
- 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 +0 -55
- package/dist/tools/tasks-add-multiple.d.ts.map +0 -1
- package/dist/tools/tasks-add-multiple.js +0 -52
- 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
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
import { TEST_IDS, createMockProject, extractStructuredContent, extractTextContent, } 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
|
+
});
|
|
94
|
+
describe('creating multiple projects', () => {
|
|
95
|
+
it('should create multiple projects and return mapped results', async () => {
|
|
96
|
+
const mockProjects = [
|
|
97
|
+
createMockProject({ id: 'project-1', name: 'First Project' }),
|
|
98
|
+
createMockProject({ id: 'project-2', name: 'Second Project' }),
|
|
99
|
+
createMockProject({ id: 'project-3', name: 'Third Project' }),
|
|
100
|
+
];
|
|
101
|
+
const [project1, project2, project3] = mockProjects;
|
|
102
|
+
mockTodoistApi.addProject
|
|
103
|
+
.mockResolvedValueOnce(project1)
|
|
104
|
+
.mockResolvedValueOnce(project2)
|
|
105
|
+
.mockResolvedValueOnce(project3);
|
|
106
|
+
const result = await addProjects.execute({
|
|
107
|
+
projects: [
|
|
108
|
+
{ name: 'First Project' },
|
|
109
|
+
{ name: 'Second Project' },
|
|
110
|
+
{ name: 'Third Project' },
|
|
111
|
+
],
|
|
112
|
+
}, mockTodoistApi);
|
|
113
|
+
// Verify API was called correctly for each project
|
|
114
|
+
expect(mockTodoistApi.addProject).toHaveBeenCalledTimes(3);
|
|
115
|
+
expect(mockTodoistApi.addProject).toHaveBeenNthCalledWith(1, { name: 'First Project' });
|
|
116
|
+
expect(mockTodoistApi.addProject).toHaveBeenNthCalledWith(2, { name: 'Second Project' });
|
|
117
|
+
expect(mockTodoistApi.addProject).toHaveBeenNthCalledWith(3, { name: 'Third Project' });
|
|
118
|
+
const textContent = extractTextContent(result);
|
|
119
|
+
expect(textContent).toMatchSnapshot();
|
|
120
|
+
expect(textContent).toContain('Added 3 projects:');
|
|
121
|
+
expect(textContent).toContain('First Project (id=project-1)');
|
|
122
|
+
expect(textContent).toContain('Second Project (id=project-2)');
|
|
123
|
+
expect(textContent).toContain('Third Project (id=project-3)');
|
|
124
|
+
expect(textContent).toContain(`Use ${ADD_SECTIONS} to organize these projects`);
|
|
125
|
+
// Verify structured content
|
|
126
|
+
const structuredContent = extractStructuredContent(result);
|
|
127
|
+
expect(structuredContent).toEqual(expect.objectContaining({
|
|
128
|
+
projects: mockProjects,
|
|
129
|
+
totalCount: 3,
|
|
130
|
+
}));
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
describe('error handling', () => {
|
|
134
|
+
it('should propagate API errors', async () => {
|
|
135
|
+
const apiError = new Error('API Error: Project name is required');
|
|
136
|
+
mockTodoistApi.addProject.mockRejectedValue(apiError);
|
|
137
|
+
await expect(addProjects.execute({ projects: [{ name: '' }] }, mockTodoistApi)).rejects.toThrow('API Error: Project name is required');
|
|
138
|
+
});
|
|
139
|
+
it('should handle partial failures in multiple projects', async () => {
|
|
140
|
+
const mockProject = createMockProject({
|
|
141
|
+
id: 'project-1',
|
|
142
|
+
name: 'First Project',
|
|
143
|
+
});
|
|
144
|
+
mockTodoistApi.addProject
|
|
145
|
+
.mockResolvedValueOnce(mockProject)
|
|
146
|
+
.mockRejectedValueOnce(new Error('API Error: Invalid project name'));
|
|
147
|
+
await expect(addProjects.execute({
|
|
148
|
+
projects: [{ name: 'First Project' }, { name: 'Invalid' }],
|
|
149
|
+
}, mockTodoistApi)).rejects.toThrow('API Error: Invalid project name');
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-sections.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/add-sections.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
import { TEST_IDS, createMockSection, extractStructuredContent, extractTextContent, } from '../../utils/test-helpers.js';
|
|
3
|
+
import { ToolNames } from '../../utils/tool-names.js';
|
|
4
|
+
import { addSections } from '../add-sections.js';
|
|
5
|
+
// Mock the Todoist API
|
|
6
|
+
const mockTodoistApi = {
|
|
7
|
+
addSection: jest.fn(),
|
|
8
|
+
};
|
|
9
|
+
const { ADD_TASKS, ADD_SECTIONS, FIND_TASKS } = ToolNames;
|
|
10
|
+
describe(`${ADD_SECTIONS} tool`, () => {
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
jest.clearAllMocks();
|
|
13
|
+
});
|
|
14
|
+
describe('creating a single section', () => {
|
|
15
|
+
it('should create a section and return mapped result', async () => {
|
|
16
|
+
const mockApiResponse = createMockSection({
|
|
17
|
+
id: TEST_IDS.SECTION_1,
|
|
18
|
+
projectId: TEST_IDS.PROJECT_TEST,
|
|
19
|
+
name: 'test-abc123def456-section',
|
|
20
|
+
});
|
|
21
|
+
mockTodoistApi.addSection.mockResolvedValue(mockApiResponse);
|
|
22
|
+
const result = await addSections.execute({
|
|
23
|
+
sections: [
|
|
24
|
+
{ name: 'test-abc123def456-section', projectId: TEST_IDS.PROJECT_TEST },
|
|
25
|
+
],
|
|
26
|
+
}, mockTodoistApi);
|
|
27
|
+
// Verify API was called correctly
|
|
28
|
+
expect(mockTodoistApi.addSection).toHaveBeenCalledWith({
|
|
29
|
+
name: 'test-abc123def456-section',
|
|
30
|
+
projectId: TEST_IDS.PROJECT_TEST,
|
|
31
|
+
});
|
|
32
|
+
const textContent = extractTextContent(result);
|
|
33
|
+
expect(textContent).toMatchSnapshot();
|
|
34
|
+
expect(textContent).toContain('Added 1 section:');
|
|
35
|
+
expect(textContent).toContain('test-abc123def456-section');
|
|
36
|
+
expect(textContent).toContain(`id=${TEST_IDS.SECTION_1}`);
|
|
37
|
+
expect(textContent).toContain(`Use ${ADD_TASKS} with sectionId`);
|
|
38
|
+
// Verify structured content
|
|
39
|
+
const structuredContent = extractStructuredContent(result);
|
|
40
|
+
expect(structuredContent).toEqual(expect.objectContaining({
|
|
41
|
+
sections: [
|
|
42
|
+
expect.objectContaining({
|
|
43
|
+
id: TEST_IDS.SECTION_1,
|
|
44
|
+
name: 'test-abc123def456-section',
|
|
45
|
+
}),
|
|
46
|
+
],
|
|
47
|
+
totalCount: 1,
|
|
48
|
+
}));
|
|
49
|
+
});
|
|
50
|
+
it('should handle different section properties from API', async () => {
|
|
51
|
+
const mockApiResponse = createMockSection({
|
|
52
|
+
id: TEST_IDS.SECTION_2,
|
|
53
|
+
projectId: 'project-789',
|
|
54
|
+
sectionOrder: 2,
|
|
55
|
+
name: 'My Section Name',
|
|
56
|
+
});
|
|
57
|
+
mockTodoistApi.addSection.mockResolvedValue(mockApiResponse);
|
|
58
|
+
const result = await addSections.execute({ sections: [{ name: 'My Section Name', projectId: 'project-789' }] }, mockTodoistApi);
|
|
59
|
+
expect(mockTodoistApi.addSection).toHaveBeenCalledWith({
|
|
60
|
+
name: 'My Section Name',
|
|
61
|
+
projectId: 'project-789',
|
|
62
|
+
});
|
|
63
|
+
const textContent = extractTextContent(result);
|
|
64
|
+
expect(textContent).toMatchSnapshot();
|
|
65
|
+
expect(textContent).toContain('Added 1 section:');
|
|
66
|
+
expect(textContent).toContain('My Section Name');
|
|
67
|
+
expect(textContent).toContain(`id=${TEST_IDS.SECTION_2}`);
|
|
68
|
+
expect(textContent).toContain(`Use ${FIND_TASKS} with sectionId`);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe('creating multiple sections', () => {
|
|
72
|
+
it('should create multiple sections and return mapped results', async () => {
|
|
73
|
+
const mockSections = [
|
|
74
|
+
createMockSection({
|
|
75
|
+
id: 'section-1',
|
|
76
|
+
projectId: TEST_IDS.PROJECT_TEST,
|
|
77
|
+
name: 'First Section',
|
|
78
|
+
}),
|
|
79
|
+
createMockSection({
|
|
80
|
+
id: 'section-2',
|
|
81
|
+
projectId: TEST_IDS.PROJECT_TEST,
|
|
82
|
+
name: 'Second Section',
|
|
83
|
+
}),
|
|
84
|
+
createMockSection({
|
|
85
|
+
id: 'section-3',
|
|
86
|
+
projectId: 'different-project',
|
|
87
|
+
name: 'Third Section',
|
|
88
|
+
}),
|
|
89
|
+
];
|
|
90
|
+
const [section1, section2, section3] = mockSections;
|
|
91
|
+
mockTodoistApi.addSection
|
|
92
|
+
.mockResolvedValueOnce(section1)
|
|
93
|
+
.mockResolvedValueOnce(section2)
|
|
94
|
+
.mockResolvedValueOnce(section3);
|
|
95
|
+
const result = await addSections.execute({
|
|
96
|
+
sections: [
|
|
97
|
+
{ name: 'First Section', projectId: TEST_IDS.PROJECT_TEST },
|
|
98
|
+
{ name: 'Second Section', projectId: TEST_IDS.PROJECT_TEST },
|
|
99
|
+
{ name: 'Third Section', projectId: 'different-project' },
|
|
100
|
+
],
|
|
101
|
+
}, mockTodoistApi);
|
|
102
|
+
// Verify API was called correctly for each section
|
|
103
|
+
expect(mockTodoistApi.addSection).toHaveBeenCalledTimes(3);
|
|
104
|
+
expect(mockTodoistApi.addSection).toHaveBeenNthCalledWith(1, {
|
|
105
|
+
name: 'First Section',
|
|
106
|
+
projectId: TEST_IDS.PROJECT_TEST,
|
|
107
|
+
});
|
|
108
|
+
expect(mockTodoistApi.addSection).toHaveBeenNthCalledWith(2, {
|
|
109
|
+
name: 'Second Section',
|
|
110
|
+
projectId: TEST_IDS.PROJECT_TEST,
|
|
111
|
+
});
|
|
112
|
+
expect(mockTodoistApi.addSection).toHaveBeenNthCalledWith(3, {
|
|
113
|
+
name: 'Third Section',
|
|
114
|
+
projectId: 'different-project',
|
|
115
|
+
});
|
|
116
|
+
const textContent = extractTextContent(result);
|
|
117
|
+
expect(textContent).toMatchSnapshot();
|
|
118
|
+
expect(textContent).toContain('Added 3 sections:');
|
|
119
|
+
expect(textContent).toContain('First Section (id=section-1, projectId=');
|
|
120
|
+
expect(textContent).toContain('Second Section (id=section-2, projectId=');
|
|
121
|
+
expect(textContent).toContain('Third Section (id=section-3, projectId=different-project)');
|
|
122
|
+
// Verify structured content
|
|
123
|
+
const structuredContent = extractStructuredContent(result);
|
|
124
|
+
expect(structuredContent).toEqual(expect.objectContaining({
|
|
125
|
+
sections: mockSections,
|
|
126
|
+
totalCount: 3,
|
|
127
|
+
}));
|
|
128
|
+
});
|
|
129
|
+
it('should handle sections for the same project', async () => {
|
|
130
|
+
const mockSections = [
|
|
131
|
+
createMockSection({
|
|
132
|
+
id: 'section-1',
|
|
133
|
+
projectId: TEST_IDS.PROJECT_TEST,
|
|
134
|
+
name: 'To Do',
|
|
135
|
+
}),
|
|
136
|
+
createMockSection({
|
|
137
|
+
id: 'section-2',
|
|
138
|
+
projectId: TEST_IDS.PROJECT_TEST,
|
|
139
|
+
name: 'In Progress',
|
|
140
|
+
}),
|
|
141
|
+
];
|
|
142
|
+
const [section1, section2] = mockSections;
|
|
143
|
+
mockTodoistApi.addSection
|
|
144
|
+
.mockResolvedValueOnce(section1)
|
|
145
|
+
.mockResolvedValueOnce(section2);
|
|
146
|
+
const result = await addSections.execute({
|
|
147
|
+
sections: [
|
|
148
|
+
{ name: 'To Do', projectId: TEST_IDS.PROJECT_TEST },
|
|
149
|
+
{ name: 'In Progress', projectId: TEST_IDS.PROJECT_TEST },
|
|
150
|
+
],
|
|
151
|
+
}, mockTodoistApi);
|
|
152
|
+
const textContent = extractTextContent(result);
|
|
153
|
+
expect(textContent).toMatchSnapshot();
|
|
154
|
+
expect(textContent).toContain('Added 2 sections:');
|
|
155
|
+
expect(textContent).toContain(`Use ${ADD_TASKS} to add tasks to these new sections`);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
describe('error handling', () => {
|
|
159
|
+
it('should propagate API errors', async () => {
|
|
160
|
+
const apiError = new Error('API Error: Section name is required');
|
|
161
|
+
mockTodoistApi.addSection.mockRejectedValue(apiError);
|
|
162
|
+
await expect(addSections.execute({ sections: [{ name: '', projectId: TEST_IDS.PROJECT_TEST }] }, mockTodoistApi)).rejects.toThrow('API Error: Section name is required');
|
|
163
|
+
});
|
|
164
|
+
it('should handle partial failures in multiple sections', async () => {
|
|
165
|
+
const mockSection = createMockSection({
|
|
166
|
+
id: 'section-1',
|
|
167
|
+
projectId: TEST_IDS.PROJECT_TEST,
|
|
168
|
+
name: 'First Section',
|
|
169
|
+
});
|
|
170
|
+
mockTodoistApi.addSection
|
|
171
|
+
.mockResolvedValueOnce(mockSection)
|
|
172
|
+
.mockRejectedValueOnce(new Error('API Error: Invalid project ID'));
|
|
173
|
+
await expect(addSections.execute({
|
|
174
|
+
sections: [
|
|
175
|
+
{ name: 'First Section', projectId: TEST_IDS.PROJECT_TEST },
|
|
176
|
+
{ name: 'Second Section', projectId: 'invalid-project' },
|
|
177
|
+
],
|
|
178
|
+
}, mockTodoistApi)).rejects.toThrow('API Error: Invalid project ID');
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-tasks.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/add-tasks.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { jest } from '@jest/globals';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { TODAY, createMockTask, extractStructuredContent, extractTextContent, } from '../../utils/test-helpers.js';
|
|
3
|
+
import { ToolNames } from '../../utils/tool-names.js';
|
|
4
|
+
import { addTasks } from '../add-tasks.js';
|
|
4
5
|
// Mock the Todoist API
|
|
5
6
|
const mockTodoistApi = {
|
|
6
7
|
addTask: jest.fn(),
|
|
7
8
|
};
|
|
8
|
-
|
|
9
|
+
const { ADD_TASKS, GET_OVERVIEW } = ToolNames;
|
|
10
|
+
describe(`${ADD_TASKS} tool`, () => {
|
|
9
11
|
beforeEach(() => {
|
|
10
12
|
jest.clearAllMocks();
|
|
11
13
|
});
|
|
@@ -38,15 +40,15 @@ describe('tasks-add-multiple tool', () => {
|
|
|
38
40
|
mockTodoistApi.addTask
|
|
39
41
|
.mockResolvedValueOnce(mockApiResponse1)
|
|
40
42
|
.mockResolvedValueOnce(mockApiResponse2);
|
|
41
|
-
const result = await
|
|
42
|
-
projectId: '6cfCcrrCFg2xP94Q',
|
|
43
|
+
const result = await addTasks.execute({
|
|
43
44
|
tasks: [
|
|
44
|
-
{ content: 'First task content' },
|
|
45
|
+
{ content: 'First task content', projectId: '6cfCcrrCFg2xP94Q' },
|
|
45
46
|
{
|
|
46
47
|
content: 'Second task content',
|
|
47
48
|
description: 'Task description',
|
|
48
49
|
priority: 2,
|
|
49
50
|
dueString: 'Aug 15',
|
|
51
|
+
projectId: '6cfCcrrCFg2xP94Q',
|
|
50
52
|
},
|
|
51
53
|
],
|
|
52
54
|
}, mockTodoistApi);
|
|
@@ -67,23 +69,18 @@ describe('tasks-add-multiple tool', () => {
|
|
|
67
69
|
sectionId: undefined,
|
|
68
70
|
parentId: undefined,
|
|
69
71
|
});
|
|
70
|
-
// Verify result is
|
|
71
|
-
expect(result).
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
id: '8485093749',
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
dueDate: '2025-08-15',
|
|
83
|
-
priority: 2,
|
|
84
|
-
labels: ['work', 'urgent'],
|
|
85
|
-
}),
|
|
86
|
-
]);
|
|
72
|
+
// Verify result is a concise summary
|
|
73
|
+
expect(extractTextContent(result)).toMatchSnapshot();
|
|
74
|
+
// Verify structured content
|
|
75
|
+
const structuredContent = extractStructuredContent(result);
|
|
76
|
+
expect(structuredContent.tasks).toHaveLength(2);
|
|
77
|
+
expect(structuredContent).toEqual(expect.objectContaining({
|
|
78
|
+
totalCount: 2,
|
|
79
|
+
tasks: expect.arrayContaining([
|
|
80
|
+
expect.objectContaining({ id: '8485093748' }),
|
|
81
|
+
expect.objectContaining({ id: '8485093749' }),
|
|
82
|
+
]),
|
|
83
|
+
}));
|
|
87
84
|
});
|
|
88
85
|
it('should handle tasks with section and parent IDs', async () => {
|
|
89
86
|
const mockApiResponse = createMockTask({
|
|
@@ -97,15 +94,15 @@ describe('tasks-add-multiple tool', () => {
|
|
|
97
94
|
addedAt: '2025-08-13T22:09:58.123456Z',
|
|
98
95
|
});
|
|
99
96
|
mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
|
|
100
|
-
const result = await
|
|
101
|
-
projectId: '6cfCcrrCFg2xP94Q',
|
|
102
|
-
sectionId: 'section-123',
|
|
103
|
-
parentId: 'parent-task-456',
|
|
97
|
+
const result = await addTasks.execute({
|
|
104
98
|
tasks: [
|
|
105
99
|
{
|
|
106
100
|
content: 'Subtask content',
|
|
107
101
|
description: 'Subtask description',
|
|
108
102
|
priority: 3,
|
|
103
|
+
projectId: '6cfCcrrCFg2xP94Q',
|
|
104
|
+
sectionId: 'section-123',
|
|
105
|
+
parentId: 'parent-task-456',
|
|
109
106
|
},
|
|
110
107
|
],
|
|
111
108
|
}, mockTodoistApi);
|
|
@@ -117,17 +114,14 @@ describe('tasks-add-multiple tool', () => {
|
|
|
117
114
|
sectionId: 'section-123',
|
|
118
115
|
parentId: 'parent-task-456',
|
|
119
116
|
});
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
labels: [],
|
|
129
|
-
}),
|
|
130
|
-
]);
|
|
117
|
+
// Verify result is a concise summary
|
|
118
|
+
expect(extractTextContent(result)).toMatchSnapshot();
|
|
119
|
+
// Verify structured content
|
|
120
|
+
const structuredContent = extractStructuredContent(result);
|
|
121
|
+
expect(structuredContent).toEqual(expect.objectContaining({
|
|
122
|
+
totalCount: 1,
|
|
123
|
+
tasks: expect.arrayContaining([expect.objectContaining({ id: '8485093750' })]),
|
|
124
|
+
}));
|
|
131
125
|
});
|
|
132
126
|
it('should add tasks with duration', async () => {
|
|
133
127
|
const mockApiResponse1 = createMockTask({
|
|
@@ -147,16 +141,17 @@ describe('tasks-add-multiple tool', () => {
|
|
|
147
141
|
mockTodoistApi.addTask
|
|
148
142
|
.mockResolvedValueOnce(mockApiResponse1)
|
|
149
143
|
.mockResolvedValueOnce(mockApiResponse2);
|
|
150
|
-
const result = await
|
|
151
|
-
projectId: '6cfCcrrCFg2xP94Q',
|
|
144
|
+
const result = await addTasks.execute({
|
|
152
145
|
tasks: [
|
|
153
146
|
{
|
|
154
147
|
content: 'Task with 2 hour duration',
|
|
155
148
|
duration: '2h',
|
|
149
|
+
projectId: '6cfCcrrCFg2xP94Q',
|
|
156
150
|
},
|
|
157
151
|
{
|
|
158
152
|
content: 'Task with 45 minute duration',
|
|
159
153
|
duration: '45m',
|
|
154
|
+
projectId: '6cfCcrrCFg2xP94Q',
|
|
160
155
|
},
|
|
161
156
|
],
|
|
162
157
|
}, mockTodoistApi);
|
|
@@ -177,19 +172,18 @@ describe('tasks-add-multiple tool', () => {
|
|
|
177
172
|
duration: 45,
|
|
178
173
|
durationUnit: 'minute',
|
|
179
174
|
});
|
|
180
|
-
// Verify result
|
|
181
|
-
expect(result).
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
expect.
|
|
188
|
-
id: '
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
]);
|
|
175
|
+
// Verify result is a concise summary
|
|
176
|
+
expect(extractTextContent(result)).toMatchSnapshot();
|
|
177
|
+
// Verify structured content
|
|
178
|
+
const structuredContent = extractStructuredContent(result);
|
|
179
|
+
expect(structuredContent.tasks).toHaveLength(2);
|
|
180
|
+
expect(structuredContent).toEqual(expect.objectContaining({
|
|
181
|
+
totalCount: 2,
|
|
182
|
+
tasks: expect.arrayContaining([
|
|
183
|
+
expect.objectContaining({ id: '8485093752' }),
|
|
184
|
+
expect.objectContaining({ id: '8485093753' }),
|
|
185
|
+
]),
|
|
186
|
+
}));
|
|
193
187
|
});
|
|
194
188
|
it('should handle various duration formats', async () => {
|
|
195
189
|
const mockApiResponse = createMockTask({
|
|
@@ -209,14 +203,7 @@ describe('tasks-add-multiple tool', () => {
|
|
|
209
203
|
];
|
|
210
204
|
for (const testCase of testCases) {
|
|
211
205
|
mockTodoistApi.addTask.mockClear();
|
|
212
|
-
await
|
|
213
|
-
tasks: [
|
|
214
|
-
{
|
|
215
|
-
content: 'Test task',
|
|
216
|
-
duration: testCase.input,
|
|
217
|
-
},
|
|
218
|
-
],
|
|
219
|
-
}, mockTodoistApi);
|
|
206
|
+
await addTasks.execute({ tasks: [{ content: 'Test task', duration: testCase.input }] }, mockTodoistApi);
|
|
220
207
|
expect(mockTodoistApi.addTask).toHaveBeenCalledWith(expect.objectContaining({
|
|
221
208
|
duration: testCase.expectedMinutes,
|
|
222
209
|
durationUnit: 'minute',
|
|
@@ -226,29 +213,15 @@ describe('tasks-add-multiple tool', () => {
|
|
|
226
213
|
});
|
|
227
214
|
describe('error handling', () => {
|
|
228
215
|
it('should throw error for invalid duration format', async () => {
|
|
229
|
-
await expect(
|
|
230
|
-
tasks: [
|
|
231
|
-
{
|
|
232
|
-
content: 'Task with invalid duration',
|
|
233
|
-
duration: 'invalid',
|
|
234
|
-
},
|
|
235
|
-
],
|
|
236
|
-
}, mockTodoistApi)).rejects.toThrow('Task "Task with invalid duration": Invalid duration format "invalid"');
|
|
216
|
+
await expect(addTasks.execute({ tasks: [{ content: 'Task with invalid duration', duration: 'invalid' }] }, mockTodoistApi)).rejects.toThrow('Task "Task with invalid duration": Invalid duration format "invalid"');
|
|
237
217
|
});
|
|
238
218
|
it('should throw error for duration exceeding 24 hours', async () => {
|
|
239
|
-
await expect(
|
|
240
|
-
tasks: [
|
|
241
|
-
{
|
|
242
|
-
content: 'Task with too long duration',
|
|
243
|
-
duration: '25h',
|
|
244
|
-
},
|
|
245
|
-
],
|
|
246
|
-
}, mockTodoistApi)).rejects.toThrow('Task "Task with too long duration": Invalid duration format "25h": Duration cannot exceed 24 hours (1440 minutes)');
|
|
219
|
+
await expect(addTasks.execute({ tasks: [{ content: 'Task with too long duration', duration: '25h' }] }, mockTodoistApi)).rejects.toThrow('Task "Task with too long duration": Invalid duration format "25h": Duration cannot exceed 24 hours (1440 minutes)');
|
|
247
220
|
});
|
|
248
221
|
it('should propagate API errors', async () => {
|
|
249
222
|
const apiError = new Error('API Error: Task content is required');
|
|
250
223
|
mockTodoistApi.addTask.mockRejectedValue(apiError);
|
|
251
|
-
await expect(
|
|
224
|
+
await expect(addTasks.execute({ tasks: [{ content: '' }] }, mockTodoistApi)).rejects.toThrow(apiError.message);
|
|
252
225
|
});
|
|
253
226
|
it('should handle partial failures when adding multiple tasks', async () => {
|
|
254
227
|
const mockApiResponse = createMockTask({
|
|
@@ -261,7 +234,7 @@ describe('tasks-add-multiple tool', () => {
|
|
|
261
234
|
mockTodoistApi.addTask
|
|
262
235
|
.mockResolvedValueOnce(mockApiResponse)
|
|
263
236
|
.mockRejectedValueOnce(apiError);
|
|
264
|
-
await expect(
|
|
237
|
+
await expect(addTasks.execute({
|
|
265
238
|
tasks: [
|
|
266
239
|
{ content: 'First task content' },
|
|
267
240
|
{ content: 'Second task content' },
|
|
@@ -271,4 +244,41 @@ describe('tasks-add-multiple tool', () => {
|
|
|
271
244
|
expect(mockTodoistApi.addTask).toHaveBeenCalledTimes(2);
|
|
272
245
|
});
|
|
273
246
|
});
|
|
247
|
+
describe('next steps logic', () => {
|
|
248
|
+
it('should suggest find-tasks-by-date for today when hasToday is true', async () => {
|
|
249
|
+
const mockApiResponse = createMockTask({
|
|
250
|
+
id: '8485093755',
|
|
251
|
+
content: 'Task due today',
|
|
252
|
+
url: 'https://todoist.com/showTask?id=8485093755',
|
|
253
|
+
addedAt: '2025-08-13T22:09:56.123456Z',
|
|
254
|
+
due: {
|
|
255
|
+
date: TODAY,
|
|
256
|
+
isRecurring: false,
|
|
257
|
+
lang: 'en',
|
|
258
|
+
string: 'today',
|
|
259
|
+
timezone: null,
|
|
260
|
+
},
|
|
261
|
+
});
|
|
262
|
+
mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
|
|
263
|
+
const result = await addTasks.execute({ tasks: [{ content: 'Task due today', dueString: 'today' }] }, mockTodoistApi);
|
|
264
|
+
const textContent = extractTextContent(result);
|
|
265
|
+
expect(textContent).toMatchSnapshot();
|
|
266
|
+
expect(textContent).toContain(`Use ${GET_OVERVIEW} to see your updated project organization`);
|
|
267
|
+
});
|
|
268
|
+
it('should suggest overview tool when no hasToday context', async () => {
|
|
269
|
+
const mockApiResponse = createMockTask({
|
|
270
|
+
id: '8485093756',
|
|
271
|
+
content: 'Regular task',
|
|
272
|
+
url: 'https://todoist.com/showTask?id=8485093756',
|
|
273
|
+
addedAt: '2025-08-13T22:09:56.123456Z',
|
|
274
|
+
});
|
|
275
|
+
mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
|
|
276
|
+
const result = await addTasks.execute({
|
|
277
|
+
tasks: [{ content: 'Regular task', projectId: '6cfCcrrCFg2xP94Q' }],
|
|
278
|
+
}, mockTodoistApi);
|
|
279
|
+
const textContent = extractTextContent(result);
|
|
280
|
+
expect(textContent).toMatchSnapshot();
|
|
281
|
+
expect(textContent).toContain(`Use ${GET_OVERVIEW} to see your updated project organization`);
|
|
282
|
+
});
|
|
283
|
+
});
|
|
274
284
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complete-tasks.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/complete-tasks.test.ts"],"names":[],"mappings":""}
|