feat(channel): 跨平台 IM 接入抽象契约(UnifiedMessage/PlatformAdapter/Capabilities/Actor 身份)
This commit is contained in:
1 parent
a21176ec0a
commit
c52ddfd9c7
8 files changed
+767
No files matched your search
@@ -0,0 +1,151 @@
|
||||
package adapter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestUnifiedMessageConstruction(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ts := time.Date(2026, 9, 6, 12, 0, 0, 0, time.UTC)
|
||||
msg := UnifiedMessage{
|
||||
Platform: "telegram",
|
||||
ChannelID: "ch-100",
|
||||
ChannelType: ChannelGroup,
|
||||
SenderID: "u-1",
|
||||
SenderName: "Alice",
|
||||
Sender: Actor{
|
||||
Role: RoleOwner,
|
||||
UserID: "u-1",
|
||||
DisplayName: "Alice",
|
||||
GroupID: "g-42",
|
||||
},
|
||||
Content: "hello @bob",
|
||||
ContentType: ContentText,
|
||||
Media: []Media{
|
||||
{Kind: MediaImage, URL: "https://example.com/a.jpg", Name: "a.jpg", Size: 1024, MIMEType: "image/jpeg"},
|
||||
},
|
||||
Mentions: []Mention{
|
||||
{UserID: "u-2", UserName: "Bob"},
|
||||
},
|
||||
ReplyToID: "m-9",
|
||||
ReplyToText: "earlier",
|
||||
GroupID: "g-42",
|
||||
GroupName: "Team",
|
||||
ThreadID: "t-7",
|
||||
MessageID: "m-10",
|
||||
Timestamp: ts,
|
||||
RawData: []byte(`{"id":"m-10"}`),
|
||||
}
|
||||
|
||||
if !msg.IsGroup() {
|
||||
t.Errorf("IsGroup() = false, want true")
|
||||
}
|
||||
if msg.ChannelType != ChannelGroup {
|
||||
t.Errorf("ChannelType = %q, want %q", msg.ChannelType, ChannelGroup)
|
||||
}
|
||||
if msg.ContentType != ContentText {
|
||||
t.Errorf("ContentType = %q, want %q", msg.ContentType, ContentText)
|
||||
}
|
||||
if len(msg.Media) != 1 || msg.Media[0].Kind != MediaImage {
|
||||
t.Errorf("Media = %+v, want one image", msg.Media)
|
||||
}
|
||||
if len(msg.Mentions) != 1 || msg.Mentions[0].UserID != "u-2" {
|
||||
t.Errorf("Mentions = %+v, want one user u-2", msg.Mentions)
|
||||
}
|
||||
if msg.ThreadID != "t-7" {
|
||||
t.Errorf("ThreadID = %q, want t-7", msg.ThreadID)
|
||||
}
|
||||
if msg.Sender.Role != RoleOwner || !msg.Sender.IsOwner() {
|
||||
t.Errorf("Sender = %+v, want owner role", msg.Sender)
|
||||
}
|
||||
if !msg.Timestamp.Equal(ts) {
|
||||
t.Errorf("Timestamp = %v, want %v", msg.Timestamp, ts)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnifiedMessageValidate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
msg UnifiedMessage
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "valid direct text",
|
||||
msg: UnifiedMessage{ChannelType: ChannelDirect, ContentType: ContentText, Content: "hi"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid group text",
|
||||
msg: UnifiedMessage{
|
||||
ChannelType: ChannelGroup, ContentType: ContentText, GroupID: "g-1", Content: "hi",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "group missing id",
|
||||
msg: UnifiedMessage{
|
||||
ChannelType: ChannelGroup, ContentType: ContentText, Content: "hi",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid channel type",
|
||||
msg: UnifiedMessage{ChannelType: ChannelType("bogus"), ContentType: ContentText},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid content type",
|
||||
msg: UnifiedMessage{ChannelType: ChannelDirect, ContentType: ContentType("bogus")},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := tt.msg.Validate()
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Fatalf("Validate() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestChannelTypeValid(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
valid := []ChannelType{ChannelDirect, ChannelGroup}
|
||||
for _, ct := range valid {
|
||||
if !ct.Valid() {
|
||||
t.Errorf("ChannelType(%q).Valid() = false, want true", ct)
|
||||
}
|
||||
}
|
||||
if ChannelType("").Valid() {
|
||||
t.Error("empty ChannelType.Valid() = true, want false")
|
||||
}
|
||||
if ChannelType("bogus").Valid() {
|
||||
t.Error("bogus ChannelType.Valid() = true, want false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestContentTypeValid(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
valid := []ContentType{ContentText, ContentImage, ContentVoice, ContentFile, ContentAction}
|
||||
for _, ct := range valid {
|
||||
if !ct.Valid() {
|
||||
t.Errorf("ContentType(%q).Valid() = false, want true", ct)
|
||||
}
|
||||
}
|
||||
if ContentType("").Valid() {
|
||||
t.Error("empty ContentType.Valid() = true, want false")
|
||||
}
|
||||
if ContentType("bogus").Valid() {
|
||||
t.Error("bogus ContentType.Valid() = true, want false")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user