owpengram-server/internal/rpc/convert_channels_monoforum_test.go

113 lines
5.8 KiB
Go

package rpc
import (
"testing"
"telesrv/internal/domain"
)
// TestTgChannelMonoforumSuppressesCreatorChrome 锁定频道私信(monoforum)渲染修复的核心不变量:
// monoforum 虚拟频道在 TDesktop 必须呈现为 Direct-Messages 容器而非普通群。真机 bug 的根因是
// mono 自身被投影了 Creator=true —— TDesktop 的 NeedAboutGroup 对 megagroup 看 amCreator() 决定
// 画 "You created a group" 群聊空状态,Leave/订阅数 chrome 也 key off amCreator/asMegagroup。
// DM 容器身份(本地 MonoforumAdmin 标志)由客户端从母频道 canAccessMonoforum 派生,与 mono 自身无关。
func TestTgChannelMonoforumSuppressesCreatorChrome(t *testing.T) {
const owner = int64(1001)
const parentID = int64(5001)
const monoID = int64(5002)
mono := domain.Channel{
ID: monoID, CreatorUserID: owner, Title: "Parent",
Megagroup: true, Monoforum: true, LinkedMonoforumID: parentID,
// monoforum 镜像母频道 DM 启用状态;启用时才下发 linked_monoforum_id。
BroadcastMessagesAllowed: true,
}
// 即便带 creator 角色的 synthetic self(admin 预览),mono 自身对象也必须 Creator=false / 无 admin_rights。
syntheticSelf := &domain.ChannelMember{ChannelID: monoID, UserID: owner, Status: domain.ChannelMemberActive, Role: domain.ChannelRoleCreator}
monoTg := tgChannel(owner, mono, syntheticSelf)
if !monoTg.Megagroup || !monoTg.Monoforum {
t.Fatalf("mono megagroup=%v monoforum=%v, want both true", monoTg.Megagroup, monoTg.Monoforum)
}
if monoTg.Creator {
t.Fatalf("mono Creator=true, want false (Creator=true paints the wrong group chrome)")
}
if _, ok := monoTg.GetAdminRights(); ok {
t.Fatalf("mono must carry no admin_rights (admin status derived client-side from parent)")
}
if monoTg.Left {
t.Fatalf("mono Left=true, want false")
}
if id, ok := monoTg.GetLinkedMonoforumID(); !ok || id != parentID {
t.Fatalf("mono linked_monoforum_id = %d ok=%v, want parent %d", id, ok, parentID)
}
// 母广播频道对 owner 投影:broadcast-only + Creator=true(canAccessMonoforum 走 amCreator 旁路)
// + broadcast_messages_allowed + 反向 linked_monoforum_id。三者共同让客户端派生 MonoforumAdmin。
parent := domain.Channel{
ID: parentID, CreatorUserID: owner, Title: "Parent",
Broadcast: true, BroadcastMessagesAllowed: true, LinkedMonoforumID: monoID,
}
parentTg := tgChannel(owner, parent, nil)
if !parentTg.Broadcast || parentTg.Megagroup || parentTg.Monoforum {
t.Fatalf("parent broadcast=%v mega=%v mono=%v, want broadcast only", parentTg.Broadcast, parentTg.Megagroup, parentTg.Monoforum)
}
if !parentTg.Creator {
t.Fatalf("parent Creator=false for owner viewer, want true (canAccessMonoforum via amCreator)")
}
if !parentTg.BroadcastMessagesAllowed {
t.Fatalf("parent broadcast_messages_allowed=false, want true")
}
if id, ok := parentTg.GetLinkedMonoforumID(); !ok || id != monoID {
t.Fatalf("parent linked_monoforum_id = %d ok=%v, want mono %d", id, ok, monoID)
}
// 普通频道(Monoforum=false)不受影响:creator self 仍投影 Creator=true。
normal := domain.Channel{ID: 6001, CreatorUserID: owner, Title: "Normal", Megagroup: true}
normalTg := tgChannel(owner, normal, &domain.ChannelMember{ChannelID: 6001, UserID: owner, Status: domain.ChannelMemberActive, Role: domain.ChannelRoleCreator})
if !normalTg.Creator {
t.Fatalf("normal megagroup creator suppressed; monoforum guard leaked to non-monoforum channels")
}
}
// TestChannelAdminRightsManageDirectMessagesRoundTrip 证明新映射的 manage_direct_messages(flags.17)
// 双向无损,且对未设置该权限的普通管理员保持惰性(不污染线格式)。
func TestChannelAdminRightsManageDirectMessagesRoundTrip(t *testing.T) {
tgRights := tgChatAdminRights(domain.ChannelAdminRights{ManageDirectMessages: true, PostMessages: true})
if !tgRights.ManageDirectMessages {
t.Fatalf("tg ManageDirectMessages=false, want true")
}
if back := domainChannelAdminRights(tgRights); !back.ManageDirectMessages {
t.Fatalf("round-trip dropped ManageDirectMessages")
}
if plain := tgChatAdminRights(domain.ChannelAdminRights{PinMessages: true}); plain.ManageDirectMessages {
t.Fatalf("normal admin rights wrongly set ManageDirectMessages (not inert)")
}
}
// TestTgChannelMonoforumDisabledHidesLink 锁定关闭 Direct Messages 时的投影:母频道与 monoforum
// **双方都**隐藏 linked_monoforum_id(都以 BroadcastMessagesAllowed 表示 DM 启用,关闭时为 false)。
// monoforum 必须也隐藏 —— 否则用户打开 monoforum 重新拉取频道对象时,mono 仍带 link →
// setMonoforumLink(parent) 触发 link&&monoforumDisabled 分支把 MonoforumDisabled 清掉,「已停用私信」
// 停用页脚消失。monoforum 自身绝不投影 broadcast_messages_allowed(它是 megagroup)。
func TestTgChannelMonoforumDisabledHidesLink(t *testing.T) {
const owner = int64(1001)
const parentID = int64(5001)
const monoID = int64(5002)
parent := domain.Channel{ID: parentID, CreatorUserID: owner, Broadcast: true, LinkedMonoforumID: monoID, BroadcastMessagesAllowed: false}
if _, ok := tgChannel(owner, parent, nil).GetLinkedMonoforumID(); ok {
t.Fatalf("disabled parent projected linked_monoforum_id, want hidden")
}
mono := domain.Channel{ID: monoID, CreatorUserID: owner, Megagroup: true, Monoforum: true, LinkedMonoforumID: parentID, BroadcastMessagesAllowed: false}
monoTg := tgChannel(owner, mono, nil)
if _, ok := monoTg.GetLinkedMonoforumID(); ok {
t.Fatalf("disabled monoforum projected linked_monoforum_id, want hidden (else opening it clears MonoforumDisabled → footer disappears)")
}
if !monoTg.Monoforum || !monoTg.Megagroup {
t.Fatalf("disabled mono monoforum=%v mega=%v, want both still true", monoTg.Monoforum, monoTg.Megagroup)
}
if monoTg.BroadcastMessagesAllowed {
t.Fatalf("monoforum leaked broadcast_messages_allowed, want never projected (it is a megagroup)")
}
}