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

     1  package merge
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"io"
     8  	"net/http"
     9  	"os"
    10  	"path/filepath"
    11  	"regexp"
    12  	"strings"
    13  	"testing"
    14  
    15  	"github.com/MakeNowJust/heredoc"
    16  	"github.com/ungtb10d/cli/v2/api"
    17  	"github.com/ungtb10d/cli/v2/context"
    18  	"github.com/ungtb10d/cli/v2/git"
    19  	"github.com/ungtb10d/cli/v2/internal/ghrepo"
    20  	"github.com/ungtb10d/cli/v2/internal/run"
    21  	"github.com/ungtb10d/cli/v2/pkg/cmd/pr/shared"
    22  	"github.com/ungtb10d/cli/v2/pkg/cmdutil"
    23  	"github.com/ungtb10d/cli/v2/pkg/httpmock"
    24  	"github.com/ungtb10d/cli/v2/pkg/iostreams"
    25  	"github.com/ungtb10d/cli/v2/pkg/prompt"
    26  	"github.com/ungtb10d/cli/v2/test"
    27  	"github.com/google/shlex"
    28  	"github.com/stretchr/testify/assert"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  func Test_NewCmdMerge(t *testing.T) {
    33  	tmpFile := filepath.Join(t.TempDir(), "my-body.md")
    34  	err := os.WriteFile(tmpFile, []byte("a body from file"), 0600)
    35  	require.NoError(t, err)
    36  
    37  	tests := []struct {
    38  		name    string
    39  		args    string
    40  		stdin   string
    41  		isTTY   bool
    42  		want    MergeOptions
    43  		wantErr string
    44  	}{
    45  		{
    46  			name:  "number argument",
    47  			args:  "123",
    48  			isTTY: true,
    49  			want: MergeOptions{
    50  				SelectorArg:             "123",
    51  				DeleteBranch:            false,
    52  				IsDeleteBranchIndicated: false,
    53  				CanDeleteLocalBranch:    true,
    54  				MergeMethod:             PullRequestMergeMethodMerge,
    55  				MergeStrategyEmpty:      true,
    56  				Body:                    "",
    57  				BodySet:                 false,
    58  				AuthorEmail:             "",
    59  			},
    60  		},
    61  		{
    62  			name:  "delete-branch specified",
    63  			args:  "--delete-branch=false",
    64  			isTTY: true,
    65  			want: MergeOptions{
    66  				SelectorArg:             "",
    67  				DeleteBranch:            false,
    68  				IsDeleteBranchIndicated: true,
    69  				CanDeleteLocalBranch:    true,
    70  				MergeMethod:             PullRequestMergeMethodMerge,
    71  				MergeStrategyEmpty:      true,
    72  				Body:                    "",
    73  				BodySet:                 false,
    74  				AuthorEmail:             "",
    75  			},
    76  		},
    77  		{
    78  			name:  "body from file",
    79  			args:  fmt.Sprintf("123 --body-file '%s'", tmpFile),
    80  			isTTY: true,
    81  			want: MergeOptions{
    82  				SelectorArg:             "123",
    83  				DeleteBranch:            false,
    84  				IsDeleteBranchIndicated: false,
    85  				CanDeleteLocalBranch:    true,
    86  				MergeMethod:             PullRequestMergeMethodMerge,
    87  				MergeStrategyEmpty:      true,
    88  				Body:                    "a body from file",
    89  				BodySet:                 true,
    90  				AuthorEmail:             "",
    91  			},
    92  		},
    93  		{
    94  			name:  "body from stdin",
    95  			args:  "123 --body-file -",
    96  			stdin: "this is on standard input",
    97  			isTTY: true,
    98  			want: MergeOptions{
    99  				SelectorArg:             "123",
   100  				DeleteBranch:            false,
   101  				IsDeleteBranchIndicated: false,
   102  				CanDeleteLocalBranch:    true,
   103  				MergeMethod:             PullRequestMergeMethodMerge,
   104  				MergeStrategyEmpty:      true,
   105  				Body:                    "this is on standard input",
   106  				BodySet:                 true,
   107  				AuthorEmail:             "",
   108  			},
   109  		},
   110  		{
   111  			name:  "body",
   112  			args:  "123 -bcool",
   113  			isTTY: true,
   114  			want: MergeOptions{
   115  				SelectorArg:             "123",
   116  				DeleteBranch:            false,
   117  				IsDeleteBranchIndicated: false,
   118  				CanDeleteLocalBranch:    true,
   119  				MergeMethod:             PullRequestMergeMethodMerge,
   120  				MergeStrategyEmpty:      true,
   121  				Body:                    "cool",
   122  				BodySet:                 true,
   123  				AuthorEmail:             "",
   124  			},
   125  		},
   126  		{
   127  			name:  "match-head-commit specified",
   128  			args:  "123 --match-head-commit 555",
   129  			isTTY: true,
   130  			want: MergeOptions{
   131  				SelectorArg:             "123",
   132  				DeleteBranch:            false,
   133  				IsDeleteBranchIndicated: false,
   134  				CanDeleteLocalBranch:    true,
   135  				MergeMethod:             PullRequestMergeMethodMerge,
   136  				MergeStrategyEmpty:      true,
   137  				Body:                    "",
   138  				BodySet:                 false,
   139  				MatchHeadCommit:         "555",
   140  				AuthorEmail:             "",
   141  			},
   142  		},
   143  		{
   144  			name:  "author email",
   145  			args:  "123 --author-email octocat@github.com",
   146  			isTTY: true,
   147  			want: MergeOptions{
   148  				SelectorArg:             "123",
   149  				DeleteBranch:            false,
   150  				IsDeleteBranchIndicated: false,
   151  				CanDeleteLocalBranch:    true,
   152  				MergeMethod:             PullRequestMergeMethodMerge,
   153  				MergeStrategyEmpty:      true,
   154  				Body:                    "",
   155  				BodySet:                 false,
   156  				AuthorEmail:             "octocat@github.com",
   157  			},
   158  		},
   159  		{
   160  			name:    "body and body-file flags",
   161  			args:    "123 --body 'test' --body-file 'test-file.txt'",
   162  			isTTY:   true,
   163  			wantErr: "specify only one of `--body` or `--body-file`",
   164  		},
   165  		{
   166  			name:    "no argument with --repo override",
   167  			args:    "-R owner/repo",
   168  			isTTY:   true,
   169  			wantErr: "argument required when using the --repo flag",
   170  		},
   171  		{
   172  			name:    "multiple merge methods",
   173  			args:    "123 --merge --rebase",
   174  			isTTY:   true,
   175  			wantErr: "only one of --merge, --rebase, or --squash can be enabled",
   176  		},
   177  		{
   178  			name:    "multiple merge methods, non-tty",
   179  			args:    "123 --merge --rebase",
   180  			isTTY:   false,
   181  			wantErr: "only one of --merge, --rebase, or --squash can be enabled",
   182  		},
   183  	}
   184  	for _, tt := range tests {
   185  		t.Run(tt.name, func(t *testing.T) {
   186  			ios, stdin, _, _ := iostreams.Test()
   187  			ios.SetStdoutTTY(tt.isTTY)
   188  			ios.SetStdinTTY(tt.isTTY)
   189  			ios.SetStderrTTY(tt.isTTY)
   190  
   191  			if tt.stdin != "" {
   192  				_, _ = stdin.WriteString(tt.stdin)
   193  			}
   194  
   195  			f := &cmdutil.Factory{
   196  				IOStreams: ios,
   197  			}
   198  
   199  			var opts *MergeOptions
   200  			cmd := NewCmdMerge(f, func(o *MergeOptions) error {
   201  				opts = o
   202  				return nil
   203  			})
   204  			cmd.PersistentFlags().StringP("repo", "R", "", "")
   205  
   206  			argv, err := shlex.Split(tt.args)
   207  			require.NoError(t, err)
   208  			cmd.SetArgs(argv)
   209  
   210  			cmd.SetIn(&bytes.Buffer{})
   211  			cmd.SetOut(io.Discard)
   212  			cmd.SetErr(io.Discard)
   213  
   214  			_, err = cmd.ExecuteC()
   215  			if tt.wantErr != "" {
   216  				require.EqualError(t, err, tt.wantErr)
   217  				return
   218  			} else {
   219  				require.NoError(t, err)
   220  			}
   221  
   222  			assert.Equal(t, tt.want.SelectorArg, opts.SelectorArg)
   223  			assert.Equal(t, tt.want.DeleteBranch, opts.DeleteBranch)
   224  			assert.Equal(t, tt.want.CanDeleteLocalBranch, opts.CanDeleteLocalBranch)
   225  			assert.Equal(t, tt.want.MergeMethod, opts.MergeMethod)
   226  			assert.Equal(t, tt.want.MergeStrategyEmpty, opts.MergeStrategyEmpty)
   227  			assert.Equal(t, tt.want.Body, opts.Body)
   228  			assert.Equal(t, tt.want.BodySet, opts.BodySet)
   229  			assert.Equal(t, tt.want.MatchHeadCommit, opts.MatchHeadCommit)
   230  			assert.Equal(t, tt.want.AuthorEmail, opts.AuthorEmail)
   231  		})
   232  	}
   233  }
   234  
   235  func baseRepo(owner, repo, branch string) ghrepo.Interface {
   236  	return api.InitRepoHostname(&api.Repository{
   237  		Name:             repo,
   238  		Owner:            api.RepositoryOwner{Login: owner},
   239  		DefaultBranchRef: api.BranchRef{Name: branch},
   240  	}, "github.com")
   241  }
   242  
   243  func stubCommit(pr *api.PullRequest, oid string) {
   244  	pr.Commits.Nodes = append(pr.Commits.Nodes, api.PullRequestCommit{
   245  		Commit: api.PullRequestCommitCommit{OID: oid},
   246  	})
   247  }
   248  
   249  func runCommand(rt http.RoundTripper, branch string, isTTY bool, cli string) (*test.CmdOut, error) {
   250  	ios, _, stdout, stderr := iostreams.Test()
   251  	ios.SetStdoutTTY(isTTY)
   252  	ios.SetStdinTTY(isTTY)
   253  	ios.SetStderrTTY(isTTY)
   254  
   255  	factory := &cmdutil.Factory{
   256  		IOStreams: ios,
   257  		HttpClient: func() (*http.Client, error) {
   258  			return &http.Client{Transport: rt}, nil
   259  		},
   260  		Branch: func() (string, error) {
   261  			return branch, nil
   262  		},
   263  		Remotes: func() (context.Remotes, error) {
   264  			return []*context.Remote{
   265  				{
   266  					Remote: &git.Remote{
   267  						Name: "origin",
   268  					},
   269  					Repo: ghrepo.New("OWNER", "REPO"),
   270  				},
   271  			}, nil
   272  		},
   273  		GitClient: &git.Client{GitPath: "some/path/git"},
   274  	}
   275  
   276  	cmd := NewCmdMerge(factory, nil)
   277  	cmd.PersistentFlags().StringP("repo", "R", "", "")
   278  
   279  	cli = strings.TrimPrefix(cli, "pr merge")
   280  	argv, err := shlex.Split(cli)
   281  	if err != nil {
   282  		return nil, err
   283  	}
   284  	cmd.SetArgs(argv)
   285  
   286  	cmd.SetIn(&bytes.Buffer{})
   287  	cmd.SetOut(io.Discard)
   288  	cmd.SetErr(io.Discard)
   289  
   290  	_, err = cmd.ExecuteC()
   291  	return &test.CmdOut{
   292  		OutBuf: stdout,
   293  		ErrBuf: stderr,
   294  	}, err
   295  }
   296  
   297  func initFakeHTTP() *httpmock.Registry {
   298  	return &httpmock.Registry{}
   299  }
   300  
   301  func TestPrMerge(t *testing.T) {
   302  	http := initFakeHTTP()
   303  	defer http.Verify(t)
   304  
   305  	shared.RunCommandFinder(
   306  		"1",
   307  		&api.PullRequest{
   308  			ID:               "THE-ID",
   309  			Number:           1,
   310  			State:            "OPEN",
   311  			Title:            "The title of the PR",
   312  			MergeStateStatus: "CLEAN",
   313  		},
   314  		baseRepo("OWNER", "REPO", "main"),
   315  	)
   316  
   317  	http.Register(
   318  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
   319  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
   320  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
   321  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
   322  			assert.NotContains(t, input, "commitHeadline")
   323  		}),
   324  	)
   325  
   326  	cs, cmdTeardown := run.Stub()
   327  	defer cmdTeardown(t)
   328  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
   329  
   330  	output, err := runCommand(http, "main", true, "pr merge 1 --merge")
   331  	if err != nil {
   332  		t.Fatalf("error running command `pr merge`: %v", err)
   333  	}
   334  
   335  	r := regexp.MustCompile(`Merged pull request #1 \(The title of the PR\)`)
   336  
   337  	if !r.MatchString(output.Stderr()) {
   338  		t.Fatalf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr())
   339  	}
   340  }
   341  
   342  func TestPrMerge_blocked(t *testing.T) {
   343  	http := initFakeHTTP()
   344  	defer http.Verify(t)
   345  
   346  	shared.RunCommandFinder(
   347  		"1",
   348  		&api.PullRequest{
   349  			ID:               "THE-ID",
   350  			Number:           1,
   351  			State:            "OPEN",
   352  			Title:            "The title of the PR",
   353  			MergeStateStatus: "BLOCKED",
   354  		},
   355  		baseRepo("OWNER", "REPO", "main"),
   356  	)
   357  
   358  	cs, cmdTeardown := run.Stub()
   359  	defer cmdTeardown(t)
   360  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
   361  
   362  	output, err := runCommand(http, "main", true, "pr merge 1 --merge")
   363  	assert.EqualError(t, err, "SilentError")
   364  
   365  	assert.Equal(t, "", output.String())
   366  	assert.Equal(t, heredoc.Docf(`
   367  		X Pull request #1 is not mergeable: the base branch policy prohibits the merge.
   368  		To have the pull request merged after all the requirements have been met, add the %[1]s--auto%[1]s flag.
   369  		To use administrator privileges to immediately merge the pull request, add the %[1]s--admin%[1]s flag.
   370  		`, "`"), output.Stderr())
   371  }
   372  
   373  func TestPrMerge_dirty(t *testing.T) {
   374  	http := initFakeHTTP()
   375  	defer http.Verify(t)
   376  
   377  	shared.RunCommandFinder(
   378  		"1",
   379  		&api.PullRequest{
   380  			ID:               "THE-ID",
   381  			Number:           123,
   382  			State:            "OPEN",
   383  			Title:            "The title of the PR",
   384  			MergeStateStatus: "DIRTY",
   385  			BaseRefName:      "trunk",
   386  			HeadRefName:      "feature",
   387  		},
   388  		baseRepo("OWNER", "REPO", "main"),
   389  	)
   390  
   391  	cs, cmdTeardown := run.Stub()
   392  	defer cmdTeardown(t)
   393  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
   394  
   395  	output, err := runCommand(http, "main", true, "pr merge 1 --merge")
   396  	assert.EqualError(t, err, "SilentError")
   397  
   398  	assert.Equal(t, "", output.String())
   399  	assert.Equal(t, heredoc.Docf(`
   400  		X Pull request #123 is not mergeable: the merge commit cannot be cleanly created.
   401  		To have the pull request merged after all the requirements have been met, add the %[1]s--auto%[1]s flag.
   402  		Run the following to resolve the merge conflicts locally:
   403  		  gh pr checkout 123 && git fetch origin trunk && git merge origin/trunk
   404  	`, "`"), output.Stderr())
   405  }
   406  
   407  func TestPrMerge_nontty(t *testing.T) {
   408  	http := initFakeHTTP()
   409  	defer http.Verify(t)
   410  
   411  	shared.RunCommandFinder(
   412  		"1",
   413  		&api.PullRequest{
   414  			ID:               "THE-ID",
   415  			Number:           1,
   416  			State:            "OPEN",
   417  			Title:            "The title of the PR",
   418  			MergeStateStatus: "CLEAN",
   419  		},
   420  		baseRepo("OWNER", "REPO", "main"),
   421  	)
   422  
   423  	http.Register(
   424  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
   425  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
   426  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
   427  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
   428  			assert.NotContains(t, input, "commitHeadline")
   429  		}))
   430  
   431  	cs, cmdTeardown := run.Stub()
   432  	defer cmdTeardown(t)
   433  
   434  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
   435  
   436  	output, err := runCommand(http, "main", false, "pr merge 1 --merge")
   437  	if err != nil {
   438  		t.Fatalf("error running command `pr merge`: %v", err)
   439  	}
   440  
   441  	assert.Equal(t, "", output.String())
   442  	assert.Equal(t, "", output.Stderr())
   443  }
   444  
   445  func TestPrMerge_editMessage_nontty(t *testing.T) {
   446  	http := initFakeHTTP()
   447  	defer http.Verify(t)
   448  
   449  	shared.RunCommandFinder(
   450  		"1",
   451  		&api.PullRequest{
   452  			ID:               "THE-ID",
   453  			Number:           1,
   454  			State:            "OPEN",
   455  			Title:            "The title of the PR",
   456  			MergeStateStatus: "CLEAN",
   457  		},
   458  		baseRepo("OWNER", "REPO", "main"),
   459  	)
   460  
   461  	http.Register(
   462  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
   463  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
   464  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
   465  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
   466  			assert.Equal(t, "mytitle", input["commitHeadline"].(string))
   467  			assert.Equal(t, "mybody", input["commitBody"].(string))
   468  		}))
   469  
   470  	cs, cmdTeardown := run.Stub()
   471  	defer cmdTeardown(t)
   472  
   473  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
   474  
   475  	output, err := runCommand(http, "main", false, "pr merge 1 --merge -t mytitle -b mybody")
   476  	if err != nil {
   477  		t.Fatalf("error running command `pr merge`: %v", err)
   478  	}
   479  
   480  	assert.Equal(t, "", output.String())
   481  	assert.Equal(t, "", output.Stderr())
   482  }
   483  
   484  func TestPrMerge_withRepoFlag(t *testing.T) {
   485  	http := initFakeHTTP()
   486  	defer http.Verify(t)
   487  
   488  	shared.RunCommandFinder(
   489  		"1",
   490  		&api.PullRequest{
   491  			ID:               "THE-ID",
   492  			Number:           1,
   493  			State:            "OPEN",
   494  			Title:            "The title of the PR",
   495  			MergeStateStatus: "CLEAN",
   496  		},
   497  		baseRepo("OWNER", "REPO", "main"),
   498  	)
   499  
   500  	http.Register(
   501  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
   502  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
   503  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
   504  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
   505  			assert.NotContains(t, input, "commitHeadline")
   506  		}))
   507  
   508  	_, cmdTeardown := run.Stub()
   509  	defer cmdTeardown(t)
   510  
   511  	output, err := runCommand(http, "main", true, "pr merge 1 --merge -R OWNER/REPO")
   512  	if err != nil {
   513  		t.Fatalf("error running command `pr merge`: %v", err)
   514  	}
   515  
   516  	r := regexp.MustCompile(`Merged pull request #1 \(The title of the PR\)`)
   517  
   518  	if !r.MatchString(output.Stderr()) {
   519  		t.Fatalf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr())
   520  	}
   521  }
   522  
   523  func TestPrMerge_withMatchCommitHeadFlag(t *testing.T) {
   524  	http := initFakeHTTP()
   525  	defer http.Verify(t)
   526  
   527  	shared.RunCommandFinder(
   528  		"1",
   529  		&api.PullRequest{
   530  			ID:               "THE-ID",
   531  			Number:           1,
   532  			State:            "OPEN",
   533  			Title:            "The title of the PR",
   534  			MergeStateStatus: "CLEAN",
   535  		},
   536  		baseRepo("OWNER", "REPO", "main"),
   537  	)
   538  
   539  	http.Register(
   540  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
   541  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
   542  			assert.Equal(t, 3, len(input))
   543  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
   544  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
   545  			assert.Equal(t, "285ed5ab740f53ff6b0b4b629c59a9df23b9c6db", input["expectedHeadOid"].(string))
   546  		}))
   547  
   548  	cs, cmdTeardown := run.Stub()
   549  	defer cmdTeardown(t)
   550  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
   551  
   552  	output, err := runCommand(http, "main", true, "pr merge 1 --merge --match-head-commit 285ed5ab740f53ff6b0b4b629c59a9df23b9c6db")
   553  	if err != nil {
   554  		t.Fatalf("error running command `pr merge`: %v", err)
   555  	}
   556  
   557  	r := regexp.MustCompile(`Merged pull request #1 \(The title of the PR\)`)
   558  
   559  	if !r.MatchString(output.Stderr()) {
   560  		t.Fatalf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr())
   561  	}
   562  }
   563  
   564  func TestPrMerge_withAuthorFlag(t *testing.T) {
   565  	http := initFakeHTTP()
   566  	defer http.Verify(t)
   567  
   568  	shared.RunCommandFinder(
   569  		"1",
   570  		&api.PullRequest{
   571  			ID:               "THE-ID",
   572  			Number:           1,
   573  			State:            "OPEN",
   574  			Title:            "The title of the PR",
   575  			MergeStateStatus: "CLEAN",
   576  		},
   577  		baseRepo("OWNER", "REPO", "main"),
   578  	)
   579  
   580  	http.Register(
   581  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
   582  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
   583  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
   584  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
   585  			assert.Equal(t, "octocat@github.com", input["authorEmail"].(string))
   586  			assert.NotContains(t, input, "commitHeadline")
   587  		}),
   588  	)
   589  
   590  	cs, cmdTeardown := run.Stub()
   591  	defer cmdTeardown(t)
   592  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
   593  
   594  	output, err := runCommand(http, "main", true, "pr merge 1 --merge --author-email octocat@github.com")
   595  	if err != nil {
   596  		t.Fatalf("error running command `pr merge`: %v", err)
   597  	}
   598  
   599  	r := regexp.MustCompile(`Merged pull request #1 \(The title of the PR\)`)
   600  
   601  	if !r.MatchString(output.Stderr()) {
   602  		t.Fatalf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr())
   603  	}
   604  }
   605  
   606  func TestPrMerge_deleteBranch(t *testing.T) {
   607  	http := initFakeHTTP()
   608  	defer http.Verify(t)
   609  
   610  	shared.RunCommandFinder(
   611  		"",
   612  		&api.PullRequest{
   613  			ID:               "PR_10",
   614  			Number:           10,
   615  			State:            "OPEN",
   616  			Title:            "Blueberries are a good fruit",
   617  			HeadRefName:      "blueberries",
   618  			BaseRefName:      "main",
   619  			MergeStateStatus: "CLEAN",
   620  		},
   621  		baseRepo("OWNER", "REPO", "main"),
   622  	)
   623  
   624  	http.Register(
   625  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
   626  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
   627  			assert.Equal(t, "PR_10", input["pullRequestId"].(string))
   628  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
   629  			assert.NotContains(t, input, "commitHeadline")
   630  		}))
   631  	http.Register(
   632  		httpmock.REST("DELETE", "repos/OWNER/REPO/git/refs/heads/blueberries"),
   633  		httpmock.StringResponse(`{}`))
   634  
   635  	cs, cmdTeardown := run.Stub()
   636  	defer cmdTeardown(t)
   637  
   638  	cs.Register(`git rev-parse --verify refs/heads/main`, 0, "")
   639  	cs.Register(`git checkout main`, 0, "")
   640  	cs.Register(`git rev-parse --verify refs/heads/blueberries`, 0, "")
   641  	cs.Register(`git branch -D blueberries`, 0, "")
   642  	cs.Register(`git pull --ff-only`, 0, "")
   643  
   644  	output, err := runCommand(http, "blueberries", true, `pr merge --merge --delete-branch`)
   645  	if err != nil {
   646  		t.Fatalf("Got unexpected error running `pr merge` %s", err)
   647  	}
   648  
   649  	assert.Equal(t, "", output.String())
   650  	assert.Equal(t, heredoc.Doc(`
   651  		✓ Merged pull request #10 (Blueberries are a good fruit)
   652  		✓ Deleted branch blueberries and switched to branch main
   653  	`), output.Stderr())
   654  }
   655  
   656  func TestPrMerge_deleteBranch_nonDefault(t *testing.T) {
   657  	http := initFakeHTTP()
   658  	defer http.Verify(t)
   659  
   660  	shared.RunCommandFinder(
   661  		"",
   662  		&api.PullRequest{
   663  			ID:               "PR_10",
   664  			Number:           10,
   665  			State:            "OPEN",
   666  			Title:            "Blueberries are a good fruit",
   667  			HeadRefName:      "blueberries",
   668  			MergeStateStatus: "CLEAN",
   669  			BaseRefName:      "fruit",
   670  		},
   671  		baseRepo("OWNER", "REPO", "main"),
   672  	)
   673  
   674  	http.Register(
   675  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
   676  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
   677  			assert.Equal(t, "PR_10", input["pullRequestId"].(string))
   678  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
   679  			assert.NotContains(t, input, "commitHeadline")
   680  		}))
   681  	http.Register(
   682  		httpmock.REST("DELETE", "repos/OWNER/REPO/git/refs/heads/blueberries"),
   683  		httpmock.StringResponse(`{}`))
   684  
   685  	cs, cmdTeardown := run.Stub()
   686  	defer cmdTeardown(t)
   687  
   688  	cs.Register(`git rev-parse --verify refs/heads/fruit`, 0, "")
   689  	cs.Register(`git checkout fruit`, 0, "")
   690  	cs.Register(`git rev-parse --verify refs/heads/blueberries`, 0, "")
   691  	cs.Register(`git branch -D blueberries`, 0, "")
   692  	cs.Register(`git pull --ff-only`, 0, "")
   693  
   694  	output, err := runCommand(http, "blueberries", true, `pr merge --merge --delete-branch`)
   695  	if err != nil {
   696  		t.Fatalf("Got unexpected error running `pr merge` %s", err)
   697  	}
   698  
   699  	assert.Equal(t, "", output.String())
   700  	assert.Equal(t, heredoc.Doc(`
   701  		✓ Merged pull request #10 (Blueberries are a good fruit)
   702  		✓ Deleted branch blueberries and switched to branch fruit
   703  	`), output.Stderr())
   704  }
   705  
   706  func TestPrMerge_deleteBranch_checkoutNewBranch(t *testing.T) {
   707  	http := initFakeHTTP()
   708  	defer http.Verify(t)
   709  
   710  	shared.RunCommandFinder(
   711  		"",
   712  		&api.PullRequest{
   713  			ID:               "PR_10",
   714  			Number:           10,
   715  			State:            "OPEN",
   716  			Title:            "Blueberries are a good fruit",
   717  			HeadRefName:      "blueberries",
   718  			MergeStateStatus: "CLEAN",
   719  			BaseRefName:      "fruit",
   720  		},
   721  		baseRepo("OWNER", "REPO", "main"),
   722  	)
   723  
   724  	http.Register(
   725  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
   726  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
   727  			assert.Equal(t, "PR_10", input["pullRequestId"].(string))
   728  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
   729  			assert.NotContains(t, input, "commitHeadline")
   730  		}))
   731  	http.Register(
   732  		httpmock.REST("DELETE", "repos/OWNER/REPO/git/refs/heads/blueberries"),
   733  		httpmock.StringResponse(`{}`))
   734  
   735  	cs, cmdTeardown := run.Stub()
   736  	defer cmdTeardown(t)
   737  
   738  	cs.Register(`git rev-parse --verify refs/heads/fruit`, 1, "")
   739  	cs.Register(`git checkout -b fruit --track origin/fruit`, 0, "")
   740  	cs.Register(`git rev-parse --verify refs/heads/blueberries`, 0, "")
   741  	cs.Register(`git branch -D blueberries`, 0, "")
   742  	cs.Register(`git pull --ff-only`, 0, "")
   743  
   744  	output, err := runCommand(http, "blueberries", true, `pr merge --merge --delete-branch`)
   745  	if err != nil {
   746  		t.Fatalf("Got unexpected error running `pr merge` %s", err)
   747  	}
   748  
   749  	assert.Equal(t, "", output.String())
   750  	assert.Equal(t, heredoc.Doc(`
   751  		✓ Merged pull request #10 (Blueberries are a good fruit)
   752  		✓ Deleted branch blueberries and switched to branch fruit
   753  	`), output.Stderr())
   754  }
   755  
   756  func TestPrMerge_deleteNonCurrentBranch(t *testing.T) {
   757  	http := initFakeHTTP()
   758  	defer http.Verify(t)
   759  
   760  	shared.RunCommandFinder(
   761  		"blueberries",
   762  		&api.PullRequest{
   763  			ID:               "PR_10",
   764  			Number:           10,
   765  			State:            "OPEN",
   766  			Title:            "Blueberries are a good fruit",
   767  			HeadRefName:      "blueberries",
   768  			MergeStateStatus: "CLEAN",
   769  		},
   770  		baseRepo("OWNER", "REPO", "main"),
   771  	)
   772  
   773  	http.Register(
   774  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
   775  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
   776  			assert.Equal(t, "PR_10", input["pullRequestId"].(string))
   777  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
   778  			assert.NotContains(t, input, "commitHeadline")
   779  		}))
   780  	http.Register(
   781  		httpmock.REST("DELETE", "repos/OWNER/REPO/git/refs/heads/blueberries"),
   782  		httpmock.StringResponse(`{}`))
   783  
   784  	cs, cmdTeardown := run.Stub()
   785  	defer cmdTeardown(t)
   786  
   787  	cs.Register(`git rev-parse --verify refs/heads/blueberries`, 0, "")
   788  	cs.Register(`git branch -D blueberries`, 0, "")
   789  
   790  	output, err := runCommand(http, "main", true, `pr merge --merge --delete-branch blueberries`)
   791  	if err != nil {
   792  		t.Fatalf("Got unexpected error running `pr merge` %s", err)
   793  	}
   794  
   795  	assert.Equal(t, "", output.String())
   796  	assert.Equal(t, heredoc.Doc(`
   797  		✓ Merged pull request #10 (Blueberries are a good fruit)
   798  		✓ Deleted branch blueberries
   799  	`), output.Stderr())
   800  }
   801  
   802  func Test_nonDivergingPullRequest(t *testing.T) {
   803  	http := initFakeHTTP()
   804  	defer http.Verify(t)
   805  
   806  	pr := &api.PullRequest{
   807  		ID:               "PR_10",
   808  		Number:           10,
   809  		Title:            "Blueberries are a good fruit",
   810  		State:            "OPEN",
   811  		MergeStateStatus: "CLEAN",
   812  		BaseRefName:      "main",
   813  	}
   814  	stubCommit(pr, "COMMITSHA1")
   815  
   816  	shared.RunCommandFinder("", pr, baseRepo("OWNER", "REPO", "main"))
   817  
   818  	http.Register(
   819  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
   820  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
   821  			assert.Equal(t, "PR_10", input["pullRequestId"].(string))
   822  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
   823  			assert.NotContains(t, input, "commitHeadline")
   824  		}))
   825  
   826  	cs, cmdTeardown := run.Stub()
   827  	defer cmdTeardown(t)
   828  
   829  	cs.Register(`git .+ show .+ HEAD`, 0, "COMMITSHA1,title")
   830  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
   831  
   832  	output, err := runCommand(http, "blueberries", true, "pr merge --merge")
   833  	if err != nil {
   834  		t.Fatalf("error running command `pr merge`: %v", err)
   835  	}
   836  
   837  	assert.Equal(t, heredoc.Doc(`
   838  		✓ Merged pull request #10 (Blueberries are a good fruit)
   839  	`), output.Stderr())
   840  }
   841  
   842  func Test_divergingPullRequestWarning(t *testing.T) {
   843  	http := initFakeHTTP()
   844  	defer http.Verify(t)
   845  
   846  	pr := &api.PullRequest{
   847  		ID:               "PR_10",
   848  		Number:           10,
   849  		Title:            "Blueberries are a good fruit",
   850  		State:            "OPEN",
   851  		MergeStateStatus: "CLEAN",
   852  		BaseRefName:      "main",
   853  	}
   854  	stubCommit(pr, "COMMITSHA1")
   855  
   856  	shared.RunCommandFinder("", pr, baseRepo("OWNER", "REPO", "main"))
   857  
   858  	http.Register(
   859  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
   860  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
   861  			assert.Equal(t, "PR_10", input["pullRequestId"].(string))
   862  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
   863  			assert.NotContains(t, input, "commitHeadline")
   864  		}))
   865  
   866  	cs, cmdTeardown := run.Stub()
   867  	defer cmdTeardown(t)
   868  
   869  	cs.Register(`git .+ show .+ HEAD`, 0, "COMMITSHA2,title")
   870  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
   871  
   872  	output, err := runCommand(http, "blueberries", true, "pr merge --merge")
   873  	if err != nil {
   874  		t.Fatalf("error running command `pr merge`: %v", err)
   875  	}
   876  
   877  	assert.Equal(t, heredoc.Doc(`
   878  		! Pull request #10 (Blueberries are a good fruit) has diverged from local branch
   879  		✓ Merged pull request #10 (Blueberries are a good fruit)
   880  	`), output.Stderr())
   881  }
   882  
   883  func Test_pullRequestWithoutCommits(t *testing.T) {
   884  	http := initFakeHTTP()
   885  	defer http.Verify(t)
   886  
   887  	shared.RunCommandFinder(
   888  		"",
   889  		&api.PullRequest{
   890  			ID:               "PR_10",
   891  			Number:           10,
   892  			Title:            "Blueberries are a good fruit",
   893  			State:            "OPEN",
   894  			MergeStateStatus: "CLEAN",
   895  		},
   896  		baseRepo("OWNER", "REPO", "main"),
   897  	)
   898  
   899  	http.Register(
   900  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
   901  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
   902  			assert.Equal(t, "PR_10", input["pullRequestId"].(string))
   903  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
   904  			assert.NotContains(t, input, "commitHeadline")
   905  		}))
   906  
   907  	cs, cmdTeardown := run.Stub()
   908  	defer cmdTeardown(t)
   909  
   910  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
   911  
   912  	output, err := runCommand(http, "blueberries", true, "pr merge --merge")
   913  	if err != nil {
   914  		t.Fatalf("error running command `pr merge`: %v", err)
   915  	}
   916  
   917  	assert.Equal(t, heredoc.Doc(`
   918  		✓ Merged pull request #10 (Blueberries are a good fruit)
   919  	`), output.Stderr())
   920  }
   921  
   922  func TestPrMerge_rebase(t *testing.T) {
   923  	http := initFakeHTTP()
   924  	defer http.Verify(t)
   925  
   926  	shared.RunCommandFinder(
   927  		"2",
   928  		&api.PullRequest{
   929  			ID:               "THE-ID",
   930  			Number:           2,
   931  			Title:            "The title of the PR",
   932  			State:            "OPEN",
   933  			MergeStateStatus: "CLEAN",
   934  		},
   935  		baseRepo("OWNER", "REPO", "main"),
   936  	)
   937  
   938  	http.Register(
   939  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
   940  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
   941  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
   942  			assert.Equal(t, "REBASE", input["mergeMethod"].(string))
   943  			assert.NotContains(t, input, "commitHeadline")
   944  		}))
   945  
   946  	cs, cmdTeardown := run.Stub()
   947  	defer cmdTeardown(t)
   948  
   949  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
   950  
   951  	output, err := runCommand(http, "main", true, "pr merge 2 --rebase")
   952  	if err != nil {
   953  		t.Fatalf("error running command `pr merge`: %v", err)
   954  	}
   955  
   956  	r := regexp.MustCompile(`Rebased and merged pull request #2 \(The title of the PR\)`)
   957  
   958  	if !r.MatchString(output.Stderr()) {
   959  		t.Fatalf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr())
   960  	}
   961  }
   962  
   963  func TestPrMerge_squash(t *testing.T) {
   964  	http := initFakeHTTP()
   965  	defer http.Verify(t)
   966  
   967  	shared.RunCommandFinder(
   968  		"3",
   969  		&api.PullRequest{
   970  			ID:               "THE-ID",
   971  			Number:           3,
   972  			Title:            "The title of the PR",
   973  			State:            "OPEN",
   974  			MergeStateStatus: "CLEAN",
   975  		},
   976  		baseRepo("OWNER", "REPO", "main"),
   977  	)
   978  
   979  	http.Register(
   980  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
   981  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
   982  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
   983  			assert.Equal(t, "SQUASH", input["mergeMethod"].(string))
   984  			assert.NotContains(t, input, "commitHeadline")
   985  		}))
   986  
   987  	cs, cmdTeardown := run.Stub()
   988  	defer cmdTeardown(t)
   989  
   990  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
   991  
   992  	output, err := runCommand(http, "main", true, "pr merge 3 --squash")
   993  	if err != nil {
   994  		t.Fatalf("error running command `pr merge`: %v", err)
   995  	}
   996  
   997  	assert.Equal(t, "", output.String())
   998  	assert.Equal(t, heredoc.Doc(`
   999  		✓ Squashed and merged pull request #3 (The title of the PR)
  1000  	`), output.Stderr())
  1001  }
  1002  
  1003  func TestPrMerge_alreadyMerged(t *testing.T) {
  1004  	http := initFakeHTTP()
  1005  	defer http.Verify(t)
  1006  
  1007  	shared.RunCommandFinder(
  1008  		"4",
  1009  		&api.PullRequest{
  1010  			ID:               "THE-ID",
  1011  			Number:           4,
  1012  			State:            "MERGED",
  1013  			HeadRefName:      "blueberries",
  1014  			BaseRefName:      "main",
  1015  			MergeStateStatus: "CLEAN",
  1016  		},
  1017  		baseRepo("OWNER", "REPO", "main"),
  1018  	)
  1019  
  1020  	cs, cmdTeardown := run.Stub()
  1021  	defer cmdTeardown(t)
  1022  
  1023  	cs.Register(`git rev-parse --verify refs/heads/main`, 0, "")
  1024  	cs.Register(`git checkout main`, 0, "")
  1025  	cs.Register(`git rev-parse --verify refs/heads/blueberries`, 0, "")
  1026  	cs.Register(`git branch -D blueberries`, 0, "")
  1027  	cs.Register(`git pull --ff-only`, 0, "")
  1028  
  1029  	//nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock
  1030  	as := prompt.NewAskStubber(t)
  1031  	as.StubPrompt("Pull request #4 was already merged. Delete the branch locally?").AnswerWith(true)
  1032  
  1033  	output, err := runCommand(http, "blueberries", true, "pr merge 4")
  1034  	assert.NoError(t, err)
  1035  	assert.Equal(t, "", output.String())
  1036  	assert.Equal(t, "✓ Deleted branch blueberries and switched to branch main\n", output.Stderr())
  1037  }
  1038  
  1039  func TestPrMerge_alreadyMerged_withMergeStrategy(t *testing.T) {
  1040  	http := initFakeHTTP()
  1041  	defer http.Verify(t)
  1042  
  1043  	shared.RunCommandFinder(
  1044  		"4",
  1045  		&api.PullRequest{
  1046  			ID:                  "THE-ID",
  1047  			Number:              4,
  1048  			State:               "MERGED",
  1049  			HeadRepositoryOwner: api.Owner{Login: "OWNER"},
  1050  			MergeStateStatus:    "CLEAN",
  1051  		},
  1052  		baseRepo("OWNER", "REPO", "main"),
  1053  	)
  1054  
  1055  	cs, cmdTeardown := run.Stub()
  1056  	defer cmdTeardown(t)
  1057  
  1058  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
  1059  
  1060  	output, err := runCommand(http, "blueberries", false, "pr merge 4 --merge")
  1061  	if err != nil {
  1062  		t.Fatalf("Got unexpected error running `pr merge` %s", err)
  1063  	}
  1064  
  1065  	assert.Equal(t, "", output.String())
  1066  	assert.Equal(t, "! Pull request #4 was already merged\n", output.Stderr())
  1067  }
  1068  
  1069  func TestPrMerge_alreadyMerged_withMergeStrategy_TTY(t *testing.T) {
  1070  	http := initFakeHTTP()
  1071  	defer http.Verify(t)
  1072  
  1073  	shared.RunCommandFinder(
  1074  		"4",
  1075  		&api.PullRequest{
  1076  			ID:                  "THE-ID",
  1077  			Number:              4,
  1078  			State:               "MERGED",
  1079  			HeadRepositoryOwner: api.Owner{Login: "OWNER"},
  1080  			MergeStateStatus:    "CLEAN",
  1081  		},
  1082  		baseRepo("OWNER", "REPO", "main"),
  1083  	)
  1084  
  1085  	cs, cmdTeardown := run.Stub()
  1086  	defer cmdTeardown(t)
  1087  
  1088  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
  1089  	cs.Register(`git branch -D `, 0, "")
  1090  
  1091  	//nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock
  1092  	as := prompt.NewAskStubber(t)
  1093  	as.StubPrompt("Pull request #4 was already merged. Delete the branch locally?").AnswerWith(true)
  1094  
  1095  	output, err := runCommand(http, "blueberries", true, "pr merge 4 --merge")
  1096  	if err != nil {
  1097  		t.Fatalf("Got unexpected error running `pr merge` %s", err)
  1098  	}
  1099  
  1100  	assert.Equal(t, "", output.String())
  1101  	assert.Equal(t, "✓ Deleted branch \n", output.Stderr())
  1102  }
  1103  
  1104  func TestPrMerge_alreadyMerged_withMergeStrategy_crossRepo(t *testing.T) {
  1105  	http := initFakeHTTP()
  1106  	defer http.Verify(t)
  1107  
  1108  	shared.RunCommandFinder(
  1109  		"4",
  1110  		&api.PullRequest{
  1111  			ID:                  "THE-ID",
  1112  			Number:              4,
  1113  			State:               "MERGED",
  1114  			HeadRepositoryOwner: api.Owner{Login: "monalisa"},
  1115  			MergeStateStatus:    "CLEAN",
  1116  		},
  1117  		baseRepo("OWNER", "REPO", "main"),
  1118  	)
  1119  
  1120  	cs, cmdTeardown := run.Stub()
  1121  	defer cmdTeardown(t)
  1122  
  1123  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
  1124  
  1125  	output, err := runCommand(http, "blueberries", true, "pr merge 4 --merge")
  1126  	if err != nil {
  1127  		t.Fatalf("Got unexpected error running `pr merge` %s", err)
  1128  	}
  1129  
  1130  	assert.Equal(t, "", output.String())
  1131  	assert.Equal(t, "", output.Stderr())
  1132  }
  1133  func TestPRMergeTTY(t *testing.T) {
  1134  	http := initFakeHTTP()
  1135  	defer http.Verify(t)
  1136  
  1137  	shared.RunCommandFinder(
  1138  		"",
  1139  		&api.PullRequest{
  1140  			ID:               "THE-ID",
  1141  			Number:           3,
  1142  			Title:            "It was the best of times",
  1143  			HeadRefName:      "blueberries",
  1144  			MergeStateStatus: "CLEAN",
  1145  		},
  1146  		baseRepo("OWNER", "REPO", "main"),
  1147  	)
  1148  
  1149  	http.Register(
  1150  		httpmock.GraphQL(`query RepositoryInfo\b`),
  1151  		httpmock.StringResponse(`
  1152  		{ "data": { "repository": {
  1153  			"mergeCommitAllowed": true,
  1154  			"rebaseMergeAllowed": true,
  1155  			"squashMergeAllowed": true
  1156  		} } }`))
  1157  
  1158  	http.Register(
  1159  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
  1160  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
  1161  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
  1162  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
  1163  			assert.NotContains(t, input, "commitHeadline")
  1164  		}))
  1165  
  1166  	cs, cmdTeardown := run.Stub()
  1167  	defer cmdTeardown(t)
  1168  
  1169  	cs.Register(`git rev-parse --verify refs/heads/blueberries`, 0, "")
  1170  
  1171  	//nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock
  1172  	as := prompt.NewAskStubber(t)
  1173  	as.StubPrompt("What merge method would you like to use?").AnswerDefault()
  1174  	as.StubPrompt("Delete the branch locally and on GitHub?").AnswerDefault()
  1175  	as.StubPrompt("What's next?").AnswerWith("Submit")
  1176  
  1177  	output, err := runCommand(http, "blueberries", true, "")
  1178  	if err != nil {
  1179  		t.Fatalf("Got unexpected error running `pr merge` %s", err)
  1180  	}
  1181  
  1182  	assert.Equal(t, "✓ Merged pull request #3 (It was the best of times)\n", output.Stderr())
  1183  }
  1184  
  1185  func TestPRMergeTTY_withDeleteBranch(t *testing.T) {
  1186  	http := initFakeHTTP()
  1187  	defer http.Verify(t)
  1188  
  1189  	shared.RunCommandFinder(
  1190  		"",
  1191  		&api.PullRequest{
  1192  			ID:               "THE-ID",
  1193  			Number:           3,
  1194  			Title:            "It was the best of times",
  1195  			HeadRefName:      "blueberries",
  1196  			MergeStateStatus: "CLEAN",
  1197  			BaseRefName:      "main",
  1198  		},
  1199  		baseRepo("OWNER", "REPO", "main"),
  1200  	)
  1201  
  1202  	http.Register(
  1203  		httpmock.GraphQL(`query RepositoryInfo\b`),
  1204  		httpmock.StringResponse(`
  1205  		{ "data": { "repository": {
  1206  			"mergeCommitAllowed": true,
  1207  			"rebaseMergeAllowed": true,
  1208  			"squashMergeAllowed": true,
  1209  			"mergeQueue": {
  1210  				"mergeMethod": ""
  1211  			}
  1212  		} } }`))
  1213  	http.Register(
  1214  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
  1215  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
  1216  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
  1217  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
  1218  			assert.NotContains(t, input, "commitHeadline")
  1219  		}))
  1220  	http.Register(
  1221  		httpmock.REST("DELETE", "repos/OWNER/REPO/git/refs/heads/blueberries"),
  1222  		httpmock.StringResponse(`{}`))
  1223  
  1224  	cs, cmdTeardown := run.Stub()
  1225  	defer cmdTeardown(t)
  1226  
  1227  	cs.Register(`git rev-parse --verify refs/heads/main`, 0, "")
  1228  	cs.Register(`git checkout main`, 0, "")
  1229  	cs.Register(`git rev-parse --verify refs/heads/blueberries`, 0, "")
  1230  	cs.Register(`git branch -D blueberries`, 0, "")
  1231  	cs.Register(`git pull --ff-only`, 0, "")
  1232  
  1233  	//nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock
  1234  	as := prompt.NewAskStubber(t)
  1235  	as.StubPrompt("What merge method would you like to use?").AnswerDefault()
  1236  	as.StubPrompt("What's next?").AnswerWith("Submit")
  1237  
  1238  	output, err := runCommand(http, "blueberries", true, "-d")
  1239  	if err != nil {
  1240  		t.Fatalf("Got unexpected error running `pr merge` %s", err)
  1241  	}
  1242  
  1243  	assert.Equal(t, "", output.String())
  1244  	assert.Equal(t, heredoc.Doc(`
  1245  		✓ Merged pull request #3 (It was the best of times)
  1246  		✓ Deleted branch blueberries and switched to branch main
  1247  	`), output.Stderr())
  1248  }
  1249  
  1250  func TestPRMergeTTY_squashEditCommitMsgAndSubject(t *testing.T) {
  1251  	ios, _, stdout, stderr := iostreams.Test()
  1252  	ios.SetStdinTTY(true)
  1253  	ios.SetStdoutTTY(true)
  1254  	ios.SetStderrTTY(true)
  1255  
  1256  	tr := initFakeHTTP()
  1257  	defer tr.Verify(t)
  1258  
  1259  	tr.Register(
  1260  		httpmock.GraphQL(`query RepositoryInfo\b`),
  1261  		httpmock.StringResponse(`
  1262  		{ "data": { "repository": {
  1263  			"mergeCommitAllowed": true,
  1264  			"rebaseMergeAllowed": true,
  1265  			"squashMergeAllowed": true
  1266  		} } }`))
  1267  	tr.Register(
  1268  		httpmock.GraphQL(`query PullRequestMergeText\b`),
  1269  		httpmock.StringResponse(`
  1270  		{ "data": { "node": {
  1271  			"viewerMergeHeadlineText": "default headline text",
  1272  			"viewerMergeBodyText": "default body text"
  1273  		} } }`))
  1274  	tr.Register(
  1275  		httpmock.GraphQL(`query PullRequestMergeText\b`),
  1276  		httpmock.StringResponse(`
  1277  		{ "data": { "node": {
  1278  			"viewerMergeHeadlineText": "default headline text",
  1279  			"viewerMergeBodyText": "default body text"
  1280  		} } }`))
  1281  	tr.Register(
  1282  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
  1283  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
  1284  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
  1285  			assert.Equal(t, "SQUASH", input["mergeMethod"].(string))
  1286  			assert.Equal(t, "DEFAULT HEADLINE TEXT", input["commitHeadline"].(string))
  1287  			assert.Equal(t, "DEFAULT BODY TEXT", input["commitBody"].(string))
  1288  		}))
  1289  
  1290  	_, cmdTeardown := run.Stub()
  1291  	defer cmdTeardown(t)
  1292  
  1293  	//nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock
  1294  	as := prompt.NewAskStubber(t)
  1295  	as.StubPrompt("What merge method would you like to use?").AnswerWith("Squash and merge")
  1296  	as.StubPrompt("Delete the branch on GitHub?").AnswerDefault()
  1297  	as.StubPrompt("What's next?").AnswerWith("Edit commit message")
  1298  	as.StubPrompt("What's next?").AnswerWith("Edit commit subject")
  1299  	as.StubPrompt("What's next?").AnswerWith("Submit")
  1300  
  1301  	err := mergeRun(&MergeOptions{
  1302  		IO:     ios,
  1303  		Editor: testEditor{},
  1304  		HttpClient: func() (*http.Client, error) {
  1305  			return &http.Client{Transport: tr}, nil
  1306  		},
  1307  		SelectorArg:        "https://github.com/OWNER/REPO/pull/123",
  1308  		MergeStrategyEmpty: true,
  1309  		Finder: shared.NewMockFinder(
  1310  			"https://github.com/OWNER/REPO/pull/123",
  1311  			&api.PullRequest{ID: "THE-ID", Number: 123, Title: "title", MergeStateStatus: "CLEAN"},
  1312  			ghrepo.New("OWNER", "REPO"),
  1313  		),
  1314  	})
  1315  	assert.NoError(t, err)
  1316  
  1317  	assert.Equal(t, "", stdout.String())
  1318  	assert.Equal(t, "✓ Squashed and merged pull request #123 (title)\n", stderr.String())
  1319  }
  1320  
  1321  func TestPRMergeEmptyStrategyNonTTY(t *testing.T) {
  1322  	http := initFakeHTTP()
  1323  	defer http.Verify(t)
  1324  
  1325  	shared.RunCommandFinder(
  1326  		"1",
  1327  		&api.PullRequest{
  1328  			ID:               "THE-ID",
  1329  			Number:           1,
  1330  			State:            "OPEN",
  1331  			Title:            "The title of the PR",
  1332  			MergeStateStatus: "CLEAN",
  1333  			BaseRefName:      "main",
  1334  		},
  1335  		baseRepo("OWNER", "REPO", "main"),
  1336  	)
  1337  
  1338  	cs, cmdTeardown := run.Stub()
  1339  	defer cmdTeardown(t)
  1340  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
  1341  
  1342  	output, err := runCommand(http, "blueberries", false, "pr merge 1")
  1343  	assert.EqualError(t, err, "--merge, --rebase, or --squash required when not running interactively")
  1344  	assert.Equal(t, "", output.String())
  1345  	assert.Equal(t, "", output.Stderr())
  1346  }
  1347  
  1348  func TestPRTTY_cancelled(t *testing.T) {
  1349  	http := initFakeHTTP()
  1350  	defer http.Verify(t)
  1351  
  1352  	shared.RunCommandFinder(
  1353  		"",
  1354  		&api.PullRequest{ID: "THE-ID", Number: 123, MergeStateStatus: "CLEAN"},
  1355  		ghrepo.New("OWNER", "REPO"),
  1356  	)
  1357  
  1358  	http.Register(
  1359  		httpmock.GraphQL(`query RepositoryInfo\b`),
  1360  		httpmock.StringResponse(`
  1361  		{ "data": { "repository": {
  1362  			"mergeCommitAllowed": true,
  1363  			"rebaseMergeAllowed": true,
  1364  			"squashMergeAllowed": true
  1365  		} } }`))
  1366  
  1367  	cs, cmdTeardown := run.Stub()
  1368  	defer cmdTeardown(t)
  1369  
  1370  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
  1371  
  1372  	//nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock
  1373  	as := prompt.NewAskStubber(t)
  1374  	as.StubPrompt("What merge method would you like to use?").AnswerDefault()
  1375  	as.StubPrompt("Delete the branch locally and on GitHub?").AnswerDefault()
  1376  	as.StubPrompt("What's next?").AnswerWith("Cancel")
  1377  
  1378  	output, err := runCommand(http, "blueberries", true, "")
  1379  	if !errors.Is(err, cmdutil.CancelError) {
  1380  		t.Fatalf("got error %v", err)
  1381  	}
  1382  
  1383  	assert.Equal(t, "Cancelled.\n", output.Stderr())
  1384  }
  1385  
  1386  func Test_mergeMethodSurvey(t *testing.T) {
  1387  	repo := &api.Repository{
  1388  		MergeCommitAllowed: false,
  1389  		RebaseMergeAllowed: true,
  1390  		SquashMergeAllowed: true,
  1391  	}
  1392  	//nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock
  1393  	as := prompt.NewAskStubber(t)
  1394  	as.StubPrompt("What merge method would you like to use?").AnswerWith("Rebase and merge")
  1395  
  1396  	method, err := mergeMethodSurvey(repo)
  1397  	assert.Nil(t, err)
  1398  	assert.Equal(t, PullRequestMergeMethodRebase, method)
  1399  }
  1400  
  1401  func TestMergeRun_autoMerge(t *testing.T) {
  1402  	ios, _, stdout, stderr := iostreams.Test()
  1403  	ios.SetStdoutTTY(true)
  1404  	ios.SetStderrTTY(true)
  1405  
  1406  	tr := initFakeHTTP()
  1407  	defer tr.Verify(t)
  1408  	tr.Register(
  1409  		httpmock.GraphQL(`mutation PullRequestAutoMerge\b`),
  1410  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
  1411  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
  1412  			assert.Equal(t, "SQUASH", input["mergeMethod"].(string))
  1413  		}))
  1414  
  1415  	_, cmdTeardown := run.Stub()
  1416  	defer cmdTeardown(t)
  1417  
  1418  	err := mergeRun(&MergeOptions{
  1419  		IO: ios,
  1420  		HttpClient: func() (*http.Client, error) {
  1421  			return &http.Client{Transport: tr}, nil
  1422  		},
  1423  		SelectorArg:     "https://github.com/OWNER/REPO/pull/123",
  1424  		AutoMergeEnable: true,
  1425  		MergeMethod:     PullRequestMergeMethodSquash,
  1426  		Finder: shared.NewMockFinder(
  1427  			"https://github.com/OWNER/REPO/pull/123",
  1428  			&api.PullRequest{ID: "THE-ID", Number: 123, MergeStateStatus: "BLOCKED"},
  1429  			ghrepo.New("OWNER", "REPO"),
  1430  		),
  1431  	})
  1432  	assert.NoError(t, err)
  1433  
  1434  	assert.Equal(t, "", stdout.String())
  1435  	assert.Equal(t, "✓ Pull request #123 will be automatically merged via squash when all requirements are met\n", stderr.String())
  1436  }
  1437  
  1438  func TestMergeRun_autoMerge_directMerge(t *testing.T) {
  1439  	ios, _, stdout, stderr := iostreams.Test()
  1440  	ios.SetStdoutTTY(true)
  1441  	ios.SetStderrTTY(true)
  1442  
  1443  	tr := initFakeHTTP()
  1444  	defer tr.Verify(t)
  1445  	tr.Register(
  1446  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
  1447  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
  1448  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
  1449  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
  1450  			assert.NotContains(t, input, "commitHeadline")
  1451  		}))
  1452  
  1453  	_, cmdTeardown := run.Stub()
  1454  	defer cmdTeardown(t)
  1455  
  1456  	err := mergeRun(&MergeOptions{
  1457  		IO: ios,
  1458  		HttpClient: func() (*http.Client, error) {
  1459  			return &http.Client{Transport: tr}, nil
  1460  		},
  1461  		SelectorArg:     "https://github.com/OWNER/REPO/pull/123",
  1462  		AutoMergeEnable: true,
  1463  		MergeMethod:     PullRequestMergeMethodMerge,
  1464  		Finder: shared.NewMockFinder(
  1465  			"https://github.com/OWNER/REPO/pull/123",
  1466  			&api.PullRequest{ID: "THE-ID", Number: 123, MergeStateStatus: "CLEAN"},
  1467  			ghrepo.New("OWNER", "REPO"),
  1468  		),
  1469  	})
  1470  	assert.NoError(t, err)
  1471  
  1472  	assert.Equal(t, "", stdout.String())
  1473  	assert.Equal(t, "✓ Merged pull request #123 ()\n", stderr.String())
  1474  }
  1475  
  1476  func TestMergeRun_disableAutoMerge(t *testing.T) {
  1477  	ios, _, stdout, stderr := iostreams.Test()
  1478  	ios.SetStdoutTTY(true)
  1479  	ios.SetStderrTTY(true)
  1480  
  1481  	tr := initFakeHTTP()
  1482  	defer tr.Verify(t)
  1483  	tr.Register(
  1484  		httpmock.GraphQL(`mutation PullRequestAutoMergeDisable\b`),
  1485  		httpmock.GraphQLQuery(`{}`, func(s string, m map[string]interface{}) {
  1486  			assert.Equal(t, map[string]interface{}{"prID": "THE-ID"}, m)
  1487  		}))
  1488  
  1489  	_, cmdTeardown := run.Stub()
  1490  	defer cmdTeardown(t)
  1491  
  1492  	err := mergeRun(&MergeOptions{
  1493  		IO: ios,
  1494  		HttpClient: func() (*http.Client, error) {
  1495  			return &http.Client{Transport: tr}, nil
  1496  		},
  1497  		SelectorArg:      "https://github.com/OWNER/REPO/pull/123",
  1498  		AutoMergeDisable: true,
  1499  		Finder: shared.NewMockFinder(
  1500  			"https://github.com/OWNER/REPO/pull/123",
  1501  			&api.PullRequest{ID: "THE-ID", Number: 123},
  1502  			ghrepo.New("OWNER", "REPO"),
  1503  		),
  1504  	})
  1505  	assert.NoError(t, err)
  1506  
  1507  	assert.Equal(t, "", stdout.String())
  1508  	assert.Equal(t, "✓ Auto-merge disabled for pull request #123\n", stderr.String())
  1509  }
  1510  
  1511  func TestPrInMergeQueue(t *testing.T) {
  1512  	http := initFakeHTTP()
  1513  	defer http.Verify(t)
  1514  
  1515  	shared.RunCommandFinder(
  1516  		"1",
  1517  		&api.PullRequest{
  1518  			ID:                  "THE-ID",
  1519  			Number:              1,
  1520  			State:               "OPEN",
  1521  			Title:               "The title of the PR",
  1522  			MergeStateStatus:    "CLEAN",
  1523  			IsInMergeQueue:      true,
  1524  			IsMergeQueueEnabled: true,
  1525  		},
  1526  		baseRepo("OWNER", "REPO", "main"),
  1527  	)
  1528  
  1529  	cs, cmdTeardown := run.Stub()
  1530  	defer cmdTeardown(t)
  1531  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
  1532  
  1533  	output, err := runCommand(http, "blueberries", true, "pr merge 1")
  1534  	if err != nil {
  1535  		t.Fatalf("error running command `pr merge`: %v", err)
  1536  	}
  1537  
  1538  	assert.Equal(t, "", output.String())
  1539  	assert.Equal(t, "! Pull request #1 is already queued to merge\n", output.Stderr())
  1540  }
  1541  
  1542  func TestPrAddToMergeQueueWithMergeMethod(t *testing.T) {
  1543  	http := initFakeHTTP()
  1544  	defer http.Verify(t)
  1545  
  1546  	shared.RunCommandFinder(
  1547  		"1",
  1548  		&api.PullRequest{
  1549  			ID:                  "THE-ID",
  1550  			Number:              1,
  1551  			State:               "OPEN",
  1552  			Title:               "The title of the PR",
  1553  			MergeStateStatus:    "CLEAN",
  1554  			IsInMergeQueue:      false,
  1555  			IsMergeQueueEnabled: true,
  1556  			BaseRefName:         "main",
  1557  		},
  1558  		baseRepo("OWNER", "REPO", "main"),
  1559  	)
  1560  	http.Register(
  1561  		httpmock.GraphQL(`mutation PullRequestAutoMerge\b`),
  1562  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
  1563  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
  1564  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
  1565  		}),
  1566  	)
  1567  
  1568  	cs, cmdTeardown := run.Stub()
  1569  	defer cmdTeardown(t)
  1570  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
  1571  
  1572  	output, err := runCommand(http, "blueberries", true, "pr merge 1 --merge")
  1573  	if err != nil {
  1574  		t.Fatalf("error running command `pr merge`: %v", err)
  1575  	}
  1576  	assert.Equal(t, "", output.String())
  1577  	assert.Equal(t, "! The merge strategy for main is set by the merge queue\n✓ Pull request #1 will be added to the merge queue for main when ready\n", output.Stderr())
  1578  }
  1579  
  1580  func TestPrAddToMergeQueueClean(t *testing.T) {
  1581  	http := initFakeHTTP()
  1582  	defer http.Verify(t)
  1583  
  1584  	shared.RunCommandFinder(
  1585  		"1",
  1586  		&api.PullRequest{
  1587  			ID:                  "THE-ID",
  1588  			Number:              1,
  1589  			State:               "OPEN",
  1590  			Title:               "The title of the PR",
  1591  			MergeStateStatus:    "CLEAN",
  1592  			IsInMergeQueue:      false,
  1593  			IsMergeQueueEnabled: true,
  1594  			BaseRefName:         "main",
  1595  		},
  1596  		baseRepo("OWNER", "REPO", "main"),
  1597  	)
  1598  
  1599  	http.Register(
  1600  		httpmock.GraphQL(`mutation PullRequestAutoMerge\b`),
  1601  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
  1602  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
  1603  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
  1604  		}),
  1605  	)
  1606  
  1607  	cs, cmdTeardown := run.Stub()
  1608  	defer cmdTeardown(t)
  1609  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
  1610  
  1611  	output, err := runCommand(http, "blueberries", true, "pr merge 1")
  1612  	if err != nil {
  1613  		t.Fatalf("error running command `pr merge`: %v", err)
  1614  	}
  1615  
  1616  	assert.Equal(t, "", output.String())
  1617  	assert.Equal(t, "✓ Pull request #1 will be added to the merge queue for main when ready\n", output.Stderr())
  1618  }
  1619  
  1620  func TestPrAddToMergeQueueBlocked(t *testing.T) {
  1621  	http := initFakeHTTP()
  1622  	defer http.Verify(t)
  1623  
  1624  	shared.RunCommandFinder(
  1625  		"1",
  1626  		&api.PullRequest{
  1627  			ID:                  "THE-ID",
  1628  			Number:              1,
  1629  			State:               "OPEN",
  1630  			Title:               "The title of the PR",
  1631  			MergeStateStatus:    "BLOCKED",
  1632  			IsInMergeQueue:      false,
  1633  			IsMergeQueueEnabled: true,
  1634  			BaseRefName:         "main",
  1635  		},
  1636  		baseRepo("OWNER", "REPO", "main"),
  1637  	)
  1638  
  1639  	http.Register(
  1640  		httpmock.GraphQL(`mutation PullRequestAutoMerge\b`),
  1641  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
  1642  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
  1643  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
  1644  		}),
  1645  	)
  1646  
  1647  	cs, cmdTeardown := run.Stub()
  1648  	defer cmdTeardown(t)
  1649  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
  1650  
  1651  	output, err := runCommand(http, "blueberries", true, "pr merge 1")
  1652  	if err != nil {
  1653  		t.Fatalf("error running command `pr merge`: %v", err)
  1654  	}
  1655  
  1656  	assert.Equal(t, "", output.String())
  1657  	assert.Equal(t, "✓ Pull request #1 will be added to the merge queue for main when ready\n", output.Stderr())
  1658  }
  1659  
  1660  func TestPrAddToMergeQueueAdmin(t *testing.T) {
  1661  	http := initFakeHTTP()
  1662  	defer http.Verify(t)
  1663  
  1664  	shared.RunCommandFinder(
  1665  		"1",
  1666  		&api.PullRequest{
  1667  			ID:                  "THE-ID",
  1668  			Number:              1,
  1669  			State:               "OPEN",
  1670  			Title:               "The title of the PR",
  1671  			MergeStateStatus:    "CLEAN",
  1672  			IsInMergeQueue:      false,
  1673  			IsMergeQueueEnabled: true,
  1674  		},
  1675  		baseRepo("OWNER", "REPO", "main"),
  1676  	)
  1677  
  1678  	http.Register(
  1679  		httpmock.GraphQL(`query RepositoryInfo\b`),
  1680  		httpmock.StringResponse(`
  1681  		{ "data": { "repository": {
  1682  			"mergeCommitAllowed": true,
  1683  			"rebaseMergeAllowed": true,
  1684  			"squashMergeAllowed": true
  1685  		} } }`))
  1686  
  1687  	http.Register(
  1688  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
  1689  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
  1690  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
  1691  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
  1692  			assert.NotContains(t, input, "commitHeadline")
  1693  		}),
  1694  	)
  1695  
  1696  	cs, cmdTeardown := run.Stub()
  1697  	defer cmdTeardown(t)
  1698  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
  1699  
  1700  	//nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock
  1701  	as := prompt.NewAskStubber(t)
  1702  	as.StubPrompt("What merge method would you like to use?").AnswerDefault()
  1703  	as.StubPrompt("Delete the branch locally and on GitHub?").AnswerDefault()
  1704  	as.StubPrompt("What's next?").AnswerDefault()
  1705  
  1706  	output, err := runCommand(http, "blueberries", true, "pr merge 1 --admin")
  1707  	if err != nil {
  1708  		t.Fatalf("error running command `pr merge`: %v", err)
  1709  	}
  1710  
  1711  	assert.Equal(t, "", output.String())
  1712  	assert.Equal(t, "✓ Merged pull request #1 (The title of the PR)\n", output.Stderr())
  1713  }
  1714  
  1715  func TestPrAddToMergeQueueAdminWithMergeStrategy(t *testing.T) {
  1716  	http := initFakeHTTP()
  1717  	defer http.Verify(t)
  1718  
  1719  	shared.RunCommandFinder(
  1720  		"1",
  1721  		&api.PullRequest{
  1722  			ID:               "THE-ID",
  1723  			Number:           1,
  1724  			State:            "OPEN",
  1725  			Title:            "The title of the PR",
  1726  			MergeStateStatus: "CLEAN",
  1727  			IsInMergeQueue:   false,
  1728  		},
  1729  		baseRepo("OWNER", "REPO", "main"),
  1730  	)
  1731  
  1732  	http.Register(
  1733  		httpmock.GraphQL(`mutation PullRequestMerge\b`),
  1734  		httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) {
  1735  			assert.Equal(t, "THE-ID", input["pullRequestId"].(string))
  1736  			assert.Equal(t, "MERGE", input["mergeMethod"].(string))
  1737  			assert.NotContains(t, input, "commitHeadline")
  1738  		}),
  1739  	)
  1740  
  1741  	cs, cmdTeardown := run.Stub()
  1742  	defer cmdTeardown(t)
  1743  	cs.Register(`git rev-parse --verify refs/heads/`, 0, "")
  1744  
  1745  	output, err := runCommand(http, "blueberries", true, "pr merge 1 --admin --merge")
  1746  	if err != nil {
  1747  		t.Fatalf("error running command `pr merge`: %v", err)
  1748  	}
  1749  
  1750  	assert.Equal(t, "", output.String())
  1751  	assert.Equal(t, "✓ Merged pull request #1 (The title of the PR)\n", output.Stderr())
  1752  }
  1753  
  1754  type testEditor struct{}
  1755  
  1756  func (e testEditor) Edit(filename, text string) (string, error) {
  1757  	return strings.ToUpper(text), nil
  1758  }