From efb8af3b53f07a75f9c0acb6309a54f4c07b7158 Mon Sep 17 00:00:00 2001 From: kshitij katiyar Date: Thu, 28 Nov 2024 14:41:30 +0530 Subject: [PATCH 1/3] [MM-974]: Added testcase fore more functions in webhook.go --- server/plugin/test_utils.go | 84 +++++- server/plugin/webhook_test.go | 535 +++++++++++++++++++++++++++++++++- 2 files changed, 608 insertions(+), 11 deletions(-) diff --git a/server/plugin/test_utils.go b/server/plugin/test_utils.go index 3761f613e..e5737e5b2 100644 --- a/server/plugin/test_utils.go +++ b/server/plugin/test_utils.go @@ -21,6 +21,8 @@ const ( MockChannelID = "mockChannelID" MockCreatorID = "mockCreatorID" MockBotID = "mockBotID" + MockOrg = "mockOrg" + MockSender = "mockSender" MockPostMessage = "mockPostMessage" MockOrgRepo = "mockOrg/mockRepo" MockHead = "mockHead" @@ -253,22 +255,25 @@ func GetMockDeleteEventWithInvalidType() *github.DeleteEvent { } } -func GetMockPullRequestReviewEvent(action, state string) *github.PullRequestReviewEvent { +func GetMockPullRequestReviewEvent(action, state, repo string, isPrivate bool, reviewer, author string) *github.PullRequestReviewEvent { return &github.PullRequestReviewEvent{ Action: github.String(action), Repo: &github.Repository{ - Name: github.String(MockRepoName), + Name: github.String(repo), FullName: github.String(MockOrgRepo), - Private: github.Bool(false), + Private: github.Bool(isPrivate), HTMLURL: github.String(fmt.Sprintf("%s%s", GithubBaseURL, MockOrgRepo)), }, + Sender: &github.User{Login: github.String(reviewer)}, Review: &github.PullRequestReview{ + User: &github.User{ + Login: github.String(reviewer), + }, State: github.String(state), }, - Sender: &github.User{ - Login: github.String(MockUserLogin), + PullRequest: &github.PullRequest{ + User: &github.User{Login: github.String(author)}, }, - PullRequest: &github.PullRequest{}, } } @@ -366,3 +371,70 @@ func GetMockPullRequestEvent(action, repoName string, isPrivate bool, sender, us RequestedReviewer: &github.User{Login: github.String(user)}, } } + +func GetMockIssuesEvent(action, repoName string, isPrivate bool, author, sender, assignee string) *github.IssuesEvent { + return &github.IssuesEvent{ + Action: &action, + Repo: &github.Repository{FullName: &repoName, Private: &isPrivate}, + Issue: &github.Issue{User: &github.User{Login: &author}}, + Sender: &github.User{Login: &sender}, + Assignee: func() *github.User { + if assignee == "" { + return nil + } + return &github.User{Login: &assignee} + }(), + } +} + +func GetMockStarEvent(repo, org string, isPrivate bool, sender string) *github.StarEvent { + return &github.StarEvent{ + Repo: &github.Repository{ + Name: github.String(repo), + Private: github.Bool(isPrivate), + FullName: github.String(fmt.Sprintf("%s/%s", repo, org)), + }, + Sender: &github.User{Login: github.String(sender)}, + } +} + +func GetMockReleaseEvent(repo, org, action, sender string) *github.ReleaseEvent { + return &github.ReleaseEvent{ + Action: &action, + Repo: &github.Repository{ + Name: github.String(repo), + Owner: &github.User{Login: github.String(org)}, + FullName: github.String(fmt.Sprintf("%s/%s", repo, org)), + }, + Sender: &github.User{Login: github.String(sender)}, + } +} + +func GetMockDiscussionEvent(repo, org, sender string) *github.DiscussionEvent { + return &github.DiscussionEvent{ + Repo: &github.Repository{ + Name: github.String(repo), + Owner: &github.User{Login: github.String(org)}, + FullName: github.String(fmt.Sprintf("%s/%s", repo, org)), + }, + Sender: &github.User{Login: github.String(sender)}, + Discussion: &github.Discussion{ + Number: github.Int(123), + }, + } +} + +func GetMockDiscussionCommentEvent(repo, org, action, sender string) *github.DiscussionCommentEvent { + return &github.DiscussionCommentEvent{ + Action: &action, + Repo: &github.Repository{ + Name: github.String(repo), + Owner: &github.User{Login: github.String(org)}, + FullName: github.String(fmt.Sprintf("%s/%s", repo, org)), + }, + Sender: &github.User{Login: github.String(sender)}, + Comment: &github.CommentDiscussion{ + ID: github.Int64(456), + }, + } +} diff --git a/server/plugin/webhook_test.go b/server/plugin/webhook_test.go index 1334f97d3..80f75b67c 100644 --- a/server/plugin/webhook_test.go +++ b/server/plugin/webhook_test.go @@ -368,14 +368,14 @@ func TestPostPullRequestReviewEvent(t *testing.T) { }{ { name: "no subscriptions found", - event: GetMockPullRequestReviewEvent("submitted", "approved"), + event: GetMockPullRequestReviewEvent("submitted", "approved", MockRepoName, false, MockUserLogin, MockIssueAuthor), setup: func() { mockKvStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).Return(nil).Times(1) }, }, { name: "unsupported action in event", - event: GetMockPullRequestReviewEvent("deleted", "approved"), + event: GetMockPullRequestReviewEvent("deleted", "approved", MockRepoName, false, MockUserLogin, MockIssueAuthor), setup: func() { mockKvStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { @@ -387,7 +387,7 @@ func TestPostPullRequestReviewEvent(t *testing.T) { }, { name: "unsupported review state", - event: GetMockPullRequestReviewEvent("submitted", "canceled"), + event: GetMockPullRequestReviewEvent("submitted", "canceled", MockRepoName, false, MockUserLogin, MockIssueAuthor), setup: func() { mockKvStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { @@ -400,7 +400,7 @@ func TestPostPullRequestReviewEvent(t *testing.T) { }, { name: "error creating post", - event: GetMockPullRequestReviewEvent("submitted", "approved"), + event: GetMockPullRequestReviewEvent("submitted", "approved", MockRepoName, false, MockUserLogin, MockIssueAuthor), setup: func() { mockKvStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { @@ -414,7 +414,7 @@ func TestPostPullRequestReviewEvent(t *testing.T) { }, { name: "successful handling of pull request review event", - event: GetMockPullRequestReviewEvent("submitted", "approved"), + event: GetMockPullRequestReviewEvent("submitted", "approved", MockRepoName, false, MockUserLogin, MockIssueAuthor), setup: func() { mockKvStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { @@ -867,3 +867,528 @@ func TestHandlePullRequestNotification(t *testing.T) { }) } } + +func TestHandleIssueNotification(t *testing.T) { + mockKvStore, mockAPI, _, _, _ := GetTestSetup(t) + p := getPluginTest(mockAPI, mockKvStore) + + tests := []struct { + name string + event *github.IssuesEvent + setup func() + }{ + { + name: "issue closed by author", + event: GetMockIssuesEvent(actionClosed, MockRepo, false, "authorUser", "authorUser", ""), + setup: func() {}, + }, + { + name: "issue closed successfully", + event: GetMockIssuesEvent(actionClosed, MockRepo, true, "authorUser", "senderUser", ""), + setup: func() { + mockKvStore.EXPECT().Get("authorUser_githubusername", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(*[]byte); ok { + *v = []byte("authorUserID") + } + return nil + }).Times(1) + mockKvStore.EXPECT().Get("authorUserID_githubtoken", gomock.Any()).Return(nil).Times(1) + }, + }, + { + name: "issue reopened with no repo permission", + event: GetMockIssuesEvent(actionReopened, MockRepo, true, "authorUser", "senderUser", ""), + setup: func() { + mockKvStore.EXPECT().Get("authorUser_githubusername", gomock.Any()).Return(nil).Times(1) + }, + }, + { + name: "issue assigned to self", + event: GetMockIssuesEvent(actionAssigned, MockRepo, false, "assigneeUser", "assigneeUser", "assigneeUser"), + setup: func() {}, + }, + { + name: "issue assigned successfully", + event: GetMockIssuesEvent(actionAssigned, MockRepo, false, "senderUser", "assigneeUser", "assigneeUser"), + setup: func() { + mockKvStore.EXPECT().Get("assigneeUser_githubusername", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(*[]byte); ok { + *v = []byte("assigneeUserID") + } + return nil + }).Times(1) + }, + }, + { + name: "issue assigned with no repo permission for assignee", + event: GetMockIssuesEvent(actionAssigned, MockRepo, true, "senderUser", "demoassigneeUser", "assigneeUser"), + setup: func() { + mockKvStore.EXPECT().Get("assigneeUser_githubusername", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(*[]byte); ok { + *v = []byte("assigneeUserID") + } + return nil + }).Times(1) + }, + }, + { + name: "unhandled event action", + event: GetMockIssuesEvent("unsupported_action", MockRepo, false, "senderUser", "", ""), + setup: func() { + mockAPI.On("LogDebug", "Unhandled event action", "action", "unsupported_action").Return(nil).Times(1) + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + tc.setup() + + p.handleIssueNotification(tc.event) + + mockAPI.AssertExpectations(t) + }) + } +} + +func TestHandlePullRequestReviewNotification(t *testing.T) { + mockKvStore, mockAPI, _, _, _ := GetTestSetup(t) + p := getPluginTest(mockAPI, mockKvStore) + + tests := []struct { + name string + event *github.PullRequestReviewEvent + setup func() + }{ + { + name: "review submitted by author", + event: GetMockPullRequestReviewEvent(actionSubmitted, "approved", MockRepo, false, "authorUser", "authorUser"), + setup: func() {}, + }, + { + name: "review action not submitted", + event: GetMockPullRequestReviewEvent("dismissed", "approved", MockRepo, false, "authorUser", "reviewerUser"), + setup: func() {}, + }, + { + name: "review with author not mapped to user ID", + event: GetMockPullRequestReviewEvent(actionSubmitted, "approved", MockRepo, false, "unknownAuthor", "reviewerUser"), + setup: func() { + mockKvStore.EXPECT().Get("reviewerUser_githubusername", gomock.Any()).Return(nil).Times(1) + }, + }, + { + name: "private repo, no permission for author", + event: GetMockPullRequestReviewEvent(actionSubmitted, "approved", MockRepo, true, "authorUser", "reviewerUser"), + setup: func() { + mockKvStore.EXPECT().Get("reviewerUser_githubusername", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(*[]byte); ok { + *v = []byte("authorUserID") + } + return nil + }).Times(1) + mockKvStore.EXPECT().Get("authorUserID_githubtoken", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(*[]byte); ok { + *v = []byte("authorUserID") + } + return nil + }).Times(1) + }, + }, + { + name: "successful review notification", + event: GetMockPullRequestReviewEvent(actionSubmitted, "approved", MockRepo, false, "authorUser", "reviewerUser"), + setup: func() { + mockKvStore.EXPECT().Get("reviewerUser_githubusername", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(*[]byte); ok { + *v = []byte("authorUserID") + } + return nil + }).Times(1) + mockAPI.On("GetDirectChannel", "authorUserID", "mockBotID").Return(nil, &model.AppError{Message: "error getting channel"}).Times(1) + mockAPI.On("LogWarn", "Couldn't get bot's DM channel", "userID", "authorUserID", "error", "error getting channel") + mockKvStore.EXPECT().Get("authorUserID_githubtoken", gomock.Any()).Return(nil).Times(1) + mockAPI.On("LogWarn", "Failed to get github user info", "error", "Must connect user account to GitHub first.") + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + tc.setup() + + p.handlePullRequestReviewNotification(tc.event) + + mockAPI.AssertExpectations(t) + }) + } +} + +func TestPostStarEvent(t *testing.T) { + mockKvStore, mockAPI, _, _, _ := GetTestSetup(t) + p := getPluginTest(mockAPI, mockKvStore) + + tests := []struct { + name string + event *github.StarEvent + setup func() + }{ + { + name: "no subscribed channels for repository", + event: GetMockStarEvent(MockRepo, MockOrg, false, MockSender), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + }, + }, + { + name: "error creating post", + event: GetMockStarEvent(MockRepo, MockOrg, false, MockSender), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: featureStars, + Repository: MockRepo, + }, + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: featureDeletes, + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error webhook post", "post", mock.Anything, "error", "error creating post") + }, + }, + { + name: "successful star event notification", + event: GetMockStarEvent(MockRepo, MockOrg, false, MockSender), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: featureStars, + Repository: MockRepo, + }, + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: featureDeletes, + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + tc.setup() + + p.postStarEvent(tc.event) + + mockAPI.AssertExpectations(t) + }) + } +} + +func TestPostReleaseEvent(t *testing.T) { + mockKvStore, mockAPI, _, _, _ := GetTestSetup(t) + p := getPluginTest(mockAPI, mockKvStore) + + tests := []struct { + name string + event *github.ReleaseEvent + setup func() + }{ + { + name: "no subscribed channels for repository", + event: GetMockReleaseEvent(MockRepo, MockOrg, "created", MockSender), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + }, + }, + { + name: "unsupported action", + event: GetMockReleaseEvent(MockRepo, MockOrg, "edited", MockSender), + setup: func() {}, + }, + { + name: "error creating post", + event: GetMockReleaseEvent(MockRepo, MockOrg, "created", MockSender), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: featureReleases, + Repository: MockRepo, + }, + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: featureDeletes, + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error webhook post", "Post", mock.Anything, "Error", "error creating post") + }, + }, + { + name: "successful release event notification", + event: GetMockReleaseEvent(MockRepo, MockOrg, "created", MockSender), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: featureReleases, + Repository: MockRepo, + }, + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: featureDeletes, + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + tc.setup() + + p.postReleaseEvent(tc.event) + + mockAPI.AssertExpectations(t) + }) + } +} + +func TestPostDiscussionEvent(t *testing.T) { + mockKvStore, mockAPI, _, _, _ := GetTestSetup(t) + p := getPluginTest(mockAPI, mockKvStore) + + tests := []struct { + name string + event *github.DiscussionEvent + setup func() + }{ + { + name: "no subscribed channels for repository", + event: GetMockDiscussionEvent(MockRepo, MockOrg, MockSender), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + }, + }, + { + name: "error creating discussion post", + event: GetMockDiscussionEvent(MockRepo, MockOrg, MockSender), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: featureDiscussions, + Repository: MockRepo, + }, + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: featureDeletes, + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error creating discussion notification post", "Post", mock.Anything, "Error", "error creating post") + }, + }, + { + name: "successful discussion notification", + event: GetMockDiscussionEvent(MockRepo, MockOrg, MockSender), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: featureDiscussions, + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + tc.setup() + + p.postDiscussionEvent(tc.event) + + mockAPI.AssertExpectations(t) + }) + } +} + +func TestPostDiscussionCommentEvent(t *testing.T) { + mockKvStore, mockAPI, _, _, _ := GetTestSetup(t) + p := getPluginTest(mockAPI, mockKvStore) + + tests := []struct { + name string + event *github.DiscussionCommentEvent + setup func() + }{ + { + name: "no subscribed channels for repository", + event: GetMockDiscussionCommentEvent(MockRepo, MockOrg, "created", MockSender), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + }, + }, + { + name: "unsupported action", + event: GetMockDiscussionCommentEvent(MockRepo, MockOrg, "edited", MockSender), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: featureDiscussionComments, + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + }, + }, + { + name: "error creating discussion comment post", + event: GetMockDiscussionCommentEvent(MockRepo, MockOrg, "created", MockSender), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: featureDiscussionComments, + Repository: MockRepo, + }, { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: featureDeletes, + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error creating discussion comment post", "Post", mock.Anything, "Error", "error creating post") + }, + }, + { + name: "successful discussion comment notification", + event: GetMockDiscussionCommentEvent(MockRepo, MockOrg, "created", MockSender), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: featureDiscussionComments, + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + tc.setup() + + p.postDiscussionCommentEvent(tc.event) + + mockAPI.AssertExpectations(t) + }) + } +} From a1dbb99d99744058649963acd2bb72e93c5c44f1 Mon Sep 17 00:00:00 2001 From: kshitij katiyar Date: Mon, 2 Dec 2024 13:39:45 +0530 Subject: [PATCH 2/3] [MM-979]: Added more testcase for webhool.go --- server/plugin/test_utils.go | 149 +++- server/plugin/webhook_test.go | 1346 ++++++++++++++++++++++++++++++++- 2 files changed, 1467 insertions(+), 28 deletions(-) diff --git a/server/plugin/test_utils.go b/server/plugin/test_utils.go index e5737e5b2..231851203 100644 --- a/server/plugin/test_utils.go +++ b/server/plugin/test_utils.go @@ -2,8 +2,12 @@ package plugin import ( "context" + "crypto/hmac" + "crypto/sha1" // #nosec G505 + "encoding/hex" "fmt" "testing" + "time" "github.com/golang/mock/gomock" "github.com/google/go-github/v54/github" @@ -15,24 +19,30 @@ import ( ) const ( - MockUserID = "mockUserID" - MockUsername = "mockUsername" - MockAccessToken = "mockAccessToken" - MockChannelID = "mockChannelID" - MockCreatorID = "mockCreatorID" - MockBotID = "mockBotID" - MockOrg = "mockOrg" - MockSender = "mockSender" - MockPostMessage = "mockPostMessage" - MockOrgRepo = "mockOrg/mockRepo" - MockHead = "mockHead" - MockRepoName = "mockRepoName" - MockEventReference = "refs/heads/main" - MockUserLogin = "mockUser" - MockBranch = "mockBranch" - MockRepo = "mockRepo" - MockIssueAuthor = "issueAuthor" - GithubBaseURL = "https://github.com/" + MockUserID = "mockUserID" + MockUsername = "mockUsername" + MockAccessToken = "mockAccessToken" + MockChannelID = "mockChannelID" + MockCreatorID = "mockCreatorID" + MockWebhookSecret = "mockWebhookSecret" // #nosec G101 + MockBotID = "mockBotID" + MockOrg = "mockOrg" + MockSender = "mockSender" + MockPostMessage = "mockPostMessage" + MockOrgRepo = "mockOrg/mockRepo" + MockHead = "mockHead" + MockPRTitle = "mockPRTitle" + MockProfileUsername = "@username" + MockPostID = "mockPostID" + MockRepoName = "mockRepoName" + MockEventReference = "refs/heads/main" + MockUserLogin = "mockUser" + MockBranch = "mockBranch" + MockRepo = "mockRepo" + MockLabel = "mockLabel" + MockValidLabel = "validLabel" + MockIssueAuthor = "issueAuthor" + GithubBaseURL = "https://github.com/" ) type GitHubUserResponse struct { @@ -93,6 +103,104 @@ func GetMockUserContext(p *Plugin, mockLogger *mocks.MockLogger) (*UserContext, return mockUserContext, nil } +func generateSignature(secret, body []byte) string { + h := hmac.New(sha1.New, secret) + h.Write(body) + return "sha1=" + hex.EncodeToString(h.Sum(nil)) +} + +func GetMockPingEvent() *github.PingEvent { + return &github.PingEvent{ + Zen: github.String("Keep it logically awesome."), + HookID: github.Int64(123456), + Hook: &github.Hook{ + Type: github.String("Repository"), + ID: github.Int64(654321), + Config: map[string]interface{}{ + "url": "https://example.com/webhook", + "content_type": "json", + "secret": "mocksecret", + "insecure_ssl": "0", + }, + Active: github.Bool(true), + }, + Repo: &github.Repository{ + Name: github.String(MockRepoName), + FullName: github.String(MockOrgRepo), + Private: github.Bool(false), + HTMLURL: github.String(fmt.Sprintf("%s/%s", GithubBaseURL, MockOrgRepo)), + }, + Org: &github.Organization{ + Login: github.String("mockorg"), + ID: github.Int64(12345), + URL: github.String(fmt.Sprintf("%s/mockorg", GithubBaseURL)), + }, + Sender: &github.User{ + Login: github.String(MockUserLogin), + ID: github.Int64(98765), + URL: github.String(fmt.Sprintf("%s/users/%s", GithubBaseURL, MockUserLogin)), + }, + Installation: &github.Installation{ + ID: github.Int64(246810), + NodeID: github.String("MDQ6VXNlcjE="), + }, + } +} + +func GetMockPRDescriptionEvent(repo, org, sender, prUser, action, label string) *github.PullRequestEvent { + return &github.PullRequestEvent{ + Action: github.String(action), + PullRequest: &github.PullRequest{ + Title: github.String(MockPRTitle), + Body: github.String("Mock PR description with label: " + label), + State: github.String("open"), + User: &github.User{Login: github.String(prUser)}, + Head: &github.PullRequestBranch{Ref: github.String(MockBranch)}, + Base: &github.PullRequestBranch{Ref: github.String("main")}, + HTMLURL: github.String(GithubBaseURL + org + "/" + repo + "/pull/1"), + Number: github.Int(1), + }, + Repo: &github.Repository{ + Name: github.String(repo), + Owner: &github.User{Login: github.String(org)}, + FullName: github.String(org + "/" + repo), + }, + Sender: &github.User{ + Login: github.String(sender), + }, + } +} + +func GetMockIssueEvent(repo, org, sender, action, label string) *github.IssuesEvent { + event := &github.IssuesEvent{ + Repo: &github.Repository{ + Name: github.String(repo), + Owner: &github.User{Login: github.String(org)}, + FullName: github.String(fmt.Sprintf("%s/%s", repo, org)), + }, + Sender: &github.User{Login: github.String(sender)}, + Issue: &github.Issue{ + Number: github.Int(123), + Labels: []*github.Label{ + {Name: github.String(label)}, + }, + }, + Action: github.String(action), + } + + if action == actionLabeled || action == "unlabeled" { + event.Label = &github.Label{Name: github.String(label)} + } + + return event +} + +func GetMockIssueEventWithTimeDiff(repo, org, sender, action, label string, timeDiff time.Duration) *github.IssuesEvent { + event := GetMockIssueEvent(repo, org, sender, action, label) + event.Issue.CreatedAt = &github.Timestamp{Time: time.Now().Add(timeDiff)} + return event +} + func GetMockPushEvent() *github.PushEvent { return &github.PushEvent{ PushID: github.Int64(1), @@ -351,9 +459,10 @@ func GetMockIssueCommentEventWithAssignees(eventType, action, body, sender strin } } -func GetMockPullRequestEvent(action, repoName string, isPrivate bool, sender, user, assignee string) *github.PullRequestEvent { +func GetMockPullRequestEvent(action, repoName, eventLabel string, isPrivate bool, sender, user, assignee string) *github.PullRequestEvent { return &github.PullRequestEvent{ Action: github.String(action), + Label: &github.Label{Name: github.String(eventLabel)}, Repo: &github.Repository{ Name: github.String(repoName), FullName: github.String(fmt.Sprintf("mockOrg/%s", repoName)), @@ -364,6 +473,8 @@ func GetMockPullRequestEvent(action, repoName string, isPrivate bool, sender, us HTMLURL: github.String(fmt.Sprintf("%s%s/%s/pull/123", GithubBaseURL, MockOrgRepo, repoName)), Assignee: &github.User{Login: github.String(assignee)}, RequestedReviewers: []*github.User{{Login: github.String(user)}}, + Labels: []*github.Label{{Name: github.String("validLabel")}}, + Draft: github.Bool(true), }, Sender: &github.User{ Login: github.String(sender), diff --git a/server/plugin/webhook_test.go b/server/plugin/webhook_test.go index 80f75b67c..24012cdcd 100644 --- a/server/plugin/webhook_test.go +++ b/server/plugin/webhook_test.go @@ -1,7 +1,14 @@ package plugin import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "sync" "testing" + "time" "github.com/golang/mock/gomock" "github.com/google/go-github/v54/github" @@ -11,6 +18,1327 @@ import ( "github.com/stretchr/testify/mock" ) +func TestVerifyWebhookSignature(t *testing.T) { + tests := []struct { + name string + secret []byte + signature string + body []byte + assertions func(t *testing.T, valid bool, err error) + }{ + { + name: "Valid signature", + secret: []byte("test-secret"), + signature: func() string { + secret := []byte("test-secret") + body := []byte("test-body") + return generateSignature(secret, body) + }(), + body: []byte("test-body"), + assertions: func(t *testing.T, valid bool, err error) { + assert.NoError(t, err) + assert.True(t, valid) + }, + }, + { + name: "Invalid signature prefix", + secret: []byte("test-secret"), + signature: "invalid-prefix=1234567890abcdef", + body: []byte("test-body"), + assertions: func(t *testing.T, valid bool, err error) { + assert.NoError(t, err) + assert.False(t, valid) + }, + }, + { + name: "Invalid signature length", + secret: []byte("test-secret"), + signature: "sha1=short", + body: []byte("test-body"), + assertions: func(t *testing.T, valid bool, err error) { + assert.NoError(t, err) + assert.False(t, valid) + }, + }, + { + name: "Hex decode error", + secret: []byte("test-secret"), + signature: "sha1=gggggggggggggggggggggggggggggggggggggggg", + body: []byte("test-body"), + assertions: func(t *testing.T, valid bool, err error) { + assert.Error(t, err) + assert.False(t, valid) + }, + }, + { + name: "HMAC mismatch", + secret: []byte("test-secret"), + signature: "sha1=38cb0302e94c235fb349ac026084db66bc64a979", + body: []byte("different-body"), + assertions: func(t *testing.T, valid bool, err error) { + assert.NoError(t, err) + assert.False(t, valid) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + valid, err := verifyWebhookSignature(tt.secret, tt.signature, tt.body) + + tt.assertions(t, valid, err) + }) + } +} + +func TestGetEventWithRenderConfig(t *testing.T) { + tests := []struct { + name string + event interface{} + sub *Subscription + assertions func(t *testing.T, result *EventWithRenderConfig) + }{ + { + name: "No Subscription", + event: "test-event", + sub: nil, + assertions: func(t *testing.T, result *EventWithRenderConfig) { + assert.Equal(t, "test-event", result.Event) + assert.Empty(t, result.Config.Style) + }, + }, + { + name: "Subscription with RenderStyle", + event: "test-event", + sub: &Subscription{ + ChannelID: "channel-1", + CreatorID: "creator-1", + Repository: "repo-1", + }, + assertions: func(t *testing.T, result *EventWithRenderConfig) { + assert.Equal(t, "test-event", result.Event) + assert.Empty(t, result.Config.Style) + }, + }, + { + name: "Subscription with Custom RenderStyle", + event: "test-event", + sub: &Subscription{ + ChannelID: "channel-1", + CreatorID: "creator-1", + Flags: SubscriptionFlags{RenderStyle: "custom-style"}, + Repository: "repo-1", + }, + assertions: func(t *testing.T, result *EventWithRenderConfig) { + assert.Equal(t, "test-event", result.Event) + assert.Equal(t, "custom-style", result.Config.Style) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := GetEventWithRenderConfig(tt.event, tt.sub) + + tt.assertions(t, result) + }) + } +} + +func TestNewWebhookBroker(t *testing.T) { + called := false + mockSendGitHubPingEvent := func(event *github.PingEvent) { + called = true + } + + broker := NewWebhookBroker(mockSendGitHubPingEvent) + + mockSendGitHubPingEvent(nil) + + assert.NotNil(t, broker) + assert.True(t, called, "sendGitHubPingEvent should have been called") +} + +func TestSubscribePings(t *testing.T) { + broker := &WebhookBroker{} + + ch := broker.SubscribePings() + assert.NotNil(t, ch, "Channel should not be nil") + assert.Len(t, broker.pingSubs, 1, "pingSubs should contain one channel") + + testCh := make(chan *github.PingEvent, 1) + go func() { + event := &github.PingEvent{} + testCh <- event + }() + + receivedEvent := <-testCh + assert.NotNil(t, receivedEvent, "Received event should not be nil") +} + +func TestUnsubscribePings(t *testing.T) { + broker := &WebhookBroker{} + ch := broker.SubscribePings() + assert.NotNil(t, ch, "Channel should not be nil") + assert.Len(t, broker.pingSubs, 1, "pingSubs should contain one channel") + + broker.UnsubscribePings(ch) + + broker.UnsubscribePings(ch) + assert.Len(t, broker.pingSubs, 0, "pingSubs should be empty after unsubscribe") + assert.Len(t, broker.pingSubs, 0, "pingSubs should still be empty after second unsubscribe") +} + +func TestPublishPing(t *testing.T) { + broker := &WebhookBroker{pingSubs: []chan *github.PingEvent{}} + event := &github.PingEvent{} + mockSendGitHubPingEvent := func(event *github.PingEvent) {} + broker.sendGitHubPingEvent = mockSendGitHubPingEvent + ch := broker.SubscribePings() + + go func() { + broker.publishPing(event, false) + }() + + var wg sync.WaitGroup + wg.Add(1) + + go func() { + defer wg.Done() + receivedEvent := <-ch + assert.NotNil(t, receivedEvent, "Received event should not be nil") + assert.Equal(t, event, receivedEvent, "Received event should match the published event") + }() + + wg.Wait() + + broker.closed = true + broker.publishPing(event, false) +} + +func TestClose(t *testing.T) { + broker := &WebhookBroker{pingSubs: []chan *github.PingEvent{}} + ch := make(chan *github.PingEvent, 1) + broker.pingSubs = append(broker.pingSubs, ch) + + broker.Close() + + assert.True(t, broker.closed, "Broker should be marked as closed") + select { + case _, open := <-ch: + assert.False(t, open, "Channel should be closed") + default: + t.Error("Channel should be closed") + } +} + +func TestHandleWebhookBadRequestBody(t *testing.T) { + mockKvStore, mockAPI, _, _, _ := GetTestSetup(t) + p := getPluginTest(mockAPI, mockKvStore) + + tests := []struct { + name string + signature func([]byte) string + body []byte + githubEventType string + setup func() + assertions func(t *testing.T, resp *httptest.ResponseRecorder) + }{ + { + name: "failed signature verification (invalid signature)", + body: []byte("valid body"), + signature: func(body []byte) string { return "" }, + githubEventType: "", + setup: func() { + p.setConfiguration(&Configuration{ + WebhookSecret: MockWebhookSecret, + }) + }, + assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusUnauthorized, resp.Code) + }, + }, + { + name: "Request body is not webhook content type", + body: []byte("valid body"), + signature: func(body []byte) string { + return generateSignature([]byte(MockWebhookSecret), body) + }, + githubEventType: "", + setup: func() { + p.setConfiguration(&Configuration{ + WebhookSecret: MockWebhookSecret, + }) + mockAPI.On("LogDebug", "GitHub webhook content type should be set to \"application/json\"", "error", "unknown X-Github-Event in message: ").Times(1) + }, + assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusBadRequest, resp.Code) + }, + }, + { + name: "Successful handle ping event", + body: func() []byte { + event := GetMockPingEvent() + body, err := json.Marshal(event) + assert.NoError(t, err) + return body + }(), + signature: func(body []byte) string { + return generateSignature([]byte(MockWebhookSecret), body) + }, + githubEventType: "ping", + setup: func() { + p.webhookBroker = NewWebhookBroker(p.sendGitHubPingEvent) + p.setConfiguration(&Configuration{ + WebhookSecret: MockWebhookSecret, + EnableWebhookEventLogging: true, + }) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockAPI.On("PublishPluginClusterEvent", mock.Anything, mock.Anything).Return(nil).Times(1) + }, + assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusOK, resp.Code) + }, + }, + { + name: "Successful handle pull request event", + body: func() []byte { + event := GetMockPullRequestEvent(actionOpened, MockRepo, "", false, MockSender, MockUserLogin, "") + body, err := json.Marshal(event) + assert.NoError(t, err) + return body + }(), + signature: func(body []byte) string { + return generateSignature([]byte(MockWebhookSecret), body) + }, + githubEventType: "pull_request", + setup: func() { + p.webhookBroker = NewWebhookBroker(p.sendGitHubPingEvent) + p.setConfiguration(&Configuration{ + WebhookSecret: MockWebhookSecret, + EnableWebhookEventLogging: true, + }) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + mockAPI.On("LogDebug", "Unhandled event action", "action", "opened").Times(1) + }, + assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusOK, resp.Code) + }, + }, + { + name: "Successfully handle issue event", + body: func() []byte { + event := GetMockIssueEvent("", "", "", "", "") + body, err := json.Marshal(event) + assert.NoError(t, err) + return body + }(), + signature: func(body []byte) string { + return generateSignature([]byte(MockWebhookSecret), body) + }, + githubEventType: "issues", + setup: func() { + p.webhookBroker = NewWebhookBroker(p.sendGitHubPingEvent) + p.setConfiguration(&Configuration{ + WebhookSecret: MockWebhookSecret, + EnableWebhookEventLogging: true, + }) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + }, + assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusOK, resp.Code) + }, + }, + { + name: "Successfully handle issue comment event", + body: func() []byte { + event := GetMockIssueCommentEvent("", "", "") + body, err := json.Marshal(event) + assert.NoError(t, err) + return body + }(), + signature: func(body []byte) string { + return generateSignature([]byte(MockWebhookSecret), body) + }, + githubEventType: "issue_comment", + setup: func() { + p.webhookBroker = NewWebhookBroker(p.sendGitHubPingEvent) + p.setConfiguration(&Configuration{ + WebhookSecret: MockWebhookSecret, + EnableWebhookEventLogging: true, + }) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + mockKvStore.EXPECT().Get("issueAuthor_githubusername", gomock.Any()).Return(nil).Times(1) + }, + assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusOK, resp.Code) + }, + }, + { + name: "Successfully handle pull request review event", + body: func() []byte { + event := GetMockPullRequestReviewEvent("", "", "", true, "", "") + body, err := json.Marshal(event) + assert.NoError(t, err) + return body + }(), + signature: func(body []byte) string { + return generateSignature([]byte(MockWebhookSecret), body) + }, + githubEventType: "pull_request_review", + setup: func() { + p.webhookBroker = NewWebhookBroker(p.sendGitHubPingEvent) + p.setConfiguration(&Configuration{ + WebhookSecret: MockWebhookSecret, + EnableWebhookEventLogging: true, + }) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + }, + assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusOK, resp.Code) + }, + }, + { + name: "Successfully handle pull request review comment event", + body: func() []byte { + event := GetMockPullRequestReviewCommentEvent() + body, err := json.Marshal(event) + assert.NoError(t, err) + return body + }(), + signature: func(body []byte) string { + return generateSignature([]byte(MockWebhookSecret), body) + }, + githubEventType: "pull_request_review_comment", + setup: func() { + p.webhookBroker = NewWebhookBroker(p.sendGitHubPingEvent) + p.setConfiguration(&Configuration{ + WebhookSecret: MockWebhookSecret, + EnableWebhookEventLogging: true, + }) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + }, + assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusOK, resp.Code) + }, + }, + { + name: "Successfully handle push event", + body: func() []byte { + event := GetMockPushEvent() + body, err := json.Marshal(event) + assert.NoError(t, err) + return body + }(), + signature: func(body []byte) string { + return generateSignature([]byte(MockWebhookSecret), body) + }, + githubEventType: "push", + setup: func() { + p.webhookBroker = NewWebhookBroker(p.sendGitHubPingEvent) + p.setConfiguration(&Configuration{ + WebhookSecret: MockWebhookSecret, + EnableWebhookEventLogging: true, + }) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + }, + assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusOK, resp.Code) + }, + }, + { + name: "Successfully handle create event", + body: func() []byte { + event := GetMockCreateEvent() + body, err := json.Marshal(event) + assert.NoError(t, err) + return body + }(), + signature: func(body []byte) string { + return generateSignature([]byte(MockWebhookSecret), body) + }, + githubEventType: "create", + setup: func() { + p.webhookBroker = NewWebhookBroker(p.sendGitHubPingEvent) + p.setConfiguration(&Configuration{ + WebhookSecret: MockWebhookSecret, + EnableWebhookEventLogging: true, + }) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + }, + assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusOK, resp.Code) + }, + }, + { + name: "Successfully handle delete event", + body: func() []byte { + event := GetMockDeleteEvent() + body, err := json.Marshal(event) + assert.NoError(t, err) + return body + }(), + signature: func(body []byte) string { + return generateSignature([]byte(MockWebhookSecret), body) + }, + githubEventType: "delete", + setup: func() { + p.webhookBroker = NewWebhookBroker(p.sendGitHubPingEvent) + p.setConfiguration(&Configuration{ + WebhookSecret: MockWebhookSecret, + EnableWebhookEventLogging: true, + }) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + }, + assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusOK, resp.Code) + }, + }, + { + name: "Successfully handle start event", + body: func() []byte { + event := GetMockStarEvent("", "", true, "") + body, err := json.Marshal(event) + assert.NoError(t, err) + return body + }(), + signature: func(body []byte) string { + return generateSignature([]byte(MockWebhookSecret), body) + }, + githubEventType: "star", + setup: func() { + p.webhookBroker = NewWebhookBroker(p.sendGitHubPingEvent) + p.setConfiguration(&Configuration{ + WebhookSecret: MockWebhookSecret, + EnableWebhookEventLogging: true, + }) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + }, + assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusOK, resp.Code) + }, + }, + { + name: "Successfully handle release event", + body: func() []byte { + event := GetMockReleaseEvent("", "", "", "") + body, err := json.Marshal(event) + assert.NoError(t, err) + return body + }(), + signature: func(body []byte) string { + return generateSignature([]byte(MockWebhookSecret), body) + }, + githubEventType: "release", + setup: func() { + p.webhookBroker = NewWebhookBroker(p.sendGitHubPingEvent) + p.setConfiguration(&Configuration{ + WebhookSecret: MockWebhookSecret, + EnableWebhookEventLogging: true, + }) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + }, + assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusOK, resp.Code) + }, + }, + { + name: "Successfully handle discussion event", + body: func() []byte { + event := GetMockDiscussionEvent("", "", "") + body, err := json.Marshal(event) + assert.NoError(t, err) + return body + }(), + signature: func(body []byte) string { + return generateSignature([]byte(MockWebhookSecret), body) + }, + githubEventType: "discussion", + setup: func() { + p.webhookBroker = NewWebhookBroker(p.sendGitHubPingEvent) + p.setConfiguration(&Configuration{ + WebhookSecret: MockWebhookSecret, + EnableWebhookEventLogging: true, + }) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + }, + assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusOK, resp.Code) + }, + }, + { + name: "Successfully handle discussion comment event", + body: func() []byte { + event := GetMockDiscussionCommentEvent("", "", "", "") + body, err := json.Marshal(event) + assert.NoError(t, err) + return body + }(), + signature: func(body []byte) string { + return generateSignature([]byte(MockWebhookSecret), body) + }, + githubEventType: "discussion_comment", + setup: func() { + p.webhookBroker = NewWebhookBroker(p.sendGitHubPingEvent) + p.setConfiguration(&Configuration{ + WebhookSecret: MockWebhookSecret, + EnableWebhookEventLogging: true, + }) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + }, + assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusOK, resp.Code) + }, + }, + { + name: "Successfully handle discussion comment event", + body: func() []byte { + event := GetMockDiscussionCommentEvent("", "", "", "") + body, err := json.Marshal(event) + assert.NoError(t, err) + return body + }(), + signature: func(body []byte) string { + return generateSignature([]byte(MockWebhookSecret), body) + }, + githubEventType: "discussion_comment", + setup: func() { + p.webhookBroker = NewWebhookBroker(p.sendGitHubPingEvent) + p.setConfiguration(&Configuration{ + WebhookSecret: MockWebhookSecret, + EnableWebhookEventLogging: true, + }) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + }, + assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusOK, resp.Code) + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + tc.setup() + + req := httptest.NewRequest(http.MethodPost, "/webhook", bytes.NewReader(tc.body)) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("X-Hub-Signature", tc.signature(tc.body)) + req.Header.Set("X-GitHub-Event", tc.githubEventType) + resp := httptest.NewRecorder() + + p.handleWebhook(resp, req) + + tc.assertions(t, resp) + }) + } +} + +func TestPostPullRequestEvent(t *testing.T) { + mockKvStore, mockAPI, _, _, _ := GetTestSetup(t) + p := getPluginTest(mockAPI, mockKvStore) + + tests := []struct { + name string + event *github.PullRequestEvent + setup func() + }{ + { + name: "No subscription for channel", + event: GetMockPullRequestEvent(actionCreated, MockRepo, MockValidLabel, false, MockSender, MockUserID, MockUsername), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + }, + }, + { + name: "Unsupported action", + event: GetMockPullRequestEvent(actionCreated, MockRepo, MockValidLabel, false, MockSender, MockUserID, MockUsername), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockorg/mockrepo": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("issues,label:\"validLabel\""), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + }, + }, + { + name: "Valid subscription does not exist", + event: GetMockPullRequestEvent(actionOpened, MockRepo, MockValidLabel, false, MockSender, MockUserID, MockUsername), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockorg/mockrepo": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("issues,label:\"validLabel\""), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + }, + }, + { + name: "PullsMerged subscription exist but PR action is not closed", + event: GetMockPullRequestEvent(actionOpened, MockRepo, MockValidLabel, false, MockSender, MockUserID, MockUsername), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockorg/mockrepo": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("pulls_merged,label:\"validLabel\""), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + }, + }, + { + name: "PullsCreated subscription exist but PR action is not opened", + event: GetMockPullRequestEvent(actionClosed, MockRepo, MockValidLabel, false, MockSender, MockUserID, MockUsername), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockorg/mockrepo": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("pulls_created,label:\"validLabel\""), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + }, + }, + { + name: "no valid label exists", + event: GetMockPullRequestEvent(actionOpened, MockRepo, MockValidLabel, false, MockSender, MockUserID, MockUsername), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockorg/mockrepo": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("pulls_created,label:\"invalidLabel\""), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + }, + }, + { + name: "Error creating post for action labeled", + event: GetMockPullRequestEvent(actionLabeled, MockRepo, MockValidLabel, false, MockSender, MockUserID, MockUsername), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockorg/mockrepo": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("pulls,label:\"validLabel\""), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error webhook post", "post", mock.Anything, "error", "error creating post") + }, + }, + { + name: "event label is not equal to subscription label", + event: GetMockPullRequestEvent(actionLabeled, MockRepo, "invalidLabel", false, MockSender, MockUserID, MockUsername), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockorg/mockrepo": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("pulls,label:\"validLabel\""), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + }, + }, + { + name: "success creating post for action labeled", + event: GetMockPullRequestEvent(actionLabeled, MockRepo, MockValidLabel, false, MockSender, MockUserID, MockUsername), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockorg/mockrepo": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("pulls,label:\"validLabel\""), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + }, + }, + { + name: "Success creating post for action opened", + event: GetMockPullRequestEvent(actionOpened, MockRepo, MockValidLabel, false, MockSender, MockUserID, MockUsername), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockorg/mockrepo": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("pulls_created,label:\"validLabel\""), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + }, + }, + { + name: "Success creating post for action reopened", + event: GetMockPullRequestEvent(actionReopened, MockRepo, MockValidLabel, false, MockSender, MockUserID, MockUsername), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockorg/mockrepo": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("pulls,label:\"validLabel\""), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + }, + }, + { + name: "Success creating post for action MarkedReadyForReview", + event: GetMockPullRequestEvent(actionMarkedReadyForReview, MockRepo, MockValidLabel, false, MockSender, MockUserID, MockUsername), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockorg/mockrepo": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("pulls,label:\"validLabel\""), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + }, + }, + { + name: "Success creating post for action closed", + event: GetMockPullRequestEvent(actionClosed, MockRepo, MockValidLabel, false, MockSender, MockUserID, MockUsername), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockorg/mockrepo": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("pulls,label:\"validLabel\""), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + tc.setup() + + p.postPullRequestEvent(tc.event) + + mockAPI.AssertExpectations(t) + }) + } +} + +func TestSanitizeDescription(t *testing.T) { + tests := []struct { + name string + description string + expected string + }{ + { + name: "description with
", + description: "description with
MockDetails
and the values", + expected: "description with and the values", + }, + { + name: "description without
", + description: "Content without details tag.", + expected: "Content without details tag.", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mockKvStore, mockAPI, _, _, _ := GetTestSetup(t) + p := getPluginTest(mockAPI, mockKvStore) + + sanitizedDescription := p.sanitizeDescription(tt.description) + + assert.Equal(t, tt.expected, sanitizedDescription) + }) + } +} + +func TestHandlePRDescriptionMentionNotification(t *testing.T) { + mockKvStore, mockAPI, _, _, _ := GetTestSetup(t) + p := getPluginTest(mockAPI, mockKvStore) + + tests := []struct { + name string + event *github.PullRequestEvent + setup func() + }{ + { + name: "action other than opened", + event: GetMockPRDescriptionEvent(MockRepo, MockOrg, MockSender, MockSender, actionClosed, ""), + setup: func() {}, + }, + { + name: "no mentioned users in PR description", + event: GetMockPRDescriptionEvent(MockRepo, MockOrg, MockSender, MockSender, actionOpened, ""), + setup: func() {}, + }, + { + name: "PR description mentions a user but they are the PR author", + event: GetMockPRDescriptionEvent(MockRepo, MockOrg, MockSender, MockSender, actionOpened, fmt.Sprintf("@%s", MockSender)), + setup: func() { + mockKvStore.EXPECT().Get("prAuthor_githubusername", gomock.Any()).Return(nil).Times(1) + }, + }, + { + name: "Skip notification for pull request", + event: GetMockPRDescriptionEvent(MockRepo, MockOrg, "mockSender2", MockSender, actionOpened, fmt.Sprintf("@%s", MockSender)), + setup: func() { + mockKvStore.EXPECT().Get("prAuthor_githubusername", gomock.Any()).Return(nil).Times(1) + }, + }, + { + name: "user id not mapped with github", + event: GetMockPRDescriptionEvent(MockRepo, MockOrg, MockSender, MockSender, actionOpened, MockProfileUsername), + setup: func() { + mockKvStore.EXPECT().Get("username_githubusername", gomock.Any()).Return(nil).Times(1) + }, + }, + { + name: "Error getting channel", + event: GetMockPRDescriptionEvent(MockRepo, MockOrg, MockSender, MockSender, actionOpened, MockProfileUsername), + setup: func() { + mockKvStore.EXPECT().Get("username_githubusername", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(*[]byte); ok { + *v = []byte(MockUserID) + } + return nil + }).Times(1) + mockKvStore.EXPECT().Get("mockUserID_githubtoken", gomock.Any()).Return(nil).Times(1) + mockAPI.On("GetDirectChannel", MockUserID, p.BotUserID).Return(nil, &model.AppError{Message: "error getting direct channel"}).Times(1) + }, + }, + { + name: "PR description mentions a user, post created", + event: GetMockPRDescriptionEvent(MockRepo, MockOrg, MockSender, MockSender, actionOpened, MockProfileUsername), + setup: func() { + mockKvStore.EXPECT().Get("username_githubusername", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(*[]byte); ok { + *v = []byte(MockUserID) + } + return nil + }).Times(1) + mockKvStore.EXPECT().Get("mockUserID_githubtoken", gomock.Any()).Return(nil).Times(1) + mockAPI.On("GetDirectChannel", MockUserID, p.BotUserID).Return(&model.Channel{Id: MockChannelID}, nil).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{Id: MockPostID}, nil).Times(1) + mockAPI.On("LogWarn", "Failed to get github user info", "error", "Must connect user account to GitHub first.") + }, + }, + { + name: "Error creating post", + event: GetMockPRDescriptionEvent(MockRepo, MockOrg, MockSender, MockSender, actionOpened, MockProfileUsername), + setup: func() { + mockKvStore.EXPECT().Get("username_githubusername", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(*[]byte); ok { + *v = []byte(MockUserID) + } + return nil + }).Times(1) + mockKvStore.EXPECT().Get("mockUserID_githubtoken", gomock.Any()).Return(nil).Times(1) + mockAPI.On("GetDirectChannel", MockUserID, p.BotUserID).Return(&model.Channel{Id: MockChannelID}, nil).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Failed to get github user info", "error", "Must connect user account to GitHub first.") + mockAPI.On("LogWarn", "Error webhook post", "post", mock.Anything, "error", "error creating post") + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + tc.setup() + + p.handlePRDescriptionMentionNotification(tc.event) + + mockAPI.AssertExpectations(t) + }) + } +} + +func TestPostIssueEvent(t *testing.T) { + mockKvStore, mockAPI, _, _, _ := GetTestSetup(t) + p := getPluginTest(mockAPI, mockKvStore) + + tests := []struct { + name string + event *github.IssuesEvent + setup func() + }{ + { + name: "no subscribed channels for repository", + event: GetMockIssueEvent(MockRepo, MockOrg, MockSender, actionOpened, MockLabel), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) + }, + }, + { + name: "issue labeled but recently created, no post sent", + event: GetMockIssueEventWithTimeDiff(MockRepo, MockOrg, MockSender, actionLabeled, MockLabel, -2*time.Second), + setup: func() {}, + }, + { + name: "issue labeled with matching label", + event: GetMockIssueEventWithTimeDiff(MockRepo, MockOrg, MockSender, actionLabeled, MockValidLabel, -5*time.Second), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("issues,label:\"validLabel\""), + Repository: MockRepo, + }, + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: featureDeletes, + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + }, + }, + { + name: "error creating post", + event: GetMockIssueEventWithTimeDiff(MockRepo, MockOrg, MockSender, actionLabeled, MockValidLabel, -5*time.Second), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("issues,label:\"validLabel\""), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error webhook post", "post", mock.Anything, "error", "error creating post") + }, + }, + { + name: "issue creation skipped due to unsupported action", + event: GetMockIssueEventWithTimeDiff(MockRepo, MockOrg, MockSender, actionClosed, MockLabel, -5*time.Second), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("issue_creations"), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + }, + }, + { + name: "issue skipped due to unmatched label", + event: GetMockIssueEventWithTimeDiff(MockRepo, MockOrg, MockSender, actionLabeled, "nonMatchingLabel", -5*time.Second), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("issues,label:\"validLabel\""), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + }, + }, + { + name: "issue skipped due to mismatched event label", + event: func() *github.IssuesEvent { + event := GetMockIssueEventWithTimeDiff(MockRepo, MockOrg, MockSender, actionLabeled, "eventLabel", -5*time.Second) + event.GetIssue().Labels = []*github.Label{{Name: github.String("subscriptionLabel")}} + return event + }(), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("issues,label:\"subscriptionLabel\""), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + }, + }, + { + name: "success creating post for issue opened", + event: GetMockIssueEvent(MockRepo, MockOrg, MockSender, actionOpened, MockLabel), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("issue_creations"), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + }, + }, + { + name: "success creating post for issue closed", + event: GetMockIssueEvent(MockRepo, MockOrg, MockSender, actionOpened, MockLabel), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("issue_creations"), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + }, + }, + { + name: "success creating post for issue reopened", + event: GetMockIssueEvent(MockRepo, MockOrg, MockSender, actionReopened, MockLabel), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("issue_creations"), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + }, + }, + { + name: "unsupported action", + event: GetMockIssueEvent(MockRepo, MockOrg, MockSender, actionDeleted, MockLabel), + setup: func() { + mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { + if v, ok := value.(**Subscriptions); ok { + *v = &Subscriptions{ + Repositories: map[string][]*Subscription{ + "mockrepo/mockorg": { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features("issue_creations"), + Repository: MockRepo, + }, + }, + }, + } + } + return nil + }).Times(1) + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + tc.setup() + + p.postIssueEvent(tc.event) + + mockAPI.AssertExpectations(t) + }) + } +} + func TestPostPushEvent(t *testing.T) { mockKvStore, mockAPI, _, _, _ := GetTestSetup(t) p := getPluginTest(mockAPI, mockKvStore) @@ -773,24 +2101,24 @@ func TestHandlePullRequestNotification(t *testing.T) { }{ { name: "review requested by sender", - event: GetMockPullRequestEvent("review_requested", "mockRepo", false, "senderUser", "senderUser", ""), + event: GetMockPullRequestEvent("review_requested", "mockRepo", MockValidLabel, false, "senderUser", "senderUser", ""), setup: func() {}, }, { name: "review requested with no repo permission", - event: GetMockPullRequestEvent("review_requested", "mockRepo", true, "senderUser", "requestedReviewer", ""), + event: GetMockPullRequestEvent("review_requested", "mockRepo", MockValidLabel, true, "senderUser", "requestedReviewer", ""), setup: func() { mockKvStore.EXPECT().Get("requestedReviewer_githubusername", gomock.Any()).Return(nil).Times(1) }, }, { name: "pull request closed by author", - event: GetMockPullRequestEvent(actionClosed, "mockRepo", false, "authorUser", "authorUser", ""), + event: GetMockPullRequestEvent(actionClosed, "mockRepo", MockValidLabel, false, "authorUser", "authorUser", ""), setup: func() {}, }, { name: "pull request closed successfully", - event: GetMockPullRequestEvent(actionClosed, "mockRepo", false, "authorUser", "senderUser", ""), + event: GetMockPullRequestEvent(actionClosed, "mockRepo", MockValidLabel, false, "authorUser", "senderUser", ""), setup: func() { mockKvStore.EXPECT().Get("senderUser_githubusername", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(*[]byte); ok { @@ -806,19 +2134,19 @@ func TestHandlePullRequestNotification(t *testing.T) { }, { name: "pull request reopened with no repo permission", - event: GetMockPullRequestEvent(actionReopened, "mockRepo", true, "authorUser", "senderUser", ""), + event: GetMockPullRequestEvent(actionReopened, "mockRepo", MockValidLabel, true, "authorUser", "senderUser", ""), setup: func() { mockKvStore.EXPECT().Get("senderUser_githubusername", gomock.Any()).Return(nil).Times(1) }, }, { name: "pull request assigned to self", - event: GetMockPullRequestEvent(actionAssigned, "mockRepo", false, "assigneeUser", "assigneeUser", "assigneeUser"), + event: GetMockPullRequestEvent(actionAssigned, "mockRepo", MockValidLabel, false, "assigneeUser", "assigneeUser", "assigneeUser"), setup: func() {}, }, { name: "pull request assigned successfully", - event: GetMockPullRequestEvent(actionAssigned, "mockRepo", false, "senderUser", "assigneeUser", "assigneeUser"), + event: GetMockPullRequestEvent(actionAssigned, "mockRepo", MockValidLabel, false, "senderUser", "assigneeUser", "assigneeUser"), setup: func() { mockKvStore.EXPECT().Get("assigneeUser_githubusername", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(*[]byte); ok { @@ -834,7 +2162,7 @@ func TestHandlePullRequestNotification(t *testing.T) { }, { name: "review requested with valid user ID", - event: GetMockPullRequestEvent("review_requested", "mockRepo", false, "senderUser", "requestedReviewer", ""), + event: GetMockPullRequestEvent("review_requested", "mockRepo", MockValidLabel, false, "senderUser", "requestedReviewer", ""), setup: func() { mockKvStore.EXPECT().Get("requestedReviewer_githubusername", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(*[]byte); ok { @@ -851,7 +2179,7 @@ func TestHandlePullRequestNotification(t *testing.T) { { name: "unhandled event action", event: GetMockPullRequestEvent( - "unsupported_action", "mockRepo", false, "senderUser", "", ""), + "unsupported_action", "mockRepo", MockValidLabel, false, "senderUser", "", ""), setup: func() { mockAPI.On("LogDebug", "Unhandled event action", "action", "unsupported_action").Return(nil).Times(1) }, From 77d23bb1774166f97df363fb4cac13474e18d13b Mon Sep 17 00:00:00 2001 From: kshitij katiyar Date: Wed, 15 Jan 2025 16:03:17 +0530 Subject: [PATCH 3/3] [MM-979]: review fixes --- server/plugin/utils.go | 15 + server/plugin/webhook_test.go | 550 +++++++--------------------------- 2 files changed, 115 insertions(+), 450 deletions(-) diff --git a/server/plugin/utils.go b/server/plugin/utils.go index 4094c9801..f1e7f61d6 100644 --- a/server/plugin/utils.go +++ b/server/plugin/utils.go @@ -389,3 +389,18 @@ func lastN(s string, n int) string { return string(out) } + +func GetMockSubscriptionWithLabel(repo string, feature string) *Subscriptions { + return &Subscriptions{ + Repositories: map[string][]*Subscription{ + repo: { + { + ChannelID: MockChannelID, + CreatorID: MockCreatorID, + Features: Features(feature), + Repository: MockRepo, + }, + }, + }, + } +} diff --git a/server/plugin/webhook_test.go b/server/plugin/webhook_test.go index 24012cdcd..d5eea10fd 100644 --- a/server/plugin/webhook_test.go +++ b/server/plugin/webhook_test.go @@ -292,8 +292,8 @@ func TestHandleWebhookBadRequestBody(t *testing.T) { WebhookSecret: MockWebhookSecret, EnableWebhookEventLogging: true, }) - mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) - mockAPI.On("PublishPluginClusterEvent", mock.Anything, mock.Anything).Return(nil).Times(1) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.AnythingOfType("string")).Times(1) + mockAPI.On("PublishPluginClusterEvent", mock.AnythingOfType("model.PluginClusterEvent"), mock.AnythingOfType("model.PluginClusterEventSendOptions")).Return(nil).Times(1) }, assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { assert.Equal(t, http.StatusOK, resp.Code) @@ -317,7 +317,7 @@ func TestHandleWebhookBadRequestBody(t *testing.T) { WebhookSecret: MockWebhookSecret, EnableWebhookEventLogging: true, }) - mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.AnythingOfType("string")).Times(1) mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) mockAPI.On("LogDebug", "Unhandled event action", "action", "opened").Times(1) }, @@ -343,7 +343,7 @@ func TestHandleWebhookBadRequestBody(t *testing.T) { WebhookSecret: MockWebhookSecret, EnableWebhookEventLogging: true, }) - mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.AnythingOfType("string")).Times(1) mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) }, assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { @@ -368,7 +368,7 @@ func TestHandleWebhookBadRequestBody(t *testing.T) { WebhookSecret: MockWebhookSecret, EnableWebhookEventLogging: true, }) - mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.AnythingOfType("string")).Times(1) mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) mockKvStore.EXPECT().Get("issueAuthor_githubusername", gomock.Any()).Return(nil).Times(1) }, @@ -394,7 +394,7 @@ func TestHandleWebhookBadRequestBody(t *testing.T) { WebhookSecret: MockWebhookSecret, EnableWebhookEventLogging: true, }) - mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.AnythingOfType("string")).Times(1) mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) }, assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { @@ -419,7 +419,7 @@ func TestHandleWebhookBadRequestBody(t *testing.T) { WebhookSecret: MockWebhookSecret, EnableWebhookEventLogging: true, }) - mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.AnythingOfType("string")).Times(1) mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) }, assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { @@ -444,7 +444,7 @@ func TestHandleWebhookBadRequestBody(t *testing.T) { WebhookSecret: MockWebhookSecret, EnableWebhookEventLogging: true, }) - mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.AnythingOfType("string")).Times(1) mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) }, assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { @@ -469,7 +469,7 @@ func TestHandleWebhookBadRequestBody(t *testing.T) { WebhookSecret: MockWebhookSecret, EnableWebhookEventLogging: true, }) - mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.AnythingOfType("string")).Times(1) mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) }, assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { @@ -494,7 +494,7 @@ func TestHandleWebhookBadRequestBody(t *testing.T) { WebhookSecret: MockWebhookSecret, EnableWebhookEventLogging: true, }) - mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.AnythingOfType("string")).Times(1) mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) }, assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { @@ -519,7 +519,7 @@ func TestHandleWebhookBadRequestBody(t *testing.T) { WebhookSecret: MockWebhookSecret, EnableWebhookEventLogging: true, }) - mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.AnythingOfType("string")).Times(1) mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) }, assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { @@ -544,7 +544,7 @@ func TestHandleWebhookBadRequestBody(t *testing.T) { WebhookSecret: MockWebhookSecret, EnableWebhookEventLogging: true, }) - mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.AnythingOfType("string")).Times(1) mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) }, assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { @@ -569,7 +569,7 @@ func TestHandleWebhookBadRequestBody(t *testing.T) { WebhookSecret: MockWebhookSecret, EnableWebhookEventLogging: true, }) - mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.AnythingOfType("string")).Times(1) mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) }, assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { @@ -594,7 +594,7 @@ func TestHandleWebhookBadRequestBody(t *testing.T) { WebhookSecret: MockWebhookSecret, EnableWebhookEventLogging: true, }) - mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.AnythingOfType("string")).Times(1) mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) }, assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { @@ -619,7 +619,7 @@ func TestHandleWebhookBadRequestBody(t *testing.T) { WebhookSecret: MockWebhookSecret, EnableWebhookEventLogging: true, }) - mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.Anything).Times(1) + mockAPI.On("LogDebug", "Webhook Event Log", "event", mock.AnythingOfType("string")).Times(1) mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).Return(nil).Times(1) }, assertions: func(t *testing.T, resp *httptest.ResponseRecorder) { @@ -666,18 +666,7 @@ func TestPostPullRequestEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockorg/mockrepo": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("issues,label:\"validLabel\""), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockorg/mockrepo", "issues,label:\"validLabel\"") } return nil }).Times(1) @@ -689,18 +678,7 @@ func TestPostPullRequestEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockorg/mockrepo": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("issues,label:\"validLabel\""), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockorg/mockrepo", "issues,label:\"validLabel\"") } return nil }).Times(1) @@ -712,18 +690,7 @@ func TestPostPullRequestEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockorg/mockrepo": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("pulls_merged,label:\"validLabel\""), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockorg/mockrepo", "pulls_merged,label:\"validLabel\"") } return nil }).Times(1) @@ -735,18 +702,7 @@ func TestPostPullRequestEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockorg/mockrepo": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("pulls_created,label:\"validLabel\""), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockorg/mockrepo", "pulls_created,label:\"validLabel\"") } return nil }).Times(1) @@ -758,18 +714,7 @@ func TestPostPullRequestEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockorg/mockrepo": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("pulls_created,label:\"invalidLabel\""), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockorg/mockrepo", "pulls_created,label:\"invalidLabel\"") } return nil }).Times(1) @@ -796,8 +741,8 @@ func TestPostPullRequestEvent(t *testing.T) { } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) - mockAPI.On("LogWarn", "Error webhook post", "post", mock.Anything, "error", "error creating post") + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error webhook post", "post", mock.AnythingOfType("*model.Post"), "error", "error creating post") }, }, { @@ -806,18 +751,7 @@ func TestPostPullRequestEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockorg/mockrepo": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("pulls,label:\"validLabel\""), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockorg/mockrepo", "pulls,label:\"validLabel\"") } return nil }).Times(1) @@ -844,55 +778,33 @@ func TestPostPullRequestEvent(t *testing.T) { } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, { - name: "Success creating post for action opened", + name: "Success creating post for pull requeset opened", event: GetMockPullRequestEvent(actionOpened, MockRepo, MockValidLabel, false, MockSender, MockUserID, MockUsername), setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockorg/mockrepo": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("pulls_created,label:\"validLabel\""), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockorg/mockrepo", "pulls_created,label:\"validLabel\"") } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, { - name: "Success creating post for action reopened", + name: "Success creating post for pull opened", event: GetMockPullRequestEvent(actionReopened, MockRepo, MockValidLabel, false, MockSender, MockUserID, MockUsername), setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockorg/mockrepo": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("pulls,label:\"validLabel\""), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockorg/mockrepo", "pulls,label:\"validLabel\"") } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, { @@ -901,22 +813,11 @@ func TestPostPullRequestEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockorg/mockrepo": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("pulls,label:\"validLabel\""), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockorg/mockrepo", "pulls,label:\"validLabel\"") } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, { @@ -925,22 +826,11 @@ func TestPostPullRequestEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockorg/mockrepo": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("pulls,label:\"validLabel\""), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockorg/mockrepo", "pulls,label:\"validLabel\"") } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, } @@ -1050,7 +940,7 @@ func TestHandlePRDescriptionMentionNotification(t *testing.T) { }).Times(1) mockKvStore.EXPECT().Get("mockUserID_githubtoken", gomock.Any()).Return(nil).Times(1) mockAPI.On("GetDirectChannel", MockUserID, p.BotUserID).Return(&model.Channel{Id: MockChannelID}, nil).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{Id: MockPostID}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{Id: MockPostID}, nil).Times(1) mockAPI.On("LogWarn", "Failed to get github user info", "error", "Must connect user account to GitHub first.") }, }, @@ -1066,9 +956,9 @@ func TestHandlePRDescriptionMentionNotification(t *testing.T) { }).Times(1) mockKvStore.EXPECT().Get("mockUserID_githubtoken", gomock.Any()).Return(nil).Times(1) mockAPI.On("GetDirectChannel", MockUserID, p.BotUserID).Return(&model.Channel{Id: MockChannelID}, nil).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) mockAPI.On("LogWarn", "Failed to get github user info", "error", "Must connect user account to GitHub first.") - mockAPI.On("LogWarn", "Error webhook post", "post", mock.Anything, "error", "error creating post") + mockAPI.On("LogWarn", "Error webhook post", "post", mock.AnythingOfType("*model.Post"), "error", "error creating post") }, }, } @@ -1110,28 +1000,11 @@ func TestPostIssueEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("issues,label:\"validLabel\""), - Repository: MockRepo, - }, - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: featureDeletes, - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockrepo/mockorg", "issues,label:\"validLabel\"") } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, { @@ -1140,23 +1013,12 @@ func TestPostIssueEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("issues,label:\"validLabel\""), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockrepo/mockorg", "issues,label:\"validLabel\"") } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) - mockAPI.On("LogWarn", "Error webhook post", "post", mock.Anything, "error", "error creating post") + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error webhook post", "post", mock.AnythingOfType("*model.Post"), "error", "error creating post") }, }, { @@ -1165,18 +1027,7 @@ func TestPostIssueEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("issue_creations"), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockorg/mockrepo", featureIssueCreation) } return nil }).Times(1) @@ -1188,18 +1039,7 @@ func TestPostIssueEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("issues,label:\"validLabel\""), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockorg/mockrepo", "issues,label:\"validLabel\"") } return nil }).Times(1) @@ -1215,18 +1055,7 @@ func TestPostIssueEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("issues,label:\"subscriptionLabel\""), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockorg/mockrepo", "issues,label:\"subscriptionLabel\"") } return nil }).Times(1) @@ -1238,22 +1067,11 @@ func TestPostIssueEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("issue_creations"), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockrepo/mockorg", featureIssueCreation) } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, { @@ -1262,22 +1080,11 @@ func TestPostIssueEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("issue_creations"), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockrepo/mockorg", featureIssueCreation) } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, { @@ -1286,22 +1093,11 @@ func TestPostIssueEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("issue_creations"), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockrepo/mockorg", featureIssueCreation) } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, { @@ -1310,18 +1106,7 @@ func TestPostIssueEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: Features("issue_creations"), - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockorg/mockrepo", featureIssueCreation) } return nil }).Times(1) @@ -1335,6 +1120,7 @@ func TestPostIssueEvent(t *testing.T) { p.postIssueEvent(tc.event) mockAPI.AssertExpectations(t) + mockAPI.ExpectedCalls = nil }) } } @@ -1377,8 +1163,8 @@ func TestPostPushEvent(t *testing.T) { } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) - mockAPI.On("LogWarn", "Error webhook post", "post", mock.Anything, "error", "error creating post") + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error webhook post", "post", mock.AnythingOfType("*model.Post"), "error", "error creating post") }, }, { @@ -1391,7 +1177,7 @@ func TestPostPushEvent(t *testing.T) { } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, } @@ -1444,8 +1230,8 @@ func TestPostCreateEvent(t *testing.T) { } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) - mockAPI.On("LogWarn", "Error webhook post", "post", mock.Anything, "error", "error creating post") + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error webhook post", "post", mock.AnythingOfType("*model.Post"), "error", "error creating post") }, }, { @@ -1458,7 +1244,7 @@ func TestPostCreateEvent(t *testing.T) { } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, } @@ -1511,8 +1297,8 @@ func TestPostDeleteEvent(t *testing.T) { } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) - mockAPI.On("LogWarn", "Error webhook post", "post", mock.Anything, "error", "error creating post") + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error webhook post", "post", mock.AnythingOfType("*model.Post"), "error", "error creating post") }, }, { @@ -1525,7 +1311,7 @@ func TestPostDeleteEvent(t *testing.T) { } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, } @@ -1580,7 +1366,7 @@ func TestPostIssueCommentEvent(t *testing.T) { } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, { @@ -1593,8 +1379,8 @@ func TestPostIssueCommentEvent(t *testing.T) { } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) - mockAPI.On("LogWarn", "Error webhook post", "post", mock.Anything, "error", "error creating post").Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error webhook post", "post", mock.AnythingOfType("*model.Post"), "error", "error creating post").Times(1) }, }, { @@ -1607,7 +1393,7 @@ func TestPostIssueCommentEvent(t *testing.T) { } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, } @@ -1736,8 +1522,8 @@ func TestPostPullRequestReviewEvent(t *testing.T) { } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) - mockAPI.On("LogWarn", "Error webhook post", "post", mock.Anything, "error", "error creating post").Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error webhook post", "post", mock.AnythingOfType("*model.Post"), "error", "error creating post").Times(1) }, }, { @@ -1750,7 +1536,7 @@ func TestPostPullRequestReviewEvent(t *testing.T) { } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, } @@ -1792,8 +1578,8 @@ func TestPostPullRequestReviewCommentEvent(t *testing.T) { } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) - mockAPI.On("LogWarn", "Error webhook post", "post", mock.Anything, "error", "error creating post").Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error webhook post", "post", mock.AnythingOfType("*model.Post"), "error", "error creating post").Times(1) }, }, { @@ -1806,7 +1592,7 @@ func TestPostPullRequestReviewCommentEvent(t *testing.T) { } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, } @@ -1878,7 +1664,7 @@ func TestHandleCommentMentionNotification(t *testing.T) { }).Times(1) mockKvStore.EXPECT().Get("otherUserID_githubtoken", gomock.Any()).Return(nil).Times(1) mockAPI.On("GetDirectChannel", "otherUserID", "mockBotID").Return(&model.Channel{Id: "mockChannelID"}, nil).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) mockAPI.On("LogWarn", "Error creating mention post", "error", "error creating post").Times(1) mockAPI.On("LogWarn", "Failed to get github user info", "error", "Must connect user account to GitHub first.").Times(1) }, @@ -1895,7 +1681,7 @@ func TestHandleCommentMentionNotification(t *testing.T) { }).Times(1) mockKvStore.EXPECT().Get("otherUserID_githubtoken", gomock.Any()).Return(nil).Times(1) mockAPI.On("GetDirectChannel", "otherUserID", "mockBotID").Return(&model.Channel{Id: "mockChannelID"}, nil).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) mockAPI.On("LogWarn", "Failed to get github user info", "error", "Must connect user account to GitHub first.") }, }, @@ -1975,7 +1761,7 @@ func TestHandleCommentAuthorNotification(t *testing.T) { mockKvStore.EXPECT().Get("authorUserID-muted-users", gomock.Any()).Return(nil).Times(1) mockKvStore.EXPECT().Get("authorUserID_githubtoken", gomock.Any()).Return(nil).Times(1) mockAPI.On("GetDirectChannel", "authorUserID", "mockBotID").Return(&model.Channel{Id: "mockChannelID"}, nil).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil, &model.AppError{Message: "error creating post"}).Times(1) mockAPI.On("LogWarn", "Failed to get github user info", "error", "Must connect user account to GitHub first.").Times(1) }, }, @@ -1993,7 +1779,7 @@ func TestHandleCommentAuthorNotification(t *testing.T) { mockKvStore.EXPECT().Get("authorUserID_githubtoken", gomock.Any()).Return(nil).Times(1) mockAPI.On("LogWarn", "Failed to get github user info", "error", "Must connect user account to GitHub first.").Times(1) mockAPI.On("GetDirectChannel", "authorUserID", "mockBotID").Return(&model.Channel{Id: "mockChannelID"}, nil).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, } @@ -2061,8 +1847,6 @@ func TestHandleCommentAssigneeNotification(t *testing.T) { return nil }).Times(1) mockKvStore.EXPECT().Get("assigneeUserID_githubtoken", gomock.Any()).Return(nil).Times(1) - // mockAPI.On("LogDebug", "Commenter is muted, skipping notification") - // mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) }, }, { @@ -2128,7 +1912,7 @@ func TestHandlePullRequestNotification(t *testing.T) { }).Times(1) mockKvStore.EXPECT().Get("authorUserID_githubtoken", gomock.Any()).Return(nil).Times(1) mockAPI.On("GetDirectChannel", "authorUserID", "mockBotID").Return(&model.Channel{Id: "mockChannelID"}, nil) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) mockAPI.On("LogWarn", "Failed to get github user info", "error", "Must connect user account to GitHub first.").Times(1) }, }, @@ -2155,7 +1939,7 @@ func TestHandlePullRequestNotification(t *testing.T) { return nil }).Times(1) mockAPI.On("GetDirectChannel", "assigneeUserID", "mockBotID").Return(&model.Channel{Id: "mockChannelID"}, nil) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) mockKvStore.EXPECT().Get("assigneeUserID_githubtoken", gomock.Any()).Return(nil).Times(1) mockAPI.On("LogWarn", "Failed to get github user info", "error", "Must connect user account to GitHub first.").Times(1) }, @@ -2171,7 +1955,7 @@ func TestHandlePullRequestNotification(t *testing.T) { return nil }).Times(1) mockAPI.On("GetDirectChannel", "requestedUserID", "mockBotID").Return(&model.Channel{Id: "mockChannelID"}, nil) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) mockKvStore.EXPECT().Get("requestedUserID_githubtoken", gomock.Any()).Return(nil).Times(1) mockAPI.On("LogWarn", "Failed to get github user info", "error", "Must connect user account to GitHub first.").Times(1) }, @@ -2372,29 +2156,12 @@ func TestPostStarEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: featureStars, - Repository: MockRepo, - }, - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: featureDeletes, - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockrepo/mockorg", featureStars) } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) - mockAPI.On("LogWarn", "Error webhook post", "post", mock.Anything, "error", "error creating post") + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error webhook post", "post", mock.AnythingOfType("*model.Post"), "error", "error creating post") }, }, { @@ -2403,28 +2170,11 @@ func TestPostStarEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: featureStars, - Repository: MockRepo, - }, - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: featureDeletes, - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockrepo/mockorg", featureStars) } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, } @@ -2466,29 +2216,12 @@ func TestPostReleaseEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: featureReleases, - Repository: MockRepo, - }, - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: featureDeletes, - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockrepo/mockorg", featureReleases) } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) - mockAPI.On("LogWarn", "Error webhook post", "Post", mock.Anything, "Error", "error creating post") + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error webhook post", "Post", mock.AnythingOfType("*model.Post"), "Error", "error creating post") }, }, { @@ -2497,28 +2230,11 @@ func TestPostReleaseEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: featureReleases, - Repository: MockRepo, - }, - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: featureDeletes, - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockrepo/mockorg", featureReleases) } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, } @@ -2555,29 +2271,12 @@ func TestPostDiscussionEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: featureDiscussions, - Repository: MockRepo, - }, - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: featureDeletes, - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockrepo/mockorg", featureDiscussions) } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) - mockAPI.On("LogWarn", "Error creating discussion notification post", "Post", mock.Anything, "Error", "error creating post") + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error creating discussion notification post", "Post", mock.AnythingOfType("*model.Post"), "Error", "error creating post") }, }, { @@ -2586,22 +2285,11 @@ func TestPostDiscussionEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: featureDiscussions, - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockrepo/mockorg", featureDiscussions) } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, } @@ -2638,18 +2326,7 @@ func TestPostDiscussionCommentEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: featureDiscussionComments, - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockrepo/mockorg", featureDiscussionComments) } return nil }).Times(1) @@ -2661,28 +2338,12 @@ func TestPostDiscussionCommentEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: featureDiscussionComments, - Repository: MockRepo, - }, { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: featureDeletes, - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockrepo/mockorg", featureDiscussionComments) } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) - mockAPI.On("LogWarn", "Error creating discussion comment post", "Post", mock.Anything, "Error", "error creating post") + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(nil, &model.AppError{Message: "error creating post"}).Times(1) + mockAPI.On("LogWarn", "Error creating discussion comment post", "Post", mock.AnythingOfType("*model.Post"), "Error", "error creating post") }, }, { @@ -2691,22 +2352,11 @@ func TestPostDiscussionCommentEvent(t *testing.T) { setup: func() { mockKvStore.EXPECT().Get("subscriptions", gomock.Any()).DoAndReturn(func(key string, value interface{}) error { if v, ok := value.(**Subscriptions); ok { - *v = &Subscriptions{ - Repositories: map[string][]*Subscription{ - "mockrepo/mockorg": { - { - ChannelID: MockChannelID, - CreatorID: MockCreatorID, - Features: featureDiscussionComments, - Repository: MockRepo, - }, - }, - }, - } + *v = GetMockSubscriptionWithLabel("mockrepo/mockorg", featureDiscussionComments) } return nil }).Times(1) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockAPI.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil).Times(1) }, }, }