Files
Cyrene_v2/internal/channel/adapter/adapter_test.go
T

108 lines
3.1 KiB
Go

package adapter
import (
"context"
"testing"
)
// mockAdapter is a minimal in-memory PlatformAdapter used to prove the
// interface is satisfiable and to exercise its surface. It mocks the contract,
// not a concrete adapter type.
type mockAdapter struct {
name string
cfg map[string]any
caps Capabilities
handler MessageHandler
sent []UnifiedMessage
}
func (m *mockAdapter) Name() string { return m.name }
func (m *mockAdapter) Config() map[string]any { return m.cfg }
func (m *mockAdapter) Connect(context.Context) error {
return nil
}
func (m *mockAdapter) Disconnect(context.Context) error { return nil }
func (m *mockAdapter) IsConnected() bool { return true }
func (m *mockAdapter) HealthCheck(context.Context) error {
return nil
}
func (m *mockAdapter) ReadMessages(context.Context, func(UnifiedMessage)) {}
func (m *mockAdapter) SendMessage(_ context.Context, resp UnifiedResponse) error {
m.sent = resp.Messages
return nil
}
func (m *mockAdapter) SendProactive(context.Context, UnifiedMessage) error { return nil }
func (m *mockAdapter) SetMessageHandler(fn MessageHandler) { m.handler = fn }
func (m *mockAdapter) Capabilities() Capabilities { return m.caps }
func (m *mockAdapter) ListChannels(context.Context) ([]ChannelInfo, error) {
return nil, nil
}
// Interface conformance is enforced at compile time.
var _ PlatformAdapter = (*mockAdapter)(nil)
func TestMockAdapterSatisfiesContract(t *testing.T) {
t.Parallel()
ad := &mockAdapter{
name: "telegram",
cfg: map[string]any{"token": "t-1"},
caps: DefaultCapabilities(),
}
if got := ad.Name(); got != "telegram" {
t.Errorf("Name() = %q, want telegram", got)
}
if got := ad.Config()["token"]; got != "t-1" {
t.Errorf("Config() token = %v, want t-1", got)
}
if got := ad.IsConnected(); !got {
t.Error("IsConnected() = false, want true")
}
if got := ad.Capabilities().MaxMessageLength; got != defaultMaxMessageLength {
t.Errorf("Capabilities().MaxMessageLength = %d, want %d", got, defaultMaxMessageLength)
}
}
func TestMockAdapterSendMessageRecords(t *testing.T) {
t.Parallel()
ad := &mockAdapter{}
msg := UnifiedMessage{ChannelType: ChannelDirect, ContentType: ContentText, Content: "pong"}
resp := UnifiedResponse{Messages: []UnifiedMessage{msg}, ReplyTo: "m-1", Hint: "ok"}
if err := ad.SendMessage(context.Background(), resp); err != nil {
t.Fatalf("SendMessage() error = %v", err)
}
if len(ad.sent) != 1 || ad.sent[0].Content != "pong" {
t.Errorf("sent = %+v, want one message with content pong", ad.sent)
}
}
func TestDecodeConfig(t *testing.T) {
t.Parallel()
type cfg struct {
Token string
Port int
}
raw := map[string]any{"token": "abc", "port": 8080}
var c cfg
if err := DecodeConfig(raw, &c); err != nil {
t.Fatalf("DecodeConfig() error = %v", err)
}
if c.Token != "abc" || c.Port != 8080 {
t.Errorf("DecodeConfig() = %+v, want {abc 8080}", c)
}
}
func TestDecodeConfigNil(t *testing.T) {
t.Parallel()
var c struct{ Token string }
if err := DecodeConfig(nil, &c); err == nil {
t.Error("DecodeConfig(nil, ...) error = nil, want non-nil")
}
}