|
1
|
package ircagent |
|
2
|
|
|
3
|
import "testing" |
|
4
|
|
|
5
|
func TestMentionsNick(t *testing.T) { |
|
6
|
t.Helper() |
|
7
|
|
|
8
|
tests := []struct { |
|
9
|
name string |
|
10
|
text string |
|
11
|
nick string |
|
12
|
want bool |
|
13
|
}{ |
|
14
|
{name: "simple mention", text: "codex: hello", nick: "codex", want: true}, |
|
15
|
{name: "mention in sentence", text: "hey codex can you help", nick: "codex", want: true}, |
|
16
|
{name: "path does not trigger", text: "look at .claude/hooks/settings.json", nick: "claude", want: false}, |
|
17
|
{name: "windows path does not trigger", text: `check C:\Users\me\.codex\hooks`, nick: "codex", want: false}, |
|
18
|
{name: "substring does not trigger", text: "codexagent is a process", nick: "codex", want: false}, |
|
19
|
{name: "hyphen boundary does not trigger", text: "claude-scuttlebot-a1b2c3d4 posted status", nick: "claude", want: false}, |
|
20
|
} |
|
21
|
|
|
22
|
for _, tt := range tests { |
|
23
|
t.Run(tt.name, func(t *testing.T) { |
|
24
|
got := MentionsNick(tt.text, tt.nick) |
|
25
|
if got != tt.want { |
|
26
|
t.Fatalf("MentionsNick(%q, %q) = %v, want %v", tt.text, tt.nick, got, tt.want) |
|
27
|
} |
|
28
|
}) |
|
29
|
} |
|
30
|
} |
|
31
|
|
|
32
|
func TestSplitCSV(t *testing.T) { |
|
33
|
t.Helper() |
|
34
|
|
|
35
|
got := SplitCSV(" #general, #fleet ,, #agent.codex ") |
|
36
|
want := []string{"#general", "#fleet", "#agent.codex"} |
|
37
|
if len(got) != len(want) { |
|
38
|
t.Fatalf("len(SplitCSV) = %d, want %d", len(got), len(want)) |
|
39
|
} |
|
40
|
for i := range want { |
|
41
|
if got[i] != want[i] { |
|
42
|
t.Fatalf("SplitCSV()[%d] = %q, want %q", i, got[i], want[i]) |
|
43
|
} |
|
44
|
} |
|
45
|
} |
|
46
|
|
|
47
|
func TestHasAnyPrefix(t *testing.T) { |
|
48
|
t.Helper() |
|
49
|
|
|
50
|
prefixes := []string{"claude-", "codex-", "gemini-"} |
|
51
|
if !HasAnyPrefix("claude-abc", prefixes) { |
|
52
|
t.Fatalf("expected claude prefix match") |
|
53
|
} |
|
54
|
if !HasAnyPrefix("codex-1234", prefixes) { |
|
55
|
t.Fatalf("expected codex prefix match") |
|
56
|
} |
|
57
|
if !HasAnyPrefix("gemini-1234", prefixes) { |
|
58
|
t.Fatalf("expected gemini prefix match") |
|
59
|
} |
|
60
|
if HasAnyPrefix("glengoolie", prefixes) { |
|
61
|
t.Fatalf("did not expect non-activity sender to match") |
|
62
|
} |
|
63
|
} |
|
64
|
|
|
65
|
func TestTrimAddressedText(t *testing.T) { |
|
66
|
t.Helper() |
|
67
|
|
|
68
|
tests := []struct { |
|
69
|
name string |
|
70
|
text string |
|
71
|
nick string |
|
72
|
want string |
|
73
|
}{ |
|
74
|
{name: "colon address", text: "codex-scuttlebot-1234: read README.md", nick: "codex-scuttlebot-1234", want: "read README.md"}, |
|
75
|
{name: "comma address", text: "codex, status?", nick: "codex", want: "status?"}, |
|
76
|
{name: "plain text stays", text: "hello there", nick: "codex", want: "hello there"}, |
|
77
|
} |
|
78
|
|
|
79
|
for _, tt := range tests { |
|
80
|
t.Run(tt.name, func(t *testing.T) { |
|
81
|
got := TrimAddressedText(tt.text, tt.nick) |
|
82
|
if got != tt.want { |
|
83
|
t.Fatalf("TrimAddressedText(%q, %q) = %q, want %q", tt.text, tt.nick, got, tt.want) |
|
84
|
} |
|
85
|
}) |
|
86
|
} |
|
87
|
} |
|
88
|
|
|
89
|
func TestMatchesGroupMention(t *testing.T) { |
|
90
|
tests := []struct { |
|
91
|
name, text, nick, agentType string |
|
92
|
want bool |
|
93
|
}{ |
|
94
|
{"@all matches everyone", "@all stop working", "claude-kohakku-abc", "worker", true}, |
|
95
|
{"@all mid-sentence", "hey @all check this", "gemini-foo-123", "worker", true}, |
|
96
|
{"@worker matches worker type", "@worker report status", "claude-kohakku-abc", "worker", true}, |
|
97
|
{"@worker doesn't match observer", "@worker report", "obs-bot", "observer", false}, |
|
98
|
{"@observer matches observer", "@observer watch this", "obs-bot", "observer", true}, |
|
99
|
{"@claude-* matches claude agents", "@claude-* pause", "claude-kohakku-abc", "worker", true}, |
|
100
|
{"@claude-* doesn't match gemini", "@claude-* pause", "gemini-kohakku-abc", "worker", false}, |
|
101
|
{"@claude-kohakku-* matches specific", "@claude-kohakku-* stop", "claude-kohakku-abc", "worker", true}, |
|
102
|
{"@gemini-* matches gemini", "@gemini-* summarize", "gemini-proj-123", "worker", true}, |
|
103
|
{"no mention no match", "hello world", "claude-abc", "worker", false}, |
|
104
|
{"partial @all no match", "install @alloy", "claude-abc", "worker", false}, |
|
105
|
} |
|
106
|
for _, tt := range tests { |
|
107
|
t.Run(tt.name, func(t *testing.T) { |
|
108
|
got := MatchesGroupMention(tt.text, tt.nick, tt.agentType) |
|
109
|
if got != tt.want { |
|
110
|
t.Errorf("MatchesGroupMention(%q, %q, %q) = %v, want %v", tt.text, tt.nick, tt.agentType, got, tt.want) |
|
111
|
} |
|
112
|
}) |
|
113
|
} |
|
114
|
} |
|
115
|
|