status-go/protocol/messenger_unread_test.go

336 lines
10 KiB
Go

package protocol
import (
"context"
"errors"
_ "github.com/mutecomm/go-sqlcipher/v4" // require go-sqlcipher that overrides default implementation
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/requests"
"github.com/status-im/status-go/protocol/tt"
)
func (s *MessengerSuite) checkMessageSeen(messageID string, expectedSeen bool) {
message, err := s.m.MessageByID(messageID)
s.Require().NoError(err)
s.Require().Equal(expectedSeen, message.Seen)
}
func (s *MessengerSuite) retrieveAllWithRetry(errorMessage string) (*MessengerResponse, error) {
var response *MessengerResponse
var err error
retryFunc := func() error {
response, err = s.m.RetrieveAll()
if err != nil {
return err
}
if len(response.messages) == 0 {
return errors.New(errorMessage)
}
return nil
}
err = tt.RetryWithBackOff(retryFunc)
return response, err
}
func (s *MessengerSuite) TestMarkMessageAsUnreadWhenMessageListContainsSingleMessage() {
chat := CreatePublicChat("test-chat-1", s.m.transport)
chat.UnviewedMessagesCount = 2
chat.UnviewedMentionsCount = 2
chat.Highlight = true
err := s.m.SaveChat(chat)
s.Require().NoError(err)
inputMessage1 := buildTestMessage(*chat)
inputMessage1.ID = "1"
inputMessage1.Seen = true
inputMessage1.Mentioned = true
err = s.m.SaveMessages([]*common.Message{inputMessage1})
s.Require().NoError(err)
_, err = s.m.MarkAllRead(context.Background(), chat.ID)
s.Require().NoError(err)
chats := s.m.allChats
actualChat, ok := chats.Load(chat.ID)
s.Require().True(ok)
s.Require().Equal(uint(0), actualChat.UnviewedMessagesCount)
s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
s.Require().False(actualChat.Highlight)
s.checkMessageSeen(inputMessage1.ID, true)
count, countWithMentions, notifications, err := s.m.MarkMessageAsUnread(chat.ID, inputMessage1.ID)
s.Require().NoError(err)
s.Require().Equal(uint64(1), count)
s.Require().Equal(uint64(1), countWithMentions)
s.Require().Len(notifications, 0)
chats = s.m.allChats
actualChat, ok = chats.Load(chat.ID)
s.Require().True(ok)
s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount)
s.Require().Equal(uint(1), actualChat.UnviewedMentionsCount)
s.Require().False(actualChat.Highlight)
s.checkMessageSeen(inputMessage1.ID, false)
}
func (s *MessengerSuite) TestMarkMessageAsUnreadWhenMessageListContainsSeveralMessages() {
chat := CreatePublicChat("test-chat-2", s.m.transport)
chat.UnviewedMessagesCount = 0
chat.UnviewedMentionsCount = 0
chat.Highlight = true
err := s.m.SaveChat(chat)
s.Require().NoError(err)
inputMessage1 := buildTestMessage(*chat)
inputMessage1.ID = "1"
inputMessage1.Seen = true
inputMessage1.Mentioned = true
inputMessage1.Timestamp = 1
inputMessage2 := buildTestMessage(*chat)
inputMessage2.ID = "2"
inputMessage2.Seen = true
inputMessage2.Mentioned = false
inputMessage2.Timestamp = 2
inputMessage3 := buildTestMessage(*chat)
inputMessage3.ID = "3"
inputMessage3.Seen = true
inputMessage3.Mentioned = false
inputMessage3.Timestamp = 3
err = s.m.SaveMessages([]*common.Message{
inputMessage1,
inputMessage2,
inputMessage3,
})
s.Require().NoError(err)
_, err = s.m.MarkAllRead(context.Background(), chat.ID)
s.Require().NoError(err)
chats := s.m.allChats
actualChat, ok := chats.Load(chat.ID)
s.Require().True(ok)
s.Require().Equal(uint(0), actualChat.UnviewedMessagesCount)
s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
s.Require().False(actualChat.Highlight)
s.checkMessageSeen(inputMessage1.ID, true)
s.checkMessageSeen(inputMessage2.ID, true)
s.checkMessageSeen(inputMessage3.ID, true)
count, countWithMentions, notifications, err := s.m.MarkMessageAsUnread(chat.ID, inputMessage2.ID)
s.Require().NoError(err)
// count is 2 because the messages are layout the following way :
//
// inputMessage1 read <-- mentioned
// ----------------------------- <-- marker
// inputMessage2 unread
// inputMessage3 unread
//
// And the inputMessage3 has greater timestamp than inputMessage2
// Similarly, the mentioned message is inputMessage1, therefore the
// countWithMentions is 0
s.Require().Equal(uint64(2), count)
s.Require().Equal(uint64(0), countWithMentions)
s.Require().Len(notifications, 0)
chats = s.m.allChats
actualChat, ok = chats.Load(chat.ID)
s.Require().True(ok)
s.Require().Equal(uint(2), actualChat.UnviewedMessagesCount)
s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
s.Require().False(actualChat.Highlight)
s.checkMessageSeen(inputMessage1.ID, true)
s.checkMessageSeen(inputMessage2.ID, false)
s.checkMessageSeen(inputMessage3.ID, false)
}
func (s *MessengerSuite) TestMarkMessageAsUnreadWhenMessageIsAlreadyInUnreadState() {
chat := CreatePublicChat("test-chat-3", s.m.transport)
chat.UnviewedMessagesCount = 1
chat.UnviewedMentionsCount = 0
chat.Highlight = true
err := s.m.SaveChat(chat)
s.Require().NoError(err)
inputMessage1 := buildTestMessage(*chat)
inputMessage1.ID = "1"
inputMessage1.Seen = false
inputMessage1.Mentioned = false
err = s.m.SaveMessages([]*common.Message{inputMessage1})
s.Require().NoError(err)
chats := s.m.allChats
actualChat, ok := chats.Load(chat.ID)
s.Require().True(ok)
s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount)
s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
s.Require().True(actualChat.Highlight)
s.checkMessageSeen(inputMessage1.ID, false)
count, countWithMentions, notifications, err := s.m.MarkMessageAsUnread(chat.ID, inputMessage1.ID)
s.Require().NoError(err)
s.Require().Equal(uint64(1), count)
s.Require().Equal(uint64(0), countWithMentions)
s.Require().Len(notifications, 0)
chats = s.m.allChats
actualChat, ok = chats.Load(chat.ID)
s.Require().True(ok)
s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount)
s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
s.Require().False(actualChat.Highlight)
s.checkMessageSeen(inputMessage1.ID, false)
}
func (s *MessengerSuite) TestMarkMessageAsUnreadInOneChatDoesNotImpactOtherChats() {
chat1 := CreatePublicChat("test-chat-1", s.m.transport)
err := s.m.SaveChat(chat1)
s.Require().NoError(err)
chat2 := CreatePublicChat("test-chat-2", s.m.transport)
err = s.m.SaveChat(chat2)
s.Require().NoError(err)
chat1.UnviewedMessagesCount = 2
chat1.UnviewedMentionsCount = 0
chat1.Highlight = true
inputMessage1 := buildTestMessage(*chat1)
inputMessage1.ID = "1"
inputMessage1.Seen = true
inputMessage1.Mentioned = false
inputMessage2 := buildTestMessage(*chat1)
inputMessage2.ID = "2"
inputMessage2.Seen = true
inputMessage2.Mentioned = false
err = s.m.SaveMessages([]*common.Message{inputMessage1, inputMessage2})
s.Require().NoError(err)
chat2.UnviewedMessagesCount = 1
chat2.UnviewedMentionsCount = 0
chat2.Highlight = true
inputMessage3 := buildTestMessage(*chat2)
inputMessage3.ID = "3"
inputMessage3.Seen = false
inputMessage3.Mentioned = false
err = s.m.SaveMessages([]*common.Message{inputMessage3})
s.Require().NoError(err)
_, err = s.m.MarkAllRead(context.Background(), chat1.ID)
s.Require().NoError(err)
s.checkMessageSeen(inputMessage1.ID, true)
s.checkMessageSeen(inputMessage2.ID, true)
count, countWithMentions, notifications, err := s.m.MarkMessageAsUnread(chat1.ID, inputMessage1.ID)
s.Require().NoError(err)
s.Require().Equal(uint(1), chat2.UnviewedMessagesCount)
s.Require().Equal(uint64(2), count)
s.Require().Equal(uint64(0), countWithMentions)
s.Require().Len(notifications, 0)
chats := s.m.allChats
actualChat, ok := chats.Load(chat1.ID)
s.Require().True(ok)
s.Require().Equal(uint(2), actualChat.UnviewedMessagesCount)
s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
s.Require().False(actualChat.Highlight)
s.checkMessageSeen(inputMessage1.ID, false)
s.checkMessageSeen(inputMessage2.ID, false)
actualChat, ok = chats.Load(chat2.ID)
s.Require().True(ok)
s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount)
s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
s.Require().True(actualChat.Highlight)
s.checkMessageSeen(inputMessage3.ID, false)
}
func (s *MessengerSuite) TestMarkMessageWithNotificationAsUnreadInCommunityChatSetsNotificationAsUnread() {
other := s.newMessenger()
description := &requests.CreateCommunity{
Membership: protobuf.CommunityPermissions_AUTO_ACCEPT,
Name: "status",
Color: "#ffffff",
Description: "This is just a test description for the community",
}
response, err := other.CreateCommunity(description, true)
s.Require().NoError(err)
s.Require().NotNil(response)
s.Require().Len(response.Communities(), 1)
community := response.Communities()[0]
communityChat := response.Chats()[0]
_, err = community.AddMember(&s.m.identity.PublicKey, []protobuf.CommunityMember_Roles{})
s.Require().NoError(err)
err = other.communitiesManager.SaveCommunity(community)
s.Require().NoError(err)
advertiseCommunityToUserOldWay(&s.Suite, community, other, s.m)
inputMessage1 := buildTestMessage(*communityChat)
inputMessage1.ChatId = communityChat.ID
inputMessage1.ContentType = protobuf.ChatMessage_TEXT_PLAIN
inputMessage1.Text = "Hello @" + common.EveryoneMentionTag + " !"
sendResponse, err := other.SendChatMessage(context.Background(), inputMessage1)
s.NoError(err)
s.Require().Len(sendResponse.Messages(), 1)
response, err = s.retrieveAllWithRetry("message from other chatter not received")
s.Require().NoError(err)
s.Require().Len(response.Chats(), 1)
s.Require().Len(response.Messages(), 1)
s.Require().Len(response.ActivityCenterNotifications(), 1)
s.Require().False(response.ActivityCenterNotifications()[0].Read)
response, err = s.m.MarkAllRead(context.Background(), communityChat.ID)
s.Require().NoError(err)
s.Require().Len(response.ActivityCenterNotifications(), 1)
s.Require().True(response.ActivityCenterNotifications()[0].Read)
count, countWithMentions, notifications, err := s.m.MarkMessageAsUnread(communityChat.ID, inputMessage1.ID)
s.Require().NoError(err)
s.Require().Equal(count, uint64(1))
s.Require().Equal(countWithMentions, uint64(1))
s.Require().Len(notifications, 1)
s.Require().False(notifications[0].Read)
}