plugin: search and replace
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/tag/release Pipeline was successful

This commit is contained in:
Felipe M 2025-05-09 14:00:08 +02:00
parent 4a154f16f9
commit a9b4ad52cb
Signed by: fmartingr
GPG key ID: CCFBC5637D4000A8
4 changed files with 450 additions and 0 deletions

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