100 lines
3.3 KiB
Go
100 lines
3.3 KiB
Go
package postgres
|
||
|
||
import (
|
||
"context"
|
||
"testing"
|
||
|
||
"telesrv/internal/domain"
|
||
)
|
||
|
||
// TestChannelDialogTopMessageCarriesMentionFlags 复现 @ 角标重启回潮:
|
||
// getDialogs 的 channel top message 必须按 viewer 携带 mentioned/media_unread,
|
||
// 否则 TDesktop 先入缓存的残缺版永不触发 contents-read,服务端 unread
|
||
// 提及挂死、每次冷启动 unread_mentions_count 把 @ 角标带回来。
|
||
func TestChannelDialogTopMessageCarriesMentionFlags(t *testing.T) {
|
||
pool := testPool(t)
|
||
ctx := context.Background()
|
||
suffix := randomSuffix(t)
|
||
|
||
users := NewUserStore(pool)
|
||
owner, err := users.Create(ctx, domain.User{AccessHash: 97, Phone: "+1675" + suffix + "01", FirstName: "MentionOwner"})
|
||
if err != nil {
|
||
t.Fatalf("create owner: %v", err)
|
||
}
|
||
member, err := users.Create(ctx, domain.User{AccessHash: 98, Phone: "+1675" + suffix + "02", FirstName: "MentionMember"})
|
||
if err != nil {
|
||
t.Fatalf("create member: %v", err)
|
||
}
|
||
t.Cleanup(func() {
|
||
_, _ = pool.Exec(ctx, "DELETE FROM users WHERE id = ANY($1::bigint[])", []int64{owner.ID, member.ID})
|
||
})
|
||
|
||
channels := NewChannelStore(pool)
|
||
created, err := channels.CreateChannel(ctx, domain.CreateChannelRequest{
|
||
CreatorUserID: owner.ID,
|
||
Title: "MentionDialog " + suffix,
|
||
Megagroup: true,
|
||
MemberUserIDs: []int64{member.ID},
|
||
Date: 1700000910,
|
||
})
|
||
if err != nil {
|
||
t.Fatalf("create channel: %v", err)
|
||
}
|
||
sent, err := channels.SendChannelMessage(ctx, domain.SendChannelMessageRequest{
|
||
UserID: owner.ID,
|
||
ChannelID: created.Channel.ID,
|
||
RandomID: 851001,
|
||
Message: "ping member",
|
||
MentionUserIDs: []int64{member.ID},
|
||
Date: 1700000911,
|
||
})
|
||
if err != nil {
|
||
t.Fatalf("send mention: %v", err)
|
||
}
|
||
|
||
assertFlags := func(name string, list domain.ChannelDialogList) {
|
||
t.Helper()
|
||
found := false
|
||
for _, msg := range list.Messages {
|
||
if msg.ChannelID != created.Channel.ID || msg.ID != sent.Message.ID {
|
||
continue
|
||
}
|
||
found = true
|
||
if !msg.Mentioned || !msg.MediaUnread {
|
||
t.Fatalf("%s top message flags = mentioned %v media_unread %v, want both true(缺失会让 @ 角标重启回潮)", name, msg.Mentioned, msg.MediaUnread)
|
||
}
|
||
}
|
||
if !found {
|
||
t.Fatalf("%s lacks top message %d: %+v", name, sent.Message.ID, list.Messages)
|
||
}
|
||
}
|
||
|
||
list, err := channels.ListChannelDialogs(ctx, member.ID, domain.DialogFilter{Limit: 50})
|
||
if err != nil {
|
||
t.Fatalf("list channel dialogs: %v", err)
|
||
}
|
||
assertFlags("ListChannelDialogs", list)
|
||
|
||
got, err := channels.GetChannelDialogs(ctx, member.ID, []int64{created.Channel.ID})
|
||
if err != nil {
|
||
t.Fatalf("get channel dialogs: %v", err)
|
||
}
|
||
assertFlags("GetChannelDialogs", got)
|
||
|
||
// 提及读掉后:mentioned 永久保留、media_unread 翻为 false。
|
||
if _, err := channels.ReadChannelMentions(ctx, domain.ReadChannelMentionsRequest{
|
||
UserID: member.ID,
|
||
ChannelID: created.Channel.ID,
|
||
}); err != nil {
|
||
t.Fatalf("read mentions: %v", err)
|
||
}
|
||
after, err := channels.GetChannelDialogs(ctx, member.ID, []int64{created.Channel.ID})
|
||
if err != nil {
|
||
t.Fatalf("get channel dialogs after read: %v", err)
|
||
}
|
||
for _, msg := range after.Messages {
|
||
if msg.ID == sent.Message.ID && (!msg.Mentioned || msg.MediaUnread) {
|
||
t.Fatalf("after read flags = mentioned %v media_unread %v, want mentioned kept with media_unread cleared", msg.Mentioned, msg.MediaUnread)
|
||
}
|
||
}
|
||
}
|