github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/pr/status/status_test.go (about)

     1  package status
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"net/http"
     7  	"regexp"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/MakeNowJust/heredoc"
    12  	"github.com/ungtb10d/cli/v2/context"
    13  	"github.com/ungtb10d/cli/v2/git"
    14  	"github.com/ungtb10d/cli/v2/internal/config"
    15  	"github.com/ungtb10d/cli/v2/internal/ghrepo"
    16  	"github.com/ungtb10d/cli/v2/internal/run"
    17  	"github.com/ungtb10d/cli/v2/pkg/cmdutil"
    18  	"github.com/ungtb10d/cli/v2/pkg/httpmock"
    19  	"github.com/ungtb10d/cli/v2/pkg/iostreams"
    20  	"github.com/ungtb10d/cli/v2/test"
    21  	"github.com/google/shlex"
    22  )
    23  
    24  func runCommand(rt http.RoundTripper, branch string, isTTY bool, cli string) (*test.CmdOut, error) {
    25  	ios, _, stdout, stderr := iostreams.Test()
    26  	ios.SetStdoutTTY(isTTY)
    27  	ios.SetStdinTTY(isTTY)
    28  	ios.SetStderrTTY(isTTY)
    29  
    30  	factory := &cmdutil.Factory{
    31  		IOStreams: ios,
    32  		HttpClient: func() (*http.Client, error) {
    33  			return &http.Client{Transport: rt}, nil
    34  		},
    35  		Config: func() (config.Config, error) {
    36  			return config.NewBlankConfig(), nil
    37  		},
    38  		BaseRepo: func() (ghrepo.Interface, error) {
    39  			return ghrepo.New("OWNER", "REPO"), nil
    40  		},
    41  		Remotes: func() (context.Remotes, error) {
    42  			return context.Remotes{
    43  				{
    44  					Remote: &git.Remote{Name: "origin"},
    45  					Repo:   ghrepo.New("OWNER", "REPO"),
    46  				},
    47  			}, nil
    48  		},
    49  		Branch: func() (string, error) {
    50  			if branch == "" {
    51  				return "", git.ErrNotOnAnyBranch
    52  			}
    53  			return branch, nil
    54  		},
    55  		GitClient: &git.Client{GitPath: "some/path/git"},
    56  	}
    57  
    58  	cmd := NewCmdStatus(factory, nil)
    59  	cmd.PersistentFlags().StringP("repo", "R", "", "")
    60  
    61  	argv, err := shlex.Split(cli)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  	cmd.SetArgs(argv)
    66  
    67  	cmd.SetIn(&bytes.Buffer{})
    68  	cmd.SetOut(io.Discard)
    69  	cmd.SetErr(io.Discard)
    70  
    71  	_, err = cmd.ExecuteC()
    72  	return &test.CmdOut{
    73  		OutBuf: stdout,
    74  		ErrBuf: stderr,
    75  	}, err
    76  }
    77  
    78  func initFakeHTTP() *httpmock.Registry {
    79  	return &httpmock.Registry{}
    80  }
    81  
    82  func TestPRStatus(t *testing.T) {
    83  	http := initFakeHTTP()
    84  	defer http.Verify(t)
    85  	http.Register(httpmock.GraphQL(`query PullRequestStatus\b`), httpmock.FileResponse("./fixtures/prStatus.json"))
    86  
    87  	output, err := runCommand(http, "blueberries", true, "")
    88  	if err != nil {
    89  		t.Errorf("error running command `pr status`: %v", err)
    90  	}
    91  
    92  	expectedPrs := []*regexp.Regexp{
    93  		regexp.MustCompile(`#8.*\[strawberries\]`),
    94  		regexp.MustCompile(`#9.*\[apples\]`),
    95  		regexp.MustCompile(`#10.*\[blueberries\]`),
    96  		regexp.MustCompile(`#11.*\[figs\]`),
    97  	}
    98  
    99  	for _, r := range expectedPrs {
   100  		if !r.MatchString(output.String()) {
   101  			t.Errorf("output did not match regexp /%s/", r)
   102  		}
   103  	}
   104  }
   105  
   106  func TestPRStatus_reviewsAndChecks(t *testing.T) {
   107  	http := initFakeHTTP()
   108  	defer http.Verify(t)
   109  	http.Register(httpmock.GraphQL(`query PullRequestStatus\b`), httpmock.FileResponse("./fixtures/prStatusChecks.json"))
   110  
   111  	output, err := runCommand(http, "blueberries", true, "")
   112  	if err != nil {
   113  		t.Errorf("error running command `pr status`: %v", err)
   114  	}
   115  
   116  	expected := []string{
   117  		"✓ Checks passing + Changes requested ! Merge conflict status unknown",
   118  		"- Checks pending ✓ 2 Approved",
   119  		"× 1/3 checks failing - Review required ✓ No merge conflicts",
   120  		"✓ Checks passing × Merge conflicts",
   121  	}
   122  
   123  	for _, line := range expected {
   124  		if !strings.Contains(output.String(), line) {
   125  			t.Errorf("output did not contain %q: %q", line, output.String())
   126  		}
   127  	}
   128  }
   129  
   130  func TestPRStatus_currentBranch_showTheMostRecentPR(t *testing.T) {
   131  	http := initFakeHTTP()
   132  	defer http.Verify(t)
   133  	http.Register(httpmock.GraphQL(`query PullRequestStatus\b`), httpmock.FileResponse("./fixtures/prStatusCurrentBranch.json"))
   134  
   135  	output, err := runCommand(http, "blueberries", true, "")
   136  	if err != nil {
   137  		t.Errorf("error running command `pr status`: %v", err)
   138  	}
   139  
   140  	expectedLine := regexp.MustCompile(`#10  Blueberries are certainly a good fruit \[blueberries\]`)
   141  	if !expectedLine.MatchString(output.String()) {
   142  		t.Errorf("output did not match regexp /%s/\n> output\n%s\n", expectedLine, output)
   143  		return
   144  	}
   145  
   146  	unexpectedLines := []*regexp.Regexp{
   147  		regexp.MustCompile(`#9  Blueberries are a good fruit \[blueberries\] - Merged`),
   148  		regexp.MustCompile(`#8  Blueberries are probably a good fruit \[blueberries\] - Closed`),
   149  	}
   150  	for _, r := range unexpectedLines {
   151  		if r.MatchString(output.String()) {
   152  			t.Errorf("output unexpectedly match regexp /%s/\n> output\n%s\n", r, output)
   153  			return
   154  		}
   155  	}
   156  }
   157  
   158  func TestPRStatus_currentBranch_defaultBranch(t *testing.T) {
   159  	http := initFakeHTTP()
   160  	defer http.Verify(t)
   161  	http.Register(httpmock.GraphQL(`query PullRequestStatus\b`), httpmock.FileResponse("./fixtures/prStatusCurrentBranch.json"))
   162  
   163  	output, err := runCommand(http, "blueberries", true, "")
   164  	if err != nil {
   165  		t.Errorf("error running command `pr status`: %v", err)
   166  	}
   167  
   168  	expectedLine := regexp.MustCompile(`#10  Blueberries are certainly a good fruit \[blueberries\]`)
   169  	if !expectedLine.MatchString(output.String()) {
   170  		t.Errorf("output did not match regexp /%s/\n> output\n%s\n", expectedLine, output)
   171  		return
   172  	}
   173  }
   174  
   175  func TestPRStatus_currentBranch_defaultBranch_repoFlag(t *testing.T) {
   176  	http := initFakeHTTP()
   177  	defer http.Verify(t)
   178  	http.Register(httpmock.GraphQL(`query PullRequestStatus\b`), httpmock.FileResponse("./fixtures/prStatusCurrentBranchClosedOnDefaultBranch.json"))
   179  
   180  	output, err := runCommand(http, "blueberries", true, "-R OWNER/REPO")
   181  	if err != nil {
   182  		t.Errorf("error running command `pr status`: %v", err)
   183  	}
   184  
   185  	expectedLine := regexp.MustCompile(`#8  Blueberries are a good fruit \[blueberries\]`)
   186  	if expectedLine.MatchString(output.String()) {
   187  		t.Errorf("output not expected to match regexp /%s/\n> output\n%s\n", expectedLine, output)
   188  		return
   189  	}
   190  }
   191  
   192  func TestPRStatus_currentBranch_Closed(t *testing.T) {
   193  	http := initFakeHTTP()
   194  	defer http.Verify(t)
   195  	http.Register(httpmock.GraphQL(`query PullRequestStatus\b`), httpmock.FileResponse("./fixtures/prStatusCurrentBranchClosed.json"))
   196  
   197  	output, err := runCommand(http, "blueberries", true, "")
   198  	if err != nil {
   199  		t.Errorf("error running command `pr status`: %v", err)
   200  	}
   201  
   202  	expectedLine := regexp.MustCompile(`#8  Blueberries are a good fruit \[blueberries\] - Closed`)
   203  	if !expectedLine.MatchString(output.String()) {
   204  		t.Errorf("output did not match regexp /%s/\n> output\n%s\n", expectedLine, output)
   205  		return
   206  	}
   207  }
   208  
   209  func TestPRStatus_currentBranch_Closed_defaultBranch(t *testing.T) {
   210  	http := initFakeHTTP()
   211  	defer http.Verify(t)
   212  	http.Register(httpmock.GraphQL(`query PullRequestStatus\b`), httpmock.FileResponse("./fixtures/prStatusCurrentBranchClosedOnDefaultBranch.json"))
   213  
   214  	output, err := runCommand(http, "blueberries", true, "")
   215  	if err != nil {
   216  		t.Errorf("error running command `pr status`: %v", err)
   217  	}
   218  
   219  	expectedLine := regexp.MustCompile(`There is no pull request associated with \[blueberries\]`)
   220  	if !expectedLine.MatchString(output.String()) {
   221  		t.Errorf("output did not match regexp /%s/\n> output\n%s\n", expectedLine, output)
   222  		return
   223  	}
   224  }
   225  
   226  func TestPRStatus_currentBranch_Merged(t *testing.T) {
   227  	http := initFakeHTTP()
   228  	defer http.Verify(t)
   229  	http.Register(httpmock.GraphQL(`query PullRequestStatus\b`), httpmock.FileResponse("./fixtures/prStatusCurrentBranchMerged.json"))
   230  
   231  	output, err := runCommand(http, "blueberries", true, "")
   232  	if err != nil {
   233  		t.Errorf("error running command `pr status`: %v", err)
   234  	}
   235  
   236  	expectedLine := regexp.MustCompile(`#8  Blueberries are a good fruit \[blueberries\] - Merged`)
   237  	if !expectedLine.MatchString(output.String()) {
   238  		t.Errorf("output did not match regexp /%s/\n> output\n%s\n", expectedLine, output)
   239  		return
   240  	}
   241  }
   242  
   243  func TestPRStatus_currentBranch_Merged_defaultBranch(t *testing.T) {
   244  	http := initFakeHTTP()
   245  	defer http.Verify(t)
   246  	http.Register(httpmock.GraphQL(`query PullRequestStatus\b`), httpmock.FileResponse("./fixtures/prStatusCurrentBranchMergedOnDefaultBranch.json"))
   247  
   248  	output, err := runCommand(http, "blueberries", true, "")
   249  	if err != nil {
   250  		t.Errorf("error running command `pr status`: %v", err)
   251  	}
   252  
   253  	expectedLine := regexp.MustCompile(`There is no pull request associated with \[blueberries\]`)
   254  	if !expectedLine.MatchString(output.String()) {
   255  		t.Errorf("output did not match regexp /%s/\n> output\n%s\n", expectedLine, output)
   256  		return
   257  	}
   258  }
   259  
   260  func TestPRStatus_blankSlate(t *testing.T) {
   261  	http := initFakeHTTP()
   262  	defer http.Verify(t)
   263  	http.Register(httpmock.GraphQL(`query PullRequestStatus\b`), httpmock.StringResponse(`{"data": {}}`))
   264  
   265  	output, err := runCommand(http, "blueberries", true, "")
   266  	if err != nil {
   267  		t.Errorf("error running command `pr status`: %v", err)
   268  	}
   269  
   270  	expected := `
   271  Relevant pull requests in OWNER/REPO
   272  
   273  Current branch
   274    There is no pull request associated with [blueberries]
   275  
   276  Created by you
   277    You have no open pull requests
   278  
   279  Requesting a code review from you
   280    You have no pull requests to review
   281  
   282  `
   283  	if output.String() != expected {
   284  		t.Errorf("expected %q, got %q", expected, output.String())
   285  	}
   286  }
   287  
   288  func TestPRStatus_detachedHead(t *testing.T) {
   289  	http := initFakeHTTP()
   290  	defer http.Verify(t)
   291  	http.Register(httpmock.GraphQL(`query PullRequestStatus\b`), httpmock.StringResponse(`{"data": {}}`))
   292  
   293  	output, err := runCommand(http, "", true, "")
   294  	if err != nil {
   295  		t.Errorf("error running command `pr status`: %v", err)
   296  	}
   297  
   298  	expected := `
   299  Relevant pull requests in OWNER/REPO
   300  
   301  Current branch
   302    There is no current branch
   303  
   304  Created by you
   305    You have no open pull requests
   306  
   307  Requesting a code review from you
   308    You have no pull requests to review
   309  
   310  `
   311  	if output.String() != expected {
   312  		t.Errorf("expected %q, got %q", expected, output.String())
   313  	}
   314  }
   315  
   316  func Test_prSelectorForCurrentBranch(t *testing.T) {
   317  	rs, cleanup := run.Stub()
   318  	defer cleanup(t)
   319  
   320  	rs.Register(`git config --get-regexp \^branch\\.`, 0, heredoc.Doc(`
   321  		branch.Frederick888/main.remote git@github.com:Frederick888/playground.git
   322  		branch.Frederick888/main.merge refs/heads/main
   323  	`))
   324  
   325  	repo := ghrepo.NewWithHost("octocat", "playground", "github.com")
   326  	rem := context.Remotes{
   327  		&context.Remote{
   328  			Remote: &git.Remote{Name: "origin"},
   329  			Repo:   repo,
   330  		},
   331  	}
   332  	gitClient := &git.Client{GitPath: "some/path/git"}
   333  	prNum, headRef, err := prSelectorForCurrentBranch(gitClient, repo, "Frederick888/main", rem)
   334  	if err != nil {
   335  		t.Fatalf("prSelectorForCurrentBranch error: %v", err)
   336  	}
   337  	if prNum != 0 {
   338  		t.Errorf("expected prNum to be 0, got %q", prNum)
   339  	}
   340  	if headRef != "Frederick888:main" {
   341  		t.Errorf("expected headRef to be \"Frederick888:main\", got %q", headRef)
   342  	}
   343  }