diff --git a/src/TodoistApi.tasks.test.ts b/src/TodoistApi.tasks.test.ts index 0060b73..1cc0ab1 100644 --- a/src/TodoistApi.tasks.test.ts +++ b/src/TodoistApi.tasks.test.ts @@ -14,6 +14,7 @@ import { ENDPOINT_REST_TASKS_FILTER, ENDPOINT_REST_TASKS_COMPLETED_BY_COMPLETION_DATE, ENDPOINT_REST_TASKS_COMPLETED_BY_DUE_DATE, + ENDPOINT_REST_TASKS_COMPLETED_SEARCH, ENDPOINT_SYNC_QUICK_ADD, } from './consts/endpoints' import { setupRestClientMock } from './testUtils/mocks' @@ -430,4 +431,50 @@ describe('TodoistApi task endpoints', () => { ).rejects.toThrow() }) }) + + describe('searchCompletedTasks', () => { + const DEFAULT_SEARCH_COMPLETED_TASKS_ARGS = { + query: 'buy milk', + cursor: null, + limit: 10, + } + + test('calls get request with expected url', async () => { + const requestMock = setupRestClientMock({ items: [DEFAULT_TASK], nextCursor: null }) + const api = getTarget() + + await api.searchCompletedTasks(DEFAULT_SEARCH_COMPLETED_TASKS_ARGS) + + expect(requestMock).toHaveBeenCalledTimes(1) + expect(requestMock).toHaveBeenCalledWith( + 'GET', + getSyncBaseUri(), + ENDPOINT_REST_TASKS_COMPLETED_SEARCH, + DEFAULT_AUTH_TOKEN, + DEFAULT_SEARCH_COMPLETED_TASKS_ARGS, + ) + }) + + test('returns result from rest client', async () => { + setupRestClientMock({ items: [DEFAULT_TASK], nextCursor: '789' }) + const api = getTarget() + + const response = await api.searchCompletedTasks(DEFAULT_SEARCH_COMPLETED_TASKS_ARGS) + + expect(response).toEqual({ + items: [DEFAULT_TASK], + nextCursor: '789', + }) + }) + + test('validates task array in response', async () => { + const invalidTask = { ...DEFAULT_TASK, due: '2020-01-31' } + setupRestClientMock({ items: [invalidTask], nextCursor: null }) + const api = getTarget() + + await expect( + api.searchCompletedTasks(DEFAULT_SEARCH_COMPLETED_TASKS_ARGS), + ).rejects.toThrow() + }) + }) }) diff --git a/src/TodoistApi.ts b/src/TodoistApi.ts index 8662603..7710207 100644 --- a/src/TodoistApi.ts +++ b/src/TodoistApi.ts @@ -44,6 +44,7 @@ import { GetCompletedTasksResponse, GetArchivedProjectsArgs, GetArchivedProjectsResponse, + SearchCompletedTasksArgs, } from './types/requests' import { request, isSuccess } from './restClient' import { @@ -52,6 +53,7 @@ import { ENDPOINT_REST_TASKS_FILTER, ENDPOINT_REST_TASKS_COMPLETED_BY_COMPLETION_DATE, ENDPOINT_REST_TASKS_COMPLETED_BY_DUE_DATE, + ENDPOINT_REST_TASKS_COMPLETED_SEARCH, ENDPOINT_REST_PROJECTS, ENDPOINT_SYNC_QUICK_ADD, ENDPOINT_REST_TASK_CLOSE, @@ -271,6 +273,29 @@ export class TodoistApi { } } + /** + * Searches completed tasks by query string. + * + * @param args - Parameters for searching, including the query string. + * @returns A promise that resolves to a paginated response of completed tasks. + */ + async searchCompletedTasks(args: SearchCompletedTasksArgs): Promise { + const { + data: { items, nextCursor }, + } = await request( + 'GET', + this.syncApiBase, + ENDPOINT_REST_TASKS_COMPLETED_SEARCH, + this.authToken, + args, + ) + + return { + items: validateTaskArray(items), + nextCursor, + } + } + /** * Creates a new task with the provided parameters. * diff --git a/src/consts/endpoints.ts b/src/consts/endpoints.ts index 9a1f5c4..d60e09d 100644 --- a/src/consts/endpoints.ts +++ b/src/consts/endpoints.ts @@ -23,6 +23,7 @@ export const ENDPOINT_REST_TASKS_COMPLETED_BY_COMPLETION_DATE = ENDPOINT_REST_TASKS + '/completed/by_completion_date' export const ENDPOINT_REST_TASKS_COMPLETED_BY_DUE_DATE = ENDPOINT_REST_TASKS + '/completed/by_due_date' +export const ENDPOINT_REST_TASKS_COMPLETED_SEARCH = 'completed/search' export const ENDPOINT_REST_SECTIONS = 'sections' export const ENDPOINT_REST_LABELS = 'labels' export const ENDPOINT_REST_LABELS_SHARED = ENDPOINT_REST_LABELS + '/shared' diff --git a/src/types/requests.ts b/src/types/requests.ts index 1144bb2..f587603 100644 --- a/src/types/requests.ts +++ b/src/types/requests.ts @@ -98,6 +98,15 @@ export type GetCompletedTasksByDueDateArgs = { limit?: number } +/** + * Arguments for searching completed tasks. + */ +export type SearchCompletedTasksArgs = { + query: string + cursor?: string | null + limit?: number +} + /** * @see https://todoist.com/api/v1/docs#tag/Tasks/operation/get_tasks_api_v1_tasks_get */