github.com/abayer/test-infra@v0.0.5/prow/plugins/welcome/welcome_test.go (about) 1 /* 2 Copyright 2018 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package welcome 18 19 import ( 20 "fmt" 21 "regexp" 22 "testing" 23 24 "github.com/sirupsen/logrus" 25 26 "k8s.io/apimachinery/pkg/util/sets" 27 "k8s.io/test-infra/prow/github" 28 ) 29 30 // TODO(bentheelder): these tests are a bit lame. 31 // There has to be a better way to write tests like this. 32 33 const ( 34 testWelcomeTemplate = "Welcome human! 🤖 {{.AuthorName}} {{.AuthorLogin}} {{.Repo}} {{.Org}}}" 35 ) 36 37 type fakeClient struct { 38 commentsAdded map[int][]string 39 prs map[string]sets.Int 40 } 41 42 func newFakeClient() *fakeClient { 43 return &fakeClient{ 44 commentsAdded: make(map[int][]string), 45 prs: make(map[string]sets.Int), 46 } 47 } 48 49 // CreateComment adds and tracks a comment in the client 50 func (fc *fakeClient) CreateComment(owner, repo string, number int, comment string) error { 51 fc.commentsAdded[number] = append(fc.commentsAdded[number], comment) 52 return nil 53 } 54 55 // ClearComments removes all comments in the client 56 func (fc *fakeClient) ClearComments() { 57 fc.commentsAdded = map[int][]string{} 58 } 59 60 // NumComments counts the number of tracked comments 61 func (fc *fakeClient) NumComments() int { 62 n := 0 63 for _, comments := range fc.commentsAdded { 64 n += len(comments) 65 } 66 return n 67 } 68 69 var ( 70 expectedQueryRegex = regexp.MustCompile(`is:pr repo:(.+)/(.+) author:(.+)`) 71 ) 72 73 // AddPR records an PR in the client 74 func (fc *fakeClient) AddPR(owner, repo, author string, number int) { 75 key := fmt.Sprintf("%s,%s,%s", owner, repo, author) 76 if _, ok := fc.prs[key]; !ok { 77 fc.prs[key] = sets.Int{} 78 } 79 fc.prs[key].Insert(number) 80 } 81 82 // ClearPRs removes all PRs from the client 83 func (fc *fakeClient) ClearPRs() { 84 fc.prs = make(map[string]sets.Int) 85 } 86 87 // FindIssues fails if the query does not match the expected query regex and 88 // looks up issues based on parsing the expected query format 89 func (fc *fakeClient) FindIssues(query, sort string, asc bool) ([]github.Issue, error) { 90 fields := expectedQueryRegex.FindStringSubmatch(query) 91 if fields == nil || len(fields) != 4 { 92 return nil, fmt.Errorf("invalid query: `%s` does not match expected regex `%s`", query, expectedQueryRegex.String()) 93 } 94 // "find" results 95 owner, repo, author := fields[1], fields[2], fields[3] 96 key := fmt.Sprintf("%s,%s,%s", owner, repo, author) 97 98 issues := []github.Issue{} 99 for _, number := range fc.prs[key].List() { 100 issues = append(issues, github.Issue{ 101 Number: number, 102 }) 103 } 104 return issues, nil 105 } 106 107 func makeFakePullRequestEvent(owner, repo, author string, number int, action github.PullRequestEventAction) github.PullRequestEvent { 108 return github.PullRequestEvent{ 109 Action: action, 110 Number: number, 111 PullRequest: github.PullRequest{ 112 Base: github.PullRequestBranch{ 113 Repo: github.Repo{ 114 Owner: github.User{ 115 Login: owner, 116 }, 117 Name: repo, 118 }, 119 }, 120 User: github.User{ 121 Login: author, 122 Name: author + "fullname", 123 }, 124 }, 125 } 126 } 127 128 func TestHandlePR(t *testing.T) { 129 fc := newFakeClient() 130 // old PRs 131 fc.AddPR("kubernetes", "test-infra", "contributorA", 1) 132 fc.AddPR("kubernetes", "test-infra", "contributorB", 2) 133 fc.AddPR("kubernetes", "test-infra", "contributorB", 3) 134 135 testCases := []struct { 136 name string 137 repoOwner string 138 repoName string 139 author string 140 prNumber int 141 prAction github.PullRequestEventAction 142 expectComment bool 143 }{ 144 { 145 name: "existing contributorA", 146 repoOwner: "kubernetes", 147 repoName: "test-infra", 148 author: "contributorA", 149 prNumber: 20, 150 prAction: github.PullRequestActionOpened, 151 expectComment: false, 152 }, 153 { 154 name: "existing contributorB", 155 repoOwner: "kubernetes", 156 repoName: "test-infra", 157 author: "contributorB", 158 prNumber: 40, 159 prAction: github.PullRequestActionOpened, 160 expectComment: false, 161 }, 162 { 163 name: "new contributor", 164 repoOwner: "kubernetes", 165 repoName: "test-infra", 166 author: "newContributor", 167 prAction: github.PullRequestActionOpened, 168 prNumber: 50, 169 expectComment: true, 170 }, 171 { 172 name: "new contributor, not PR open event", 173 repoOwner: "kubernetes", 174 repoName: "test-infra", 175 author: "newContributor", 176 prAction: github.PullRequestActionEdited, 177 prNumber: 50, 178 expectComment: false, 179 }, 180 } 181 182 c := client{ 183 GitHubClient: fc, 184 Logger: &logrus.Entry{}, 185 } 186 for _, tc := range testCases { 187 // clear out comments from the last test case 188 fc.ClearComments() 189 190 event := makeFakePullRequestEvent(tc.repoOwner, tc.repoName, tc.author, tc.prNumber, tc.prAction) 191 // make sure the PR in the event is recorded 192 fc.AddPR(tc.repoOwner, tc.repoName, tc.author, tc.prNumber) 193 194 // try handling it 195 if err := handlePR(c, event, testWelcomeTemplate); err != nil { 196 t.Fatalf("did not expect error handling PR for case '%s': %v", tc.name, err) 197 } 198 199 // verify that comments were made 200 numComments := fc.NumComments() 201 if numComments > 1 { 202 t.Fatalf("did not expect multiple comments for any test case and got %d comments", numComments) 203 } 204 if numComments == 0 && tc.expectComment { 205 t.Fatalf("expected a comment for case '%s' and got none", tc.name) 206 } else if numComments > 0 && !tc.expectComment { 207 t.Fatalf("did not expect comments for case '%s' and got %d comments", tc.name, numComments) 208 } 209 } 210 }