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  }