2023-10-22 09:41:20 +00:00
|
|
|
package protocol
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-10-26 04:17:18 +00:00
|
|
|
"encoding/hex"
|
2023-10-22 09:41:20 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2023-10-26 04:17:18 +00:00
|
|
|
"github.com/status-im/status-go/protocol/protobuf"
|
|
|
|
|
|
|
|
"github.com/status-im/status-go/eth-node/crypto"
|
|
|
|
"github.com/status-im/status-go/protocol/common"
|
|
|
|
"github.com/status-im/status-go/protocol/requests"
|
|
|
|
|
2023-10-22 09:41:20 +00:00
|
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
|
|
|
|
"github.com/status-im/status-go/eth-node/types"
|
|
|
|
)
|
|
|
|
|
2023-10-26 04:17:18 +00:00
|
|
|
const (
|
|
|
|
actionAccept = "Accept"
|
|
|
|
actionDecline = "Decline"
|
|
|
|
)
|
|
|
|
|
2023-10-22 09:41:20 +00:00
|
|
|
type MessengerSyncActivityCenterSuite struct {
|
|
|
|
MessengerBaseTestSuite
|
2023-10-26 04:17:18 +00:00
|
|
|
m2 *Messenger
|
2023-10-22 09:41:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestMessengerSyncActivityCenter(t *testing.T) {
|
|
|
|
suite.Run(t, new(MessengerSyncActivityCenterSuite))
|
|
|
|
}
|
|
|
|
|
2023-10-26 04:17:18 +00:00
|
|
|
func (s *MessengerSyncActivityCenterSuite) SetupTest() {
|
|
|
|
s.MessengerBaseTestSuite.SetupTest()
|
|
|
|
|
|
|
|
m2, err := newMessengerWithKey(s.shh, s.privateKey, s.logger, nil)
|
2023-10-22 09:41:20 +00:00
|
|
|
s.Require().NoError(err)
|
2023-10-26 04:17:18 +00:00
|
|
|
s.m2 = m2
|
|
|
|
|
|
|
|
PairDevices(&s.Suite, m2, s.m)
|
|
|
|
PairDevices(&s.Suite, s.m, m2)
|
|
|
|
}
|
2023-10-22 09:41:20 +00:00
|
|
|
|
2023-10-26 04:17:18 +00:00
|
|
|
func (s *MessengerSyncActivityCenterSuite) TearDownTest() {
|
|
|
|
s.Require().NoError(s.m2.Shutdown())
|
|
|
|
s.MessengerBaseTestSuite.TearDownTest()
|
2023-10-22 09:41:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncActivityCenterSuite) createAndSaveNotification(m *Messenger, t ActivityCenterType, read bool) types.HexBytes {
|
|
|
|
now := uint64(time.Now().Unix())
|
|
|
|
id := types.HexBytes{0x01}
|
|
|
|
notification := &ActivityCenterNotification{
|
|
|
|
ID: id,
|
|
|
|
Timestamp: now,
|
|
|
|
Type: t,
|
|
|
|
Read: read,
|
|
|
|
Dismissed: false,
|
|
|
|
Accepted: false,
|
|
|
|
MembershipStatus: ActivityCenterMembershipStatusIdle,
|
|
|
|
Deleted: false,
|
|
|
|
UpdatedAt: now,
|
|
|
|
}
|
|
|
|
|
|
|
|
num, err := m.persistence.SaveActivityCenterNotification(notification, true)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Equal(1, int(num))
|
|
|
|
return id
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncActivityCenterSuite) TestSyncUnread() {
|
|
|
|
s.syncTest(ActivityCenterNotificationTypeMention, true, (*Messenger).MarkActivityCenterNotificationsUnread, func(n *ActivityCenterNotification) bool { return !n.Read })
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncActivityCenterSuite) TestSyncDeleted() {
|
|
|
|
s.syncTest(ActivityCenterNotificationTypeMention, true, (*Messenger).MarkActivityCenterNotificationsDeleted, func(n *ActivityCenterNotification) bool { return n.Deleted })
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncActivityCenterSuite) TestSyncRead() {
|
|
|
|
s.syncTest(ActivityCenterNotificationTypeMention, false, (*Messenger).MarkActivityCenterNotificationsRead, func(n *ActivityCenterNotification) bool { return n.Read })
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncActivityCenterSuite) TestSyncAccepted() {
|
|
|
|
s.syncTest(ActivityCenterNotificationTypeContactRequest, false, (*Messenger).AcceptActivityCenterNotifications, func(n *ActivityCenterNotification) bool { return n.Accepted })
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncActivityCenterSuite) TestSyncDismissed() {
|
|
|
|
s.syncTest(ActivityCenterNotificationTypeContactRequest, false, (*Messenger).DismissActivityCenterNotifications, func(n *ActivityCenterNotification) bool { return n.Dismissed })
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncActivityCenterSuite) syncTest(notiType ActivityCenterType, initial bool, action func(*Messenger, context.Context, []types.HexBytes, uint64, bool) (*MessengerResponse, error), validator func(*ActivityCenterNotification) bool) {
|
|
|
|
|
2023-10-26 04:17:18 +00:00
|
|
|
id := s.createAndSaveNotification(s.m, notiType, initial)
|
|
|
|
s.createAndSaveNotification(s.m2, notiType, initial)
|
2023-10-22 09:41:20 +00:00
|
|
|
|
|
|
|
now := uint64(time.Now().Unix())
|
2023-10-26 04:17:18 +00:00
|
|
|
_, err := action(s.m, context.Background(), []types.HexBytes{id}, now+1, true)
|
2023-10-22 09:41:20 +00:00
|
|
|
s.Require().NoError(err)
|
|
|
|
|
2023-10-26 04:17:18 +00:00
|
|
|
_, err = WaitOnMessengerResponse(s.m2, func(r *MessengerResponse) bool {
|
2023-10-22 09:41:20 +00:00
|
|
|
return r.ActivityCenterState() != nil
|
|
|
|
}, "activity center notification state not received")
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
2023-10-26 04:17:18 +00:00
|
|
|
notificationByID, err := s.m2.persistence.GetActivityCenterNotificationByID(id)
|
2023-10-22 09:41:20 +00:00
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().True(validator(notificationByID))
|
|
|
|
}
|
2023-10-26 04:17:18 +00:00
|
|
|
|
|
|
|
func (s *MessengerSyncActivityCenterSuite) TestSyncCommunityRequestDecisionAccept() {
|
|
|
|
s.testSyncCommunityRequestDecision(actionAccept)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncActivityCenterSuite) TestSyncCommunityRequestDecisionDecline() {
|
|
|
|
s.testSyncCommunityRequestDecision(actionDecline)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncActivityCenterSuite) testSyncCommunityRequestDecision(action string) {
|
|
|
|
userB := s.createUserB()
|
|
|
|
defer func() {
|
|
|
|
s.Require().NoError(userB.Shutdown())
|
|
|
|
}()
|
|
|
|
|
|
|
|
communityID := s.createClosedCommunity()
|
|
|
|
|
|
|
|
s.addContactAndShareCommunity(userB, communityID)
|
|
|
|
|
|
|
|
s.requestToJoinCommunity(userB, communityID)
|
|
|
|
|
|
|
|
requestToJoinID := s.waitForRequestToJoin(s.m)
|
|
|
|
|
|
|
|
s.waitForRequestToJoinOnDevice2()
|
|
|
|
|
|
|
|
switch action {
|
|
|
|
case actionAccept:
|
|
|
|
_, err := s.m.AcceptRequestToJoinCommunity(&requests.AcceptRequestToJoinCommunity{ID: requestToJoinID})
|
|
|
|
s.Require().NoError(err)
|
|
|
|
case actionDecline:
|
|
|
|
_, err := s.m.DeclineRequestToJoinCommunity(&requests.DeclineRequestToJoinCommunity{ID: requestToJoinID})
|
|
|
|
s.Require().NoError(err)
|
|
|
|
default:
|
|
|
|
s.T().Fatal("Unknown action")
|
|
|
|
}
|
|
|
|
|
|
|
|
s.waitForDecisionOnDevice2(requestToJoinID, action)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncActivityCenterSuite) createUserB() *Messenger {
|
|
|
|
key, err := crypto.GenerateKey()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
userB, err := newMessengerWithKey(s.shh, key, s.logger, nil)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
return userB
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncActivityCenterSuite) createClosedCommunity() types.HexBytes {
|
|
|
|
response, err := s.m.CreateClosedCommunity()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(response.Communities(), 1)
|
|
|
|
|
|
|
|
response, err = WaitOnMessengerResponse(s.m2, func(r *MessengerResponse) bool {
|
|
|
|
return len(r.Communities()) > 0
|
|
|
|
}, "community not received on device 2")
|
|
|
|
s.Require().NoError(err)
|
|
|
|
return response.Communities()[0].ID()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncActivityCenterSuite) addContactAndShareCommunity(userB *Messenger, communityID types.HexBytes) {
|
|
|
|
request := &requests.AddContact{ID: common.PubkeyToHex(&s.m2.identity.PublicKey)}
|
|
|
|
response, err := userB.AddContact(context.Background(), request)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(response.Messages(), 2)
|
|
|
|
s.Require().Equal(protobuf.ChatMessage_CONTACT_REQUEST, response.Messages()[1].ContentType)
|
|
|
|
var contactRequestMessageID types.HexBytes
|
|
|
|
_, err = WaitOnMessengerResponse(s.m, func(r *MessengerResponse) bool {
|
|
|
|
if len(r.ActivityCenterNotifications()) > 0 {
|
|
|
|
for _, n := range r.ActivityCenterNotifications() {
|
|
|
|
if n.Type == ActivityCenterNotificationTypeContactRequest {
|
|
|
|
contactRequestMessageID = n.ID
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}, "contact request not received on device 1")
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
_, err = WaitOnMessengerResponse(s.m2, func(r *MessengerResponse) bool {
|
|
|
|
if len(r.ActivityCenterNotifications()) > 0 {
|
|
|
|
for _, n := range r.ActivityCenterNotifications() {
|
|
|
|
if n.Type == ActivityCenterNotificationTypeContactRequest {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}, "contact request not received on device 2")
|
|
|
|
s.Require().NoError(err)
|
|
|
|
_, err = s.m.AcceptContactRequest(context.Background(), &requests.AcceptContactRequest{ID: contactRequestMessageID})
|
|
|
|
s.Require().NoError(err)
|
|
|
|
_, err = WaitOnMessengerResponse(s.m2, func(r *MessengerResponse) bool {
|
|
|
|
if len(r.ActivityCenterNotifications()) > 0 {
|
|
|
|
for _, n := range r.ActivityCenterNotifications() {
|
|
|
|
if n.Type == ActivityCenterNotificationTypeContactRequest && n.Accepted {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}, "contact request not accepted on device 2")
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
_, err = s.m.ShareCommunity(&requests.ShareCommunity{
|
|
|
|
CommunityID: communityID,
|
|
|
|
Users: []types.HexBytes{common.PubkeyToHexBytes(&userB.identity.PublicKey)},
|
|
|
|
InviteMessage: "invite to community testing message",
|
|
|
|
})
|
|
|
|
s.Require().NoError(err)
|
|
|
|
_, err = WaitOnMessengerResponse(userB, func(r *MessengerResponse) bool {
|
|
|
|
return len(r.Communities()) > 0
|
|
|
|
}, "community not received")
|
|
|
|
s.Require().NoError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncActivityCenterSuite) requestToJoinCommunity(userB *Messenger, communityID types.HexBytes) {
|
|
|
|
_, err := userB.RequestToJoinCommunity(&requests.RequestToJoinCommunity{CommunityID: communityID})
|
|
|
|
s.Require().NoError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncActivityCenterSuite) waitForRequestToJoin(messenger *Messenger) types.HexBytes {
|
|
|
|
var requestToJoinID types.HexBytes
|
|
|
|
_, err := WaitOnMessengerResponse(messenger, func(r *MessengerResponse) bool {
|
|
|
|
for _, n := range r.ActivityCenterNotifications() {
|
|
|
|
if n.Type == ActivityCenterNotificationTypeCommunityMembershipRequest {
|
|
|
|
requestToJoinID = n.ID
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}, "community request to join not received")
|
|
|
|
s.Require().NoError(err)
|
|
|
|
return requestToJoinID
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncActivityCenterSuite) waitForRequestToJoinOnDevice2() {
|
|
|
|
_, err := WaitOnMessengerResponse(s.m2, func(r *MessengerResponse) bool {
|
|
|
|
for _, n := range r.ActivityCenterNotifications() {
|
|
|
|
if n.Type == ActivityCenterNotificationTypeCommunityMembershipRequest {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}, "community request to join not received on device 2")
|
|
|
|
s.Require().NoError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncActivityCenterSuite) waitForDecisionOnDevice2(requestToJoinID types.HexBytes, action string) {
|
|
|
|
requestToJoinIDString := hex.Dump(requestToJoinID)
|
|
|
|
conditionFunc := func(r *MessengerResponse) bool {
|
|
|
|
for _, n := range r.ActivityCenterNotifications() {
|
|
|
|
if n.Type == ActivityCenterNotificationTypeCommunityMembershipRequest && hex.Dump(n.ID) == requestToJoinIDString {
|
|
|
|
if action == actionAccept && n.Accepted {
|
|
|
|
return true
|
|
|
|
} else if action == actionDecline && n.Dismissed {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
_, err := WaitOnMessengerResponse(s.m2, conditionFunc, "community request decision not received on device 2")
|
|
|
|
s.Require().NoError(err)
|
|
|
|
}
|