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  }