sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/plugins/help/help_test.go (about) 1 /* 2 Copyright 2017 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 help 18 19 import ( 20 "fmt" 21 "reflect" 22 "sort" 23 "testing" 24 25 "github.com/sirupsen/logrus" 26 "sigs.k8s.io/prow/pkg/github" 27 "sigs.k8s.io/prow/pkg/github/fakegithub" 28 "sigs.k8s.io/prow/pkg/labels" 29 ) 30 31 type fakePruner struct{} 32 33 func (fp *fakePruner) PruneComments(shouldPrune func(github.IssueComment) bool) {} 34 35 func formatLabels(labels ...string) []string { 36 r := []string{} 37 for _, l := range labels { 38 r = append(r, fmt.Sprintf("%s/%s#%d:%s", "org", "repo", 1, l)) 39 } 40 if len(r) == 0 { 41 return nil 42 } 43 return r 44 } 45 46 func TestLabel(t *testing.T) { 47 type testCase struct { 48 name string 49 isPR bool 50 issueState string 51 action github.GenericCommentEventAction 52 body string 53 expectedNewLabels []string 54 expectedRemovedLabels []string 55 issueLabels []string 56 } 57 testcases := []testCase{ 58 { 59 name: "Ignore irrelevant comment", 60 body: "irrelelvant", 61 expectedNewLabels: []string{}, 62 expectedRemovedLabels: []string{}, 63 issueLabels: []string{}, 64 }, 65 { 66 name: "Ignore a PR", 67 isPR: true, 68 body: "/help", 69 expectedNewLabels: []string{}, 70 expectedRemovedLabels: []string{}, 71 issueLabels: []string{}, 72 }, 73 { 74 name: "Ignore a closed issue", 75 issueState: "closed", 76 body: "/help", 77 expectedNewLabels: []string{}, 78 expectedRemovedLabels: []string{}, 79 issueLabels: []string{}, 80 }, 81 { 82 name: "Ignore a non-created comment", 83 action: github.GenericCommentActionEdited, 84 body: "/help", 85 expectedNewLabels: []string{}, 86 expectedRemovedLabels: []string{}, 87 issueLabels: []string{}, 88 }, 89 { 90 name: "Want helpLabel", 91 body: "/help", 92 expectedNewLabels: formatLabels(labels.Help), 93 expectedRemovedLabels: []string{}, 94 issueLabels: []string{}, 95 }, 96 { 97 name: "Want helpLabel, already have it.", 98 body: "/help", 99 expectedNewLabels: []string{}, 100 expectedRemovedLabels: []string{}, 101 issueLabels: []string{labels.Help}, 102 }, 103 { 104 name: "Want to remove helpLabel, have it", 105 body: "/remove-help", 106 expectedNewLabels: []string{}, 107 expectedRemovedLabels: formatLabels(labels.Help), 108 issueLabels: []string{labels.Help}, 109 }, 110 { 111 name: "Want to remove helpLabel, don't have it", 112 body: "/remove-help", 113 expectedNewLabels: []string{}, 114 expectedRemovedLabels: []string{}, 115 issueLabels: []string{}, 116 }, 117 { 118 name: "Want to remove helpLabel and goodFirstIssueLabel, have helpLabel and goodFirstIssueLabel", 119 body: "/remove-help", 120 expectedNewLabels: []string{}, 121 expectedRemovedLabels: formatLabels(labels.Help, labels.GoodFirstIssue), 122 issueLabels: []string{labels.Help, labels.GoodFirstIssue}, 123 }, 124 { 125 name: "Want to add goodFirstIssueLabel and helpLabel, don't have both", 126 body: "/good-first-issue", 127 expectedNewLabels: formatLabels(labels.Help, labels.GoodFirstIssue), 128 expectedRemovedLabels: []string{}, 129 issueLabels: []string{}, 130 }, 131 { 132 name: "Want to add goodFirstIssueLabel and helpLabel, don't have goodFirstIssueLabel but have helpLabel", 133 body: "/good-first-issue", 134 expectedNewLabels: formatLabels(labels.GoodFirstIssue), 135 expectedRemovedLabels: []string{}, 136 issueLabels: []string{labels.Help}, 137 }, 138 { 139 name: "Want to add goodFirstIssueLabel and helpLabel, have both", 140 body: "/good-first-issue", 141 expectedNewLabels: []string{}, 142 expectedRemovedLabels: []string{}, 143 issueLabels: []string{labels.Help, labels.GoodFirstIssue}, 144 }, 145 { 146 name: "Want to remove goodFirstIssueLabel, have helpLabel and goodFirstIssueLabel", 147 body: "/remove-good-first-issue", 148 expectedNewLabels: []string{}, 149 expectedRemovedLabels: formatLabels(labels.GoodFirstIssue), 150 issueLabels: []string{labels.Help, labels.GoodFirstIssue}, 151 }, 152 { 153 name: "Want to remove goodFirstIssueLabel, have goodFirstIssueLabel", 154 body: "/remove-good-first-issue", 155 expectedNewLabels: []string{}, 156 expectedRemovedLabels: formatLabels(labels.GoodFirstIssue), 157 issueLabels: []string{labels.GoodFirstIssue}, 158 }, 159 { 160 name: "Want to remove goodFirstIssueLabel, have helpLabel but don't have goodFirstIssueLabel", 161 body: "/remove-good-first-issue", 162 expectedNewLabels: []string{}, 163 expectedRemovedLabels: []string{}, 164 issueLabels: []string{labels.Help}, 165 }, 166 { 167 name: "Want to remove goodFirstIssueLabel, but don't have it", 168 body: "/remove-good-first-issue", 169 expectedNewLabels: []string{}, 170 expectedRemovedLabels: []string{}, 171 issueLabels: []string{}, 172 }, 173 } 174 175 ig := issueGuidelines{ 176 issueGuidelinesURL: "https://git.k8s.io/community/contributors/guide/help-wanted.md", 177 } 178 179 for _, tc := range testcases { 180 sort.Strings(tc.expectedNewLabels) 181 fakeClient := fakegithub.NewFakeClient() 182 fakeClient.Issues = make(map[int]*github.Issue) 183 fakeClient.IssueComments = make(map[int][]github.IssueComment) 184 fakeClient.RepoLabelsExisting = []string{labels.Help, labels.GoodFirstIssue} 185 fakeClient.IssueLabelsAdded = []string{} 186 fakeClient.IssueLabelsRemoved = []string{} 187 // Add initial labels 188 for _, label := range tc.issueLabels { 189 fakeClient.AddLabel("org", "repo", 1, label) 190 } 191 192 if len(tc.issueState) == 0 { 193 tc.issueState = "open" 194 } 195 if len(tc.action) == 0 { 196 tc.action = github.GenericCommentActionCreated 197 } 198 199 e := &github.GenericCommentEvent{ 200 IsPR: tc.isPR, 201 IssueState: tc.issueState, 202 Action: tc.action, 203 Body: tc.body, 204 Number: 1, 205 Repo: github.Repo{Owner: github.User{Login: "org"}, Name: "repo"}, 206 User: github.User{Login: "Alice"}, 207 } 208 err := handle(fakeClient, logrus.WithField("plugin", pluginName), &fakePruner{}, e, ig) 209 if err != nil { 210 t.Errorf("For case %s, didn't expect error from label test: %v", tc.name, err) 211 continue 212 } 213 214 // Check that all the correct labels (and only the correct labels) were added. 215 expectLabels := append(formatLabels(tc.issueLabels...), tc.expectedNewLabels...) 216 if expectLabels == nil { 217 expectLabels = []string{} 218 } 219 sort.Strings(expectLabels) 220 sort.Strings(fakeClient.IssueLabelsAdded) 221 if !reflect.DeepEqual(expectLabels, fakeClient.IssueLabelsAdded) { 222 t.Errorf("(%s): Expected the labels %q to be added, but %q were added.", tc.name, expectLabels, fakeClient.IssueLabelsAdded) 223 } 224 225 sort.Strings(tc.expectedRemovedLabels) 226 sort.Strings(fakeClient.IssueLabelsRemoved) 227 if !reflect.DeepEqual(tc.expectedRemovedLabels, fakeClient.IssueLabelsRemoved) { 228 t.Errorf("(%s): Expected the labels %q to be removed, but %q were removed.", tc.name, tc.expectedRemovedLabels, fakeClient.IssueLabelsRemoved) 229 } 230 } 231 } 232 233 func TestIssueGuidelines(t *testing.T) { 234 url := "https://git.k8s.io/community/contributors/guide/help-wanted.md" 235 guidelineSummary := "This is a guideline" 236 type testCase struct { 237 name string 238 hasGuidelineSummary bool 239 isForHelpWanted bool 240 expectedMsg string 241 } 242 testCases := []testCase{ 243 { 244 name: "Help message with guidelines summary", 245 hasGuidelineSummary: true, 246 isForHelpWanted: true, 247 expectedMsg: fmt.Sprintf(` 248 This request has been marked as needing help from a contributor. 249 250 ### Guidelines 251 %s 252 253 For more details on the requirements of such an issue, please see [here](%s) and ensure that they are met. 254 255 If this request no longer meets these requirements, the label can be removed 256 by commenting with the `+"`/remove-help`"+` command. 257 `, guidelineSummary, url), 258 }, 259 { 260 name: "Help message without guidelines summary", 261 isForHelpWanted: true, 262 expectedMsg: fmt.Sprintf(` 263 This request has been marked as needing help from a contributor. 264 265 Please ensure the request meets the requirements listed [here](%s). 266 267 If this request no longer meets these requirements, the label can be removed 268 by commenting with the `+"`/remove-help`"+` command. 269 `, url), 270 }, 271 { 272 name: "Good First Issue message with guidelines summary", 273 hasGuidelineSummary: true, 274 expectedMsg: fmt.Sprintf(` 275 This request has been marked as suitable for new contributors. 276 277 ### Guidelines 278 %s 279 280 For more details on the requirements of such an issue, please see [here](%s#good-first-issue) and ensure that they are met. 281 282 If this request no longer meets these requirements, the label can be removed 283 by commenting with the `+"`/remove-good-first-issue`"+` command. 284 `, guidelineSummary, url), 285 }, 286 { 287 name: "Good First Issue message without guidelines summary", 288 expectedMsg: fmt.Sprintf(` 289 This request has been marked as suitable for new contributors. 290 291 Please ensure the request meets the requirements listed [here](%s#good-first-issue). 292 293 If this request no longer meets these requirements, the label can be removed 294 by commenting with the `+"`/remove-good-first-issue`"+` command. 295 `, url), 296 }, 297 } 298 299 for _, tc := range testCases { 300 ig := issueGuidelines{ 301 issueGuidelinesURL: url, 302 } 303 if tc.hasGuidelineSummary { 304 ig.issueGuidelinesSummary = guidelineSummary 305 } 306 var returnedMsg string 307 if tc.isForHelpWanted { 308 returnedMsg = ig.helpMsg() 309 } else { 310 returnedMsg = ig.goodFirstIssueMsg() 311 } 312 if returnedMsg != tc.expectedMsg { 313 t.Errorf("(%s): Expected message: %sReturned message: %s", tc.name, tc.expectedMsg, returnedMsg) 314 } 315 } 316 }