github.com/status-im/status-go@v1.1.0/protocol/messenger_remove_message_test.go (about) 1 package protocol 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/stretchr/testify/suite" 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/server" 12 ) 13 14 func TestMessengerRemoveMessageSuite(t *testing.T) { 15 suite.Run(t, new(MessengerRemoveMessageSuite)) 16 } 17 18 type MessengerRemoveMessageSuite struct { 19 MessengerBaseTestSuite 20 } 21 22 func (s *MessengerRemoveMessageSuite) TestDeleteMessage() { 23 theirMessenger := s.newMessenger() 24 defer TearDownMessenger(&s.Suite, theirMessenger) 25 26 theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport) 27 err := theirMessenger.SaveChat(theirChat) 28 s.Require().NoError(err) 29 30 ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport) 31 err = s.m.SaveChat(ourChat) 32 s.Require().NoError(err) 33 34 inputMessage := buildTestMessage(*theirChat) 35 sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage) 36 s.NoError(err) 37 s.Require().Len(sendResponse.Messages(), 1) 38 39 messageID := sendResponse.Messages()[0].ID 40 41 response, err := WaitOnMessengerResponse( 42 s.m, 43 func(r *MessengerResponse) bool { return len(r.messages) > 0 }, 44 "no messages", 45 ) 46 s.Require().NoError(err) 47 s.Require().Len(response.Chats(), 1) 48 s.Require().Len(response.Messages(), 1) 49 50 ogMessage := sendResponse.Messages()[0] 51 52 sendResponse, err = theirMessenger.DeleteMessageAndSend(context.Background(), ogMessage.ID) 53 54 s.Require().NoError(err) 55 s.Require().Len(sendResponse.Messages(), 0) 56 s.Require().Len(sendResponse.RemovedMessages(), 1) 57 s.Require().Equal(messageID, sendResponse.RemovedMessages()[0].MessageID) 58 s.Require().Equal(sendResponse.RemovedMessages()[0].DeletedBy, "") 59 s.Require().Len(sendResponse.Chats(), 1) 60 // LastMessage is marked as deleted 61 lastRemovedMessage := sendResponse.Chats()[0].LastMessage 62 s.Require().Equal(lastRemovedMessage.ID, messageID) 63 s.Require().Equal(lastRemovedMessage.Deleted, true) 64 65 // Main instance user attempts to delete the message it received from theirMessenger 66 _, err = s.m.DeleteMessageAndSend(context.Background(), ogMessage.ID) 67 68 s.Require().ErrorContains(err, "can't find chat") 69 } 70 71 func (s *MessengerRemoveMessageSuite) TestDeleteMessagePreviousLastMessage() { 72 theirMessenger := s.newMessenger() 73 defer TearDownMessenger(&s.Suite, theirMessenger) 74 75 theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport) 76 err := theirMessenger.SaveChat(theirChat) 77 s.Require().NoError(err) 78 79 ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport) 80 err = s.m.SaveChat(ourChat) 81 s.Require().NoError(err) 82 83 inputMessage1 := buildTestMessage(*theirChat) 84 sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage1) 85 s.NoError(err) 86 s.Require().Len(sendResponse.Messages(), 1) 87 88 inputMessage2 := buildTestMessage(*theirChat) 89 sendResponse, err = theirMessenger.SendChatMessage(context.Background(), inputMessage2) 90 s.NoError(err) 91 s.Require().Len(sendResponse.Messages(), 1) 92 93 messageID := sendResponse.Messages()[0].ID 94 95 response, err := WaitOnMessengerResponse( 96 s.m, 97 func(r *MessengerResponse) bool { return len(r.messages) > 0 }, 98 "no messages", 99 ) 100 s.Require().NoError(err) 101 s.Require().Len(response.Chats(), 1) 102 s.Require().Len(response.Messages(), 2) 103 104 ogMessage := sendResponse.Messages()[0] 105 106 sendResponse, err = theirMessenger.DeleteMessageAndSend(context.Background(), ogMessage.ID) 107 108 s.Require().NoError(err) 109 s.Require().Len(sendResponse.Messages(), 0) 110 s.Require().Len(sendResponse.RemovedMessages(), 1) 111 s.Require().Equal(messageID, sendResponse.RemovedMessages()[0].MessageID) 112 s.Require().Len(sendResponse.Chats(), 1) 113 // LastMessage is updated and marked as deleted 114 s.Require().NotNil(sendResponse.Chats()[0].LastMessage) 115 s.Require().Equal(inputMessage2.ID, sendResponse.Chats()[0].LastMessage.ID) 116 s.Require().Equal(sendResponse.Chats()[0].LastMessage.Deleted, true) 117 118 } 119 120 func (s *MessengerRemoveMessageSuite) TestDeleteWrongMessageType() { 121 theirMessenger := s.newMessenger() 122 defer TearDownMessenger(&s.Suite, theirMessenger) 123 124 theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport) 125 err := theirMessenger.SaveChat(theirChat) 126 s.Require().NoError(err) 127 128 ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport) 129 err = s.m.SaveChat(ourChat) 130 s.Require().NoError(err) 131 132 inputMessage := buildTestGapMessage(*theirChat) 133 sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage) 134 s.NoError(err) 135 s.Require().Len(sendResponse.Messages(), 1) 136 137 ogMessage := sendResponse.Messages()[0] 138 139 // Delete should not work 140 _, err = theirMessenger.DeleteMessageAndSend(context.Background(), ogMessage.ID) 141 142 s.Require().Equal(ErrInvalidDeleteTypeAuthor, err) 143 } 144 145 // TODO fix activity center notifications not being deleted when a message is deleted 146 147 func (s *MessengerRemoveMessageSuite) TestDeleteMessageFirstThenMessage() { 148 theirMessenger := s.newMessenger() 149 defer TearDownMessenger(&s.Suite, theirMessenger) 150 151 theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport) 152 err := theirMessenger.SaveChat(theirChat) 153 s.Require().NoError(err) 154 155 contact, err := BuildContactFromPublicKey(&theirMessenger.identity.PublicKey) 156 s.Require().NoError(err) 157 158 ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport) 159 err = s.m.SaveChat(ourChat) 160 s.Require().NoError(err) 161 messageID := "message-id" 162 163 inputMessage := buildTestMessage(*theirChat) 164 inputMessage.Clock = 1 165 deleteMessage := &DeleteMessage{ 166 DeleteMessage: &protobuf.DeleteMessage{ 167 Clock: 2, 168 MessageType: protobuf.MessageType_ONE_TO_ONE, 169 MessageId: messageID, 170 ChatId: theirChat.ID, 171 }, 172 From: common.PubkeyToHex(&theirMessenger.identity.PublicKey), 173 } 174 175 state := &ReceivedMessageState{ 176 Response: &MessengerResponse{}, 177 } 178 179 // Handle Delete first 180 err = s.m.handleDeleteMessage(state, deleteMessage) 181 s.Require().NoError(err) 182 183 // // Handle chat message 184 state = &ReceivedMessageState{ 185 Response: &MessengerResponse{}, 186 CurrentMessageState: &CurrentMessageState{ 187 MessageID: messageID, 188 WhisperTimestamp: s.m.getTimesource().GetCurrentTime(), 189 Contact: contact, 190 PublicKey: &theirMessenger.identity.PublicKey, 191 }, 192 } 193 err = s.m.HandleChatMessage(state, inputMessage.ChatMessage, nil, false) 194 s.Require().NoError(err) 195 s.Require().Len(state.Response.Messages(), 0) // Message should not be added to response 196 s.Require().Len(state.Response.RemovedMessages(), 0) 197 s.Require().Nil(state.Response.Chats()[0].LastMessage) 198 } 199 200 func (s *MessengerRemoveMessageSuite) TestDeleteImageMessage() { 201 theirMessenger := s.newMessenger() 202 defer TearDownMessenger(&s.Suite, theirMessenger) 203 204 theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport) 205 err := theirMessenger.SaveChat(theirChat) 206 s.Require().NoError(err) 207 208 ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport) 209 err = s.m.SaveChat(ourChat) 210 s.Require().NoError(err) 211 212 messageCount := 3 213 var album []*common.Message 214 for i := 0; i < messageCount; i++ { 215 image, err := buildImageWithoutAlbumIDMessage(*ourChat) 216 s.NoError(err) 217 album = append(album, image) 218 } 219 220 response, err := s.m.SendChatMessages(context.Background(), album) 221 s.NoError(err) 222 223 // Check that album count was the number of the images sent 224 imagesCount := uint32(0) 225 for _, message := range response.Messages() { 226 if message.ContentType == protobuf.ChatMessage_IMAGE { 227 imagesCount++ 228 } 229 } 230 for _, message := range response.Messages() { 231 s.Require().NotNil(message.GetImage()) 232 s.Require().Equal(message.GetImage().AlbumImagesCount, imagesCount) 233 } 234 235 s.Require().Equal(messageCount, len(response.Messages()), "it returns the messages") 236 s.Require().NoError(err) 237 s.Require().Len(response.Messages(), messageCount) 238 239 response, err = WaitOnMessengerResponse( 240 theirMessenger, 241 func(r *MessengerResponse) bool { return len(r.messages) == messageCount }, 242 "no messages", 243 ) 244 245 s.Require().NoError(err) 246 s.Require().Len(response.Chats(), 1) 247 s.Require().Len(response.Messages(), messageCount) 248 for _, message := range response.Messages() { 249 image := message.GetImage() 250 s.Require().NotNil(image, "Message.ID=%s", message.ID) 251 s.Require().Equal(image.AlbumImagesCount, imagesCount) 252 s.Require().NotEmpty(image.AlbumId, "Message.ID=%s", message.ID) 253 } 254 255 firstMessageID := response.Messages()[0].ID 256 sendResponse, err := s.m.DeleteMessageAndSend(context.Background(), firstMessageID) 257 258 s.Require().NoError(err) 259 s.Require().Len(sendResponse.Messages(), 0) 260 s.Require().Len(sendResponse.RemovedMessages(), 3) 261 s.Require().Equal(sendResponse.RemovedMessages()[0].DeletedBy, "") 262 s.Require().Len(sendResponse.Chats(), 1) 263 264 // LastMessage marked as deleted 265 s.Require().Equal(sendResponse.Chats()[0].LastMessage.ID, album[2].ID) 266 s.Require().Equal(sendResponse.Chats()[0].LastMessage.Deleted, true) 267 268 // Main instance user attempts to delete the message it received from theirMessenger 269 _, err = theirMessenger.DeleteMessageAndSend(context.Background(), firstMessageID) 270 271 s.Require().ErrorContains(err, "can't find chat") 272 } 273 274 func (s *MessengerRemoveMessageSuite) TestDeleteImageMessageFirstThenMessage() { 275 theirMessenger := s.newMessenger() 276 defer TearDownMessenger(&s.Suite, theirMessenger) 277 278 theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport) 279 err := theirMessenger.SaveChat(theirChat) 280 s.Require().NoError(err) 281 282 contact, err := BuildContactFromPublicKey(&theirMessenger.identity.PublicKey) 283 s.Require().NoError(err) 284 285 ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport) 286 err = s.m.SaveChat(ourChat) 287 s.Require().NoError(err) 288 messageID1 := "message-id1" 289 messageID2 := "message-id2" 290 albumID := "album-id1" 291 292 messageCount := 2 293 var album []*common.Message 294 for i := 0; i < messageCount; i++ { 295 image, err := buildImageWithAlbumIDMessage(*ourChat, albumID) 296 image.Clock = 1 297 s.NoError(err) 298 album = append(album, image) 299 } 300 301 deleteMessage := &DeleteMessage{ 302 DeleteMessage: &protobuf.DeleteMessage{ 303 Clock: 2, 304 MessageType: protobuf.MessageType_ONE_TO_ONE, 305 MessageId: messageID1, 306 ChatId: theirChat.ID, 307 }, 308 From: common.PubkeyToHex(&theirMessenger.identity.PublicKey), 309 } 310 311 state := &ReceivedMessageState{ 312 Response: &MessengerResponse{}, 313 } 314 315 // Handle Delete first 316 err = s.m.handleDeleteMessage(state, deleteMessage) 317 s.Require().NoError(err) 318 319 // Handle first image message 320 state = &ReceivedMessageState{ 321 Response: &MessengerResponse{}, 322 CurrentMessageState: &CurrentMessageState{ 323 MessageID: messageID1, 324 WhisperTimestamp: s.m.getTimesource().GetCurrentTime(), 325 Contact: contact, 326 PublicKey: &theirMessenger.identity.PublicKey, 327 }, 328 } 329 err = s.m.HandleChatMessage(state, album[0].ChatMessage, nil, false) 330 s.Require().NoError(err) 331 s.Require().Len(state.Response.Messages(), 0) // Message should not be added to response 332 s.Require().Len(state.Response.RemovedMessages(), 0) 333 s.Require().Nil(state.Response.Chats()[0].LastMessage) 334 335 // Handle second image message 336 state = &ReceivedMessageState{ 337 Response: &MessengerResponse{}, 338 CurrentMessageState: &CurrentMessageState{ 339 MessageID: messageID2, 340 WhisperTimestamp: s.m.getTimesource().GetCurrentTime(), 341 Contact: contact, 342 PublicKey: &theirMessenger.identity.PublicKey, 343 }, 344 } 345 err = s.m.HandleChatMessage(state, album[1].ChatMessage, nil, false) 346 s.Require().NoError(err) 347 s.Require().Len(state.Response.Messages(), 0) // Message should not be added to response even if we didn't delete that ID 348 s.Require().Len(state.Response.RemovedMessages(), 0) 349 s.Require().Nil(state.Response.Chats()[0].LastMessage) 350 } 351 352 func (s *MessengerRemoveMessageSuite) TestDeleteMessageWithAMention() { 353 theirMessenger := s.newMessenger() 354 defer TearDownMessenger(&s.Suite, theirMessenger) 355 356 theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport) 357 err := theirMessenger.SaveChat(theirChat) 358 s.Require().NoError(err) 359 360 ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport) 361 err = s.m.SaveChat(ourChat) 362 s.Require().NoError(err) 363 364 inputMessage := buildTestMessage(*theirChat) 365 inputMessage.Text = "text with a mention @" + common.PubkeyToHex(&s.privateKey.PublicKey) 366 sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage) 367 s.NoError(err) 368 s.Require().Len(sendResponse.Messages(), 1) 369 370 messageID := sendResponse.Messages()[0].ID 371 372 response, err := WaitOnMessengerResponse( 373 s.m, 374 func(r *MessengerResponse) bool { return len(r.messages) == 1 }, 375 "no messages", 376 ) 377 s.Require().NoError(err) 378 s.Require().Len(response.Chats(), 1) 379 s.Require().Len(response.Messages(), 1) 380 // Receiver (us) is mentioned 381 s.Require().Equal(int(response.Chats()[0].UnviewedMessagesCount), 1) 382 s.Require().Equal(int(response.Chats()[0].UnviewedMentionsCount), 1) 383 s.Require().True(response.Messages()[0].Mentioned) 384 385 deleteMessage := &DeleteMessage{ 386 DeleteMessage: &protobuf.DeleteMessage{ 387 Clock: 2, 388 MessageType: protobuf.MessageType_ONE_TO_ONE, 389 MessageId: messageID, 390 ChatId: theirChat.ID, 391 }, 392 From: common.PubkeyToHex(&theirMessenger.identity.PublicKey), 393 } 394 395 state := &ReceivedMessageState{ 396 Response: &MessengerResponse{}, 397 } 398 399 // Handle Delete first 400 err = s.m.handleDeleteMessage(state, deleteMessage) 401 402 s.Require().NoError(err) 403 s.Require().Len(response.Chats(), 1) 404 s.Require().Len(response.Messages(), 1) 405 // Receiver (us) is no longer mentioned 406 s.Require().Equal(int(state.Response.Chats()[0].UnviewedMessagesCount), 0) 407 s.Require().Equal(int(state.Response.Chats()[0].UnviewedMentionsCount), 0) 408 } 409 410 // This test makes sure the UnviewMessageCount doesn't go below 0 in a very rare case where the Chat could be marked 411 // as read but the message still unseen (Seen == false) 412 func (s *MessengerRemoveMessageSuite) TestDeleteMessageAndChatIsAlreadyRead() { 413 theirMessenger := s.newMessenger() 414 defer TearDownMessenger(&s.Suite, theirMessenger) 415 416 theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport) 417 err := theirMessenger.SaveChat(theirChat) 418 s.Require().NoError(err) 419 420 ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport) 421 err = s.m.SaveChat(ourChat) 422 s.Require().NoError(err) 423 424 inputMessage := buildTestMessage(*theirChat) 425 sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage) 426 s.NoError(err) 427 s.Require().Len(sendResponse.Messages(), 1) 428 429 response, err := WaitOnMessengerResponse( 430 s.m, 431 func(r *MessengerResponse) bool { return len(r.messages) == 1 }, 432 "no messages", 433 ) 434 s.Require().NoError(err) 435 s.Require().Len(response.Chats(), 1) 436 s.Require().Equal(response.Chats()[0].UnviewedMessagesCount, uint(1)) 437 s.Require().Len(response.Messages(), 1) 438 439 // Force UnviewedMessagesCount to 0 to test if the uint validation is done correctly 440 ourChat.UnviewedMessagesCount = 0 441 err = s.m.saveChat(ourChat) 442 443 s.Require().NoError(err) 444 445 ogMessage := sendResponse.Messages()[0] 446 447 deleteMessage := &DeleteMessage{ 448 DeleteMessage: &protobuf.DeleteMessage{ 449 Clock: 2, 450 MessageType: protobuf.MessageType_ONE_TO_ONE, 451 MessageId: ogMessage.ID, 452 ChatId: theirChat.ID, 453 }, 454 From: common.PubkeyToHex(&theirMessenger.identity.PublicKey), 455 } 456 457 state := &ReceivedMessageState{ 458 Response: &MessengerResponse{}, 459 } 460 461 // Handle Delete first 462 err = s.m.handleDeleteMessage(state, deleteMessage) 463 464 s.Require().NoError(err) 465 s.Require().Len(response.Chats(), 1) 466 s.Require().Len(response.Messages(), 1) 467 // Receiver (us) no longer has unread messages and it's not negative 468 s.Require().Equal(0, int(state.Response.Chats()[0].UnviewedMessagesCount)) 469 } 470 471 func (s *MessengerRemoveMessageSuite) TestDeleteMessageReplyToImage() { 472 theirMessenger := s.newMessenger() 473 defer TearDownMessenger(&s.Suite, theirMessenger) 474 475 theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport) 476 err := theirMessenger.SaveChat(theirChat) 477 s.Require().NoError(err) 478 479 ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport) 480 err = s.m.SaveChat(ourChat) 481 s.Require().NoError(err) 482 483 inputMessage := buildTestMessage(*theirChat) 484 sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage) 485 s.NoError(err) 486 s.Require().Len(sendResponse.Messages(), 1) 487 488 response, err := WaitOnMessengerResponse( 489 s.m, 490 func(r *MessengerResponse) bool { return len(r.messages) == 1 }, 491 "no messages", 492 ) 493 s.Require().NoError(err) 494 s.Require().Len(response.Chats(), 1) 495 s.Require().Len(response.Messages(), 1) 496 497 ogMessage := sendResponse.Messages()[0] 498 499 // create an http server 500 mediaServer, err := server.NewMediaServer(nil, nil, nil, nil) 501 s.Require().NoError(err) 502 s.Require().NotNil(mediaServer) 503 s.Require().NoError(mediaServer.Start()) 504 505 theirMessenger.SetMediaServer(mediaServer) 506 507 // We reply to our own message with an image 508 imageMessage, err := buildImageWithoutAlbumIDMessage(*theirChat) 509 s.NoError(err) 510 511 imageMessage.ResponseTo = ogMessage.ID 512 513 _, err = theirMessenger.SendChatMessages(context.Background(), []*common.Message{imageMessage}) 514 s.NoError(err) 515 516 // We check that the URL is correctly returned 517 sendResponse, err = theirMessenger.DeleteMessageAndSend(context.Background(), ogMessage.ID) 518 519 s.Require().NoError(err) 520 s.Require().Len(sendResponse.Messages(), 1) 521 s.Require().NotEmpty(sendResponse.Messages()[0].ImageLocalURL) 522 } 523 524 func (s *MessengerRemoveMessageSuite) TestDeleteMessageForMeReplyToImage() { 525 theirMessenger := s.newMessenger() 526 defer TearDownMessenger(&s.Suite, theirMessenger) 527 528 theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport) 529 err := theirMessenger.SaveChat(theirChat) 530 s.Require().NoError(err) 531 532 ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport) 533 err = s.m.SaveChat(ourChat) 534 s.Require().NoError(err) 535 536 inputMessage := buildTestMessage(*theirChat) 537 sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage) 538 s.NoError(err) 539 s.Require().Len(sendResponse.Messages(), 1) 540 541 response, err := WaitOnMessengerResponse( 542 s.m, 543 func(r *MessengerResponse) bool { return len(r.messages) == 1 }, 544 "no messages", 545 ) 546 s.Require().NoError(err) 547 s.Require().Len(response.Chats(), 1) 548 s.Require().Len(response.Messages(), 1) 549 550 ogMessage := sendResponse.Messages()[0] 551 552 // create an http server 553 mediaServer, err := server.NewMediaServer(nil, nil, nil, nil) 554 s.Require().NoError(err) 555 s.Require().NotNil(mediaServer) 556 s.Require().NoError(mediaServer.Start()) 557 558 theirMessenger.SetMediaServer(mediaServer) 559 560 // We reply to our own message with an image 561 imageMessage, err := buildImageWithoutAlbumIDMessage(*theirChat) 562 s.NoError(err) 563 564 imageMessage.ResponseTo = ogMessage.ID 565 566 _, err = theirMessenger.SendChatMessages(context.Background(), []*common.Message{imageMessage}) 567 s.NoError(err) 568 569 // We check that the URL is correctly returned 570 sendResponse, err = theirMessenger.DeleteMessageForMeAndSync(context.Background(), theirChat.ID, ogMessage.ID) 571 572 s.Require().NoError(err) 573 messages := sendResponse.Messages() 574 s.Require().Len(messages, 2) 575 576 var deletedMessage, replyMessage *common.Message 577 if messages[0].ID == ogMessage.ID { 578 deletedMessage = messages[0] 579 replyMessage = messages[1] 580 } else { 581 deletedMessage = messages[1] 582 replyMessage = messages[0] 583 } 584 585 s.Require().True(deletedMessage.DeletedForMe) 586 s.Require().NotEmpty(replyMessage.ImageLocalURL) 587 }