Use unique user in unknown command test to avoid last-command fallback interference. Add plugin architecture with registered commands. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
115 lines
2.7 KiB
Go
115 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"os/exec"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func makeMsg(user, body string) BotMessage {
|
|
var msg BotMessage
|
|
msg.User.Name = user
|
|
msg.Message.Body.Plain = body
|
|
return msg
|
|
}
|
|
|
|
func qalcAvailable() bool {
|
|
_, err := exec.LookPath("qalc")
|
|
return err == nil
|
|
}
|
|
|
|
func TestExecuteCommand(t *testing.T) {
|
|
tests := []struct {
|
|
user string
|
|
body string
|
|
exact string
|
|
contains []string
|
|
}{
|
|
{user: "anyone", body: "ping", exact: "Pong!"},
|
|
{user: "Alice", body: "hi", exact: "Hello Alice! How are you doing today?"},
|
|
{user: "anyone", body: "help math", contains: []string{"qalc"}},
|
|
{user: "anyone", body: "help bogus", contains: []string{"No help found for 'bogus'"}},
|
|
{user: "anyone", body: "help", contains: []string{"ping", "math", "hi", "trace", "help"}},
|
|
{user: "nobody", body: "unknown command", contains: []string{"Not sure what to do"}},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.body, func(t *testing.T) {
|
|
got := executeCommand(makeMsg(tt.user, tt.body))
|
|
if tt.exact != "" && got != tt.exact {
|
|
t.Errorf("got %q, want %q", got, tt.exact)
|
|
}
|
|
for _, sub := range tt.contains {
|
|
if !strings.Contains(got, sub) {
|
|
t.Errorf("output %q does not contain %q", got, sub)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLastCommandMemoryPing(t *testing.T) {
|
|
user := "testmem-ping-fallback"
|
|
got := executeCommand(makeMsg(user, "ping"))
|
|
if got != "Pong!" {
|
|
t.Fatalf("expected Pong!, got %q", got)
|
|
}
|
|
|
|
got = executeCommand(makeMsg(user, "anything"))
|
|
if got != "Pong!" {
|
|
t.Errorf("expected fallback to ping, got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestLastCommandMemoryMath(t *testing.T) {
|
|
if !qalcAvailable() {
|
|
t.Skip("qalc not on PATH")
|
|
}
|
|
|
|
user := "testmem-math-fallback"
|
|
got := executeCommand(makeMsg(user, "math 2+2"))
|
|
if !strings.Contains(got, "4") {
|
|
t.Fatalf("math 2+2 expected output containing '4', got %q", got)
|
|
}
|
|
|
|
got = executeCommand(makeMsg(user, "3+3"))
|
|
if !strings.Contains(got, "6") {
|
|
t.Errorf("fallback math 3+3 expected output containing '6', got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestSplitFirstWord(t *testing.T) {
|
|
tests := []struct {
|
|
input string
|
|
wantWord string
|
|
wantRest string
|
|
}{
|
|
{"ping", "ping", ""},
|
|
{"math 2+2", "math", "2+2"},
|
|
{"MATH 2+2", "math", "2+2"},
|
|
{"", "", ""},
|
|
{" ping ", "ping", ""},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.input, func(t *testing.T) {
|
|
word, rest := SplitFirstWord(tt.input)
|
|
if word != tt.wantWord || rest != tt.wantRest {
|
|
t.Errorf("SplitFirstWord(%q) = (%q, %q), want (%q, %q)",
|
|
tt.input, word, rest, tt.wantWord, tt.wantRest)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMath(t *testing.T) {
|
|
if !qalcAvailable() {
|
|
t.Skip("qalc not on PATH")
|
|
}
|
|
|
|
got := executeCommand(makeMsg("anyone", "math 2+2"))
|
|
if !strings.Contains(got, "4") {
|
|
t.Errorf("math 2+2 expected output containing '4', got %q", got)
|
|
}
|
|
}
|