sox/sox_test.go
Waldo 0b2e83ba0c Fix test isolation bug and refactor command handling into plugins
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>
2026-03-06 21:27:53 -07:00

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)
}
}