2023-02-24 23:47:04 +00:00
|
|
|
package protocol
|
|
|
|
|
|
|
|
import (
|
2023-07-19 12:14:42 +00:00
|
|
|
"context"
|
2023-02-24 23:47:04 +00:00
|
|
|
"strconv"
|
|
|
|
"testing"
|
2023-06-10 02:00:17 +00:00
|
|
|
"time"
|
2023-02-24 23:47:04 +00:00
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
|
|
|
"github.com/status-im/status-go/eth-node/types"
|
|
|
|
"github.com/status-im/status-go/protocol/common"
|
2023-07-19 12:14:42 +00:00
|
|
|
"github.com/status-im/status-go/protocol/protobuf"
|
|
|
|
"github.com/status-im/status-go/protocol/requests"
|
2023-02-24 23:47:04 +00:00
|
|
|
)
|
|
|
|
|
2023-06-10 02:00:17 +00:00
|
|
|
func currentMilliseconds() uint64 {
|
|
|
|
c := time.Now().UnixMilli()
|
|
|
|
return uint64(c)
|
|
|
|
}
|
|
|
|
|
2023-02-24 23:47:04 +00:00
|
|
|
func createNotifications(t *testing.T, p *sqlitePersistence, notifications []*ActivityCenterNotification) []*ActivityCenterNotification {
|
2023-06-10 02:00:17 +00:00
|
|
|
now := currentMilliseconds()
|
2023-02-24 23:47:04 +00:00
|
|
|
for index, notif := range notifications {
|
|
|
|
if notif.Timestamp == 0 {
|
2023-06-10 02:00:17 +00:00
|
|
|
notif.Timestamp = now
|
2023-02-24 23:47:04 +00:00
|
|
|
}
|
|
|
|
if len(notif.ID) == 0 {
|
|
|
|
notif.ID = types.HexBytes(strconv.Itoa(index))
|
|
|
|
}
|
2023-06-10 02:00:17 +00:00
|
|
|
if notif.UpdatedAt == 0 {
|
|
|
|
notif.UpdatedAt = now
|
|
|
|
}
|
|
|
|
_, err := p.SaveActivityCenterNotification(notif, true)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err, notif.ID)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetches notifications to get an up-to-date slice.
|
|
|
|
var createdNotifications []*ActivityCenterNotification
|
|
|
|
for _, notif := range notifications {
|
|
|
|
n, err := p.GetActivityCenterNotificationByID(notif.ID)
|
2023-06-10 02:00:17 +00:00
|
|
|
require.NoError(t, err, notif.ID)
|
2023-02-24 23:47:04 +00:00
|
|
|
createdNotifications = append(createdNotifications, n)
|
|
|
|
}
|
|
|
|
|
|
|
|
return createdNotifications
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDeleteActivityCenterNotificationsWhenEmpty(t *testing.T) {
|
|
|
|
db, err := openTestDB()
|
|
|
|
require.NoError(t, err)
|
|
|
|
p := newSQLitePersistence(db)
|
|
|
|
|
|
|
|
chat := CreatePublicChat("test-chat", &testTimeSource{})
|
2023-08-18 11:39:59 +00:00
|
|
|
message := common.NewMessage()
|
2023-02-24 23:47:04 +00:00
|
|
|
message.Text = "sample text"
|
|
|
|
chat.LastMessage = message
|
|
|
|
err = p.SaveChat(*chat)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
createNotifications(t, p, []*ActivityCenterNotification{
|
|
|
|
{
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
var count uint64
|
2023-03-03 14:31:48 +00:00
|
|
|
count, _ = p.ActivityCenterNotificationsCount([]ActivityCenterType{}, ActivityCenterQueryParamsReadUnread, false)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.Equal(t, uint64(1), count)
|
|
|
|
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.DeleteActivityCenterNotifications([]types.HexBytes{}, currentMilliseconds())
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2023-03-03 14:31:48 +00:00
|
|
|
count, _ = p.ActivityCenterNotificationsCount([]ActivityCenterType{}, ActivityCenterQueryParamsReadUnread, false)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.Equal(t, uint64(1), count)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDeleteActivityCenterNotificationsWithMultipleIds(t *testing.T) {
|
|
|
|
db, err := openTestDB()
|
|
|
|
require.NoError(t, err)
|
|
|
|
p := newSQLitePersistence(db)
|
|
|
|
|
|
|
|
chat := CreatePublicChat("test-chat", &testTimeSource{})
|
2023-08-18 11:39:59 +00:00
|
|
|
message := common.NewMessage()
|
2023-02-24 23:47:04 +00:00
|
|
|
message.Text = "sample text"
|
|
|
|
chat.LastMessage = message
|
|
|
|
err = p.SaveChat(*chat)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
notifications := createNotifications(t, p, []*ActivityCenterNotification{
|
|
|
|
{Type: ActivityCenterNotificationTypeMention},
|
|
|
|
{Type: ActivityCenterNotificationTypeNewOneToOne},
|
|
|
|
{Type: ActivityCenterNotificationTypeNewOneToOne},
|
|
|
|
})
|
|
|
|
|
|
|
|
var count uint64
|
2023-03-03 14:31:48 +00:00
|
|
|
count, _ = p.ActivityCenterNotificationsCount([]ActivityCenterType{}, ActivityCenterQueryParamsReadUnread, false)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.Equal(t, uint64(3), count)
|
|
|
|
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.DeleteActivityCenterNotifications([]types.HexBytes{notifications[1].ID, notifications[2].ID}, currentMilliseconds())
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2023-03-03 14:31:48 +00:00
|
|
|
count, _ = p.ActivityCenterNotificationsCount([]ActivityCenterType{}, ActivityCenterQueryParamsReadUnread, false)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.Equal(t, uint64(1), count)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDeleteActivityCenterNotificationsForMessage(t *testing.T) {
|
|
|
|
db, err := openTestDB()
|
|
|
|
require.NoError(t, err)
|
|
|
|
p := newSQLitePersistence(db)
|
|
|
|
|
|
|
|
chat := CreatePublicChat("test-chat", &testTimeSource{})
|
|
|
|
err = p.SaveChat(*chat)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
chat2 := CreatePublicChat("test-chat", &testTimeSource{})
|
|
|
|
err = p.SaveChat(*chat2)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
messages := []*common.Message{
|
|
|
|
{
|
|
|
|
ID: "0x1",
|
2023-08-18 11:39:59 +00:00
|
|
|
ChatMessage: &protobuf.ChatMessage{},
|
2023-02-24 23:47:04 +00:00
|
|
|
LocalChatID: chat.ID,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: "0x2",
|
2023-08-18 11:39:59 +00:00
|
|
|
ChatMessage: &protobuf.ChatMessage{},
|
2023-02-24 23:47:04 +00:00
|
|
|
LocalChatID: chat.ID,
|
|
|
|
},
|
|
|
|
{
|
2023-08-18 11:39:59 +00:00
|
|
|
ChatMessage: &protobuf.ChatMessage{},
|
|
|
|
ID: "0x3",
|
2023-02-24 23:47:04 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
err = p.SaveMessages(messages)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
chat.LastMessage = messages[1]
|
|
|
|
err = p.SaveChat(*chat)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
chatMessages, _, err := p.MessageByChatID(chat.ID, "", 2)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, chatMessages, 2)
|
|
|
|
|
|
|
|
nID1 := types.HexBytes("1")
|
|
|
|
nID2 := types.HexBytes("2")
|
|
|
|
nID3 := types.HexBytes("3")
|
|
|
|
nID4 := types.HexBytes("4")
|
|
|
|
|
|
|
|
createNotifications(t, p, []*ActivityCenterNotification{
|
|
|
|
{
|
|
|
|
ID: nID1,
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
Message: messages[0],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: nID2,
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
Message: messages[1],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: nID3,
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: nID4,
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
// Test: soft delete only the notifications that have Message.ID == messages[0].ID.
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.DeleteActivityCenterNotificationForMessage(chat.ID, messages[0].ID, currentMilliseconds())
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
notif, err := p.GetActivityCenterNotificationByID(nID1)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.True(t, notif.Deleted)
|
|
|
|
require.True(t, notif.Dismissed)
|
|
|
|
require.True(t, notif.Read)
|
|
|
|
|
|
|
|
// Other notifications are not affected.
|
|
|
|
for _, id := range []types.HexBytes{nID2, nID3, nID4} {
|
|
|
|
notif, err = p.GetActivityCenterNotificationByID(id)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, notif.Deleted, notif.ID)
|
|
|
|
require.False(t, notif.Dismissed, notif.ID)
|
|
|
|
require.False(t, notif.Read, notif.ID)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test: soft delete the notifications that have Message.ID == messages[1].ID
|
|
|
|
// or LastMessage.ID == chat.LastMessage.
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.DeleteActivityCenterNotificationForMessage(chat.ID, messages[1].ID, currentMilliseconds())
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
for _, id := range []types.HexBytes{nID2, nID3} {
|
|
|
|
notif, err = p.GetActivityCenterNotificationByID(id)
|
|
|
|
require.NoError(t, err, notif.ID)
|
|
|
|
require.True(t, notif.Deleted, notif.ID)
|
|
|
|
require.True(t, notif.Dismissed, notif.ID)
|
|
|
|
require.True(t, notif.Read, notif.ID)
|
|
|
|
}
|
|
|
|
|
|
|
|
notif, err = p.GetActivityCenterNotificationByID(nID4)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, notif.Deleted)
|
|
|
|
require.False(t, notif.Dismissed)
|
|
|
|
require.False(t, notif.Read)
|
|
|
|
|
|
|
|
// Test: don't do anything if passed a chat and message without notifications.
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.DeleteActivityCenterNotificationForMessage(chat2.ID, messages[2].ID, currentMilliseconds())
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
2023-07-19 12:14:42 +00:00
|
|
|
func (s *MessengerActivityCenterMessageSuite) TestMuteCommunityActivityCenterNotifications() {
|
|
|
|
|
|
|
|
description := &requests.CreateCommunity{
|
|
|
|
Membership: protobuf.CommunityPermissions_NO_MEMBERSHIP,
|
|
|
|
Name: "status",
|
|
|
|
Color: "#ffffff",
|
|
|
|
Description: "status community description",
|
|
|
|
}
|
|
|
|
|
|
|
|
alice := s.m
|
|
|
|
bob := s.newMessenger()
|
|
|
|
_, err := bob.Start()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// Create an community chat
|
|
|
|
response, err := bob.CreateCommunity(description, true)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(response.Communities(), 1)
|
|
|
|
|
|
|
|
community := response.Communities()[0]
|
|
|
|
s.Require().NotNil(community)
|
|
|
|
|
|
|
|
chat := CreateOneToOneChat(common.PubkeyToHex(&alice.identity.PublicKey), &alice.identity.PublicKey, bob.transport)
|
|
|
|
|
|
|
|
// bob sends a community message
|
2023-08-18 11:39:59 +00:00
|
|
|
inputMessage := common.NewMessage()
|
2023-07-19 12:14:42 +00:00
|
|
|
inputMessage.ChatId = chat.ID
|
|
|
|
inputMessage.Text = "some text"
|
|
|
|
inputMessage.CommunityID = community.IDString()
|
|
|
|
|
|
|
|
err = bob.SaveChat(chat)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
_, err = bob.SendChatMessage(context.Background(), inputMessage)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
alice,
|
|
|
|
func(r *MessengerResponse) bool { return len(r.Communities()) == 1 },
|
|
|
|
"no messages",
|
|
|
|
)
|
|
|
|
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// Alice joins the community
|
|
|
|
response, err = alice.JoinCommunity(context.Background(), community.ID(), true)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(response)
|
|
|
|
s.Require().Len(response.Communities(), 1)
|
|
|
|
s.Require().True(response.Communities()[0].Joined())
|
|
|
|
s.Require().Len(response.Chats(), 1)
|
|
|
|
|
|
|
|
defaultCommunityChatID := response.Chats()[0].ID
|
|
|
|
|
|
|
|
// Bob mutes the community
|
|
|
|
time, err := bob.MuteAllCommunityChats(&requests.MuteCommunity{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
MutedType: MuteTillUnmuted,
|
|
|
|
})
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(time)
|
|
|
|
|
|
|
|
bobCommunity, err := bob.GetCommunityByID(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().True(bobCommunity.Muted())
|
|
|
|
|
|
|
|
// alice sends a community message
|
2023-08-18 11:39:59 +00:00
|
|
|
inputMessage = common.NewMessage()
|
2023-07-19 12:14:42 +00:00
|
|
|
inputMessage.ChatId = defaultCommunityChatID
|
|
|
|
inputMessage.Text = "Good news, @" + common.EveryoneMentionTag + " !"
|
|
|
|
inputMessage.CommunityID = community.IDString()
|
|
|
|
|
|
|
|
response, err = alice.SendChatMessage(context.Background(), inputMessage)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
s.Require().Len(response.Messages(), 1)
|
|
|
|
|
|
|
|
s.Require().True(response.Messages()[0].Mentioned)
|
|
|
|
|
|
|
|
response, err = WaitOnMessengerResponse(
|
|
|
|
bob,
|
|
|
|
func(r *MessengerResponse) bool { return len(r.Messages()) == 1 },
|
|
|
|
"no messages",
|
|
|
|
)
|
|
|
|
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
s.Require().Len(response.Messages(), 1)
|
|
|
|
|
|
|
|
s.Require().True(response.Messages()[0].Mentioned)
|
|
|
|
s.Require().Len(response.ActivityCenterNotifications(), 0)
|
|
|
|
}
|
|
|
|
|
2023-02-24 23:47:04 +00:00
|
|
|
func TestAcceptActivityCenterNotificationsForInvitesFromUser(t *testing.T) {
|
|
|
|
db, err := openTestDB()
|
|
|
|
require.NoError(t, err)
|
|
|
|
p := newSQLitePersistence(db)
|
|
|
|
|
|
|
|
nID1 := types.HexBytes("1")
|
|
|
|
nID2 := types.HexBytes("2")
|
|
|
|
nID3 := types.HexBytes("3")
|
|
|
|
nID4 := types.HexBytes("4")
|
|
|
|
|
|
|
|
userPublicKey := "zQ3sh"
|
|
|
|
|
|
|
|
notifications := []*ActivityCenterNotification{
|
|
|
|
{
|
|
|
|
ID: nID1,
|
|
|
|
Type: ActivityCenterNotificationTypeNewPrivateGroupChat,
|
|
|
|
Timestamp: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: nID2,
|
|
|
|
Type: ActivityCenterNotificationTypeNewPrivateGroupChat,
|
|
|
|
Timestamp: 1,
|
|
|
|
Author: userPublicKey,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: nID3,
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
Timestamp: 1,
|
|
|
|
Author: userPublicKey,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: nID4,
|
|
|
|
Timestamp: 1,
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
var notif *ActivityCenterNotification
|
|
|
|
for _, notif = range notifications {
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.SaveActivityCenterNotification(notif, true)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err, notif.ID)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only notifications of type new private group chat and with Author equal to
|
|
|
|
// userPublicKey should be marked as accepted & read.
|
|
|
|
_, err = p.GetActivityCenterNotificationByID(nID2)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, notifications[0].Accepted)
|
|
|
|
require.False(t, notifications[0].Read)
|
|
|
|
|
2023-06-10 02:00:17 +00:00
|
|
|
notifications, err = p.AcceptActivityCenterNotificationsForInvitesFromUser(userPublicKey, 1)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, notifications, 1)
|
|
|
|
require.Equal(t, nID2, notifications[0].ID)
|
|
|
|
|
|
|
|
notif, err = p.GetActivityCenterNotificationByID(nID2)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.True(t, notif.Accepted)
|
|
|
|
require.True(t, notif.Read)
|
|
|
|
|
|
|
|
// Deleted notifications are ignored.
|
|
|
|
notif = &ActivityCenterNotification{
|
|
|
|
ID: types.HexBytes("99"),
|
|
|
|
Type: ActivityCenterNotificationTypeNewPrivateGroupChat,
|
|
|
|
Timestamp: 1,
|
|
|
|
Author: userPublicKey,
|
|
|
|
Deleted: true,
|
|
|
|
}
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.SaveActivityCenterNotification(notif, true)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.AcceptActivityCenterNotificationsForInvitesFromUser(userPublicKey, currentMilliseconds())
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
notif, err = p.GetActivityCenterNotificationByID(notif.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, notif.Accepted)
|
|
|
|
require.False(t, notif.Read)
|
|
|
|
require.True(t, notif.Deleted)
|
|
|
|
|
|
|
|
// Dismissed notifications are ignored.
|
|
|
|
notif = &ActivityCenterNotification{
|
|
|
|
ID: types.HexBytes("100"),
|
|
|
|
Type: ActivityCenterNotificationTypeNewPrivateGroupChat,
|
|
|
|
Timestamp: 1,
|
|
|
|
Author: userPublicKey,
|
|
|
|
Dismissed: true,
|
|
|
|
}
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.SaveActivityCenterNotification(notif, true)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.AcceptActivityCenterNotificationsForInvitesFromUser(userPublicKey, currentMilliseconds())
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
notif, err = p.GetActivityCenterNotificationByID(notif.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, notif.Accepted)
|
|
|
|
require.False(t, notif.Read)
|
|
|
|
require.True(t, notif.Dismissed)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetToProcessActivityCenterNotificationIds(t *testing.T) {
|
|
|
|
db, err := openTestDB()
|
|
|
|
require.NoError(t, err)
|
|
|
|
p := newSQLitePersistence(db)
|
|
|
|
|
|
|
|
notifications := createNotifications(t, p, []*ActivityCenterNotification{
|
|
|
|
{
|
|
|
|
Type: ActivityCenterNotificationTypeNewPrivateGroupChat,
|
|
|
|
Deleted: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ActivityCenterNotificationTypeNewPrivateGroupChat,
|
|
|
|
Dismissed: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
Accepted: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
ids, err := p.GetToProcessActivityCenterNotificationIds()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, ids, 1)
|
|
|
|
require.Equal(t, notifications[3].ID, types.HexBytes(ids[0]))
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHasPendingNotificationsForChat(t *testing.T) {
|
|
|
|
db, err := openTestDB()
|
|
|
|
require.NoError(t, err)
|
|
|
|
p := newSQLitePersistence(db)
|
|
|
|
|
|
|
|
chat := CreatePublicChat("test-chat", &testTimeSource{})
|
|
|
|
err = p.SaveChat(*chat)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Test: there are no notifications.
|
|
|
|
result, err := p.HasPendingNotificationsForChat(chat.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, result)
|
|
|
|
|
|
|
|
// Test: there are only deleted, dismissed or accepted notifications,
|
|
|
|
// therefore, no pending notifications.
|
|
|
|
createNotifications(t, p, []*ActivityCenterNotification{
|
|
|
|
{
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Type: ActivityCenterNotificationTypeNewPrivateGroupChat,
|
|
|
|
Deleted: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Type: ActivityCenterNotificationTypeNewPrivateGroupChat,
|
|
|
|
Dismissed: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
Accepted: true,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
result, err = p.HasPendingNotificationsForChat(chat.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, result)
|
|
|
|
|
|
|
|
// Test: there's one pending notification.
|
|
|
|
notif := &ActivityCenterNotification{
|
|
|
|
ID: types.HexBytes("99"),
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Type: ActivityCenterNotificationTypeCommunityRequest,
|
|
|
|
Timestamp: 1,
|
|
|
|
}
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.SaveActivityCenterNotification(notif, true)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
result, err = p.HasPendingNotificationsForChat(chat.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.True(t, result)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDismissAllActivityCenterNotificationsFromUser(t *testing.T) {
|
|
|
|
db, err := openTestDB()
|
|
|
|
require.NoError(t, err)
|
|
|
|
p := newSQLitePersistence(db)
|
|
|
|
|
|
|
|
publicKey := "0x04"
|
|
|
|
|
|
|
|
notifications := createNotifications(t, p, []*ActivityCenterNotification{
|
|
|
|
{
|
|
|
|
Type: ActivityCenterNotificationTypeNewPrivateGroupChat,
|
|
|
|
Author: publicKey,
|
|
|
|
Deleted: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ActivityCenterNotificationTypeNewPrivateGroupChat,
|
|
|
|
Author: publicKey,
|
|
|
|
Dismissed: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
Author: publicKey,
|
|
|
|
Accepted: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
Author: "0x09",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
Author: publicKey,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.DismissAllActivityCenterNotificationsFromUser(publicKey, 1)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Ignores already soft deleted.
|
|
|
|
notif, err := p.GetActivityCenterNotificationByID(notifications[0].ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, notif.Accepted)
|
|
|
|
require.False(t, notif.Read)
|
|
|
|
require.False(t, notif.Dismissed)
|
|
|
|
require.True(t, notif.Deleted)
|
|
|
|
|
|
|
|
// Ignores already dismissed.
|
|
|
|
notif, err = p.GetActivityCenterNotificationByID(notifications[1].ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, notif.Accepted)
|
|
|
|
require.False(t, notif.Read)
|
|
|
|
require.True(t, notif.Dismissed)
|
|
|
|
require.False(t, notif.Deleted)
|
|
|
|
|
|
|
|
// Ignores already accepted.
|
|
|
|
notif, err = p.GetActivityCenterNotificationByID(notifications[2].ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.True(t, notif.Accepted)
|
|
|
|
require.False(t, notif.Read)
|
|
|
|
require.False(t, notif.Dismissed)
|
|
|
|
require.False(t, notif.Deleted)
|
|
|
|
|
|
|
|
// Ignores notification from different author.
|
|
|
|
notif, err = p.GetActivityCenterNotificationByID(notifications[3].ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, notif.Accepted)
|
|
|
|
require.False(t, notif.Read)
|
|
|
|
require.False(t, notif.Dismissed)
|
|
|
|
require.False(t, notif.Deleted)
|
|
|
|
|
|
|
|
// Finally, dismiss and mark as read this one notification.
|
|
|
|
notif, err = p.GetActivityCenterNotificationByID(notifications[4].ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, notif.Accepted)
|
|
|
|
require.True(t, notif.Read)
|
|
|
|
require.True(t, notif.Dismissed)
|
|
|
|
require.False(t, notif.Deleted)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDismissAllActivityCenterNotificationsFromChatID(t *testing.T) {
|
|
|
|
db, err := openTestDB()
|
|
|
|
require.NoError(t, err)
|
|
|
|
p := newSQLitePersistence(db)
|
|
|
|
|
|
|
|
chatID := "0x99"
|
|
|
|
|
|
|
|
notifications := createNotifications(t, p, []*ActivityCenterNotification{
|
|
|
|
{
|
|
|
|
ChatID: chatID,
|
|
|
|
Type: ActivityCenterNotificationTypeNewPrivateGroupChat,
|
|
|
|
Deleted: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ChatID: chatID,
|
|
|
|
Type: ActivityCenterNotificationTypeNewPrivateGroupChat,
|
|
|
|
Dismissed: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ChatID: chatID,
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
Accepted: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ChatID: chatID,
|
|
|
|
Type: ActivityCenterNotificationTypeContactRequest,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ChatID: chatID,
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.DismissAllActivityCenterNotificationsFromChatID(chatID, currentMilliseconds())
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Ignores already soft deleted.
|
|
|
|
notif, err := p.GetActivityCenterNotificationByID(notifications[0].ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, notif.Accepted)
|
|
|
|
require.False(t, notif.Read)
|
|
|
|
require.False(t, notif.Dismissed)
|
|
|
|
require.True(t, notif.Deleted)
|
|
|
|
|
|
|
|
// Do not ignore already dismissed, because notifications can become
|
|
|
|
// read/unread AND dismissed, and the method should still update the Read
|
|
|
|
// column.
|
|
|
|
notif, err = p.GetActivityCenterNotificationByID(notifications[1].ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, notif.Accepted)
|
|
|
|
require.True(t, notif.Read)
|
|
|
|
require.True(t, notif.Dismissed)
|
|
|
|
require.False(t, notif.Deleted)
|
|
|
|
|
|
|
|
// Ignores already accepted.
|
|
|
|
notif, err = p.GetActivityCenterNotificationByID(notifications[2].ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.True(t, notif.Accepted)
|
|
|
|
require.False(t, notif.Read)
|
|
|
|
require.False(t, notif.Dismissed)
|
|
|
|
require.False(t, notif.Deleted)
|
|
|
|
|
|
|
|
// Ignores notification from different chat.
|
|
|
|
notif, err = p.GetActivityCenterNotificationByID(notifications[3].ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, notif.Accepted)
|
|
|
|
require.False(t, notif.Read)
|
|
|
|
require.False(t, notif.Dismissed)
|
|
|
|
require.False(t, notif.Deleted)
|
|
|
|
|
|
|
|
// Ignores contact request notifications.
|
|
|
|
notif, err = p.GetActivityCenterNotificationByID(notifications[4].ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, notif.Accepted)
|
|
|
|
require.False(t, notif.Read)
|
|
|
|
require.False(t, notif.Dismissed)
|
|
|
|
require.False(t, notif.Deleted)
|
|
|
|
|
|
|
|
// Finally, dismiss and mark as read this one notification.
|
|
|
|
notif, err = p.GetActivityCenterNotificationByID(notifications[5].ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, notif.Accepted)
|
|
|
|
require.True(t, notif.Read)
|
|
|
|
require.True(t, notif.Dismissed)
|
|
|
|
require.False(t, notif.Deleted)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestActiveContactRequestNotification(t *testing.T) {
|
|
|
|
db, err := openTestDB()
|
|
|
|
require.NoError(t, err)
|
|
|
|
p := newSQLitePersistence(db)
|
|
|
|
|
|
|
|
chat := CreatePublicChat("test-chat", &testTimeSource{})
|
|
|
|
err = p.SaveChat(*chat)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
contactID := "0x99"
|
|
|
|
|
|
|
|
// Test: ignores deleted/dismissed/accepted notifications, as well as
|
|
|
|
// notifications not associated to any chat.
|
|
|
|
createNotifications(t, p, []*ActivityCenterNotification{
|
|
|
|
{
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Author: contactID,
|
|
|
|
Type: ActivityCenterNotificationTypeContactRequest,
|
|
|
|
Deleted: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Author: contactID,
|
|
|
|
Type: ActivityCenterNotificationTypeContactRequest,
|
|
|
|
Dismissed: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Author: contactID,
|
|
|
|
Type: ActivityCenterNotificationTypeContactRequest,
|
|
|
|
Accepted: true,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
notif, err := p.ActiveContactRequestNotification(contactID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Nil(t, notif)
|
|
|
|
|
|
|
|
// Test: Ignores notifications that are not contact requests.
|
|
|
|
createNotifications(t, p, []*ActivityCenterNotification{
|
|
|
|
{ChatID: chat.ID, Author: contactID, Type: ActivityCenterNotificationTypeCommunityInvitation},
|
|
|
|
{ChatID: chat.ID, Author: contactID, Type: ActivityCenterNotificationTypeCommunityKicked},
|
|
|
|
{ChatID: chat.ID, Author: contactID, Type: ActivityCenterNotificationTypeCommunityMembershipRequest},
|
|
|
|
{ChatID: chat.ID, Author: contactID, Type: ActivityCenterNotificationTypeCommunityRequest},
|
|
|
|
{ChatID: chat.ID, Author: contactID, Type: ActivityCenterNotificationTypeContactVerification},
|
|
|
|
{ChatID: chat.ID, Author: contactID, Type: ActivityCenterNotificationTypeMention},
|
|
|
|
{ChatID: chat.ID, Author: contactID, Type: ActivityCenterNotificationTypeNewOneToOne},
|
|
|
|
{ChatID: chat.ID, Author: contactID, Type: ActivityCenterNotificationTypeNewPrivateGroupChat},
|
|
|
|
{ChatID: chat.ID, Author: contactID, Type: ActivityCenterNotificationTypeReply},
|
|
|
|
})
|
|
|
|
|
|
|
|
notif, err = p.ActiveContactRequestNotification(contactID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Nil(t, notif)
|
|
|
|
|
|
|
|
// Test: Returns one, and only one contact request notification for the
|
|
|
|
// contact under test.
|
|
|
|
createNotifications(t, p, []*ActivityCenterNotification{
|
|
|
|
{ChatID: chat.ID, Author: contactID, Type: ActivityCenterNotificationTypeContactRequest},
|
|
|
|
})
|
|
|
|
|
|
|
|
notif, err = p.ActiveContactRequestNotification(contactID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, ActivityCenterNotificationTypeContactRequest, notif.Type)
|
|
|
|
|
|
|
|
// Test: In case there's more than one notification, return the most recent
|
|
|
|
// one according to the notification's timestamp.
|
|
|
|
expectedID := types.HexBytes("667")
|
|
|
|
|
2023-06-10 02:00:17 +00:00
|
|
|
t1 := currentMilliseconds()
|
|
|
|
t2 := currentMilliseconds()
|
2023-02-24 23:47:04 +00:00
|
|
|
createNotifications(t, p, []*ActivityCenterNotification{
|
|
|
|
{
|
|
|
|
ID: expectedID,
|
2023-06-10 02:00:17 +00:00
|
|
|
Timestamp: t2 + 1,
|
2023-02-24 23:47:04 +00:00
|
|
|
ChatID: chat.ID,
|
|
|
|
Author: contactID,
|
|
|
|
Type: ActivityCenterNotificationTypeContactRequest,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: types.HexBytes("666"),
|
2023-06-10 02:00:17 +00:00
|
|
|
Timestamp: t1,
|
2023-02-24 23:47:04 +00:00
|
|
|
ChatID: chat.ID,
|
|
|
|
Author: contactID,
|
|
|
|
Type: ActivityCenterNotificationTypeContactRequest,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
notif, err = p.ActiveContactRequestNotification(contactID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, expectedID, notif.ID)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnreadActivityCenterNotificationsCount(t *testing.T) {
|
|
|
|
db, err := openTestDB()
|
|
|
|
require.NoError(t, err)
|
|
|
|
p := newSQLitePersistence(db)
|
|
|
|
|
|
|
|
createNotifications(t, p, []*ActivityCenterNotification{
|
|
|
|
{Type: ActivityCenterNotificationTypeMention, Read: true},
|
|
|
|
{Type: ActivityCenterNotificationTypeNewOneToOne, Deleted: true},
|
|
|
|
{Type: ActivityCenterNotificationTypeMention, Dismissed: true},
|
|
|
|
{Type: ActivityCenterNotificationTypeCommunityRequest, Accepted: true},
|
|
|
|
{Type: ActivityCenterNotificationTypeContactRequest},
|
|
|
|
})
|
|
|
|
|
|
|
|
// Test: Ignore soft deleted and accepted.
|
2023-03-03 14:31:48 +00:00
|
|
|
count, err := p.ActivityCenterNotificationsCount([]ActivityCenterType{}, ActivityCenterQueryParamsReadUnread, true)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, uint64(3), count)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnreadAndAcceptedActivityCenterNotificationsCount(t *testing.T) {
|
|
|
|
db, err := openTestDB()
|
|
|
|
require.NoError(t, err)
|
|
|
|
p := newSQLitePersistence(db)
|
|
|
|
|
|
|
|
createNotifications(t, p, []*ActivityCenterNotification{
|
|
|
|
{Type: ActivityCenterNotificationTypeMention, Read: true},
|
|
|
|
{Type: ActivityCenterNotificationTypeNewOneToOne, Deleted: true},
|
|
|
|
{Type: ActivityCenterNotificationTypeMention, Dismissed: true},
|
|
|
|
{Type: ActivityCenterNotificationTypeCommunityRequest, Accepted: true},
|
|
|
|
{Type: ActivityCenterNotificationTypeContactRequest},
|
|
|
|
})
|
|
|
|
|
|
|
|
// Test: counts everything, except soft deleted notifications.
|
2023-03-03 14:31:48 +00:00
|
|
|
count, err := p.ActivityCenterNotificationsCount([]ActivityCenterType{}, ActivityCenterQueryParamsReadUnread, true)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, uint64(3), count)
|
|
|
|
|
|
|
|
// Test: counts everything, except soft deleted ones and limit by type.
|
2023-03-03 14:31:48 +00:00
|
|
|
count, err = p.ActivityCenterNotificationsCount([]ActivityCenterType{
|
|
|
|
ActivityCenterNotificationTypeContactRequest,
|
|
|
|
}, ActivityCenterQueryParamsReadUnread, true)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, uint64(1), count)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestActivityCenterPersistence(t *testing.T) {
|
|
|
|
nID1 := types.HexBytes([]byte("1"))
|
|
|
|
nID2 := types.HexBytes([]byte("2"))
|
|
|
|
nID3 := types.HexBytes([]byte("3"))
|
|
|
|
nID4 := types.HexBytes([]byte("4"))
|
|
|
|
|
|
|
|
db, err := openTestDB()
|
|
|
|
require.NoError(t, err)
|
|
|
|
p := newSQLitePersistence(db)
|
|
|
|
|
|
|
|
chat := CreatePublicChat("test-chat", &testTimeSource{})
|
2023-08-18 11:39:59 +00:00
|
|
|
message := common.NewMessage()
|
2023-02-24 23:47:04 +00:00
|
|
|
message.Text = "sample text"
|
|
|
|
chat.LastMessage = message
|
|
|
|
err = p.SaveChat(*chat)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
notification := &ActivityCenterNotification{
|
|
|
|
ID: nID1,
|
|
|
|
Type: ActivityCenterNotificationTypeNewOneToOne,
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Timestamp: 1,
|
|
|
|
}
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.SaveActivityCenterNotification(notification, true)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2023-03-03 14:31:48 +00:00
|
|
|
cursor, notifications, err := p.ActivityCenterNotifications("", 2, []ActivityCenterType{}, ActivityCenterQueryParamsReadAll, false)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Empty(t, cursor)
|
|
|
|
require.Len(t, notifications, 1)
|
|
|
|
require.Equal(t, chat.ID, notifications[0].ChatID)
|
|
|
|
require.Equal(t, message, notifications[0].LastMessage)
|
|
|
|
|
|
|
|
// Add another notification
|
|
|
|
|
|
|
|
notification = &ActivityCenterNotification{
|
|
|
|
ID: nID2,
|
|
|
|
Type: ActivityCenterNotificationTypeNewOneToOne,
|
|
|
|
Timestamp: 2,
|
|
|
|
}
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.SaveActivityCenterNotification(notification, true)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2023-03-03 14:31:48 +00:00
|
|
|
cursor, notifications, err = p.ActivityCenterNotifications("", 1, []ActivityCenterType{}, ActivityCenterQueryParamsReadAll, false)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, notifications, 1)
|
|
|
|
require.NotEmpty(t, cursor)
|
|
|
|
require.Equal(t, nID2, notifications[0].ID)
|
|
|
|
|
|
|
|
// fetch next pagination
|
|
|
|
|
2023-03-03 14:31:48 +00:00
|
|
|
cursor, notifications, err = p.ActivityCenterNotifications(cursor, 1, []ActivityCenterType{}, ActivityCenterQueryParamsReadAll, false)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, notifications, 1)
|
|
|
|
require.Empty(t, cursor)
|
|
|
|
require.False(t, notifications[0].Read)
|
|
|
|
require.Equal(t, nID1, notifications[0].ID)
|
|
|
|
|
|
|
|
// Check count
|
2023-03-03 14:31:48 +00:00
|
|
|
count, err := p.ActivityCenterNotificationsCount([]ActivityCenterType{}, ActivityCenterQueryParamsReadUnread, false)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, uint64(2), count)
|
|
|
|
|
2023-06-10 02:00:17 +00:00
|
|
|
var updatedAt uint64 = 1
|
2023-02-24 23:47:04 +00:00
|
|
|
// Mark first one as read
|
2023-06-10 02:00:17 +00:00
|
|
|
require.NoError(t, p.MarkActivityCenterNotificationsRead([]types.HexBytes{nID1}, updatedAt))
|
2023-03-03 14:31:48 +00:00
|
|
|
count, err = p.ActivityCenterNotificationsCount([]ActivityCenterType{}, ActivityCenterQueryParamsReadUnread, false)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, uint64(1), count)
|
|
|
|
|
|
|
|
// Mark first one as unread
|
2023-06-10 02:00:17 +00:00
|
|
|
updatedAt++
|
|
|
|
_, err = p.MarkActivityCenterNotificationsUnread([]types.HexBytes{nID1}, updatedAt)
|
|
|
|
require.NoError(t, err)
|
2023-03-03 14:31:48 +00:00
|
|
|
count, err = p.ActivityCenterNotificationsCount([]ActivityCenterType{}, ActivityCenterQueryParamsReadUnread, false)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, uint64(2), count)
|
|
|
|
|
|
|
|
// Mark all read
|
2023-06-10 02:00:17 +00:00
|
|
|
updatedAt++
|
|
|
|
require.NoError(t, p.MarkAllActivityCenterNotificationsRead(updatedAt))
|
2023-03-03 14:31:48 +00:00
|
|
|
_, notifications, err = p.ActivityCenterNotifications(cursor, 2, []ActivityCenterType{}, ActivityCenterQueryParamsReadAll, false)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, notifications, 2)
|
|
|
|
require.Empty(t, cursor)
|
|
|
|
require.True(t, notifications[0].Read)
|
|
|
|
require.True(t, notifications[1].Read)
|
|
|
|
|
|
|
|
// Check count
|
2023-03-03 14:31:48 +00:00
|
|
|
count, err = p.ActivityCenterNotificationsCount([]ActivityCenterType{}, ActivityCenterQueryParamsReadUnread, false)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, uint64(0), count)
|
|
|
|
|
|
|
|
// Mark first one as accepted
|
2023-06-10 02:00:17 +00:00
|
|
|
updatedAt++
|
|
|
|
notifications, err = p.AcceptActivityCenterNotifications([]types.HexBytes{nID1}, updatedAt)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, notifications, 1)
|
2023-03-03 14:31:48 +00:00
|
|
|
_, notifications, err = p.ActivityCenterNotifications("", 2, []ActivityCenterType{}, ActivityCenterQueryParamsReadAll, false)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
// It should not be returned anymore
|
|
|
|
require.Len(t, notifications, 1)
|
|
|
|
|
|
|
|
// Mark last one as dismissed
|
2023-06-10 02:00:17 +00:00
|
|
|
updatedAt++
|
|
|
|
require.NoError(t, p.DismissActivityCenterNotifications([]types.HexBytes{nID2}, updatedAt))
|
2023-03-03 14:31:48 +00:00
|
|
|
_, notifications, err = p.ActivityCenterNotifications("", 2, []ActivityCenterType{}, ActivityCenterQueryParamsReadAll, false)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
require.Len(t, notifications, 1)
|
|
|
|
require.True(t, notifications[0].Dismissed)
|
|
|
|
|
|
|
|
// Insert new notification
|
|
|
|
notification = &ActivityCenterNotification{
|
|
|
|
ID: nID3,
|
|
|
|
Type: ActivityCenterNotificationTypeNewOneToOne,
|
|
|
|
Timestamp: 3,
|
|
|
|
}
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.SaveActivityCenterNotification(notification, true)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Mark all as accepted
|
2023-06-10 02:00:17 +00:00
|
|
|
updatedAt++
|
|
|
|
notifications, err = p.AcceptAllActivityCenterNotifications(updatedAt)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, notifications, 2)
|
|
|
|
|
2023-03-03 14:31:48 +00:00
|
|
|
_, notifications, err = p.ActivityCenterNotifications("", 2, []ActivityCenterType{}, ActivityCenterQueryParamsReadAll, false)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
require.Len(t, notifications, 1)
|
|
|
|
|
|
|
|
// Insert new notification
|
|
|
|
notification = &ActivityCenterNotification{
|
|
|
|
ID: nID4,
|
|
|
|
Type: ActivityCenterNotificationTypeNewOneToOne,
|
|
|
|
Timestamp: 4,
|
|
|
|
}
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.SaveActivityCenterNotification(notification, true)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Mark all as dismissed
|
2023-06-10 02:00:17 +00:00
|
|
|
updatedAt++
|
|
|
|
require.NoError(t, p.DismissAllActivityCenterNotifications(updatedAt))
|
2023-03-03 14:31:48 +00:00
|
|
|
_, notifications, err = p.ActivityCenterNotifications("", 2, []ActivityCenterType{}, ActivityCenterQueryParamsReadAll, false)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
require.Len(t, notifications, 2)
|
|
|
|
require.True(t, notifications[0].Dismissed)
|
|
|
|
require.True(t, notifications[1].Dismissed)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestActivityCenterReadUnreadPagination(t *testing.T) {
|
|
|
|
db, err := openTestDB()
|
|
|
|
require.NoError(t, err)
|
|
|
|
p := newSQLitePersistence(db)
|
|
|
|
|
|
|
|
initialOrFinalCursor := ""
|
|
|
|
|
|
|
|
chat := CreatePublicChat("test-chat", &testTimeSource{})
|
2023-08-18 11:39:59 +00:00
|
|
|
message := common.NewMessage()
|
2023-02-24 23:47:04 +00:00
|
|
|
message.Text = "sample text"
|
|
|
|
chat.LastMessage = message
|
|
|
|
err = p.SaveChat(*chat)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
nID1 := types.HexBytes("1")
|
|
|
|
nID2 := types.HexBytes("2")
|
|
|
|
nID3 := types.HexBytes("3")
|
|
|
|
nID4 := types.HexBytes("4")
|
|
|
|
nID5 := types.HexBytes("5")
|
|
|
|
|
|
|
|
allNotifications := []*ActivityCenterNotification{
|
|
|
|
{
|
|
|
|
ID: nID1,
|
|
|
|
Type: ActivityCenterNotificationTypeNewOneToOne,
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Timestamp: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: nID2,
|
|
|
|
Type: ActivityCenterNotificationTypeNewOneToOne,
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Timestamp: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: nID3,
|
|
|
|
Type: ActivityCenterNotificationTypeNewOneToOne,
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Timestamp: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: nID4,
|
|
|
|
Type: ActivityCenterNotificationTypeNewOneToOne,
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Timestamp: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: nID5,
|
|
|
|
Type: ActivityCenterNotificationTypeNewOneToOne,
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Timestamp: 1,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, notification := range allNotifications {
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.SaveActivityCenterNotification(notification, true)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mark the notification as read
|
2023-06-10 02:00:17 +00:00
|
|
|
err = p.MarkActivityCenterNotificationsRead([]types.HexBytes{nID2}, currentMilliseconds())
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
2023-06-10 02:00:17 +00:00
|
|
|
err = p.MarkActivityCenterNotificationsRead([]types.HexBytes{nID4}, currentMilliseconds())
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Fetch UNREAD notifications, first page.
|
2023-03-03 14:31:48 +00:00
|
|
|
cursor, notifications, err := p.ActivityCenterNotifications(
|
2023-02-24 23:47:04 +00:00
|
|
|
initialOrFinalCursor,
|
|
|
|
1,
|
|
|
|
[]ActivityCenterType{ActivityCenterNotificationTypeNewOneToOne},
|
2023-03-03 14:31:48 +00:00
|
|
|
ActivityCenterQueryParamsReadUnread,
|
|
|
|
false,
|
2023-02-24 23:47:04 +00:00
|
|
|
)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, notifications, 1)
|
|
|
|
require.Equal(t, nID5, notifications[0].ID)
|
|
|
|
require.NotEmpty(t, cursor)
|
|
|
|
|
|
|
|
// Fetch next pages.
|
2023-03-03 14:31:48 +00:00
|
|
|
cursor, notifications, err = p.ActivityCenterNotifications(
|
2023-02-24 23:47:04 +00:00
|
|
|
cursor,
|
|
|
|
1,
|
|
|
|
[]ActivityCenterType{ActivityCenterNotificationTypeNewOneToOne},
|
2023-03-03 14:31:48 +00:00
|
|
|
ActivityCenterQueryParamsReadUnread,
|
|
|
|
false,
|
2023-02-24 23:47:04 +00:00
|
|
|
)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, notifications, 1)
|
|
|
|
require.Equal(t, nID3, notifications[0].ID)
|
|
|
|
require.NotEmpty(t, cursor)
|
|
|
|
|
2023-03-03 14:31:48 +00:00
|
|
|
cursor, notifications, err = p.ActivityCenterNotifications(
|
2023-02-24 23:47:04 +00:00
|
|
|
cursor,
|
|
|
|
1,
|
|
|
|
[]ActivityCenterType{ActivityCenterNotificationTypeNewOneToOne},
|
2023-03-03 14:31:48 +00:00
|
|
|
ActivityCenterQueryParamsReadUnread,
|
|
|
|
false,
|
2023-02-24 23:47:04 +00:00
|
|
|
)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, notifications, 1)
|
|
|
|
require.Equal(t, nID1, notifications[0].ID)
|
|
|
|
require.Empty(t, cursor)
|
|
|
|
|
|
|
|
// Fetch READ notifications, first page.
|
2023-03-03 14:31:48 +00:00
|
|
|
cursor, notifications, err = p.ActivityCenterNotifications(
|
2023-02-24 23:47:04 +00:00
|
|
|
initialOrFinalCursor,
|
|
|
|
1,
|
|
|
|
[]ActivityCenterType{ActivityCenterNotificationTypeNewOneToOne},
|
2023-03-03 14:31:48 +00:00
|
|
|
ActivityCenterQueryParamsReadRead,
|
|
|
|
false,
|
2023-02-24 23:47:04 +00:00
|
|
|
)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, notifications, 1)
|
|
|
|
require.Equal(t, nID4, notifications[0].ID)
|
|
|
|
require.NotEmpty(t, cursor)
|
|
|
|
|
|
|
|
// Fetch next page.
|
2023-03-03 14:31:48 +00:00
|
|
|
cursor, notifications, err = p.ActivityCenterNotifications(
|
2023-02-24 23:47:04 +00:00
|
|
|
cursor,
|
|
|
|
1,
|
|
|
|
[]ActivityCenterType{ActivityCenterNotificationTypeNewOneToOne},
|
2023-03-03 14:31:48 +00:00
|
|
|
ActivityCenterQueryParamsReadRead,
|
|
|
|
false,
|
2023-02-24 23:47:04 +00:00
|
|
|
)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, notifications, 1)
|
|
|
|
require.Equal(t, nID2, notifications[0].ID)
|
|
|
|
require.Empty(t, cursor)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestActivityCenterReadUnreadFilterByTypes(t *testing.T) {
|
|
|
|
db, err := openTestDB()
|
|
|
|
require.NoError(t, err)
|
|
|
|
p := newSQLitePersistence(db)
|
|
|
|
|
|
|
|
chat := CreatePublicChat("test-chat", &testTimeSource{})
|
2023-08-18 11:39:59 +00:00
|
|
|
message := common.NewMessage()
|
2023-02-24 23:47:04 +00:00
|
|
|
message.Text = "sample text"
|
|
|
|
chat.LastMessage = message
|
|
|
|
err = p.SaveChat(*chat)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
initialCursor := ""
|
|
|
|
limit := uint64(3)
|
|
|
|
|
|
|
|
nID1 := types.HexBytes("1")
|
|
|
|
nID2 := types.HexBytes("2")
|
|
|
|
nID3 := types.HexBytes("3")
|
|
|
|
|
|
|
|
allNotifications := []*ActivityCenterNotification{
|
|
|
|
{
|
|
|
|
ID: nID1,
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Timestamp: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: nID2,
|
|
|
|
Type: ActivityCenterNotificationTypeNewOneToOne,
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Timestamp: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: nID3,
|
|
|
|
Type: ActivityCenterNotificationTypeMention,
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Timestamp: 1,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, notification := range allNotifications {
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.SaveActivityCenterNotification(notification, true)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't filter by type if the array of types is empty.
|
2023-03-03 14:31:48 +00:00
|
|
|
_, notifications, err := p.ActivityCenterNotifications(
|
2023-02-24 23:47:04 +00:00
|
|
|
initialCursor,
|
|
|
|
limit,
|
|
|
|
[]ActivityCenterType{},
|
2023-03-03 14:31:48 +00:00
|
|
|
ActivityCenterQueryParamsReadUnread,
|
|
|
|
false,
|
2023-02-24 23:47:04 +00:00
|
|
|
)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, notifications, 3)
|
|
|
|
require.Equal(t, nID3, notifications[0].ID)
|
|
|
|
require.Equal(t, nID2, notifications[1].ID)
|
|
|
|
require.Equal(t, nID1, notifications[2].ID)
|
|
|
|
|
2023-03-03 14:31:48 +00:00
|
|
|
_, notifications, err = p.ActivityCenterNotifications(
|
2023-02-24 23:47:04 +00:00
|
|
|
initialCursor,
|
|
|
|
limit,
|
|
|
|
[]ActivityCenterType{ActivityCenterNotificationTypeNewOneToOne},
|
2023-03-03 14:31:48 +00:00
|
|
|
ActivityCenterQueryParamsReadUnread,
|
|
|
|
false,
|
2023-02-24 23:47:04 +00:00
|
|
|
)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, notifications, 1)
|
|
|
|
require.Equal(t, nID2, notifications[0].ID)
|
|
|
|
|
2023-03-03 14:31:48 +00:00
|
|
|
_, notifications, err = p.ActivityCenterNotifications(
|
2023-02-24 23:47:04 +00:00
|
|
|
initialCursor,
|
|
|
|
limit,
|
|
|
|
[]ActivityCenterType{ActivityCenterNotificationTypeMention},
|
2023-03-03 14:31:48 +00:00
|
|
|
ActivityCenterQueryParamsReadUnread,
|
|
|
|
false,
|
2023-02-24 23:47:04 +00:00
|
|
|
)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, notifications, 2)
|
|
|
|
require.Equal(t, nID3, notifications[0].ID)
|
|
|
|
require.Equal(t, nID1, notifications[1].ID)
|
|
|
|
|
2023-03-03 14:31:48 +00:00
|
|
|
_, notifications, err = p.ActivityCenterNotifications(
|
2023-02-24 23:47:04 +00:00
|
|
|
initialCursor,
|
|
|
|
limit,
|
|
|
|
[]ActivityCenterType{ActivityCenterNotificationTypeMention, ActivityCenterNotificationTypeNewOneToOne},
|
2023-03-03 14:31:48 +00:00
|
|
|
ActivityCenterQueryParamsReadUnread,
|
|
|
|
false,
|
2023-02-24 23:47:04 +00:00
|
|
|
)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, notifications, 3)
|
|
|
|
require.Equal(t, nID3, notifications[0].ID)
|
|
|
|
require.Equal(t, nID2, notifications[1].ID)
|
|
|
|
require.Equal(t, nID1, notifications[2].ID)
|
|
|
|
|
|
|
|
// Mark all notifications as read.
|
|
|
|
for _, notification := range allNotifications {
|
2023-06-10 02:00:17 +00:00
|
|
|
err = p.MarkActivityCenterNotificationsRead([]types.HexBytes{notification.ID}, currentMilliseconds())
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
2023-03-03 14:31:48 +00:00
|
|
|
_, notifications, err = p.ActivityCenterNotifications(
|
2023-02-24 23:47:04 +00:00
|
|
|
initialCursor,
|
|
|
|
limit,
|
|
|
|
[]ActivityCenterType{ActivityCenterNotificationTypeNewOneToOne},
|
2023-03-03 14:31:48 +00:00
|
|
|
ActivityCenterQueryParamsReadRead,
|
|
|
|
false,
|
2023-02-24 23:47:04 +00:00
|
|
|
)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, notifications, 1)
|
|
|
|
require.Equal(t, nID2, notifications[0].ID)
|
|
|
|
|
2023-03-03 14:31:48 +00:00
|
|
|
_, notifications, err = p.ActivityCenterNotifications(
|
2023-02-24 23:47:04 +00:00
|
|
|
initialCursor,
|
|
|
|
limit,
|
|
|
|
[]ActivityCenterType{ActivityCenterNotificationTypeMention},
|
2023-03-03 14:31:48 +00:00
|
|
|
ActivityCenterQueryParamsReadRead,
|
|
|
|
false,
|
2023-02-24 23:47:04 +00:00
|
|
|
)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, notifications, 2)
|
|
|
|
require.Equal(t, nID3, notifications[0].ID)
|
|
|
|
require.Equal(t, nID1, notifications[1].ID)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestActivityCenterReadUnread(t *testing.T) {
|
|
|
|
nID1 := types.HexBytes("1")
|
|
|
|
nID2 := types.HexBytes("2")
|
|
|
|
|
|
|
|
db, err := openTestDB()
|
|
|
|
require.NoError(t, err)
|
|
|
|
p := newSQLitePersistence(db)
|
|
|
|
|
|
|
|
chat := CreatePublicChat("test-chat", &testTimeSource{})
|
2023-08-18 11:39:59 +00:00
|
|
|
message := common.NewMessage()
|
2023-02-24 23:47:04 +00:00
|
|
|
message.Text = "sample text"
|
|
|
|
chat.LastMessage = message
|
|
|
|
err = p.SaveChat(*chat)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
notification := &ActivityCenterNotification{
|
|
|
|
ID: nID1,
|
|
|
|
Type: ActivityCenterNotificationTypeNewOneToOne,
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Timestamp: 1,
|
|
|
|
}
|
|
|
|
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.SaveActivityCenterNotification(notification, true)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
notification = &ActivityCenterNotification{
|
|
|
|
ID: nID2,
|
|
|
|
Type: ActivityCenterNotificationTypeNewOneToOne,
|
|
|
|
ChatID: chat.ID,
|
|
|
|
Timestamp: 1,
|
|
|
|
}
|
|
|
|
|
2023-06-10 02:00:17 +00:00
|
|
|
_, err = p.SaveActivityCenterNotification(notification, true)
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Mark the notification as read
|
2023-06-10 02:00:17 +00:00
|
|
|
err = p.MarkActivityCenterNotificationsRead([]types.HexBytes{nID2}, currentMilliseconds())
|
2023-02-24 23:47:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2023-03-03 14:31:48 +00:00
|
|
|
cursor, notifications, err := p.ActivityCenterNotifications(
|
2023-02-24 23:47:04 +00:00
|
|
|
"",
|
|
|
|
2,
|
|
|
|
[]ActivityCenterType{ActivityCenterNotificationTypeNewOneToOne},
|
2023-03-03 14:31:48 +00:00
|
|
|
ActivityCenterQueryParamsReadUnread,
|
|
|
|
false,
|
2023-02-24 23:47:04 +00:00
|
|
|
)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Empty(t, cursor)
|
|
|
|
require.Len(t, notifications, 1)
|
|
|
|
require.Equal(t, nID1, notifications[0].ID)
|
|
|
|
|
2023-03-03 14:31:48 +00:00
|
|
|
cursor, notifications, err = p.ActivityCenterNotifications(
|
2023-02-24 23:47:04 +00:00
|
|
|
"",
|
|
|
|
2,
|
|
|
|
[]ActivityCenterType{ActivityCenterNotificationTypeNewOneToOne},
|
2023-03-03 14:31:48 +00:00
|
|
|
ActivityCenterQueryParamsReadRead,
|
|
|
|
false,
|
2023-02-24 23:47:04 +00:00
|
|
|
)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Empty(t, cursor)
|
|
|
|
require.Len(t, notifications, 1)
|
|
|
|
require.Equal(t, nID2, notifications[0].ID)
|
|
|
|
}
|