diff --git a/provider/slack.go b/provider/slack.go index bda9bb2..4d0485d 100644 --- a/provider/slack.go +++ b/provider/slack.go @@ -29,14 +29,18 @@ type LocatedMessage struct { permalink string } +type HTTPClient interface { + Do(req *http.Request) (*http.Response, error) +} + type Slack struct { - client *http.Client + client HTTPClient notificationRules []model.NotificationRule reactionRules []model.ReactionRule webhookURL, message, avatar, username, token string } -func NewSlack(client *http.Client, notificationRules []model.NotificationRule, reactionRules []model.ReactionRule, webhookURL, token, message, avatar, username string) *Slack { +func NewSlack(client HTTPClient, notificationRules []model.NotificationRule, reactionRules []model.ReactionRule, webhookURL, token, message, avatar, username string) *Slack { return &Slack{ client: client, notificationRules: notificationRules, diff --git a/provider/slack_test.go b/provider/slack_test.go index 9285428..064782a 100644 --- a/provider/slack_test.go +++ b/provider/slack_test.go @@ -1,7 +1,9 @@ package provider import ( + "bytes" "encoding/json" + "errors" "io/ioutil" "net/http" "testing" @@ -10,6 +12,18 @@ import ( "github.com/stretchr/testify/assert" ) +type MockClient struct { + DoFunc func(req *http.Request) (*http.Response, error) +} + +var ( + GetDoFunc func(req *http.Request) (*http.Response, error) +) + +func (m *MockClient) Do(req *http.Request) (*http.Response, error) { + return GetDoFunc(req) +} + func TestChannelsForMergeRequestSingleRule(t *testing.T) { var mergeRequest model.MergeRequestInfo var jsonString string @@ -43,6 +57,7 @@ func TestChannelsForMergeRequestSingleRule(t *testing.T) { ) assert.Equal(t, []string{"#tested"}, slack.ChannelsForMergeRequest(mergeRequest)) + assert.Equal(t, []model.ReactionRule{{Action: "approved", Reaction: "thumbsup"}}, slack.GetReactionRules()) } func TestChannelsForMergeRequestMultipleRules(t *testing.T) { @@ -149,3 +164,114 @@ func TestChannelsForMergeRequestNotMatchingLabel(t *testing.T) { assert.Equal(t, []string{}, slack.ChannelsForMergeRequest(mergeRequest)) } + +func TestSearchForMessage(t *testing.T) { + var notifications []model.NotificationRule + var reactions []model.ReactionRule + + json := `{"messages": {"matches": [{"channel": {"name": "channel-name", "id": "channel-id"}, "ts": "123", "permalink": "http://message-link"}]}}` + client := &MockClient{} + r := ioutil.NopCloser(bytes.NewReader([]byte(json))) + GetDoFunc = func(*http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: 200, + Body: r, + }, nil + } + + slack := NewSlack( + client, + notifications, + reactions, + "https://testing.com", + "New MR", + "https://avatar", + "Username", + "Token", + ) + + locatedMessage, err := slack.search("New MergeRequest Created") + assert.Nil(t, err) + assert.Equal(t, "channel-name", locatedMessage.channelName) + assert.Equal(t, "channel-id", locatedMessage.channelID) + assert.Equal(t, "123", locatedMessage.timestamp) + assert.Equal(t, "http://message-link", locatedMessage.permalink) +} + +func TestPostReaction(t *testing.T) { + var notifications []model.NotificationRule + var reactions []model.ReactionRule + + json := `{}` + client := &MockClient{} + r := ioutil.NopCloser(bytes.NewReader([]byte(json))) + GetDoFunc = func(*http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: 200, + Body: r, + }, nil + } + + slack := NewSlack(client, notifications, reactions, "https://testing.com", "New MR", "https://avatar", "Username", "Token") + + locatedMessage := LocatedMessage{ + channelID: "channel-id", + channelName: "channel-name", + timestamp: "123", + permalink: "http://message-link", + } + + err := slack.postReaction(locatedMessage, model.ReactionRule{Action: "approved", Reaction: "thumbsup"}) + assert.Nil(t, err) +} + +func TestPostReactionFailsWithStatusCode(t *testing.T) { + var notifications []model.NotificationRule + var reactions []model.ReactionRule + + json := `{}` + client := &MockClient{} + r := ioutil.NopCloser(bytes.NewReader([]byte(json))) + GetDoFunc = func(*http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: 404, + Body: r, + }, nil + } + + slack := NewSlack(client, notifications, reactions, "https://testing.com", "New MR", "https://avatar", "Username", "Token") + + locatedMessage := LocatedMessage{ + channelID: "channel-id", + channelName: "channel-name", + timestamp: "123", + permalink: "http://message-link", + } + + err := slack.postReaction(locatedMessage, model.ReactionRule{Action: "approved", Reaction: "thumbsup"}) + assert.NotNil(t, err) + assert.ErrorContains(t, err, "response codeStatus code: 404, expected 200") +} + +func TestPostReactionFailsWithClientError(t *testing.T) { + var notifications []model.NotificationRule + var reactions []model.ReactionRule + + client := &MockClient{} + GetDoFunc = func(*http.Request) (*http.Response, error) { + return nil, errors.New("Error from web server") + } + + slack := NewSlack(client, notifications, reactions, "https://testing.com", "New MR", "https://avatar", "Username", "Token") + + locatedMessage := LocatedMessage{ + channelID: "channel-id", + channelName: "channel-name", + timestamp: "123", + permalink: "http://message-link", + } + + err := slack.postReaction(locatedMessage, model.ReactionRule{Action: "approved", Reaction: "thumbsup"}) + assert.NotNil(t, err) + assert.ErrorContains(t, err, "Error from web server") +}