@@ -33,6 +33,7 @@ describe('ChatService', () => {
3333 deleteMany : jest . fn ( ) . mockReturnValue ( createMockQuery ( { deletedCount : 0 } ) ) ,
3434 countDocuments : jest . fn ( ) . mockReturnValue ( createMockQuery ( 0 ) ) ,
3535 updateMany : jest . fn ( ) . mockReturnValue ( createMockQuery ( { modifiedCount : 0 } ) ) ,
36+ db : { readyState : 1 } ,
3637 } ;
3738
3839 const MockMessageModel = jest . fn ( ) . mockImplementation ( ( data ) => {
@@ -102,6 +103,7 @@ describe('ChatService', () => {
102103 userId : 'test-user-id' ,
103104 chatId : 'test-chat-id' ,
104105 filterConfig : { dateFilter : { type : 'custom' } } ,
106+ version : 1 ,
105107 isActive : false ,
106108 createdAt : new Date ( ) ,
107109 updatedAt : new Date ( ) ,
@@ -297,9 +299,19 @@ describe('ChatService', () => {
297299 content : 'Test message' ,
298300 } ;
299301
302+ const savedMessage = {
303+ ...mockMessage ,
304+ filterId : null ,
305+ filterVersion : null ,
306+ timestamp : expect . any ( Date ) ,
307+ } ;
308+
300309 mockChatModel . findOneAndUpdate . mockReturnValue ( createMockQuery ( mockChat ) ) ;
301310 mockMessageModel . findOne . mockReturnValue ( createMockQuery ( null ) ) ;
302- mockChatModel . findOneAndUpdate . mockReturnValue ( createMockQuery ( mockChat ) ) ;
311+ MockMessageModel . mockReturnValueOnce ( {
312+ ...savedMessage ,
313+ save : jest . fn ( ) . mockResolvedValue ( savedMessage ) ,
314+ } ) ;
303315
304316 const result = await service . addMessage ( messageDto ) ;
305317
@@ -308,7 +320,12 @@ describe('ChatService', () => {
308320 chatId : messageDto . chatId ,
309321 userId : messageDto . userId ,
310322 } ) ;
311- expect ( result ) . toEqual ( mockMessage ) ;
323+ expect ( result ) . toEqual ( expect . objectContaining ( {
324+ id : messageDto . id ,
325+ content : messageDto . content ,
326+ filterId : null ,
327+ filterVersion : null ,
328+ } ) ) ;
312329 } ) ;
313330
314331 it ( 'should skip duplicate messages' , async ( ) => {
@@ -362,15 +379,26 @@ describe('ChatService', () => {
362379 } ;
363380
364381 const chatWithFilter = { ...mockChat , activeFilterId : 'active-filter-id' } ;
382+ const activeFilter = {
383+ ...mockFilter ,
384+ filterId : 'active-filter-id' ,
385+ isActive : true ,
386+ } ;
387+
365388 mockChatModel . findOneAndUpdate . mockReturnValue ( createMockQuery ( chatWithFilter ) ) ;
366389 mockMessageModel . findOne . mockReturnValue ( createMockQuery ( null ) ) ;
367- mockFilterModel . findOne . mockReturnValue ( createMockQuery ( mockFilter ) ) ;
390+ mockFilterModel . findOne . mockReturnValue ( createMockQuery ( activeFilter ) ) ;
391+ MockMessageModel . mockReturnValueOnce ( {
392+ ...mockMessage ,
393+ save : jest . fn ( ) . mockResolvedValue ( mockMessage ) ,
394+ } ) ;
368395
369396 await service . addMessage ( messageDto ) ;
370397
371398 expect ( mockFilterModel . findOne ) . toHaveBeenCalledWith ( {
372399 filterId : 'active-filter-id' ,
373400 userId : 'test-user-id' ,
401+ isActive : true ,
374402 } ) ;
375403 } ) ;
376404 } ) ;
@@ -433,74 +461,112 @@ describe('ChatService', () => {
433461 filterConfig : { dateFilter : { type : 'custom' } } ,
434462 } ;
435463
464+ const savedFilter = { ...mockFilter , version : 1 } ;
465+
466+ mockFilterModel . findOne . mockReturnValue ( createMockQuery ( null ) ) ;
436467 mockChatModel . findOneAndUpdate . mockReturnValue ( createMockQuery ( mockChat ) ) ;
468+ MockFilterModel . mockReturnValueOnce ( {
469+ ...savedFilter ,
470+ save : jest . fn ( ) . mockResolvedValue ( savedFilter ) ,
471+ } ) ;
437472
438473 const result = await service . createFilter ( filterDto ) ;
439474
440- expect ( MockFilterModel ) . toHaveBeenCalledWith ( filterDto ) ;
475+ expect ( mockFilterModel . findOne ) . toHaveBeenCalledWith ( {
476+ filterId : filterDto . filterId ,
477+ userId : filterDto . userId ,
478+ } ) ;
479+ expect ( MockFilterModel ) . toHaveBeenCalledWith (
480+ expect . objectContaining ( { ...filterDto , version : 1 } )
481+ ) ;
441482 expect ( mockChatModel . findOneAndUpdate ) . toHaveBeenCalledWith (
442483 { chatId : filterDto . chatId , userId : filterDto . userId } ,
443484 { $addToSet : { associatedFilters : filterDto . filterId } }
444485 ) ;
445- expect ( result ) . toEqual ( mockFilter ) ;
486+ expect ( result ) . toEqual ( savedFilter ) ;
446487 } ) ;
447488 } ) ;
448489
449490 describe ( 'getFiltersForChat' , ( ) => {
450491 it ( 'should return all filters for a chat' , async ( ) => {
451- const filters = [ mockFilter , { ...mockFilter , filterId : 'filter-2' } ] ;
452- mockFilterModel . find . mockReturnValue ( createMockQuery ( filters ) ) ;
492+ const chatFilters = [ mockFilter , { ...mockFilter , filterId : 'filter-2' } ] ;
493+ const globalFilters = [ { ...mockFilter , filterId : 'global-filter' , chatId : null } ] ;
494+ mockFilterModel . find
495+ . mockReturnValueOnce ( createMockQuery ( chatFilters ) )
496+ . mockReturnValueOnce ( createMockQuery ( globalFilters ) ) ;
453497
454498 const result = await service . getFiltersForChat ( 'test-chat-id' , 'test-user-id' ) ;
455499
456- expect ( mockFilterModel . find ) . toHaveBeenCalledWith ( { chatId : 'test-chat-id' , userId : 'test-user-id' } ) ;
457- expect ( result ) . toEqual ( filters ) ;
500+ expect ( mockFilterModel . find ) . toHaveBeenNthCalledWith ( 1 , { userId : 'test-user-id' , chatId : 'test-chat-id' } ) ;
501+ expect ( mockFilterModel . find ) . toHaveBeenNthCalledWith ( 2 , { userId : 'test-user-id' , chatId : null } ) ;
502+ expect ( result ) . toEqual ( [ ...chatFilters , ...globalFilters ] ) ;
458503 } ) ;
459504 } ) ;
460505
461506 describe ( 'updateFilter' , ( ) => {
462507 it ( 'should update a filter' , async ( ) => {
463- const updatedFilter = { ...mockFilter , name : 'Updated Filter' } ;
508+ const latestFilter = { ...mockFilter , version : 1 } ;
509+ const updatedFilter = { ...mockFilter , name : 'Updated Filter' , version : 2 } ;
464510 const updateData = { name : 'Updated Filter' } ;
465511
466- mockFilterModel . findOneAndUpdate . mockReturnValue ( createMockQuery ( updatedFilter ) ) ;
512+ mockFilterModel . findOne . mockReturnValue ( createMockQuery ( latestFilter ) ) ;
513+ mockFilterModel . updateMany . mockReturnValue ( createMockQuery ( { modifiedCount : 1 } ) ) ;
514+ MockFilterModel . mockReturnValueOnce ( {
515+ ...updatedFilter ,
516+ save : jest . fn ( ) . mockResolvedValue ( updatedFilter ) ,
517+ } ) ;
467518
468519 const result = await service . updateFilter ( 'test-filter-id' , 'test-user-id' , updateData ) ;
469520
470- expect ( mockFilterModel . findOneAndUpdate ) . toHaveBeenCalledWith (
521+ expect ( mockFilterModel . findOne ) . toHaveBeenCalledWith ( {
522+ filterId : 'test-filter-id' ,
523+ userId : 'test-user-id' ,
524+ } ) ;
525+ expect ( mockFilterModel . updateMany ) . toHaveBeenCalledWith (
471526 { filterId : 'test-filter-id' , userId : 'test-user-id' } ,
472- { ...updateData , updatedAt : expect . any ( Date ) } ,
473- { new : true }
527+ { isActive : false }
528+ ) ;
529+ expect ( MockFilterModel ) . toHaveBeenCalledWith (
530+ expect . objectContaining ( {
531+ filterId : 'test-filter-id' ,
532+ version : 2 ,
533+ name : 'Updated Filter' ,
534+ } )
474535 ) ;
475536 expect ( result ) . toEqual ( updatedFilter ) ;
476537 } ) ;
477538
478539 it ( 'should throw NotFoundException if filter does not exist' , async ( ) => {
479- mockFilterModel . findOneAndUpdate . mockReturnValue ( createMockQuery ( null ) ) ;
540+ mockFilterModel . findOne . mockReturnValue ( createMockQuery ( null ) ) ;
480541
481542 await expect ( service . updateFilter ( 'non-existent-id' , 'test-user-id' , { name : 'New Name' } ) ) . rejects . toThrow ( NotFoundException ) ;
482543 } ) ;
483544 } ) ;
484545
485546 describe ( 'setActiveFilter' , ( ) => {
486547 it ( 'should set a filter as active' , async ( ) => {
487- const activeFilter = { ...mockFilter , isActive : true } ;
548+ const filterWithVersion = { ...mockFilter , version : 1 } ;
488549 const updatedChat = { ...mockChat , activeFilterId : 'test-filter-id' , currentFilterConfig : mockFilter . filterConfig } ;
489550
490551 mockFilterModel . updateMany . mockReturnValue ( createMockQuery ( { modifiedCount : 1 } ) ) ;
491- mockFilterModel . findOneAndUpdate . mockReturnValue ( createMockQuery ( activeFilter ) ) ;
552+ mockFilterModel . findOne . mockReturnValue ( createMockQuery ( filterWithVersion ) ) ;
553+ mockFilterModel . findOneAndUpdate . mockReturnValue ( createMockQuery ( { ...filterWithVersion , isActive : true } ) ) ;
492554 mockChatModel . findOneAndUpdate . mockReturnValue ( createMockQuery ( updatedChat ) ) ;
493555
494556 const result = await service . setActiveFilter ( 'test-chat-id' , 'test-user-id' , 'test-filter-id' ) ;
495557
496558 expect ( mockFilterModel . updateMany ) . toHaveBeenCalledWith (
497- { chatId : 'test-chat -id' , userId : 'test-user -id' } ,
559+ { userId : 'test-user -id' , chatId : 'test-chat -id' } ,
498560 { isActive : false }
499561 ) ;
562+ expect ( mockFilterModel . findOne ) . toHaveBeenCalledWith ( {
563+ filterId : 'test-filter-id' ,
564+ userId : 'test-user-id' ,
565+ $or : [ { chatId : 'test-chat-id' } , { chatId : null } ] ,
566+ } ) ;
500567 expect ( mockFilterModel . findOneAndUpdate ) . toHaveBeenCalledWith (
501- { filterId : 'test-filter-id' , userId : 'test-user-id' , chatId : 'test-chat-id' } ,
502- { isActive : true } ,
503- { new : true }
568+ { filterId : 'test-filter-id' , userId : 'test-user-id' , version : 1 } ,
569+ { isActive : true }
504570 ) ;
505571 expect ( mockChatModel . findOneAndUpdate ) . toHaveBeenCalledWith (
506572 { chatId : 'test-chat-id' , userId : 'test-user-id' } ,
@@ -532,13 +598,14 @@ describe('ChatService', () => {
532598
533599 it ( 'should throw NotFoundException if filter does not exist' , async ( ) => {
534600 mockFilterModel . updateMany . mockReturnValue ( createMockQuery ( { modifiedCount : 1 } ) ) ;
535- mockFilterModel . findOneAndUpdate . mockReturnValue ( createMockQuery ( null ) ) ;
601+ mockFilterModel . findOne . mockReturnValue ( createMockQuery ( null ) ) ;
536602
537603 await expect ( service . setActiveFilter ( 'test-chat-id' , 'test-user-id' , 'non-existent-id' ) ) . rejects . toThrow ( NotFoundException ) ;
538604 } ) ;
539605
540606 it ( 'should throw NotFoundException if chat does not exist' , async ( ) => {
541607 mockFilterModel . updateMany . mockReturnValue ( createMockQuery ( { modifiedCount : 1 } ) ) ;
608+ mockFilterModel . findOne . mockReturnValue ( createMockQuery ( mockFilter ) ) ;
542609 mockFilterModel . findOneAndUpdate . mockReturnValue ( createMockQuery ( mockFilter ) ) ;
543610 mockChatModel . findOneAndUpdate . mockReturnValue ( createMockQuery ( null ) ) ;
544611
@@ -548,12 +615,17 @@ describe('ChatService', () => {
548615
549616 describe ( 'deleteFilter' , ( ) => {
550617 it ( 'should delete a filter' , async ( ) => {
551- mockFilterModel . findOneAndDelete . mockReturnValue ( createMockQuery ( mockFilter ) ) ;
618+ mockFilterModel . find . mockReturnValue ( createMockQuery ( [ mockFilter ] ) ) ;
619+ mockFilterModel . deleteMany . mockReturnValue ( createMockQuery ( { deletedCount : 1 } ) ) ;
552620 mockChatModel . updateMany . mockReturnValue ( createMockQuery ( { modifiedCount : 1 } ) ) ;
553621
554622 await service . deleteFilter ( 'test-filter-id' , 'test-user-id' ) ;
555623
556- expect ( mockFilterModel . findOneAndDelete ) . toHaveBeenCalledWith ( {
624+ expect ( mockFilterModel . find ) . toHaveBeenCalledWith ( {
625+ filterId : 'test-filter-id' ,
626+ userId : 'test-user-id' ,
627+ } ) ;
628+ expect ( mockFilterModel . deleteMany ) . toHaveBeenCalledWith ( {
557629 filterId : 'test-filter-id' ,
558630 userId : 'test-user-id' ,
559631 } ) ;
@@ -568,7 +640,7 @@ describe('ChatService', () => {
568640 } ) ;
569641
570642 it ( 'should throw NotFoundException if filter does not exist' , async ( ) => {
571- mockFilterModel . findOneAndDelete . mockReturnValue ( createMockQuery ( null ) ) ;
643+ mockFilterModel . find . mockReturnValue ( createMockQuery ( [ ] ) ) ;
572644
573645 await expect ( service . deleteFilter ( 'non-existent-id' , 'test-user-id' ) ) . rejects . toThrow ( NotFoundException ) ;
574646 } ) ;
0 commit comments