github.com/status-im/status-go@v1.1.0/protocol/messenger_activity_center_test.go (about) 1 package protocol 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/stretchr/testify/suite" 8 9 multiaccountscommon "github.com/status-im/status-go/multiaccounts/common" 10 "github.com/status-im/status-go/protocol/common" 11 "github.com/status-im/status-go/protocol/communities" 12 "github.com/status-im/status-go/protocol/protobuf" 13 "github.com/status-im/status-go/protocol/requests" 14 "github.com/status-im/status-go/server" 15 ) 16 17 func TestMessengerActivityCenterMessageSuite(t *testing.T) { 18 suite.Run(t, new(MessengerActivityCenterMessageSuite)) 19 } 20 21 func (s *MessengerActivityCenterMessageSuite) createCommunity(owner *Messenger) (*communities.Community, *Chat) { 22 return createCommunity(&s.Suite, owner) 23 } 24 25 func (s *MessengerActivityCenterMessageSuite) advertiseCommunityTo(community *communities.Community, owner *Messenger, user *Messenger) { 26 advertiseCommunityTo(&s.Suite, community, owner, user) 27 } 28 29 func (s *MessengerActivityCenterMessageSuite) joinCommunity(community *communities.Community, owner *Messenger, user *Messenger) { 30 joinCommunity(&s.Suite, community.ID(), owner, user, accountPassword, []string{commonAccountAddress}) 31 } 32 33 type MessengerActivityCenterMessageSuite struct { 34 CommunitiesMessengerTestSuiteBase 35 m *Messenger // main instance of Messenger 36 } 37 38 func (s *MessengerActivityCenterMessageSuite) SetupTest() { 39 s.CommunitiesMessengerTestSuiteBase.SetupTest() 40 41 s.m = s.newMessenger(alicePassword, []string{aliceAccountAddress}) 42 s.m.account.CustomizationColor = multiaccountscommon.CustomizationColorOrange 43 44 _, err := s.m.Start() 45 s.Require().NoError(err) 46 } 47 48 func (s *MessengerActivityCenterMessageSuite) TearDownTest() { 49 TearDownMessenger(&s.Suite, s.m) 50 s.CommunitiesMessengerTestSuiteBase.TearDownTest() 51 } 52 53 func (s *MessengerActivityCenterMessageSuite) TestDeleteOneToOneChat() { 54 theirMessenger := s.newMessenger(accountPassword, []string{commonAccountAddress}) 55 defer TearDownMessenger(&s.Suite, theirMessenger) 56 57 theirChat := CreateOneToOneChat("Their 1TO1", s.m.IdentityPublicKey(), s.m.transport) 58 err := theirMessenger.SaveChat(theirChat) 59 s.Require().NoError(err) 60 61 r := &requests.SendContactRequest{ 62 ID: s.m.myHexIdentity(), 63 Message: "hello", 64 } 65 sendResponse, err := theirMessenger.SendContactRequest(context.Background(), r) 66 s.NoError(err) 67 s.Require().Len(sendResponse.Messages(), 2) 68 69 response, err := WaitOnMessengerResponse( 70 s.m, 71 func(r *MessengerResponse) bool { return len(r.messages) > 0 }, 72 "no messages", 73 ) 74 s.Require().NoError(err) 75 s.Require().Len(response.Chats(), 1) 76 s.Require().Len(response.Messages(), 2) 77 s.Require().Len(response.ActivityCenterNotifications(), 1) 78 79 request := &requests.DeactivateChat{ID: response.Chats()[0].ID} 80 response, err = s.m.DeactivateChat(request) 81 s.Require().NoError(err) 82 s.Require().Len(response.Chats(), 1) 83 deletedChat := response.Chats()[0] 84 s.Require().NotEmpty(deletedChat.DeletedAtClockValue) 85 86 // Make sure deleted at clock value is greater 87 theirChat.LastClockValue = deletedChat.DeletedAtClockValue + 1 88 err = theirMessenger.SaveChat(theirChat) 89 s.Require().NoError(err) 90 91 // Send another message 92 inputMessage := buildTestMessage(*theirChat) 93 sendResponse, err = theirMessenger.SendChatMessage(context.Background(), inputMessage) 94 s.NoError(err) 95 s.Require().Len(sendResponse.Messages(), 1) 96 97 response, err = WaitOnMessengerResponse( 98 s.m, 99 func(r *MessengerResponse) bool { return len(r.Chats()) > 0 }, 100 "no messages", 101 ) 102 s.Require().NoError(err) 103 s.Require().Len(response.Chats(), 1) 104 } 105 106 func (s *MessengerActivityCenterMessageSuite) TestEveryoneMentionTag() { 107 alice := s.m 108 bob := s.newMessenger(bobPassword, []string{bobAddress}) 109 defer TearDownMessenger(&s.Suite, bob) 110 111 // Create a community 112 community, chat := s.createCommunity(bob) 113 s.Require().NotNil(community) 114 s.Require().NotNil(chat) 115 116 // Alice joins the community 117 s.advertiseCommunityTo(community, bob, alice) 118 s.joinCommunity(community, bob, alice) 119 120 // alice sends a community message 121 inputMessage := common.NewMessage() 122 inputMessage.ChatId = chat.ID 123 inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN 124 inputMessage.Text = "Good news, @" + common.EveryoneMentionTag + " !" 125 126 response, err := alice.SendChatMessage(context.Background(), inputMessage) 127 s.Require().NoError(err) 128 s.Require().Len(response.Messages(), 1) 129 s.Require().True(response.Messages()[0].Mentioned) 130 131 response, err = WaitOnMessengerResponse( 132 bob, 133 func(r *MessengerResponse) bool { return len(r.Messages()) >= 1 }, 134 "no messages", 135 ) 136 137 s.Require().NoError(err) 138 139 s.Require().Len(response.Messages(), 1) 140 141 s.Require().True(response.Messages()[0].Mentioned) 142 s.Require().Len(response.ActivityCenterNotifications(), 1) 143 s.Require().Equal(ActivityCenterNotificationTypeMention, response.ActivityCenterNotifications()[0].Type) 144 } 145 146 func (s *MessengerActivityCenterMessageSuite) TestReplyWithImage() { 147 alice := s.m 148 bob := s.newMessenger(bobPassword, []string{bobAddress}) 149 defer TearDownMessenger(&s.Suite, bob) 150 151 // create an http server 152 mediaServer, err := server.NewMediaServer(nil, nil, nil, nil) 153 s.Require().NoError(err) 154 s.Require().NotNil(mediaServer) 155 s.Require().NoError(mediaServer.Start()) 156 alice.SetMediaServer(mediaServer) 157 158 // Create a community 159 community, chat := s.createCommunity(bob) 160 s.Require().NotNil(community) 161 s.Require().NotNil(chat) 162 163 // Alice joins the community 164 s.advertiseCommunityTo(community, bob, alice) 165 s.joinCommunity(community, bob, alice) 166 167 // Alice sends a community message 168 inputMessage := common.NewMessage() 169 inputMessage.ChatId = chat.ID 170 inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN 171 inputMessage.Text = "test message" 172 173 response, err := alice.SendChatMessage(context.Background(), inputMessage) 174 s.Require().NoError(err) 175 s.Require().Len(response.Messages(), 1) 176 response, err = WaitOnMessengerResponse( 177 bob, 178 func(r *MessengerResponse) bool { return len(r.Messages()) == 1 }, 179 "no messages", 180 ) 181 s.Require().NoError(err) 182 s.Require().Len(response.Messages(), 1) 183 184 // bob sends a reply with an image 185 inputMessage, err = buildImageWithAlbumIDMessage(*chat, "0x34") 186 s.Require().NoError(err) 187 188 inputMessage.Text = "test message reply" 189 inputMessage.ResponseTo = response.Messages()[0].ID 190 191 response, err = bob.SendChatMessage(context.Background(), inputMessage) 192 s.Require().NoError(err) 193 s.Require().Len(response.Messages(), 2) 194 response, err = WaitOnMessengerResponse( 195 alice, 196 func(r *MessengerResponse) bool { return len(r.Messages()) == 2 }, 197 "no messages", 198 ) 199 s.Require().NoError(err) 200 s.Require().Len(response.ActivityCenterNotifications(), 1) 201 202 // verify the new message 203 var newMessage *common.Message 204 for _, m := range response.Messages() { 205 if m.Text == "test message reply" { 206 newMessage = m 207 } 208 } 209 s.Require().NotNil(newMessage) 210 s.Require().Equal(protobuf.ChatMessage_IMAGE, newMessage.ContentType) 211 s.Require().NotEmpty(newMessage.ImageLocalURL) 212 213 s.Require().NotNil(response.ActivityCenterNotifications()[0].Message) 214 s.Require().NotEmpty(response.ActivityCenterNotifications()[0].Message.ImageLocalURL) 215 s.Require().Equal(ActivityCenterNotificationTypeReply, response.ActivityCenterNotifications()[0].Type) 216 217 notifResponse, err := alice.ActivityCenterNotifications(ActivityCenterNotificationsRequest{ 218 Limit: 8, 219 ReadType: ActivityCenterQueryParamsReadAll, 220 ActivityTypes: []ActivityCenterType{ActivityCenterNotificationTypeReply}, 221 }) 222 s.Require().NoError(err) 223 s.Require().Len(notifResponse.Notifications, 1) 224 s.Require().NotNil(notifResponse.Notifications[0].Message) 225 s.Require().NotEmpty(notifResponse.Notifications[0].Message.ImageLocalURL) 226 } 227 228 func (s *MessengerActivityCenterMessageSuite) TestMuteCommunityActivityCenterNotifications() { 229 alice := s.m 230 bob := s.newMessenger(bobPassword, []string{bobAddress}) 231 defer TearDownMessenger(&s.Suite, bob) 232 233 // Create a community 234 community, chat := s.createCommunity(bob) 235 s.Require().NotNil(community) 236 s.Require().NotNil(chat) 237 238 // Alice joins the community 239 s.advertiseCommunityTo(community, bob, alice) 240 s.joinCommunity(community, bob, alice) 241 242 // Bob mutes the community 243 time, err := bob.MuteAllCommunityChats(&requests.MuteCommunity{ 244 CommunityID: community.ID(), 245 MutedType: MuteTillUnmuted, 246 }) 247 s.Require().NoError(err) 248 s.Require().NotNil(time) 249 250 bobCommunity, err := bob.GetCommunityByID(community.ID()) 251 s.Require().NoError(err) 252 s.Require().True(bobCommunity.Muted()) 253 254 // alice sends a community message 255 inputMessage := common.NewMessage() 256 inputMessage.ChatId = chat.ID 257 inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN 258 inputMessage.Text = "Good news, @" + common.EveryoneMentionTag + " !" 259 260 response, err := alice.SendChatMessage(context.Background(), inputMessage) 261 s.Require().NoError(err) 262 s.Require().Len(response.Messages(), 1) 263 s.Require().True(response.Messages()[0].Mentioned) 264 265 response, err = WaitOnMessengerResponse( 266 bob, 267 func(r *MessengerResponse) bool { return len(r.Messages()) == 1 }, 268 "no messages", 269 ) 270 271 // Bob still receives it, but no AC notif 272 s.Require().NoError(err) 273 s.Require().Len(response.Messages(), 1) 274 s.Require().True(response.Messages()[0].Mentioned) 275 s.Require().Len(response.ActivityCenterNotifications(), 0) 276 } 277 278 func (s *MessengerActivityCenterMessageSuite) TestReadCommunityOverviewNotifications() { 279 alice := s.m 280 bob := s.newMessenger(bobPassword, []string{bobAddress}) 281 defer TearDownMessenger(&s.Suite, bob) 282 283 // Create a community 284 community, chat := s.createCommunity(bob) 285 s.Require().NotNil(community) 286 s.Require().NotNil(chat) 287 288 // Alice joins the community 289 s.advertiseCommunityTo(community, bob, alice) 290 s.joinCommunity(community, bob, alice) 291 292 // Mark community overview notification read 293 err := alice.DismissActivityCenterNotificationsByCommunity(context.Background(), &requests.DismissCommunityNotifications{CommunityID: community.ID()}) 294 s.Require().NoError(err) 295 296 response, err := alice.GetActivityCenterState() 297 s.Require().NoError(err) 298 s.Require().Equal(response.HasSeen, true) 299 } 300 301 func (s *MessengerActivityCenterMessageSuite) prepareCommunityChannelWithMentionAndReply() (*Messenger, *Messenger, *common.Message, *common.Message, *communities.Community) { 302 alice := s.m 303 bob := s.newMessenger(bobPassword, []string{bobAddress}) 304 defer TearDownMessenger(&s.Suite, bob) 305 306 // Create a community 307 community, chat := s.createCommunity(bob) 308 s.Require().NotNil(community) 309 s.Require().NotNil(chat) 310 311 // Alice joins the community 312 s.advertiseCommunityTo(community, bob, alice) 313 s.joinCommunity(community, bob, alice) 314 315 // Bob sends a mention message 316 mentionMessage := common.NewMessage() 317 mentionMessage.ChatId = chat.ID 318 mentionMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN 319 mentionMessage.Text = "Good news, @" + common.EveryoneMentionTag + " !" 320 321 response, err := bob.SendChatMessage(context.Background(), mentionMessage) 322 s.Require().NoError(err) 323 s.Require().Len(response.Messages(), 1) 324 s.Require().True(response.Messages()[0].Mentioned) 325 326 // check alice got the mention message 327 response, err = WaitOnMessengerResponse( 328 alice, 329 func(r *MessengerResponse) bool { 330 return len(r.Messages()) == 1 && len(r.ActivityCenterNotifications()) == 1 && 331 r.Messages()[0].ID == r.ActivityCenterNotifications()[0].Message.ID && 332 r.ActivityCenterNotifications()[0].Type == ActivityCenterNotificationTypeMention 333 }, 334 "no messages", 335 ) 336 s.Require().NoError(err) 337 338 s.Require().False(response.ActivityCenterNotifications()[0].Read) 339 s.Require().Equal(response.ActivityCenterNotifications()[0].ID.String(), response.ActivityCenterNotifications()[0].Message.ID) 340 mentionMessage = response.Messages()[0] 341 342 // Alice sends a community message 343 inputMessage := common.NewMessage() 344 inputMessage.ChatId = chat.ID 345 inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN 346 inputMessage.Text = "test message" 347 348 response, err = alice.SendChatMessage(context.Background(), inputMessage) 349 s.Require().NoError(err) 350 s.Require().Len(response.Messages(), 1) 351 352 // Check the community message is received by Bob 353 _, err = WaitOnMessengerResponse( 354 bob, 355 func(r *MessengerResponse) bool { return len(r.Messages()) == 1 }, 356 "no messages", 357 ) 358 s.Require().NoError(err) 359 360 // Bob sends a reply message 361 replyMessage := common.NewMessage() 362 replyMessage.ChatId = chat.ID 363 replyMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN 364 replyMessage.Text = "test message reply" 365 replyMessage.ResponseTo = response.Messages()[0].ID 366 367 response, err = bob.SendChatMessage(context.Background(), replyMessage) 368 s.Require().NoError(err) 369 s.Require().Len(response.Messages(), 2) 370 371 // Check Alice got the reply message 372 response, err = WaitOnMessengerResponse( 373 alice, 374 func(r *MessengerResponse) bool { 375 return len(r.Messages()) == 2 && len(r.ActivityCenterNotifications()) == 1 && 376 (r.Messages()[0].ID == r.ActivityCenterNotifications()[0].Message.ID || 377 r.Messages()[1].ID == r.ActivityCenterNotifications()[0].Message.ID) && 378 r.ActivityCenterNotifications()[0].Type == ActivityCenterNotificationTypeReply 379 }, 380 "no messages", 381 ) 382 s.Require().NoError(err) 383 replyNotification := response.ActivityCenterNotifications()[0] 384 s.Require().False(response.ActivityCenterNotifications()[0].Read) 385 386 // One message is the community message, the other is the reply to the community message 387 s.Require().Len(response.Messages(), 2) 388 389 replyMessage, ok := response.messages[replyNotification.Message.ID] 390 s.Require().True(ok) 391 s.Require().NotNil(replyMessage) 392 s.Require().Equal(replyMessage.ID, replyNotification.ID.String()) 393 394 s.confirmMentionAndReplyNotificationsRead(alice, mentionMessage, replyMessage, false) 395 396 return alice, bob, mentionMessage, replyMessage, community 397 } 398 399 func (s *MessengerActivityCenterMessageSuite) confirmMentionAndReplyNotificationsRead(user *Messenger, mentionMessage *common.Message, replyMessage *common.Message, read bool) { 400 // Confirm reply notification 401 notifResponse, err := user.ActivityCenterNotifications(ActivityCenterNotificationsRequest{ 402 Limit: 8, 403 ReadType: ActivityCenterQueryParamsReadAll, 404 ActivityTypes: []ActivityCenterType{ActivityCenterNotificationTypeReply}, 405 }) 406 s.Require().NoError(err) 407 s.Require().Len(notifResponse.Notifications, 1) 408 s.Require().Equal(read, notifResponse.Notifications[0].Read) 409 410 // Confirm mention notification 411 notifResponse, err = user.ActivityCenterNotifications(ActivityCenterNotificationsRequest{ 412 Limit: 8, 413 ReadType: ActivityCenterQueryParamsReadAll, 414 ActivityTypes: []ActivityCenterType{ActivityCenterNotificationTypeMention}, 415 }) 416 s.Require().NoError(err) 417 s.Require().Len(notifResponse.Notifications, 1) 418 s.Require().Equal(read, notifResponse.Notifications[0].Read) 419 s.Require().Equal(mentionMessage.ID, notifResponse.Notifications[0].ID.String()) 420 } 421 422 func (s *MessengerActivityCenterMessageSuite) TestMarkMessagesSeenMarksNotificationsRead() { 423 alice, _, mentionMessage, replyMessage, _ := s.prepareCommunityChannelWithMentionAndReply() 424 425 response, err := alice.MarkMessagesRead(replyMessage.ChatId, []string{mentionMessage.ID, replyMessage.ID}) 426 427 s.Require().NoError(err) 428 s.Require().Len(response.ActivityCenterNotifications(), 2) 429 s.Require().True(response.ActivityCenterNotifications()[0].Read) 430 s.Require().True(response.ActivityCenterNotifications()[1].Read) 431 432 s.confirmMentionAndReplyNotificationsRead(alice, mentionMessage, replyMessage, true) 433 } 434 435 func (s *MessengerActivityCenterMessageSuite) TestMarkAllReadMarksNotificationsRead() { 436 alice, _, mentionMessage, replyMessage, _ := s.prepareCommunityChannelWithMentionAndReply() 437 438 response, err := alice.MarkAllRead(context.Background(), mentionMessage.ChatId) 439 440 s.Require().NoError(err) 441 s.Require().Len(response.ActivityCenterNotifications(), 2) 442 s.Require().True(response.ActivityCenterNotifications()[0].Read) 443 s.Require().True(response.ActivityCenterNotifications()[1].Read) 444 445 s.confirmMentionAndReplyNotificationsRead(alice, mentionMessage, replyMessage, true) 446 } 447 448 func (s *MessengerActivityCenterMessageSuite) TestMarkAllReadInCommunityMarksNotificationsRead() { 449 alice, _, mentionMessage, replyMessage, community := s.prepareCommunityChannelWithMentionAndReply() 450 451 response, err := alice.MarkAllReadInCommunity(context.Background(), community.IDString()) 452 453 s.Require().NoError(err) 454 s.Require().Len(response.ActivityCenterNotifications(), 2) 455 s.Require().True(response.ActivityCenterNotifications()[0].Read) 456 s.Require().True(response.ActivityCenterNotifications()[1].Read) 457 458 s.confirmMentionAndReplyNotificationsRead(alice, mentionMessage, replyMessage, true) 459 } 460 461 func (s *MessengerActivityCenterMessageSuite) TestMarkAllActivityCenterNotificationsReadMarksMessagesAsSeen() { 462 alice, _, mentionMessage, replyMessage, _ := s.prepareCommunityChannelWithMentionAndReply() 463 464 response, err := alice.MarkAllActivityCenterNotificationsRead(context.Background()) 465 466 s.Require().NoError(err) 467 s.Require().Len(response.ActivityCenterNotifications(), 3) 468 s.Require().True(response.ActivityCenterNotifications()[0].Read) 469 s.Require().True(response.ActivityCenterNotifications()[1].Read) 470 s.Require().True(response.ActivityCenterNotifications()[2].Read) 471 472 s.confirmMentionAndReplyNotificationsRead(alice, mentionMessage, replyMessage, true) 473 } 474 475 func (s *MessengerActivityCenterMessageSuite) TestAliceDoesNotReceiveCommunityNotificationsBeforeJoined() { 476 alice := s.m 477 bob := s.newMessenger(bobPassword, []string{bobAddress}) 478 defer TearDownMessenger(&s.Suite, bob) 479 480 // Create a community 481 community, chat := s.createCommunity(bob) 482 s.Require().NotNil(community) 483 s.Require().NotNil(chat) 484 485 // Bob sends a mention message 486 mentionMessage := common.NewMessage() 487 mentionMessage.ChatId = chat.ID 488 mentionMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN 489 mentionMessage.Text = "Good news, @" + common.EveryoneMentionTag + " !" 490 491 response, err := bob.SendChatMessage(context.Background(), mentionMessage) 492 s.Require().NoError(err) 493 s.Require().Len(response.Messages(), 1) 494 s.Require().True(response.Messages()[0].Mentioned) 495 496 // Alice joins the community 497 s.advertiseCommunityTo(community, bob, alice) 498 s.joinCommunity(community, bob, alice) 499 500 // Bob sends an another mention message 501 mentionMessage = common.NewMessage() 502 mentionMessage.ChatId = chat.ID 503 mentionMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN 504 mentionMessage.Text = "Welcome new joiners, @" + common.EveryoneMentionTag + " !" 505 506 response, err = bob.SendChatMessage(context.Background(), mentionMessage) 507 s.Require().NoError(err) 508 s.Require().Len(response.Messages(), 1) 509 s.Require().True(response.Messages()[0].Mentioned) 510 511 // check alice got only second mention message 512 response, err = WaitOnMessengerResponse( 513 alice, 514 func(r *MessengerResponse) bool { 515 return len(r.Messages()) == 1 && len(r.ActivityCenterNotifications()) == 1 && 516 r.Messages()[0].ID == r.ActivityCenterNotifications()[0].Message.ID && 517 r.ActivityCenterNotifications()[0].Type == ActivityCenterNotificationTypeMention 518 }, 519 "no messages", 520 ) 521 s.Require().NoError(err) 522 523 s.Require().False(response.ActivityCenterNotifications()[0].Read) 524 s.Require().Equal(response.ActivityCenterNotifications()[0].ID.String(), response.ActivityCenterNotifications()[0].Message.ID) 525 }