refactor: refactor messaging and file upload with improved error handling (#66)

- Refactor message and file sending logic into separate handleMessages and handleFiles methods
- Stream file uploads via io.Copy rather than loading the entire content into memory
- Add centralized http.Client with timeout for all requests
- Enhance error handling throughout by returning more descriptive and wrapped errors
- Improve response validation for file and message uploads, checking HTTP status and parsing error details
- Update tests to cover plain text messages, embed messages, file uploads, color conversion, and combined features
- Add tests using assert.Error/assert.NoError and checking specific error messages
- Simplify and clarify configuration validation logic

Signed-off-by: appleboy <appleboy.tw@gmail.com>
This commit is contained in:
Bo-Yi Wu
2025-07-05 21:02:30 +08:00
committed by GitHub
parent 1bdf20515c
commit f2b9ede051
2 changed files with 225 additions and 146 deletions
+124 -69
View File
@@ -10,14 +10,48 @@ import (
)
func TestMissingConfig(t *testing.T) {
var plugin Plugin
plugin := Plugin{}
err := plugin.Exec(context.Background())
assert.NotNil(t, err)
assert.Error(t, err)
assert.Contains(t, err.Error(), "missing discord config")
}
func TestTemplate(t *testing.T) {
func TestSendPlainTextMessage(t *testing.T) {
plugin := Plugin{
Config: Config{
WebhookID: os.Getenv("WEBHOOK_ID"),
WebhookToken: os.Getenv("WEBHOOK_TOKEN"),
Message: []string{"Hello, world!", "This is a test."},
},
Payload: Payload{
Username: "test-bot",
},
}
err := plugin.Exec(context.Background())
assert.NoError(t, err)
}
func TestSendEmbedMessage(t *testing.T) {
plugin := Plugin{
Config: Config{
WebhookID: os.Getenv("WEBHOOK_ID"),
WebhookToken: os.Getenv("WEBHOOK_TOKEN"),
Message: []string{"This is an embed message."},
Color: "#48f442",
},
Payload: Payload{
Username: "embed-bot",
},
}
err := plugin.Exec(context.Background())
assert.NoError(t, err)
}
func TestSendDefaultMessage(t *testing.T) {
plugin := Plugin{
Repo: Repo{
Name: "go-hello",
@@ -26,99 +60,120 @@ func TestTemplate(t *testing.T) {
Commit: Commit{
Author: "appleboy",
Branch: "master",
Message: "update by drone discord plugin. \r\n update by drone discord plugin.",
Message: "feat: new feature",
Avatar: "https://avatars0.githubusercontent.com/u/21979?v=3&s=100",
},
Build: Build{
Number: 101,
Status: "success",
Link: "https://github.com/appleboy/go-hello",
Event: "tag",
Event: "push",
},
Source: Source{
Branch: "feature/awesome-feature",
},
Config: Config{
WebhookID: os.Getenv("WEBHOOK_ID"),
WebhookToken: os.Getenv("WEBHOOK_TOKEN"),
Message: []string{"test one message from drone testing", "test two message from drone testing"},
File: []string{"./images/discord-logo.png"},
Drone: true,
},
Payload: Payload{
Username: "drone",
TTS: false,
Wait: false,
Username: "default-bot",
},
}
err := plugin.Exec(context.Background())
assert.Nil(t, err)
plugin.Clear()
plugin.Config.Message = []string{"I am appleboy"}
plugin.Payload.TTS = true
plugin.Payload.Wait = true
err = plugin.Exec(context.Background())
assert.Nil(t, err)
// send success embed message
plugin.Config.Message = []string{}
plugin.Payload.TTS = false
plugin.Payload.Wait = false
plugin.Clear()
err = plugin.Exec(context.Background())
assert.Nil(t, err)
// send success embed message
plugin.Build.Status = "failure"
plugin.Commit.Message = "send failure embed message"
plugin.Clear()
err = plugin.Exec(context.Background())
assert.Nil(t, err)
time.Sleep(1 * time.Second)
// send default embed message
plugin.Build.Status = "test"
plugin.Commit.Message = "send default embed message"
plugin.Clear()
err = plugin.Exec(context.Background())
assert.Nil(t, err)
// change color for embed message
plugin.Config.Color = "#4842f4"
plugin.Commit.Message = "Change embed color to #4842f4"
plugin.Clear()
err = plugin.Exec(context.Background())
assert.Nil(t, err)
assert.NoError(t, err)
}
func TestDefaultTemplate(t *testing.T) {
func TestSendFile(t *testing.T) {
// Create a dummy file for testing
dummyFile, err := os.Create("test_file.txt")
assert.NoError(t, err)
_, err = dummyFile.WriteString("This is a test file.")
assert.NoError(t, err)
dummyFile.Close()
defer os.Remove("test_file.txt")
plugin := Plugin{
Config: Config{
WebhookID: os.Getenv("WEBHOOK_ID"),
WebhookToken: os.Getenv("WEBHOOK_TOKEN"),
Message: []string{"default message 1", "default message 2"},
Color: "#48f442",
File: []string{"test_file.txt"},
},
Payload: Payload{
Username: "drone-ci",
TTS: false,
Wait: false,
Username: "file-bot",
},
}
time.Sleep(1 * time.Second)
plugin.Clear()
err := plugin.Exec(context.Background())
assert.Nil(t, err)
plugin.Config.Color = "#f4be41"
time.Sleep(1 * time.Second)
plugin.Clear()
err = plugin.Exec(context.Background())
assert.Nil(t, err)
assert.NoError(t, err)
}
func TestColorConversion(t *testing.T) {
tests := []struct {
name string
colorHex string
expectedInt int
buildStatus string
expectedFall int
}{
{"valid hex", "#ffaa00", 16755200, "success", 1752220},
{"invalid hex", "not-a-hex", 0, "failure", 16724530},
{"status success", "", 0, "success", 1752220},
{"status failure", "", 0, "failure", 16724530},
{"status killed", "", 0, "killed", 16724530},
{"status default", "", 0, "running", 16767280},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := Plugin{
Config: Config{Color: tt.colorHex},
Build: Build{Status: tt.buildStatus},
}
if tt.colorHex != "" {
assert.Equal(t, tt.expectedInt, p.Color())
} else {
assert.Equal(t, tt.expectedFall, p.Color())
}
})
}
}
func TestExecWithAllFeatures(t *testing.T) {
time.Sleep(1 * time.Second)
// Create a dummy file for testing
dummyFile, err := os.Create("test_all.txt")
assert.NoError(t, err)
_, err = dummyFile.WriteString("This is a test file for a combined test.")
assert.NoError(t, err)
dummyFile.Close()
defer os.Remove("test_all.txt")
plugin := Plugin{
Repo: Repo{
Name: "go-hello",
Namespace: "appleboy",
},
Commit: Commit{
Author: "appleboy",
Message: "Combined test with multiple features",
},
Build: Build{
Status: "success",
Link: "http://example.com",
},
Config: Config{
WebhookID: os.Getenv("WEBHOOK_ID"),
WebhookToken: os.Getenv("WEBHOOK_TOKEN"),
Message: []string{"First line of embed.", "Second line."},
File: []string{"test_all.txt"},
Color: "#32a852",
Drone: true,
},
Payload: Payload{
Username: "super-bot",
},
}
err = plugin.Exec(context.Background())
assert.NoError(t, err)
}