github.com/status-im/status-go@v1.1.0/protocol/messenger_unread_test.go (about)

     1  package protocol
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  
     7  	_ "github.com/mutecomm/go-sqlcipher/v4" // require go-sqlcipher that overrides default implementation
     8  
     9  	"github.com/status-im/status-go/protocol/common"
    10  	"github.com/status-im/status-go/protocol/protobuf"
    11  	"github.com/status-im/status-go/protocol/requests"
    12  	"github.com/status-im/status-go/protocol/tt"
    13  )
    14  
    15  func (s *MessengerSuite) checkMessageSeen(messageID string, expectedSeen bool) {
    16  	message, err := s.m.MessageByID(messageID)
    17  
    18  	s.Require().NoError(err)
    19  	s.Require().Equal(expectedSeen, message.Seen)
    20  }
    21  
    22  func (s *MessengerSuite) retrieveAllWithRetry(errorMessage string) (*MessengerResponse, error) {
    23  	var response *MessengerResponse
    24  	var err error
    25  
    26  	retryFunc := func() error {
    27  		response, err = s.m.RetrieveAll()
    28  		if err != nil {
    29  			return err
    30  		}
    31  		if len(response.messages) == 0 {
    32  			return errors.New(errorMessage)
    33  		}
    34  		return nil
    35  	}
    36  
    37  	err = tt.RetryWithBackOff(retryFunc)
    38  	return response, err
    39  }
    40  
    41  func (s *MessengerSuite) TestMarkMessageAsUnreadWhenMessageListContainsSingleMessage() {
    42  	chat := CreatePublicChat("test-chat-1", s.m.transport)
    43  
    44  	chat.UnviewedMessagesCount = 2
    45  	chat.UnviewedMentionsCount = 2
    46  	chat.Highlight = true
    47  
    48  	err := s.m.SaveChat(chat)
    49  	s.Require().NoError(err)
    50  
    51  	inputMessage1 := buildTestMessage(*chat)
    52  	inputMessage1.ID = "1"
    53  	inputMessage1.Seen = true
    54  	inputMessage1.Mentioned = true
    55  
    56  	err = s.m.SaveMessages([]*common.Message{inputMessage1})
    57  	s.Require().NoError(err)
    58  
    59  	_, err = s.m.MarkAllRead(context.Background(), chat.ID)
    60  	s.Require().NoError(err)
    61  
    62  	chats := s.m.allChats
    63  
    64  	actualChat, ok := chats.Load(chat.ID)
    65  
    66  	s.Require().True(ok)
    67  	s.Require().Equal(uint(0), actualChat.UnviewedMessagesCount)
    68  	s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
    69  	s.Require().False(actualChat.Highlight)
    70  	s.checkMessageSeen(inputMessage1.ID, true)
    71  
    72  	response, err := s.m.MarkMessageAsUnread(chat.ID, inputMessage1.ID)
    73  	s.Require().NoError(err)
    74  	s.Require().Len(response.GetSeenAndUnseenMessages(), 1)
    75  	s.Require().Equal(chat.ID, response.GetSeenAndUnseenMessages()[0].ChatID)
    76  	s.Require().Equal(uint64(1), response.GetSeenAndUnseenMessages()[0].Count)
    77  	s.Require().Equal(uint64(1), response.GetSeenAndUnseenMessages()[0].CountWithMentions)
    78  	s.Require().Equal(false, response.GetSeenAndUnseenMessages()[0].Seen)
    79  	s.Require().Len(response.ActivityCenterNotifications(), 0)
    80  
    81  	chats = s.m.allChats
    82  
    83  	actualChat, ok = chats.Load(chat.ID)
    84  	s.Require().True(ok)
    85  	s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount)
    86  	s.Require().Equal(uint(1), actualChat.UnviewedMentionsCount)
    87  	s.Require().False(actualChat.Highlight)
    88  	s.checkMessageSeen(inputMessage1.ID, false)
    89  }
    90  
    91  func (s *MessengerSuite) TestMarkMessageAsUnreadWhenMessageListContainsSeveralMessages() {
    92  	chat := CreatePublicChat("test-chat-2", s.m.transport)
    93  
    94  	chat.UnviewedMessagesCount = 0
    95  	chat.UnviewedMentionsCount = 0
    96  	chat.Highlight = true
    97  
    98  	err := s.m.SaveChat(chat)
    99  	s.Require().NoError(err)
   100  
   101  	inputMessage1 := buildTestMessage(*chat)
   102  	inputMessage1.ID = "1"
   103  	inputMessage1.Seen = true
   104  	inputMessage1.Mentioned = true
   105  	inputMessage1.Timestamp = 1
   106  
   107  	inputMessage2 := buildTestMessage(*chat)
   108  	inputMessage2.ID = "2"
   109  	inputMessage2.Seen = true
   110  	inputMessage2.Mentioned = false
   111  	inputMessage2.Timestamp = 2
   112  
   113  	inputMessage3 := buildTestMessage(*chat)
   114  	inputMessage3.ID = "3"
   115  	inputMessage3.Seen = true
   116  	inputMessage3.Mentioned = false
   117  	inputMessage3.Timestamp = 3
   118  
   119  	err = s.m.SaveMessages([]*common.Message{
   120  		inputMessage1,
   121  		inputMessage2,
   122  		inputMessage3,
   123  	})
   124  	s.Require().NoError(err)
   125  
   126  	_, err = s.m.MarkAllRead(context.Background(), chat.ID)
   127  	s.Require().NoError(err)
   128  
   129  	chats := s.m.allChats
   130  	actualChat, ok := chats.Load(chat.ID)
   131  
   132  	s.Require().True(ok)
   133  	s.Require().Equal(uint(0), actualChat.UnviewedMessagesCount)
   134  	s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
   135  	s.Require().False(actualChat.Highlight)
   136  	s.checkMessageSeen(inputMessage1.ID, true)
   137  	s.checkMessageSeen(inputMessage2.ID, true)
   138  	s.checkMessageSeen(inputMessage3.ID, true)
   139  
   140  	response, err := s.m.MarkMessageAsUnread(chat.ID, inputMessage2.ID)
   141  	s.Require().NoError(err)
   142  
   143  	// count is 2 because the messages are layout the following way :
   144  	//
   145  	// inputMessage1   read    <-- mentioned
   146  	// ----------------------------- <-- marker
   147  	// inputMessage2   unread
   148  	// inputMessage3   unread
   149  	//
   150  	// And the inputMessage3 has greater timestamp than inputMessage2
   151  	// Similarly, the mentioned message is inputMessage1, therefore the
   152  	// countWithMentions is 0
   153  	s.Require().Len(response.GetSeenAndUnseenMessages(), 1)
   154  	s.Require().Equal(chat.ID, response.GetSeenAndUnseenMessages()[0].ChatID)
   155  	s.Require().Equal(uint64(2), response.GetSeenAndUnseenMessages()[0].Count)
   156  	s.Require().Equal(uint64(0), response.GetSeenAndUnseenMessages()[0].CountWithMentions)
   157  	s.Require().Equal(false, response.GetSeenAndUnseenMessages()[0].Seen)
   158  
   159  	chats = s.m.allChats
   160  	actualChat, ok = chats.Load(chat.ID)
   161  
   162  	s.Require().True(ok)
   163  	s.Require().Equal(uint(2), actualChat.UnviewedMessagesCount)
   164  	s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
   165  	s.Require().False(actualChat.Highlight)
   166  	s.checkMessageSeen(inputMessage1.ID, true)
   167  	s.checkMessageSeen(inputMessage2.ID, false)
   168  	s.checkMessageSeen(inputMessage3.ID, false)
   169  }
   170  
   171  func (s *MessengerSuite) TestMarkMessageAsUnreadWhenMessageIsAlreadyInUnreadState() {
   172  	chat := CreatePublicChat("test-chat-3", s.m.transport)
   173  
   174  	chat.UnviewedMessagesCount = 1
   175  	chat.UnviewedMentionsCount = 0
   176  	chat.Highlight = true
   177  
   178  	err := s.m.SaveChat(chat)
   179  	s.Require().NoError(err)
   180  
   181  	inputMessage1 := buildTestMessage(*chat)
   182  	inputMessage1.ID = "1"
   183  	inputMessage1.Seen = false
   184  	inputMessage1.Mentioned = false
   185  
   186  	err = s.m.SaveMessages([]*common.Message{inputMessage1})
   187  	s.Require().NoError(err)
   188  
   189  	chats := s.m.allChats
   190  	actualChat, ok := chats.Load(chat.ID)
   191  
   192  	s.Require().True(ok)
   193  	s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount)
   194  	s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
   195  	s.Require().True(actualChat.Highlight)
   196  	s.checkMessageSeen(inputMessage1.ID, false)
   197  
   198  	response, err := s.m.MarkMessageAsUnread(chat.ID, inputMessage1.ID)
   199  	s.Require().NoError(err)
   200  	s.Require().Len(response.GetSeenAndUnseenMessages(), 1)
   201  	s.Require().Equal(chat.ID, response.GetSeenAndUnseenMessages()[0].ChatID)
   202  	s.Require().Equal(uint64(1), response.GetSeenAndUnseenMessages()[0].Count)
   203  	s.Require().Equal(uint64(0), response.GetSeenAndUnseenMessages()[0].CountWithMentions)
   204  	s.Require().Equal(false, response.GetSeenAndUnseenMessages()[0].Seen)
   205  
   206  	chats = s.m.allChats
   207  	actualChat, ok = chats.Load(chat.ID)
   208  
   209  	s.Require().True(ok)
   210  	s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount)
   211  	s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
   212  	s.Require().False(actualChat.Highlight)
   213  	s.checkMessageSeen(inputMessage1.ID, false)
   214  }
   215  
   216  func (s *MessengerSuite) TestMarkMessageAsUnreadInOneChatDoesNotImpactOtherChats() {
   217  	chat1 := CreatePublicChat("test-chat-1", s.m.transport)
   218  	err := s.m.SaveChat(chat1)
   219  	s.Require().NoError(err)
   220  
   221  	chat2 := CreatePublicChat("test-chat-2", s.m.transport)
   222  	err = s.m.SaveChat(chat2)
   223  	s.Require().NoError(err)
   224  
   225  	chat1.UnviewedMessagesCount = 2
   226  	chat1.UnviewedMentionsCount = 0
   227  	chat1.Highlight = true
   228  
   229  	inputMessage1 := buildTestMessage(*chat1)
   230  	inputMessage1.ID = "1"
   231  	inputMessage1.Seen = true
   232  	inputMessage1.Mentioned = false
   233  
   234  	inputMessage2 := buildTestMessage(*chat1)
   235  	inputMessage2.ID = "2"
   236  	inputMessage2.Seen = true
   237  	inputMessage2.Mentioned = false
   238  
   239  	err = s.m.SaveMessages([]*common.Message{inputMessage1, inputMessage2})
   240  	s.Require().NoError(err)
   241  
   242  	chat2.UnviewedMessagesCount = 1
   243  	chat2.UnviewedMentionsCount = 0
   244  	chat2.Highlight = true
   245  
   246  	inputMessage3 := buildTestMessage(*chat2)
   247  	inputMessage3.ID = "3"
   248  	inputMessage3.Seen = false
   249  	inputMessage3.Mentioned = false
   250  
   251  	err = s.m.SaveMessages([]*common.Message{inputMessage3})
   252  	s.Require().NoError(err)
   253  
   254  	_, err = s.m.MarkAllRead(context.Background(), chat1.ID)
   255  	s.Require().NoError(err)
   256  	s.checkMessageSeen(inputMessage1.ID, true)
   257  	s.checkMessageSeen(inputMessage2.ID, true)
   258  
   259  	response, err := s.m.MarkMessageAsUnread(chat1.ID, inputMessage1.ID)
   260  
   261  	s.Require().NoError(err)
   262  	s.Require().Len(response.GetSeenAndUnseenMessages(), 1)
   263  	s.Require().Equal(chat1.ID, response.GetSeenAndUnseenMessages()[0].ChatID)
   264  	s.Require().Equal(uint64(2), response.GetSeenAndUnseenMessages()[0].Count)
   265  	s.Require().Equal(uint64(0), response.GetSeenAndUnseenMessages()[0].CountWithMentions)
   266  	s.Require().Equal(false, response.GetSeenAndUnseenMessages()[0].Seen)
   267  	s.Require().Len(response.ActivityCenterNotifications(), 0)
   268  
   269  	chats := s.m.allChats
   270  	actualChat, ok := chats.Load(chat1.ID)
   271  
   272  	s.Require().True(ok)
   273  	s.Require().Equal(uint(2), actualChat.UnviewedMessagesCount)
   274  	s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
   275  	s.Require().False(actualChat.Highlight)
   276  	s.checkMessageSeen(inputMessage1.ID, false)
   277  	s.checkMessageSeen(inputMessage2.ID, false)
   278  
   279  	actualChat, ok = chats.Load(chat2.ID)
   280  	s.Require().True(ok)
   281  	s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount)
   282  	s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
   283  	s.Require().True(actualChat.Highlight)
   284  
   285  	s.checkMessageSeen(inputMessage3.ID, false)
   286  }
   287  
   288  func (s *MessengerSuite) TestMarkMessageWithNotificationAsUnreadInCommunityChatSetsNotificationAsUnread() {
   289  	other := s.newMessenger()
   290  
   291  	description := &requests.CreateCommunity{
   292  		Membership:  protobuf.CommunityPermissions_AUTO_ACCEPT,
   293  		Name:        "status",
   294  		Color:       "#ffffff",
   295  		Description: "This is just a test description for the community",
   296  	}
   297  
   298  	response, err := other.CreateCommunity(description, true)
   299  	s.Require().NoError(err)
   300  	s.Require().NotNil(response)
   301  	s.Require().Len(response.Communities(), 1)
   302  
   303  	community := response.Communities()[0]
   304  	communityChat := response.Chats()[0]
   305  
   306  	_, err = community.AddMember(&s.m.identity.PublicKey, []protobuf.CommunityMember_Roles{}, community.Clock())
   307  	s.Require().NoError(err)
   308  
   309  	err = other.communitiesManager.SaveCommunity(community)
   310  	s.Require().NoError(err)
   311  
   312  	advertiseCommunityToUserOldWay(&s.Suite, community, other, s.m)
   313  
   314  	inputMessage1 := buildTestMessage(*communityChat)
   315  	inputMessage1.ChatId = communityChat.ID
   316  	inputMessage1.ContentType = protobuf.ChatMessage_TEXT_PLAIN
   317  	inputMessage1.Text = "Hello @" + common.EveryoneMentionTag + " !"
   318  
   319  	sendResponse, err := other.SendChatMessage(context.Background(), inputMessage1)
   320  	s.NoError(err)
   321  	s.Require().Len(sendResponse.Messages(), 1)
   322  
   323  	response, err = s.retrieveAllWithRetry("message from other chatter not received")
   324  
   325  	s.Require().NoError(err)
   326  	s.Require().Len(response.Chats(), 1)
   327  	s.Require().Len(response.Messages(), 1)
   328  	s.Require().Len(response.ActivityCenterNotifications(), 1)
   329  	s.Require().False(response.ActivityCenterNotifications()[0].Read)
   330  
   331  	response, err = s.m.MarkAllRead(context.Background(), communityChat.ID)
   332  
   333  	s.Require().NoError(err)
   334  	s.Require().Len(response.ActivityCenterNotifications(), 1)
   335  	s.Require().True(response.ActivityCenterNotifications()[0].Read)
   336  
   337  	response, err = s.m.MarkMessageAsUnread(communityChat.ID, inputMessage1.ID)
   338  
   339  	s.Require().NoError(err)
   340  	s.Require().Len(response.GetSeenAndUnseenMessages(), 1)
   341  	s.Require().Equal(communityChat.ID, response.GetSeenAndUnseenMessages()[0].ChatID)
   342  	s.Require().Equal(uint64(1), response.GetSeenAndUnseenMessages()[0].Count)
   343  	s.Require().Equal(uint64(1), response.GetSeenAndUnseenMessages()[0].CountWithMentions)
   344  	s.Require().Equal(false, response.GetSeenAndUnseenMessages()[0].Seen)
   345  	s.Require().Len(response.ActivityCenterNotifications(), 1)
   346  	s.Require().False(response.ActivityCenterNotifications()[0].Read)
   347  }