@@ -13,6 +13,7 @@ import { sinonUtil } from '../../../../utils/sinonUtil.js';
1313import commands from '../../commands.js' ;
1414import command , { options } from './chat-message-list.js' ;
1515import { settingsNames } from '../../../../settingsNames.js' ;
16+ import { z } from 'zod' ;
1617
1718describe ( commands . CHAT_MESSAGE_LIST , ( ) => {
1819
@@ -134,8 +135,10 @@ describe(commands.CHAT_MESSAGE_LIST, () => {
134135 let log : string [ ] ;
135136 let logger : Logger ;
136137 let loggerLogSpy : sinon . SinonSpy ;
138+ let loggerLogToStderrSpy : sinon . SinonSpy ;
137139 let commandInfo : CommandInfo ;
138140 let commandOptionsSchema : typeof options ;
141+ let refinedSchema : z . ZodTypeAny ;
139142
140143 before ( ( ) => {
141144 sinon . stub ( auth , 'restoreAuth' ) . resolves ( ) ;
@@ -146,6 +149,7 @@ describe(commands.CHAT_MESSAGE_LIST, () => {
146149
147150 commandInfo = cli . getCommandInfo ( command ) ;
148151 commandOptionsSchema = commandInfo . command . getSchemaToParse ( ) as typeof options ;
152+ refinedSchema = commandInfo . command . getRefinedSchema ! ( commandOptionsSchema as any ) ! ;
149153 sinon . stub ( cli , 'getSettingWithDefaultValue' ) . callsFake ( ( settingName , defaultValue ) => settingName === settingsNames . prompt ? false : defaultValue ) ;
150154 } ) ;
151155
@@ -163,6 +167,7 @@ describe(commands.CHAT_MESSAGE_LIST, () => {
163167 }
164168 } ;
165169 loggerLogSpy = sinon . spy ( logger , 'log' ) ;
170+ loggerLogToStderrSpy = sinon . spy ( logger , 'logToStderr' ) ;
166171 } ) ;
167172
168173 afterEach ( ( ) => {
@@ -213,20 +218,97 @@ describe(commands.CHAT_MESSAGE_LIST, () => {
213218
214219 it ( 'fails validation if the endDateTime is not valid' , async ( ) => {
215220 const actual = commandOptionsSchema . safeParse ( {
216- chatId : '19:2da4c29f6d7041eca70b638b43d45437' ,
221+ chatId : '19:2da4c29f6d7041eca70b638b43d45437@thread.v2 ' ,
217222 endDateTime : 'invalid date time'
218223 } ) ;
219224 assert . notStrictEqual ( actual . success , true ) ;
220225 } ) ;
221226
222- it ( 'validates for a correct input' , async ( ) => {
227+ it ( 'fails validation if the createdEndDateTime is not valid' , async ( ) => {
228+ const actual = commandOptionsSchema . safeParse ( {
229+ chatId : '19:2da4c29f6d7041eca70b638b43d45437@thread.v2' ,
230+ createdEndDateTime : 'invalid date time'
231+ } ) ;
232+ assert . notStrictEqual ( actual . success , true ) ;
233+ } ) ;
234+
235+ it ( 'fails validation if the modifiedStartDateTime is not valid' , async ( ) => {
236+ const actual = commandOptionsSchema . safeParse ( {
237+ chatId : '19:2da4c29f6d7041eca70b638b43d45437@thread.v2' ,
238+ modifiedStartDateTime : 'not a date'
239+ } ) ;
240+ assert . notStrictEqual ( actual . success , true ) ;
241+ } ) ;
242+
243+ it ( 'fails validation if the modifiedEndDateTime is not valid' , async ( ) => {
244+ const actual = commandOptionsSchema . safeParse ( {
245+ chatId : '19:2da4c29f6d7041eca70b638b43d45437@thread.v2' ,
246+ modifiedEndDateTime : 'not a date'
247+ } ) ;
248+ assert . notStrictEqual ( actual . success , true ) ;
249+ } ) ;
250+
251+ it ( 'fails validation if both endDateTime and createdEndDateTime are specified' , async ( ) => {
252+ const actual = refinedSchema . safeParse ( {
253+ chatId : '19:2da4c29f6d7041eca70b638b43d45437@thread.v2' ,
254+ endDateTime : '2025-11-01T00:00:00Z' ,
255+ createdEndDateTime : '2025-11-01T00:00:00Z'
256+ } ) ;
257+ assert . notStrictEqual ( actual . success , true ) ;
258+ } ) ;
259+
260+ it ( 'fails validation if createdEndDateTime is combined with modifiedStartDateTime' , async ( ) => {
261+ const actual = refinedSchema . safeParse ( {
262+ chatId : '19:2da4c29f6d7041eca70b638b43d45437@thread.v2' ,
263+ createdEndDateTime : '2025-11-01T00:00:00Z' ,
264+ modifiedStartDateTime : '2025-10-01T00:00:00Z'
265+ } ) ;
266+ assert . notStrictEqual ( actual . success , true ) ;
267+ } ) ;
268+
269+ it ( 'fails validation if createdEndDateTime is combined with modifiedEndDateTime' , async ( ) => {
270+ const actual = refinedSchema . safeParse ( {
271+ chatId : '19:2da4c29f6d7041eca70b638b43d45437@thread.v2' ,
272+ createdEndDateTime : '2025-11-01T00:00:00Z' ,
273+ modifiedEndDateTime : '2025-12-01T00:00:00Z'
274+ } ) ;
275+ assert . notStrictEqual ( actual . success , true ) ;
276+ } ) ;
277+
278+ it ( 'fails validation if endDateTime is combined with modifiedStartDateTime' , async ( ) => {
279+ const actual = refinedSchema . safeParse ( {
280+ chatId : '19:2da4c29f6d7041eca70b638b43d45437@thread.v2' ,
281+ endDateTime : '2025-11-01T00:00:00Z' ,
282+ modifiedStartDateTime : '2025-10-01T00:00:00Z'
283+ } ) ;
284+ assert . notStrictEqual ( actual . success , true ) ;
285+ } ) ;
286+
287+ it ( 'validates for a correct input with endDateTime' , async ( ) => {
223288 const actual = commandOptionsSchema . safeParse ( {
224289 chatId : "19:2da4c29f6d7041eca70b638b43d45437@thread.v2" ,
225290 endDateTime : "2022-11-01T00:00:00Z"
226291 } ) ;
227292 assert . strictEqual ( actual . success , true ) ;
228293 } ) ;
229294
295+ it ( 'validates for a correct input with createdEndDateTime' , async ( ) => {
296+ const actual = commandOptionsSchema . safeParse ( {
297+ chatId : "19:2da4c29f6d7041eca70b638b43d45437@thread.v2" ,
298+ createdEndDateTime : "2022-11-01T00:00:00Z"
299+ } ) ;
300+ assert . strictEqual ( actual . success , true ) ;
301+ } ) ;
302+
303+ it ( 'validates for a correct input with modifiedStartDateTime and modifiedEndDateTime' , async ( ) => {
304+ const actual = commandOptionsSchema . safeParse ( {
305+ chatId : "19:2da4c29f6d7041eca70b638b43d45437@thread.v2" ,
306+ modifiedStartDateTime : "2025-10-01T00:00:00Z" ,
307+ modifiedEndDateTime : "2025-11-01T00:00:00Z"
308+ } ) ;
309+ assert . strictEqual ( actual . success , true ) ;
310+ } ) ;
311+
230312 it ( 'lists chat messages (verbose)' , async ( ) => {
231313 sinon . stub ( request , 'get' ) . callsFake ( async ( opts ) => {
232314 if ( opts . url === `https://graph.microsoft.com/v1.0/chats/19:2da4c29f6d7041eca70b638b43d45437@thread.v2/messages` ) {
@@ -248,7 +330,7 @@ describe(commands.CHAT_MESSAGE_LIST, () => {
248330 assert ( loggerLogSpy . calledWith ( apiResponse ) ) ;
249331 } ) ;
250332
251- it ( 'lists chat messages using endDateTime' , async ( ) => {
333+ it ( 'lists chat messages using deprecated endDateTime and shows deprecation warning ' , async ( ) => {
252334 sinon . stub ( request , 'get' ) . callsFake ( async ( opts ) => {
253335 if ( opts . url === `https://graph.microsoft.com/v1.0/chats/19:2da4c29f6d7041eca70b638b43d45437@thread.v2/messages?$filter=createdDateTime lt 2025-11-01T00:00:00Z&$orderby=createdDateTime desc` ) {
254336 return {
@@ -266,6 +348,92 @@ describe(commands.CHAT_MESSAGE_LIST, () => {
266348 }
267349 } ) ;
268350
351+ assert ( loggerLogSpy . calledWith ( apiResponse ) ) ;
352+ assert ( loggerLogToStderrSpy . calledWith ( sinon . match ( `Option 'endDateTime' is deprecated. Please use 'createdEndDateTime' instead.` ) ) ) ;
353+ } ) ;
354+
355+ it ( 'lists chat messages using createdEndDateTime' , async ( ) => {
356+ sinon . stub ( request , 'get' ) . callsFake ( async ( opts ) => {
357+ if ( opts . url === `https://graph.microsoft.com/v1.0/chats/19:2da4c29f6d7041eca70b638b43d45437@thread.v2/messages?$filter=createdDateTime lt 2025-11-01T00:00:00Z&$orderby=createdDateTime desc` ) {
358+ return {
359+ value : [ ...apiResponse ]
360+ } ;
361+ }
362+
363+ throw 'Invalid request' ;
364+ } ) ;
365+
366+ await command . action ( logger , {
367+ options : {
368+ chatId : "19:2da4c29f6d7041eca70b638b43d45437@thread.v2" ,
369+ createdEndDateTime : "2025-11-01T00:00:00Z"
370+ }
371+ } ) ;
372+
373+ assert ( loggerLogSpy . calledWith ( apiResponse ) ) ;
374+ } ) ;
375+
376+ it ( 'lists chat messages using modifiedStartDateTime' , async ( ) => {
377+ sinon . stub ( request , 'get' ) . callsFake ( async ( opts ) => {
378+ if ( opts . url === `https://graph.microsoft.com/v1.0/chats/19:2da4c29f6d7041eca70b638b43d45437@thread.v2/messages?$filter=lastModifiedDateTime gt 2025-10-01T00:00:00Z&$orderby=lastModifiedDateTime desc` ) {
379+ return {
380+ value : [ ...apiResponse ]
381+ } ;
382+ }
383+
384+ throw 'Invalid request' ;
385+ } ) ;
386+
387+ await command . action ( logger , {
388+ options : {
389+ chatId : "19:2da4c29f6d7041eca70b638b43d45437@thread.v2" ,
390+ modifiedStartDateTime : "2025-10-01T00:00:00Z"
391+ }
392+ } ) ;
393+
394+ assert ( loggerLogSpy . calledWith ( apiResponse ) ) ;
395+ } ) ;
396+
397+ it ( 'lists chat messages using modifiedEndDateTime' , async ( ) => {
398+ sinon . stub ( request , 'get' ) . callsFake ( async ( opts ) => {
399+ if ( opts . url === `https://graph.microsoft.com/v1.0/chats/19:2da4c29f6d7041eca70b638b43d45437@thread.v2/messages?$filter=lastModifiedDateTime lt 2025-12-01T00:00:00Z&$orderby=lastModifiedDateTime desc` ) {
400+ return {
401+ value : [ ...apiResponse ]
402+ } ;
403+ }
404+
405+ throw 'Invalid request' ;
406+ } ) ;
407+
408+ await command . action ( logger , {
409+ options : {
410+ chatId : "19:2da4c29f6d7041eca70b638b43d45437@thread.v2" ,
411+ modifiedEndDateTime : "2025-12-01T00:00:00Z"
412+ }
413+ } ) ;
414+
415+ assert ( loggerLogSpy . calledWith ( apiResponse ) ) ;
416+ } ) ;
417+
418+ it ( 'lists chat messages using both modifiedStartDateTime and modifiedEndDateTime' , async ( ) => {
419+ sinon . stub ( request , 'get' ) . callsFake ( async ( opts ) => {
420+ if ( opts . url === `https://graph.microsoft.com/v1.0/chats/19:2da4c29f6d7041eca70b638b43d45437@thread.v2/messages?$filter=lastModifiedDateTime gt 2025-10-01T00:00:00Z and lastModifiedDateTime lt 2025-12-01T00:00:00Z&$orderby=lastModifiedDateTime desc` ) {
421+ return {
422+ value : [ ...apiResponse ]
423+ } ;
424+ }
425+
426+ throw 'Invalid request' ;
427+ } ) ;
428+
429+ await command . action ( logger , {
430+ options : {
431+ chatId : "19:2da4c29f6d7041eca70b638b43d45437@thread.v2" ,
432+ modifiedStartDateTime : "2025-10-01T00:00:00Z" ,
433+ modifiedEndDateTime : "2025-12-01T00:00:00Z"
434+ }
435+ } ) ;
436+
269437 assert ( loggerLogSpy . calledWith ( apiResponse ) ) ;
270438 } ) ;
271439
0 commit comments