215 lines
9 KiB
Go
215 lines
9 KiB
Go
package postgres
|
|
|
|
import (
|
|
"context"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"telesrv/internal/domain"
|
|
)
|
|
|
|
func TestMessageStorePrivateMessageReactionsUseOwnerVisibleBoxIDs(t *testing.T) {
|
|
pool := testPool(t)
|
|
ctx := context.Background()
|
|
suffix := randomSuffix(t)
|
|
|
|
users := NewUserStore(pool)
|
|
sender := createTestUser(t, ctx, users, "+1994"+suffix+"01", "ReactionSender", "")
|
|
recipient := createTestUser(t, ctx, users, "+1994"+suffix+"02", "ReactionRecipient", "")
|
|
t.Cleanup(func() {
|
|
_, _ = pool.Exec(ctx, "DELETE FROM users WHERE id = ANY($1::bigint[])", []int64{sender.ID, recipient.ID})
|
|
})
|
|
|
|
messages := NewMessageStore(pool)
|
|
sent, err := messages.SendPrivateText(ctx, domain.SendPrivateTextRequest{
|
|
SenderUserID: sender.ID,
|
|
RecipientUserID: recipient.ID,
|
|
RandomID: 99401,
|
|
Message: "react to me",
|
|
Date: 1700000940,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("SendPrivateText: %v", err)
|
|
}
|
|
|
|
reaction := domain.MessageReaction{Type: domain.MessageReactionEmoji, Emoticon: "\U0001f44d"}
|
|
res, err := messages.SetMessageReactions(ctx, domain.SetPrivateMessageReactionsRequest{
|
|
UserID: recipient.ID,
|
|
Peer: domain.Peer{Type: domain.PeerTypeUser, ID: sender.ID},
|
|
MessageID: sent.RecipientMessage.ID,
|
|
Reactions: []domain.MessageReaction{
|
|
reaction,
|
|
},
|
|
Big: true,
|
|
Date: 1700000950,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("SetMessageReactions: %v", err)
|
|
}
|
|
if len(res.Messages) != 2 {
|
|
t.Fatalf("reaction result messages = %d, want both owner boxes", len(res.Messages))
|
|
}
|
|
byOwner := make(map[int64]domain.Message, len(res.Messages))
|
|
for _, msg := range res.Messages {
|
|
byOwner[msg.OwnerUserID] = msg
|
|
}
|
|
senderMsg, ok := byOwner[sender.ID]
|
|
if !ok {
|
|
t.Fatalf("reaction result = %+v, want sender owner box", res.Messages)
|
|
}
|
|
if senderMsg.ID != sent.SenderMessage.ID || !senderMsg.ReactionUnread {
|
|
t.Fatalf("sender reaction box = %+v, want sender msg id %d with reaction_unread", senderMsg, sent.SenderMessage.ID)
|
|
}
|
|
recipientMsg, ok := byOwner[recipient.ID]
|
|
if !ok {
|
|
t.Fatalf("reaction result = %+v, want recipient owner box", res.Messages)
|
|
}
|
|
if recipientMsg.ID != sent.RecipientMessage.ID || recipientMsg.ReactionUnread {
|
|
t.Fatalf("recipient reaction box = %+v, want recipient msg id %d without reaction_unread", recipientMsg, sent.RecipientMessage.ID)
|
|
}
|
|
|
|
senderReactions, err := messages.GetMessageReactions(ctx, domain.PrivateMessageReactionsRequest{
|
|
OwnerUserID: sender.ID,
|
|
Peer: domain.Peer{Type: domain.PeerTypeUser, ID: recipient.ID},
|
|
IDs: []int{sent.SenderMessage.ID},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("sender GetMessageReactions: %v", err)
|
|
}
|
|
if len(senderReactions.Messages) != 1 || senderReactions.Messages[0].Reactions == nil {
|
|
t.Fatalf("sender reactions = %+v, want one enriched message", senderReactions)
|
|
}
|
|
if got := senderReactions.Messages[0].Reactions.Results; len(got) != 1 || got[0].Reaction != reaction || got[0].Count != 1 || got[0].ChosenOrder != 0 {
|
|
t.Fatalf("sender reaction counts = %+v, want one peer reaction without chosen order", got)
|
|
}
|
|
if got := senderReactions.Messages[0].Reactions.Recent; len(got) != 1 || got[0].UserID != recipient.ID || got[0].SenderUserID != sender.ID || !got[0].Unread || !got[0].Big || got[0].My {
|
|
t.Fatalf("sender recent reactions = %+v, want recipient non-my big reaction", got)
|
|
}
|
|
senderBox, err := messages.GetByIDs(ctx, sender.ID, []int{sent.SenderMessage.ID})
|
|
if err != nil {
|
|
t.Fatalf("sender GetByIDs after reaction: %v", err)
|
|
}
|
|
if len(senderBox.Messages) != 1 || !senderBox.Messages[0].ReactionUnread {
|
|
t.Fatalf("sender box after reaction = %+v, want reaction_unread", senderBox.Messages)
|
|
}
|
|
read, err := messages.ReadMessageContents(ctx, domain.ReadMessageContentsRequest{
|
|
OwnerUserID: sender.ID,
|
|
IDs: []int{sent.SenderMessage.ID},
|
|
Date: 1700000960,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("ReadMessageContents reaction: %v", err)
|
|
}
|
|
if !reflect.DeepEqual(read.MessageIDs, []int{sent.SenderMessage.ID}) || read.Event.Type != domain.UpdateEventReadMessageContents || read.Event.Pts == 0 {
|
|
t.Fatalf("read reaction contents = %+v, want one read_message_contents event", read)
|
|
}
|
|
senderBox, err = messages.GetByIDs(ctx, sender.ID, []int{sent.SenderMessage.ID})
|
|
if err != nil {
|
|
t.Fatalf("sender GetByIDs after read reaction: %v", err)
|
|
}
|
|
if len(senderBox.Messages) != 1 || senderBox.Messages[0].ReactionUnread {
|
|
t.Fatalf("sender box after read reaction = %+v, want reaction_unread cleared", senderBox.Messages)
|
|
}
|
|
if got := senderBox.Messages[0].Reactions.Recent; len(got) != 1 || got[0].Unread || got[0].SenderUserID != sender.ID {
|
|
t.Fatalf("sender recent reactions after read = %+v, want unread flag cleared", got)
|
|
}
|
|
|
|
recipientReactions, err := messages.GetMessageReactions(ctx, domain.PrivateMessageReactionsRequest{
|
|
OwnerUserID: recipient.ID,
|
|
Peer: domain.Peer{Type: domain.PeerTypeUser, ID: sender.ID},
|
|
IDs: []int{sent.RecipientMessage.ID},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("recipient GetMessageReactions: %v", err)
|
|
}
|
|
if len(recipientReactions.Messages) != 1 || recipientReactions.Messages[0].Reactions == nil {
|
|
t.Fatalf("recipient reactions = %+v, want one enriched message", recipientReactions)
|
|
}
|
|
if got := recipientReactions.Messages[0].Reactions.Results; len(got) != 1 || got[0].Reaction != reaction || got[0].ChosenOrder != 1 {
|
|
t.Fatalf("recipient reaction counts = %+v, want own chosen order", got)
|
|
}
|
|
if got := recipientReactions.Messages[0].Reactions.Recent; len(got) != 1 || got[0].UserID != recipient.ID || got[0].SenderUserID != sender.ID || got[0].Unread || !got[0].My {
|
|
t.Fatalf("recipient recent reactions = %+v, want my reaction", got)
|
|
}
|
|
}
|
|
|
|
func TestDialogTopMessagesCarryPrivateMessageReactions(t *testing.T) {
|
|
pool := testPool(t)
|
|
ctx := context.Background()
|
|
suffix := randomSuffix(t)
|
|
|
|
users := NewUserStore(pool)
|
|
alice := createTestUser(t, ctx, users, "+1995"+suffix+"01", "DialogReactionAlice", "")
|
|
bob := createTestUser(t, ctx, users, "+1995"+suffix+"02", "DialogReactionBob", "")
|
|
t.Cleanup(func() {
|
|
_, _ = pool.Exec(ctx, "DELETE FROM users WHERE id = ANY($1::bigint[])", []int64{alice.ID, bob.ID})
|
|
})
|
|
|
|
messages := NewMessageStore(pool)
|
|
dialogs := NewDialogStore(pool)
|
|
sent, err := messages.SendPrivateText(ctx, domain.SendPrivateTextRequest{
|
|
SenderUserID: alice.ID,
|
|
RecipientUserID: bob.ID,
|
|
RandomID: 99501,
|
|
Message: "latest from alice",
|
|
Date: 1700001950,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("SendPrivateText: %v", err)
|
|
}
|
|
reaction := domain.MessageReaction{Type: domain.MessageReactionEmoji, Emoticon: "\u2764"}
|
|
if _, err := messages.SetMessageReactions(ctx, domain.SetPrivateMessageReactionsRequest{
|
|
UserID: bob.ID,
|
|
Peer: domain.Peer{Type: domain.PeerTypeUser, ID: alice.ID},
|
|
MessageID: sent.RecipientMessage.ID,
|
|
Reactions: []domain.MessageReaction{
|
|
reaction,
|
|
},
|
|
Date: 1700001960,
|
|
}); err != nil {
|
|
t.Fatalf("SetMessageReactions: %v", err)
|
|
}
|
|
|
|
aliceDialogs, err := dialogs.ListByUser(ctx, alice.ID, domain.DialogFilter{Limit: 10})
|
|
if err != nil {
|
|
t.Fatalf("alice ListByUser: %v", err)
|
|
}
|
|
if len(aliceDialogs.Dialogs) != 1 || aliceDialogs.Dialogs[0].TopMessage != sent.SenderMessage.ID || aliceDialogs.Dialogs[0].UnreadReactions != 1 {
|
|
t.Fatalf("alice dialog = %+v, want top message with one unread reaction", aliceDialogs.Dialogs)
|
|
}
|
|
if len(aliceDialogs.Messages) != 1 || aliceDialogs.Messages[0].ID != sent.SenderMessage.ID || aliceDialogs.Messages[0].Reactions == nil {
|
|
t.Fatalf("alice dialog messages = %+v, want enriched top message", aliceDialogs.Messages)
|
|
}
|
|
if got := aliceDialogs.Messages[0].Reactions.Recent; len(got) != 1 || got[0].UserID != bob.ID || got[0].SenderUserID != alice.ID || !got[0].Unread || got[0].My {
|
|
t.Fatalf("alice dialog recent reactions = %+v, want bob unread non-my reaction", got)
|
|
}
|
|
|
|
bobDialogs, err := dialogs.ListByPeers(ctx, bob.ID, []domain.Peer{{Type: domain.PeerTypeUser, ID: alice.ID}})
|
|
if err != nil {
|
|
t.Fatalf("bob ListByPeers: %v", err)
|
|
}
|
|
if len(bobDialogs.Messages) != 1 || bobDialogs.Messages[0].ID != sent.RecipientMessage.ID || bobDialogs.Messages[0].Reactions == nil {
|
|
t.Fatalf("bob peer dialog messages = %+v, want enriched top message", bobDialogs.Messages)
|
|
}
|
|
if got := bobDialogs.Messages[0].Reactions.Recent; len(got) != 1 || got[0].UserID != bob.ID || got[0].SenderUserID != alice.ID || got[0].Unread || !got[0].My {
|
|
t.Fatalf("bob peer dialog recent reactions = %+v, want my read reaction", got)
|
|
}
|
|
|
|
if _, err := messages.ReadMessageContents(ctx, domain.ReadMessageContentsRequest{
|
|
OwnerUserID: alice.ID,
|
|
IDs: []int{sent.SenderMessage.ID},
|
|
Date: 1700001970,
|
|
}); err != nil {
|
|
t.Fatalf("ReadMessageContents: %v", err)
|
|
}
|
|
aliceDialogs, err = dialogs.ListByUser(ctx, alice.ID, domain.DialogFilter{Limit: 10})
|
|
if err != nil {
|
|
t.Fatalf("alice ListByUser after read: %v", err)
|
|
}
|
|
if len(aliceDialogs.Dialogs) != 1 || aliceDialogs.Dialogs[0].UnreadReactions != 0 {
|
|
t.Fatalf("alice dialog after read = %+v, want no unread reactions", aliceDialogs.Dialogs)
|
|
}
|
|
if got := aliceDialogs.Messages[0].Reactions.Recent; len(got) != 1 || got[0].Unread {
|
|
t.Fatalf("alice dialog recent reactions after read = %+v, want unread cleared", got)
|
|
}
|
|
}
|