@@ -88,7 +88,7 @@ describe('TodoistApi activity endpoints', () => {
8888 const result = await api . getActivityLogs ( )
8989
9090 expect ( result . results ) . toHaveLength ( 2 )
91- expect ( result . results [ 0 ] . objectType ) . toBe ( 'item' )
91+ expect ( result . results [ 0 ] . objectType ) . toBe ( 'task' ) // Converted from 'item' to 'task'
9292 expect ( result . results [ 0 ] . eventType ) . toBe ( 'added' )
9393 expect ( result . nextCursor ) . toBeNull ( )
9494 } )
@@ -161,5 +161,265 @@ describe('TodoistApi activity endpoints', () => {
161161 another_unknown : 123 ,
162162 } )
163163 } )
164+
165+ test ( 'converts Date objects to YYYY-MM-DD strings' , async ( ) => {
166+ const requestMock = setupRestClientMock ( {
167+ results : DEFAULT_ACTIVITY_RESPONSE ,
168+ nextCursor : null ,
169+ } )
170+ const api = getTarget ( )
171+
172+ const sinceDate = new Date ( '2025-01-15T10:30:00Z' )
173+ const untilDate = new Date ( '2025-01-20T15:45:00Z' )
174+
175+ await api . getActivityLogs ( {
176+ since : sinceDate ,
177+ until : untilDate ,
178+ } )
179+
180+ expect ( requestMock ) . toHaveBeenCalledWith (
181+ 'GET' ,
182+ getSyncBaseUri ( ) ,
183+ ENDPOINT_REST_ACTIVITIES ,
184+ DEFAULT_AUTH_TOKEN ,
185+ {
186+ since : '2025-01-15' ,
187+ until : '2025-01-20' ,
188+ } ,
189+ )
190+ } )
191+
192+ test ( 'leaves string dates as-is for backward compatibility' , async ( ) => {
193+ const requestMock = setupRestClientMock ( {
194+ results : DEFAULT_ACTIVITY_RESPONSE ,
195+ nextCursor : null ,
196+ } )
197+ const api = getTarget ( )
198+
199+ await api . getActivityLogs ( {
200+ since : '2025-01-15' ,
201+ until : '2025-01-20' ,
202+ } )
203+
204+ expect ( requestMock ) . toHaveBeenCalledWith (
205+ 'GET' ,
206+ getSyncBaseUri ( ) ,
207+ ENDPOINT_REST_ACTIVITIES ,
208+ DEFAULT_AUTH_TOKEN ,
209+ {
210+ since : '2025-01-15' ,
211+ until : '2025-01-20' ,
212+ } ,
213+ )
214+ } )
215+
216+ test ( 'converts Date objects with correct timezone handling' , async ( ) => {
217+ const requestMock = setupRestClientMock ( {
218+ results : DEFAULT_ACTIVITY_RESPONSE ,
219+ nextCursor : null ,
220+ } )
221+ const api = getTarget ( )
222+
223+ // Test with a date that has time components
224+ const sinceDate = new Date ( 2025 , 0 , 15 , 23 , 59 , 59 ) // January 15, 2025, 23:59:59 local time
225+
226+ await api . getActivityLogs ( {
227+ since : sinceDate ,
228+ } )
229+
230+ const expectedSince = `${ sinceDate . getFullYear ( ) } -01-15`
231+
232+ expect ( requestMock ) . toHaveBeenCalledWith (
233+ 'GET' ,
234+ getSyncBaseUri ( ) ,
235+ ENDPOINT_REST_ACTIVITIES ,
236+ DEFAULT_AUTH_TOKEN ,
237+ {
238+ since : expectedSince ,
239+ } ,
240+ )
241+ } )
242+
243+ test ( 'converts modern objectType "task" to legacy "item" in API request' , async ( ) => {
244+ const requestMock = setupRestClientMock ( {
245+ results : DEFAULT_ACTIVITY_RESPONSE ,
246+ nextCursor : null ,
247+ } )
248+ const api = getTarget ( )
249+
250+ await api . getActivityLogs ( {
251+ objectType : 'task' ,
252+ } )
253+
254+ expect ( requestMock ) . toHaveBeenCalledWith (
255+ 'GET' ,
256+ getSyncBaseUri ( ) ,
257+ ENDPOINT_REST_ACTIVITIES ,
258+ DEFAULT_AUTH_TOKEN ,
259+ {
260+ objectType : 'item' ,
261+ } ,
262+ )
263+ } )
264+
265+ test ( 'converts modern objectType "comment" to legacy "note" in API request' , async ( ) => {
266+ const requestMock = setupRestClientMock ( {
267+ results : DEFAULT_ACTIVITY_RESPONSE ,
268+ nextCursor : null ,
269+ } )
270+ const api = getTarget ( )
271+
272+ await api . getActivityLogs ( {
273+ objectType : 'comment' ,
274+ } )
275+
276+ expect ( requestMock ) . toHaveBeenCalledWith (
277+ 'GET' ,
278+ getSyncBaseUri ( ) ,
279+ ENDPOINT_REST_ACTIVITIES ,
280+ DEFAULT_AUTH_TOKEN ,
281+ {
282+ objectType : 'note' ,
283+ } ,
284+ )
285+ } )
286+
287+ test ( 'leaves project objectType unchanged' , async ( ) => {
288+ const requestMock = setupRestClientMock ( {
289+ results : DEFAULT_ACTIVITY_RESPONSE ,
290+ nextCursor : null ,
291+ } )
292+ const api = getTarget ( )
293+
294+ await api . getActivityLogs ( {
295+ objectType : 'project' ,
296+ } )
297+
298+ expect ( requestMock ) . toHaveBeenCalledWith (
299+ 'GET' ,
300+ getSyncBaseUri ( ) ,
301+ ENDPOINT_REST_ACTIVITIES ,
302+ DEFAULT_AUTH_TOKEN ,
303+ {
304+ objectType : 'project' ,
305+ } ,
306+ )
307+ } )
308+
309+ test ( 'converts legacy "item" to modern "task" in response' , async ( ) => {
310+ setupRestClientMock ( {
311+ results : [
312+ {
313+ id : '1' ,
314+ objectType : 'item' ,
315+ objectId : '123' ,
316+ eventType : 'added' ,
317+ eventDate : '2025-01-10T10:00:00Z' ,
318+ parentProjectId : null ,
319+ parentItemId : null ,
320+ initiatorId : 'user123' ,
321+ extraData : { } ,
322+ } ,
323+ ] ,
324+ nextCursor : null ,
325+ } )
326+ const api = getTarget ( )
327+
328+ const result = await api . getActivityLogs ( )
329+
330+ expect ( result . results [ 0 ] . objectType ) . toBe ( 'task' )
331+ } )
332+
333+ test ( 'converts legacy "note" to modern "comment" in response' , async ( ) => {
334+ setupRestClientMock ( {
335+ results : [
336+ {
337+ id : '1' ,
338+ objectType : 'note' ,
339+ objectId : '456' ,
340+ eventType : 'added' ,
341+ eventDate : '2025-01-10T10:00:00Z' ,
342+ parentProjectId : null ,
343+ parentItemId : null ,
344+ initiatorId : 'user123' ,
345+ extraData : { } ,
346+ } ,
347+ ] ,
348+ nextCursor : null ,
349+ } )
350+ const api = getTarget ( )
351+
352+ const result = await api . getActivityLogs ( )
353+
354+ expect ( result . results [ 0 ] . objectType ) . toBe ( 'comment' )
355+ } )
356+
357+ test ( 'leaves project objectType unchanged in response' , async ( ) => {
358+ setupRestClientMock ( {
359+ results : [
360+ {
361+ id : '1' ,
362+ objectType : 'project' ,
363+ objectId : '789' ,
364+ eventType : 'updated' ,
365+ eventDate : '2025-01-10T10:00:00Z' ,
366+ parentProjectId : null ,
367+ parentItemId : null ,
368+ initiatorId : 'user123' ,
369+ extraData : { } ,
370+ } ,
371+ ] ,
372+ nextCursor : null ,
373+ } )
374+ const api = getTarget ( )
375+
376+ const result = await api . getActivityLogs ( )
377+
378+ expect ( result . results [ 0 ] . objectType ) . toBe ( 'project' )
379+ } )
380+
381+ test ( 'supports backward compatibility with legacy "item" in request' , async ( ) => {
382+ const requestMock = setupRestClientMock ( {
383+ results : DEFAULT_ACTIVITY_RESPONSE ,
384+ nextCursor : null ,
385+ } )
386+ const api = getTarget ( )
387+
388+ await api . getActivityLogs ( {
389+ objectType : 'item' ,
390+ } )
391+
392+ expect ( requestMock ) . toHaveBeenCalledWith (
393+ 'GET' ,
394+ getSyncBaseUri ( ) ,
395+ ENDPOINT_REST_ACTIVITIES ,
396+ DEFAULT_AUTH_TOKEN ,
397+ {
398+ objectType : 'item' ,
399+ } ,
400+ )
401+ } )
402+
403+ test ( 'supports backward compatibility with legacy "note" in request' , async ( ) => {
404+ const requestMock = setupRestClientMock ( {
405+ results : DEFAULT_ACTIVITY_RESPONSE ,
406+ nextCursor : null ,
407+ } )
408+ const api = getTarget ( )
409+
410+ await api . getActivityLogs ( {
411+ objectType : 'note' ,
412+ } )
413+
414+ expect ( requestMock ) . toHaveBeenCalledWith (
415+ 'GET' ,
416+ getSyncBaseUri ( ) ,
417+ ENDPOINT_REST_ACTIVITIES ,
418+ DEFAULT_AUTH_TOKEN ,
419+ {
420+ objectType : 'note' ,
421+ } ,
422+ )
423+ } )
164424 } )
165425} )
0 commit comments