From 455e8b1c84f0178cc68ff30cb49723865f3465aa Mon Sep 17 00:00:00 2001 From: Mark Roberts Date: Thu, 12 Jun 2025 00:16:30 -0500 Subject: [PATCH 1/3] Fix bug with move-tasks where duplicate uuids caused only the first move to be successful --- src/TodoistApi.tasks.test.ts | 53 ++++++++++++++++++++++++++++++++++++ src/TodoistApi.ts | 3 +- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/TodoistApi.tasks.test.ts b/src/TodoistApi.tasks.test.ts index 328645f..91c76eb 100644 --- a/src/TodoistApi.tasks.test.ts +++ b/src/TodoistApi.tasks.test.ts @@ -330,4 +330,57 @@ describe('TodoistApi task endpoints', () => { await expect(api.getTasksByFilter(DEFAULT_GET_TASKS_BY_FILTER_ARGS)).rejects.toThrow() }) }) + + describe('moveTasks', () => { + const DEFAULT_MOVE_TASKS_ARGS = { + projectId: '6c6vJQjh5HFrGV5f', + } + const TASK_IDS = ['6c5rGRV6Hx6wM7g4', '6c5rGV8q9mqc4Xh4', '6c5rGVhqv6qcGfX4'] + + test('calls sync endpoint with expected parameters', async () => { + const mockSyncResponse = { + sync_status: {}, + items: [ + { ...DEFAULT_TASK, id: TASK_IDS[0] }, + { ...DEFAULT_TASK, id: TASK_IDS[1] }, + { ...DEFAULT_TASK, id: TASK_IDS[2] }, + ], + } + const requestMock = setupRestClientMock(mockSyncResponse) + const api = getTarget() + + await api.moveTasks(TASK_IDS, DEFAULT_MOVE_TASKS_ARGS, DEFAULT_REQUEST_ID) + + expect(requestMock).toBeCalledTimes(1) + const [,,,, syncRequest] = requestMock.mock.calls[0] + + expect(syncRequest.commands).toHaveLength(TASK_IDS.length) + expect(syncRequest.resource_types).toEqual(['items']) + + syncRequest.commands.forEach((cmd: any, index: number) => { + expect(cmd.type).toBe('item_move') + expect(cmd.args.id).toBe(TASK_IDS[index]) + expect(cmd.args.project_id).toBe(DEFAULT_MOVE_TASKS_ARGS.projectId) + }) + + const uuids = syncRequest.commands.map((cmd: any) => cmd.uuid) + const uniqueUuids = new Set(uuids) + expect(uniqueUuids.size).toBe(TASK_IDS.length) + }) + + test('returns result from sync client', async () => { + const movedTasks = TASK_IDS.map((id) => ({ ...DEFAULT_TASK, id })) + const mockSyncResponse = { + sync_status: {}, + items: movedTasks, + } + setupRestClientMock(mockSyncResponse) + const api = getTarget() + + const result = await api.moveTasks(TASK_IDS, DEFAULT_MOVE_TASKS_ARGS) + + expect(result).toHaveLength(TASK_IDS.length) + expect(result.map((task) => task.id)).toEqual(TASK_IDS) + }) + }) }) diff --git a/src/TodoistApi.ts b/src/TodoistApi.ts index b4ce8fc..6109040 100644 --- a/src/TodoistApi.ts +++ b/src/TodoistApi.ts @@ -254,10 +254,9 @@ export class TodoistApi { if (ids.length > MAX_COMMAND_COUNT) { throw new TodoistRequestError(`Maximum number of items is ${MAX_COMMAND_COUNT}`, 400) } - const uuid = uuidv4() const commands: Command[] = ids.map((id) => ({ type: 'item_move', - uuid, + uuid: uuidv4(), args: { id, ...(args.projectId && { project_id: args.projectId }), From 5f3350778d4a460267d3c043b2bdd9aefe263df7 Mon Sep 17 00:00:00 2001 From: Mark Roberts Date: Thu, 12 Jun 2025 08:59:37 -0500 Subject: [PATCH 2/3] lint: npx prettier --write --- src/TodoistApi.tasks.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TodoistApi.tasks.test.ts b/src/TodoistApi.tasks.test.ts index 91c76eb..5204b3b 100644 --- a/src/TodoistApi.tasks.test.ts +++ b/src/TodoistApi.tasks.test.ts @@ -352,7 +352,7 @@ describe('TodoistApi task endpoints', () => { await api.moveTasks(TASK_IDS, DEFAULT_MOVE_TASKS_ARGS, DEFAULT_REQUEST_ID) expect(requestMock).toBeCalledTimes(1) - const [,,,, syncRequest] = requestMock.mock.calls[0] + const [, , , , syncRequest] = requestMock.mock.calls[0] expect(syncRequest.commands).toHaveLength(TASK_IDS.length) expect(syncRequest.resource_types).toEqual(['items']) From cc9cc85a3638ddd0d18edc129fc71435112a8f8f Mon Sep 17 00:00:00 2001 From: Scott Lovegrove Date: Wed, 6 Aug 2025 17:40:54 +0100 Subject: [PATCH 3/3] chore: Lint fix --- src/TodoistApi.tasks.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TodoistApi.tasks.test.ts b/src/TodoistApi.tasks.test.ts index 28da9c8..0030c62 100644 --- a/src/TodoistApi.tasks.test.ts +++ b/src/TodoistApi.tasks.test.ts @@ -384,8 +384,8 @@ describe('TodoistApi task endpoints', () => { expect(result).toHaveLength(TASK_IDS.length) expect(result.map((task) => task.id)).toEqual(TASK_IDS) }) - }) - + }) + describe('getCompletedTasksByCompletionDate', () => { const DEFAULT_GET_COMPLETED_TASKS_ARGS = { since: '2025-01-01T00:00:00Z',