plugin: search and replace
This commit is contained in:
parent
4a154f16f9
commit
a9b4ad52cb
4 changed files with 450 additions and 0 deletions
216
internal/plugin/searchreplace/searchreplace_test.go
Normal file
216
internal/plugin/searchreplace/searchreplace_test.go
Normal file
|
@ -0,0 +1,216 @@
|
|||
package searchreplace
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.nakama.town/fmartingr/butterrobot/internal/model"
|
||||
)
|
||||
|
||||
func TestSearchReplace(t *testing.T) {
|
||||
// Create plugin instance
|
||||
p := New()
|
||||
|
||||
// Test cases
|
||||
tests := []struct {
|
||||
name string
|
||||
command string
|
||||
originalText string
|
||||
expectedResult string
|
||||
expectActions bool
|
||||
}{
|
||||
{
|
||||
name: "Simple replacement",
|
||||
command: "s/hello/world/",
|
||||
originalText: "hello everyone",
|
||||
expectedResult: "world everyone",
|
||||
expectActions: true,
|
||||
},
|
||||
{
|
||||
name: "Case-insensitive replacement",
|
||||
command: "s/HELLO/world/i",
|
||||
originalText: "Hello everyone",
|
||||
expectedResult: "world everyone",
|
||||
expectActions: true,
|
||||
},
|
||||
{
|
||||
name: "Global replacement",
|
||||
command: "s/a/X/g",
|
||||
originalText: "banana",
|
||||
expectedResult: "bXnXnX",
|
||||
expectActions: true,
|
||||
},
|
||||
{
|
||||
name: "No change",
|
||||
command: "s/nothing/something/",
|
||||
originalText: "test message",
|
||||
expectedResult: "test message",
|
||||
expectActions: true, // We send a "no changes" message
|
||||
},
|
||||
{
|
||||
name: "Not a search/replace command",
|
||||
command: "hello",
|
||||
originalText: "test message",
|
||||
expectedResult: "",
|
||||
expectActions: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid pattern",
|
||||
command: "s/(/)/",
|
||||
originalText: "test message",
|
||||
expectedResult: "error",
|
||||
expectActions: true, // We send an error message
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Create message
|
||||
msg := &model.Message{
|
||||
Text: tc.command,
|
||||
Chat: "test-chat",
|
||||
ReplyTo: "original-message-id",
|
||||
Date: time.Now(),
|
||||
Channel: &model.Channel{
|
||||
Platform: "test",
|
||||
},
|
||||
Raw: map[string]interface{}{
|
||||
"message": map[string]interface{}{
|
||||
"reply_to_message": map[string]interface{}{
|
||||
"text": tc.originalText,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Process message
|
||||
actions := p.OnMessage(msg, nil)
|
||||
|
||||
// Check results
|
||||
if tc.expectActions {
|
||||
if len(actions) == 0 {
|
||||
t.Fatalf("Expected actions but got none")
|
||||
}
|
||||
|
||||
action := actions[0]
|
||||
if action.Type != model.ActionSendMessage {
|
||||
t.Fatalf("Expected send message action but got %v", action.Type)
|
||||
}
|
||||
|
||||
if tc.expectedResult == "error" {
|
||||
// Just checking that we got an error message
|
||||
if action.Message == nil || action.Message.Text == "" {
|
||||
t.Fatalf("Expected error message but got empty message")
|
||||
}
|
||||
} else if tc.originalText == tc.expectedResult {
|
||||
// Check if we got the "no changes" message
|
||||
if action.Message == nil || action.Message.Text != "No changes were made to the original message." {
|
||||
t.Fatalf("Expected 'no changes' message but got: %s", action.Message.Text)
|
||||
}
|
||||
} else {
|
||||
// Check actual replacement result
|
||||
if action.Message == nil || action.Message.Text != tc.expectedResult {
|
||||
t.Fatalf("Expected result: %s, got: %s", tc.expectedResult, action.Message.Text)
|
||||
}
|
||||
}
|
||||
} else if len(actions) > 0 {
|
||||
t.Fatalf("Expected no actions but got %d", len(actions))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPerformReplacement(t *testing.T) {
|
||||
p := New()
|
||||
|
||||
// Test cases for the performReplacement function
|
||||
tests := []struct {
|
||||
name string
|
||||
text string
|
||||
search string
|
||||
replace string
|
||||
flags string
|
||||
expected string
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "Simple replacement",
|
||||
text: "Hello World",
|
||||
search: "Hello",
|
||||
replace: "Hi",
|
||||
flags: "",
|
||||
expected: "Hi World",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Case insensitive",
|
||||
text: "Hello World",
|
||||
search: "hello",
|
||||
replace: "Hi",
|
||||
flags: "i",
|
||||
expected: "Hi World",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Global replacement",
|
||||
text: "one two one two",
|
||||
search: "one",
|
||||
replace: "1",
|
||||
flags: "g",
|
||||
expected: "1 two 1 two",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "No match",
|
||||
text: "Hello World",
|
||||
search: "Goodbye",
|
||||
replace: "Hi",
|
||||
flags: "",
|
||||
expected: "Hello World",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid regex",
|
||||
text: "Hello World",
|
||||
search: "(",
|
||||
replace: "Hi",
|
||||
flags: "n", // treat as regex
|
||||
expected: "",
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "Escape special chars by default",
|
||||
text: "Hello (World)",
|
||||
search: "(World)",
|
||||
replace: "[Earth]",
|
||||
flags: "",
|
||||
expected: "Hello [Earth]",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Regex mode with n flag",
|
||||
text: "Hello (World)",
|
||||
search: "\\(World\\)",
|
||||
replace: "[Earth]",
|
||||
flags: "n",
|
||||
expected: "Hello [Earth]",
|
||||
expectErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result, err := p.performReplacement(tc.text, tc.search, tc.replace, tc.flags)
|
||||
|
||||
if tc.expectErr {
|
||||
if err == nil {
|
||||
t.Fatalf("Expected error but got none")
|
||||
}
|
||||
} else if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
} else if result != tc.expected {
|
||||
t.Fatalf("Expected result: %s, got: %s", tc.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue