test(whatsapp): add group trigger filtering tests
Covers the four cases introduced by the group_trigger fix: - mention_only: group message without mention is dropped - mention_only: group message with mentioned:true is forwarded - mention_only: group message with non-empty mentions array is forwarded - mention_only: DMs are always forwarded regardless of config - prefix: matching prefix is forwarded with prefix stripped - prefix: non-matching message is dropped - no config: permissive default forwards everything https://claude.ai/code/session_01PfpBofWnnVaNf7uyBEJA4T
This commit is contained in:
parent
ba57c99699
commit
55c15b8e29
1 changed files with 133 additions and 0 deletions
|
|
@ -9,6 +9,32 @@ import (
|
|||
"github.com/sipeed/picoclaw/pkg/config"
|
||||
)
|
||||
|
||||
func newTestChannel(gt config.GroupTriggerConfig) (*WhatsAppChannel, *bus.MessageBus) {
|
||||
messageBus := bus.NewMessageBus()
|
||||
cfg := config.WhatsAppConfig{GroupTrigger: gt}
|
||||
ch := &WhatsAppChannel{
|
||||
BaseChannel: channels.NewBaseChannel("whatsapp", cfg, messageBus, nil,
|
||||
channels.WithGroupTrigger(cfg.GroupTrigger),
|
||||
),
|
||||
ctx: context.Background(),
|
||||
}
|
||||
return ch, messageBus
|
||||
}
|
||||
|
||||
// drainInbound returns the next non-observe-only message from the bus, if any.
|
||||
// ObserveOnly messages (recorded by ObserveGroupMessage) are not counted as "forwarded".
|
||||
func drainInbound(mb *bus.MessageBus) (bus.InboundMessage, bool) {
|
||||
select {
|
||||
case msg := <-mb.InboundChan():
|
||||
if msg.ObserveOnly {
|
||||
return bus.InboundMessage{}, false
|
||||
}
|
||||
return msg, true
|
||||
default:
|
||||
return bus.InboundMessage{}, false
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleIncomingMessage_DoesNotConsumeGenericCommandsLocally(t *testing.T) {
|
||||
messageBus := bus.NewMessageBus()
|
||||
ch := &WhatsAppChannel{
|
||||
|
|
@ -35,3 +61,110 @@ func TestHandleIncomingMessage_DoesNotConsumeGenericCommandsLocally(t *testing.T
|
|||
t.Fatalf("content=%q", inbound.Content)
|
||||
}
|
||||
}
|
||||
|
||||
// TestGroupTrigger_MentionOnly verifies that with mention_only:true the bot
|
||||
// ignores group messages unless the bridge signals a mention.
|
||||
func TestGroupTrigger_MentionOnly(t *testing.T) {
|
||||
gt := config.GroupTriggerConfig{MentionOnly: true}
|
||||
|
||||
t.Run("group message without mention is dropped", func(t *testing.T) {
|
||||
ch, mb := newTestChannel(gt)
|
||||
ch.handleIncomingMessage(map[string]any{
|
||||
"from": "user1",
|
||||
"chat": "group1",
|
||||
"content": "hello everyone",
|
||||
})
|
||||
if _, ok := drainInbound(mb); ok {
|
||||
t.Fatal("expected message to be dropped, but it was forwarded")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("group message with mentioned:true is forwarded", func(t *testing.T) {
|
||||
ch, mb := newTestChannel(gt)
|
||||
ch.handleIncomingMessage(map[string]any{
|
||||
"from": "user1",
|
||||
"chat": "group1",
|
||||
"content": "hey bot",
|
||||
"mentioned": true,
|
||||
})
|
||||
msg, ok := drainInbound(mb)
|
||||
if !ok {
|
||||
t.Fatal("expected message to be forwarded, but it was dropped")
|
||||
}
|
||||
if msg.Content != "hey bot" {
|
||||
t.Fatalf("content=%q", msg.Content)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("group message with non-empty mentions array is forwarded", func(t *testing.T) {
|
||||
ch, mb := newTestChannel(gt)
|
||||
ch.handleIncomingMessage(map[string]any{
|
||||
"from": "user1",
|
||||
"chat": "group1",
|
||||
"content": "hey bot",
|
||||
"mentions": []any{"botjid@s.whatsapp.net"},
|
||||
})
|
||||
if _, ok := drainInbound(mb); !ok {
|
||||
t.Fatal("expected message to be forwarded, but it was dropped")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("DM is always forwarded regardless of mention_only", func(t *testing.T) {
|
||||
ch, mb := newTestChannel(gt)
|
||||
ch.handleIncomingMessage(map[string]any{
|
||||
"from": "user1",
|
||||
"chat": "user1", // chat == sender → DM
|
||||
"content": "private message",
|
||||
})
|
||||
if _, ok := drainInbound(mb); !ok {
|
||||
t.Fatal("expected DM to be forwarded, but it was dropped")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TestGroupTrigger_Prefix verifies prefix-based group trigger filtering.
|
||||
func TestGroupTrigger_Prefix(t *testing.T) {
|
||||
gt := config.GroupTriggerConfig{Prefixes: []string{"/ask"}}
|
||||
|
||||
t.Run("group message with matching prefix is forwarded and prefix stripped", func(t *testing.T) {
|
||||
ch, mb := newTestChannel(gt)
|
||||
ch.handleIncomingMessage(map[string]any{
|
||||
"from": "user1",
|
||||
"chat": "group1",
|
||||
"content": "/ask what time is it",
|
||||
})
|
||||
msg, ok := drainInbound(mb)
|
||||
if !ok {
|
||||
t.Fatal("expected message to be forwarded")
|
||||
}
|
||||
if msg.Content != "what time is it" {
|
||||
t.Fatalf("content=%q, want %q", msg.Content, "what time is it")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("group message without prefix is dropped", func(t *testing.T) {
|
||||
ch, mb := newTestChannel(gt)
|
||||
ch.handleIncomingMessage(map[string]any{
|
||||
"from": "user1",
|
||||
"chat": "group1",
|
||||
"content": "hello",
|
||||
})
|
||||
if _, ok := drainInbound(mb); ok {
|
||||
t.Fatal("expected message to be dropped")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TestGroupTrigger_NoConfig verifies that without any group_trigger config the
|
||||
// bot responds to all group messages (permissive default).
|
||||
func TestGroupTrigger_NoConfig(t *testing.T) {
|
||||
ch, mb := newTestChannel(config.GroupTriggerConfig{})
|
||||
ch.handleIncomingMessage(map[string]any{
|
||||
"from": "user1",
|
||||
"chat": "group1",
|
||||
"content": "any message",
|
||||
})
|
||||
if _, ok := drainInbound(mb); !ok {
|
||||
t.Fatal("expected message to be forwarded with no group_trigger config")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue