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  }