@@ -569,6 +569,108 @@ export const Generic = () => {
569569 } ) ;
570570 } ) ;
571571
572+ it ( 'should truncate the correct messages if channel.truncated arrives with truncated_at' , async ( ) => {
573+ useMockedApis ( chatClient , [ queryChannelsApi ( channels ) ] ) ;
574+
575+ renderComponent ( ) ;
576+ act ( ( ) => dispatchConnectionChangedEvent ( chatClient ) ) ;
577+ await act ( async ( ) => await chatClient . offlineDb . syncManager . invokeSyncStatusListeners ( true ) ) ;
578+ await waitFor ( ( ) => expect ( screen . getByTestId ( 'channel-list' ) ) . toBeTruthy ( ) ) ;
579+
580+ const channelResponse = channels [ getRandomInt ( 0 , channels . length - 1 ) ] ;
581+ const channelToTruncate = channelResponse . channel ;
582+ const messages = channelResponse . messages ;
583+ messages . sort ( ( a , b ) => new Date ( a . created_at ) . getTime ( ) - new Date ( b . created_at ) . getTime ( ) ) ;
584+ // truncate at the middle
585+ const truncatedAt = messages [ Number ( messages . length / 2 ) ] . created_at ;
586+ act ( ( ) =>
587+ dispatchChannelTruncatedEvent ( chatClient , {
588+ ...channelToTruncate ,
589+ truncated_at : truncatedAt ,
590+ } ) ,
591+ ) ;
592+
593+ await waitFor ( async ( ) => {
594+ const channelIdsOnUI = screen
595+ . queryAllByLabelText ( 'list-item' )
596+ . map ( ( node ) => node . _fiber . pendingProps . testID ) ;
597+ expect ( channelIdsOnUI . includes ( channelToTruncate . cid ) ) . toBeTruthy ( ) ;
598+ expectCIDsOnUIToBeInDB ( screen . queryAllByLabelText ) ;
599+
600+ const messagesRows = await BetterSqlite . selectFromTable ( 'messages' ) ;
601+ const matchingMessagesRows = messagesRows . filter ( ( m ) => m . cid === channelToTruncate . cid ) ;
602+
603+ expect ( matchingMessagesRows . length ) . toBe ( messages . length / 2 - 1 ) ;
604+ } ) ;
605+ } ) ;
606+
607+ it ( 'should gracefully handle a truncated_at date before each message' , async ( ) => {
608+ useMockedApis ( chatClient , [ queryChannelsApi ( channels ) ] ) ;
609+
610+ renderComponent ( ) ;
611+ act ( ( ) => dispatchConnectionChangedEvent ( chatClient ) ) ;
612+ await act ( async ( ) => await chatClient . offlineDb . syncManager . invokeSyncStatusListeners ( true ) ) ;
613+ await waitFor ( ( ) => expect ( screen . getByTestId ( 'channel-list' ) ) . toBeTruthy ( ) ) ;
614+
615+ const channelResponse = channels [ getRandomInt ( 0 , channels . length - 1 ) ] ;
616+ const channelToTruncate = channelResponse . channel ;
617+ const truncatedAt = new Date ( 0 ) . toISOString ( ) ;
618+ act ( ( ) =>
619+ dispatchChannelTruncatedEvent ( chatClient , {
620+ ...channelToTruncate ,
621+ truncated_at : truncatedAt ,
622+ } ) ,
623+ ) ;
624+
625+ await waitFor ( async ( ) => {
626+ const channelIdsOnUI = screen
627+ . queryAllByLabelText ( 'list-item' )
628+ . map ( ( node ) => node . _fiber . pendingProps . testID ) ;
629+ expect ( channelIdsOnUI . includes ( channelToTruncate . cid ) ) . toBeTruthy ( ) ;
630+ expectCIDsOnUIToBeInDB ( screen . queryAllByLabelText ) ;
631+
632+ const messagesRows = await BetterSqlite . selectFromTable ( 'messages' ) ;
633+ const matchingMessagesRows = messagesRows . filter ( ( m ) => m . cid === channelToTruncate . cid ) ;
634+
635+ expect ( matchingMessagesRows . length ) . toBe ( channelResponse . messages . length ) ;
636+ } ) ;
637+ } ) ;
638+
639+ it ( 'should gracefully handle a truncated_at date after each message' , async ( ) => {
640+ useMockedApis ( chatClient , [ queryChannelsApi ( channels ) ] ) ;
641+
642+ renderComponent ( ) ;
643+ act ( ( ) => dispatchConnectionChangedEvent ( chatClient ) ) ;
644+ await act ( async ( ) => await chatClient . offlineDb . syncManager . invokeSyncStatusListeners ( true ) ) ;
645+ await waitFor ( ( ) => expect ( screen . getByTestId ( 'channel-list' ) ) . toBeTruthy ( ) ) ;
646+
647+ const channelResponse = channels [ getRandomInt ( 0 , channels . length - 1 ) ] ;
648+ const channelToTruncate = channelResponse . channel ;
649+ const messages = channelResponse . messages ;
650+ const latestTimestamp = Math . max ( ...messages . map ( ( m ) => new Date ( m . created_at ) . getTime ( ) ) ) ;
651+ // truncate at the middle
652+ const truncatedAt = new Date ( latestTimestamp + 1 ) . toISOString ( ) ;
653+ act ( ( ) =>
654+ dispatchChannelTruncatedEvent ( chatClient , {
655+ ...channelToTruncate ,
656+ truncated_at : truncatedAt ,
657+ } ) ,
658+ ) ;
659+
660+ await waitFor ( async ( ) => {
661+ const channelIdsOnUI = screen
662+ . queryAllByLabelText ( 'list-item' )
663+ . map ( ( node ) => node . _fiber . pendingProps . testID ) ;
664+ expect ( channelIdsOnUI . includes ( channelToTruncate . cid ) ) . toBeTruthy ( ) ;
665+ expectCIDsOnUIToBeInDB ( screen . queryAllByLabelText ) ;
666+
667+ const messagesRows = await BetterSqlite . selectFromTable ( 'messages' ) ;
668+ const matchingMessagesRows = messagesRows . filter ( ( m ) => m . cid === channelToTruncate . cid ) ;
669+
670+ expect ( matchingMessagesRows . length ) . toBe ( 0 ) ;
671+ } ) ;
672+ } ) ;
673+
572674 it ( 'should add a reaction to DB when a new reaction is added' , async ( ) => {
573675 useMockedApis ( chatClient , [ queryChannelsApi ( channels ) ] ) ;
574676 renderComponent ( ) ;
0 commit comments