github.com/status-im/status-go@v1.1.0/protocol/messenger_sync_activity_center_test.go (about) 1 package protocol 2 3 import ( 4 "context" 5 "encoding/hex" 6 "testing" 7 "time" 8 9 "github.com/status-im/status-go/eth-node/types" 10 "github.com/status-im/status-go/protocol/common" 11 "github.com/status-im/status-go/protocol/protobuf" 12 "github.com/status-im/status-go/protocol/requests" 13 14 "github.com/stretchr/testify/suite" 15 ) 16 17 const ( 18 actionAccept = "Accept" 19 actionDecline = "Decline" 20 ) 21 22 func TestMessengerSyncActivityCenter(t *testing.T) { 23 suite.Run(t, new(MessengerSyncActivityCenterSuite)) 24 } 25 26 type MessengerSyncActivityCenterSuite struct { 27 CommunitiesMessengerTestSuiteBase 28 m *Messenger 29 m2 *Messenger 30 } 31 32 func (s *MessengerSyncActivityCenterSuite) SetupTest() { 33 s.CommunitiesMessengerTestSuiteBase.SetupTest() 34 35 s.m = s.newMessenger(alicePassword, []string{aliceAccountAddress}) 36 37 _, err := s.m.Start() 38 s.Require().NoError(err) 39 40 s.m2 = s.newMessengerWithKey(s.m.identity, alicePassword, []string{aliceAccountAddress}) 41 s.Require().NoError(err) 42 43 _, err = s.m2.Start() 44 s.Require().NoError(err) 45 46 PairDevices(&s.Suite, s.m2, s.m) 47 PairDevices(&s.Suite, s.m, s.m2) 48 } 49 50 func (s *MessengerSyncActivityCenterSuite) TearDownTest() { 51 TearDownMessenger(&s.Suite, s.m2) 52 TearDownMessenger(&s.Suite, s.m) 53 s.CommunitiesMessengerTestSuiteBase.TearDownTest() 54 } 55 56 func (s *MessengerSyncActivityCenterSuite) createAndSaveNotification(m *Messenger, t ActivityCenterType, read bool) types.HexBytes { 57 now := uint64(time.Now().Unix()) 58 id := types.HexBytes{0x01} 59 notification := &ActivityCenterNotification{ 60 ID: id, 61 Timestamp: now, 62 Type: t, 63 Read: read, 64 Dismissed: false, 65 Accepted: false, 66 MembershipStatus: ActivityCenterMembershipStatusIdle, 67 Deleted: false, 68 UpdatedAt: now, 69 } 70 71 num, err := m.persistence.SaveActivityCenterNotification(notification, true) 72 s.Require().NoError(err) 73 s.Require().Equal(1, int(num)) 74 return id 75 } 76 77 func (s *MessengerSyncActivityCenterSuite) TestSyncUnread() { 78 s.syncTest(ActivityCenterNotificationTypeMention, true, (*Messenger).MarkActivityCenterNotificationsUnread, func(n *ActivityCenterNotification) bool { return !n.Read }) 79 } 80 81 func (s *MessengerSyncActivityCenterSuite) TestSyncDeleted() { 82 s.syncTest(ActivityCenterNotificationTypeMention, true, (*Messenger).MarkActivityCenterNotificationsDeleted, func(n *ActivityCenterNotification) bool { return n.Deleted }) 83 } 84 85 func (s *MessengerSyncActivityCenterSuite) TestSyncRead() { 86 s.syncTest(ActivityCenterNotificationTypeMention, false, (*Messenger).MarkActivityCenterNotificationsRead, func(n *ActivityCenterNotification) bool { return n.Read }) 87 } 88 89 func (s *MessengerSyncActivityCenterSuite) TestSyncAccepted() { 90 s.syncTest(ActivityCenterNotificationTypeContactRequest, false, (*Messenger).AcceptActivityCenterNotifications, func(n *ActivityCenterNotification) bool { return n.Accepted }) 91 } 92 93 func (s *MessengerSyncActivityCenterSuite) TestSyncDismissed() { 94 s.syncTest(ActivityCenterNotificationTypeContactRequest, false, (*Messenger).DismissActivityCenterNotifications, func(n *ActivityCenterNotification) bool { return n.Dismissed }) 95 } 96 97 func (s *MessengerSyncActivityCenterSuite) syncTest(notiType ActivityCenterType, initial bool, action func(*Messenger, context.Context, []types.HexBytes, uint64, bool) (*MessengerResponse, error), validator func(*ActivityCenterNotification) bool) { 98 99 id := s.createAndSaveNotification(s.m, notiType, initial) 100 s.createAndSaveNotification(s.m2, notiType, initial) 101 102 now := uint64(time.Now().Unix()) 103 _, err := action(s.m, context.Background(), []types.HexBytes{id}, now+1, true) 104 s.Require().NoError(err) 105 106 _, err = WaitOnMessengerResponse(s.m2, func(r *MessengerResponse) bool { 107 return r.ActivityCenterState() != nil 108 }, "activity center notification state not received") 109 s.Require().NoError(err) 110 111 notificationByID, err := s.m2.persistence.GetActivityCenterNotificationByID(id) 112 s.Require().NoError(err) 113 s.Require().True(validator(notificationByID)) 114 } 115 116 func (s *MessengerSyncActivityCenterSuite) TestSyncCommunityRequestDecisionAccept() { 117 s.testSyncCommunityRequestDecision(actionAccept) 118 } 119 120 func (s *MessengerSyncActivityCenterSuite) TestSyncCommunityRequestDecisionDecline() { 121 s.testSyncCommunityRequestDecision(actionDecline) 122 } 123 124 func (s *MessengerSyncActivityCenterSuite) testSyncCommunityRequestDecision(action string) { 125 126 userB := s.newMessenger(accountPassword, []string{commonAccountAddress}) 127 defer func() { 128 s.Require().NoError(userB.Shutdown()) 129 }() 130 131 _, err := userB.Start() 132 s.Require().NoError(err) 133 134 communityID := s.createClosedCommunity() 135 136 s.addContactAndShareCommunity(userB, communityID) 137 138 request := createRequestToJoinCommunity(&s.Suite, communityID, userB, accountPassword, []string{commonAccountAddress}) 139 _, err = userB.RequestToJoinCommunity(request) 140 s.Require().NoError(err) 141 142 requestToJoinID := s.waitForRequestToJoin(s.m) 143 144 s.waitForRequestToJoinOnDevice2() 145 146 switch action { 147 case actionAccept: 148 _, err := s.m.AcceptRequestToJoinCommunity(&requests.AcceptRequestToJoinCommunity{ID: requestToJoinID}) 149 s.Require().NoError(err) 150 case actionDecline: 151 _, err := s.m.DeclineRequestToJoinCommunity(&requests.DeclineRequestToJoinCommunity{ID: requestToJoinID}) 152 s.Require().NoError(err) 153 default: 154 s.T().Fatal("Unknown action") 155 } 156 157 s.waitForDecisionOnDevice2(requestToJoinID, action) 158 } 159 160 func (s *MessengerSyncActivityCenterSuite) createClosedCommunity() types.HexBytes { 161 response, err := s.m.CreateClosedCommunity() 162 s.Require().NoError(err) 163 s.Require().Len(response.Communities(), 1) 164 165 response, err = WaitOnMessengerResponse(s.m2, func(r *MessengerResponse) bool { 166 return len(r.Communities()) > 0 167 }, "community not received on device 2") 168 s.Require().NoError(err) 169 return response.Communities()[0].ID() 170 } 171 172 func (s *MessengerSyncActivityCenterSuite) addContactAndShareCommunity(userB *Messenger, communityID types.HexBytes) { 173 request := &requests.AddContact{ID: common.PubkeyToHex(&s.m2.identity.PublicKey)} 174 response, err := userB.AddContact(context.Background(), request) 175 s.Require().NoError(err) 176 s.Require().Len(response.Messages(), 2) 177 existContactRequestMessage := false 178 for _, m := range response.Messages() { 179 if m.ContentType == protobuf.ChatMessage_CONTACT_REQUEST { 180 existContactRequestMessage = true 181 } 182 } 183 s.Require().True(existContactRequestMessage) 184 var contactRequestMessageID types.HexBytes 185 _, err = WaitOnMessengerResponse(s.m, func(r *MessengerResponse) bool { 186 if len(r.ActivityCenterNotifications()) > 0 { 187 for _, n := range r.ActivityCenterNotifications() { 188 if n.Type == ActivityCenterNotificationTypeContactRequest { 189 contactRequestMessageID = n.ID 190 return true 191 } 192 } 193 } 194 return false 195 }, "contact request not received on device 1") 196 s.Require().NoError(err) 197 198 _, err = WaitOnMessengerResponse(s.m2, func(r *MessengerResponse) bool { 199 if len(r.ActivityCenterNotifications()) > 0 { 200 for _, n := range r.ActivityCenterNotifications() { 201 if n.Type == ActivityCenterNotificationTypeContactRequest { 202 return true 203 } 204 } 205 } 206 return false 207 }, "contact request not received on device 2") 208 s.Require().NoError(err) 209 _, err = s.m.AcceptContactRequest(context.Background(), &requests.AcceptContactRequest{ID: contactRequestMessageID}) 210 s.Require().NoError(err) 211 _, err = WaitOnMessengerResponse(s.m2, func(r *MessengerResponse) bool { 212 if len(r.ActivityCenterNotifications()) > 0 { 213 for _, n := range r.ActivityCenterNotifications() { 214 if n.Type == ActivityCenterNotificationTypeContactRequest && n.Accepted { 215 return true 216 } 217 } 218 } 219 return false 220 }, "contact request not accepted on device 2") 221 s.Require().NoError(err) 222 community, err := s.m.GetCommunityByID(communityID) 223 s.Require().NoError(err) 224 advertiseCommunityToUserOldWay(&s.Suite, community, s.m, userB) 225 } 226 227 func (s *MessengerSyncActivityCenterSuite) waitForRequestToJoin(messenger *Messenger) types.HexBytes { 228 var requestToJoinID types.HexBytes 229 _, err := WaitOnMessengerResponse(messenger, func(r *MessengerResponse) bool { 230 for _, n := range r.ActivityCenterNotifications() { 231 if n.Type == ActivityCenterNotificationTypeCommunityMembershipRequest { 232 requestToJoinID = n.ID 233 return true 234 } 235 } 236 return false 237 }, "community request to join not received") 238 s.Require().NoError(err) 239 return requestToJoinID 240 } 241 242 func (s *MessengerSyncActivityCenterSuite) waitForRequestToJoinOnDevice2() { 243 _, err := WaitOnMessengerResponse(s.m2, func(r *MessengerResponse) bool { 244 for _, n := range r.ActivityCenterNotifications() { 245 if n.Type == ActivityCenterNotificationTypeCommunityMembershipRequest { 246 return true 247 } 248 } 249 return false 250 }, "community request to join not received on device 2") 251 s.Require().NoError(err) 252 } 253 254 func (s *MessengerSyncActivityCenterSuite) waitForDecisionOnDevice2(requestToJoinID types.HexBytes, action string) { 255 requestToJoinIDString := hex.Dump(requestToJoinID) 256 conditionFunc := func(r *MessengerResponse) bool { 257 for _, n := range r.ActivityCenterNotifications() { 258 if n.Type == ActivityCenterNotificationTypeCommunityMembershipRequest && hex.Dump(n.ID) == requestToJoinIDString { 259 if action == actionAccept && n.Accepted { 260 return true 261 } else if action == actionDecline && n.Dismissed { 262 return true 263 } 264 } 265 } 266 return false 267 } 268 _, err := WaitOnMessengerResponse(s.m2, conditionFunc, "community request decision not received on device 2") 269 s.Require().NoError(err) 270 }