github.com/secman-team/gh-api@v1.8.2/pkg/cmd/repo/fork/fork_test.go (about)

     1  package fork
     2  
     3  import (
     4  	"bytes"
     5  	"net/http"
     6  	"net/url"
     7  	"regexp"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/secman-team/gh-api/context"
    12  	"github.com/secman-team/gh-api/git"
    13  	"github.com/secman-team/gh-api/core/config"
    14  	"github.com/secman-team/gh-api/core/ghrepo"
    15  	"github.com/secman-team/gh-api/core/run"
    16  	"github.com/secman-team/gh-api/pkg/cmdutil"
    17  	"github.com/secman-team/gh-api/pkg/httpmock"
    18  	"github.com/secman-team/gh-api/pkg/iostreams"
    19  	"github.com/secman-team/gh-api/pkg/prompt"
    20  	"github.com/secman-team/gh-api/test"
    21  	"github.com/google/shlex"
    22  	"github.com/stretchr/testify/assert"
    23  )
    24  
    25  func TestNewCmdFork(t *testing.T) {
    26  	tests := []struct {
    27  		name    string
    28  		cli     string
    29  		tty     bool
    30  		wants   ForkOptions
    31  		wantErr bool
    32  	}{
    33  		{
    34  			name: "repo with git args",
    35  			cli:  "foo/bar -- --foo=bar",
    36  			wants: ForkOptions{
    37  				Repository: "foo/bar",
    38  				GitArgs:    []string{"TODO"},
    39  				RemoteName: "origin",
    40  				Rename:     true,
    41  			},
    42  		},
    43  		{
    44  			name:    "git args without repo",
    45  			cli:     "-- --foo bar",
    46  			wantErr: true,
    47  		},
    48  		{
    49  			name: "repo",
    50  			cli:  "foo/bar",
    51  			wants: ForkOptions{
    52  				Repository: "foo/bar",
    53  				RemoteName: "origin",
    54  				Rename:     true,
    55  			},
    56  		},
    57  		{
    58  			name:    "blank remote name",
    59  			cli:     "--remote --remote-name=''",
    60  			wantErr: true,
    61  		},
    62  		{
    63  			name: "remote name",
    64  			cli:  "--remote --remote-name=foo",
    65  			wants: ForkOptions{
    66  				RemoteName: "foo",
    67  				Rename:     false,
    68  				Remote:     true,
    69  			},
    70  		},
    71  		{
    72  			name: "blank nontty",
    73  			cli:  "",
    74  			wants: ForkOptions{
    75  				RemoteName: "origin",
    76  				Rename:     true,
    77  			},
    78  		},
    79  		{
    80  			name: "blank tty",
    81  			cli:  "",
    82  			tty:  true,
    83  			wants: ForkOptions{
    84  				RemoteName:   "origin",
    85  				PromptClone:  true,
    86  				PromptRemote: true,
    87  				Rename:       true,
    88  			},
    89  		},
    90  		{
    91  			name: "clone",
    92  			cli:  "--clone",
    93  			wants: ForkOptions{
    94  				RemoteName: "origin",
    95  				Rename:     true,
    96  			},
    97  		},
    98  		{
    99  			name: "remote",
   100  			cli:  "--remote",
   101  			wants: ForkOptions{
   102  				RemoteName: "origin",
   103  				Remote:     true,
   104  				Rename:     true,
   105  			},
   106  		},
   107  	}
   108  
   109  	for _, tt := range tests {
   110  		t.Run(tt.name, func(t *testing.T) {
   111  			io, _, _, _ := iostreams.Test()
   112  
   113  			f := &cmdutil.Factory{
   114  				IOStreams: io,
   115  			}
   116  
   117  			io.SetStdoutTTY(tt.tty)
   118  			io.SetStdinTTY(tt.tty)
   119  
   120  			argv, err := shlex.Split(tt.cli)
   121  			assert.NoError(t, err)
   122  
   123  			var gotOpts *ForkOptions
   124  			cmd := NewCmdFork(f, func(opts *ForkOptions) error {
   125  				gotOpts = opts
   126  				return nil
   127  			})
   128  			cmd.SetArgs(argv)
   129  			cmd.SetIn(&bytes.Buffer{})
   130  			cmd.SetOut(&bytes.Buffer{})
   131  			cmd.SetErr(&bytes.Buffer{})
   132  
   133  			_, err = cmd.ExecuteC()
   134  			if tt.wantErr {
   135  				assert.Error(t, err)
   136  				return
   137  			}
   138  			assert.NoError(t, err)
   139  
   140  			assert.Equal(t, tt.wants.RemoteName, gotOpts.RemoteName)
   141  			assert.Equal(t, tt.wants.Remote, gotOpts.Remote)
   142  			assert.Equal(t, tt.wants.PromptRemote, gotOpts.PromptRemote)
   143  			assert.Equal(t, tt.wants.PromptClone, gotOpts.PromptClone)
   144  		})
   145  	}
   146  }
   147  
   148  func runCommand(httpClient *http.Client, remotes []*context.Remote, isTTY bool, cli string) (*test.CmdOut, error) {
   149  	io, stdin, stdout, stderr := iostreams.Test()
   150  	io.SetStdoutTTY(isTTY)
   151  	io.SetStdinTTY(isTTY)
   152  	io.SetStderrTTY(isTTY)
   153  	fac := &cmdutil.Factory{
   154  		IOStreams: io,
   155  		HttpClient: func() (*http.Client, error) {
   156  			return httpClient, nil
   157  		},
   158  		Config: func() (config.Config, error) {
   159  			return config.NewBlankConfig(), nil
   160  		},
   161  		BaseRepo: func() (ghrepo.Interface, error) {
   162  			return ghrepo.New("OWNER", "REPO"), nil
   163  		},
   164  		Remotes: func() (context.Remotes, error) {
   165  			if remotes == nil {
   166  				return []*context.Remote{
   167  					{
   168  						Remote: &git.Remote{
   169  							Name:     "origin",
   170  							FetchURL: &url.URL{},
   171  						},
   172  						Repo: ghrepo.New("OWNER", "REPO"),
   173  					},
   174  				}, nil
   175  			}
   176  
   177  			return remotes, nil
   178  		},
   179  	}
   180  
   181  	cmd := NewCmdFork(fac, nil)
   182  
   183  	argv, err := shlex.Split(cli)
   184  	cmd.SetArgs(argv)
   185  
   186  	cmd.SetIn(stdin)
   187  	cmd.SetOut(stdout)
   188  	cmd.SetErr(stderr)
   189  
   190  	if err != nil {
   191  		panic(err)
   192  	}
   193  
   194  	_, err = cmd.ExecuteC()
   195  
   196  	if err != nil {
   197  		return nil, err
   198  	}
   199  
   200  	return &test.CmdOut{
   201  		OutBuf: stdout,
   202  		ErrBuf: stderr}, nil
   203  }
   204  
   205  func TestRepoFork_nontty(t *testing.T) {
   206  	defer stubSince(2 * time.Second)()
   207  	reg := &httpmock.Registry{}
   208  	defer reg.Verify(t)
   209  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   210  	httpClient := &http.Client{Transport: reg}
   211  
   212  	_, restore := run.Stub()
   213  	defer restore(t)
   214  
   215  	output, err := runCommand(httpClient, nil, false, "")
   216  	if err != nil {
   217  		t.Fatalf("error running command `repo fork`: %v", err)
   218  	}
   219  
   220  	assert.Equal(t, "", output.String())
   221  	assert.Equal(t, "", output.Stderr())
   222  
   223  }
   224  
   225  func TestRepoFork_no_conflicting_remote(t *testing.T) {
   226  	remotes := []*context.Remote{
   227  		{
   228  			Remote: &git.Remote{
   229  				Name:     "upstream",
   230  				FetchURL: &url.URL{},
   231  			},
   232  			Repo: ghrepo.New("OWNER", "REPO"),
   233  		},
   234  	}
   235  	defer stubSince(2 * time.Second)()
   236  	reg := &httpmock.Registry{}
   237  	defer reg.Verify(t)
   238  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   239  	httpClient := &http.Client{Transport: reg}
   240  
   241  	cs, restore := run.Stub()
   242  	defer restore(t)
   243  
   244  	cs.Register(`git remote add -f origin https://github\.com/someone/REPO\.git`, 0, "")
   245  
   246  	output, err := runCommand(httpClient, remotes, false, "--remote")
   247  	if err != nil {
   248  		t.Fatalf("error running command `repo fork`: %v", err)
   249  	}
   250  
   251  	assert.Equal(t, "", output.String())
   252  	assert.Equal(t, "", output.Stderr())
   253  }
   254  
   255  func TestRepoFork_existing_remote_error(t *testing.T) {
   256  	defer stubSince(2 * time.Second)()
   257  	reg := &httpmock.Registry{}
   258  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   259  	httpClient := &http.Client{Transport: reg}
   260  
   261  	_, err := runCommand(httpClient, nil, true, "--remote --remote-name='origin'")
   262  	if err == nil {
   263  		t.Fatal("expected error running command `repo fork`")
   264  	}
   265  
   266  	assert.Equal(t, "a git remote named 'origin' already exists", err.Error())
   267  
   268  	reg.Verify(t)
   269  }
   270  
   271  func TestRepoFork_in_parent_tty(t *testing.T) {
   272  	defer stubSince(2 * time.Second)()
   273  	reg := &httpmock.Registry{}
   274  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   275  	httpClient := &http.Client{Transport: reg}
   276  
   277  	cs, restore := run.Stub()
   278  	defer restore(t)
   279  
   280  	cs.Register("git remote rename origin upstream", 0, "")
   281  	cs.Register(`git remote add -f origin https://github\.com/someone/REPO\.git`, 0, "")
   282  
   283  	output, err := runCommand(httpClient, nil, true, "--remote")
   284  	if err != nil {
   285  		t.Fatalf("error running command `repo fork`: %v", err)
   286  	}
   287  
   288  	assert.Equal(t, "", output.String())
   289  	assert.Equal(t, "āœ“ Created fork someone/REPO\nāœ“ Added remote origin\n", output.Stderr())
   290  	reg.Verify(t)
   291  }
   292  func TestRepoFork_in_parent_nontty(t *testing.T) {
   293  	defer stubSince(2 * time.Second)()
   294  	reg := &httpmock.Registry{}
   295  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   296  	httpClient := &http.Client{Transport: reg}
   297  
   298  	cs, restore := run.Stub()
   299  	defer restore(t)
   300  
   301  	cs.Register("git remote rename origin upstream", 0, "")
   302  	cs.Register(`git remote add -f origin https://github\.com/someone/REPO\.git`, 0, "")
   303  
   304  	output, err := runCommand(httpClient, nil, false, "--remote")
   305  	if err != nil {
   306  		t.Fatalf("error running command `repo fork`: %v", err)
   307  	}
   308  
   309  	assert.Equal(t, "", output.String())
   310  	assert.Equal(t, "", output.Stderr())
   311  	reg.Verify(t)
   312  }
   313  
   314  func TestRepoFork_outside_parent_nontty(t *testing.T) {
   315  	defer stubSince(2 * time.Second)()
   316  	reg := &httpmock.Registry{}
   317  	reg.Verify(t)
   318  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   319  	httpClient := &http.Client{Transport: reg}
   320  
   321  	cs, restore := run.Stub()
   322  	defer restore(t)
   323  
   324  	cs.Register(`git clone https://github.com/someone/REPO\.git`, 0, "")
   325  	cs.Register(`git -C REPO remote add -f upstream https://github\.com/OWNER/REPO\.git`, 0, "")
   326  
   327  	output, err := runCommand(httpClient, nil, false, "--clone OWNER/REPO")
   328  	if err != nil {
   329  		t.Errorf("error running command `repo fork`: %v", err)
   330  	}
   331  
   332  	assert.Equal(t, "", output.String())
   333  	assert.Equal(t, output.Stderr(), "")
   334  
   335  }
   336  
   337  func TestRepoFork_already_forked(t *testing.T) {
   338  	reg := &httpmock.Registry{}
   339  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   340  	httpClient := &http.Client{Transport: reg}
   341  
   342  	_, restore := run.Stub()
   343  	defer restore(t)
   344  
   345  	output, err := runCommand(httpClient, nil, true, "--remote=false")
   346  	if err != nil {
   347  		t.Errorf("got unexpected error: %v", err)
   348  	}
   349  
   350  	r := regexp.MustCompile(`someone/REPO.*already exists`)
   351  	if !r.MatchString(output.Stderr()) {
   352  		t.Errorf("output did not match regexp /%s/\n> output\n%s\n", r, output.Stderr())
   353  		return
   354  	}
   355  
   356  	reg.Verify(t)
   357  }
   358  
   359  func TestRepoFork_reuseRemote(t *testing.T) {
   360  	remotes := []*context.Remote{
   361  		{
   362  			Remote: &git.Remote{Name: "origin", FetchURL: &url.URL{}},
   363  			Repo:   ghrepo.New("someone", "REPO"),
   364  		},
   365  		{
   366  			Remote: &git.Remote{Name: "upstream", FetchURL: &url.URL{}},
   367  			Repo:   ghrepo.New("OWNER", "REPO"),
   368  		},
   369  	}
   370  	reg := &httpmock.Registry{}
   371  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   372  	httpClient := &http.Client{Transport: reg}
   373  
   374  	output, err := runCommand(httpClient, remotes, true, "--remote")
   375  	if err != nil {
   376  		t.Errorf("got unexpected error: %v", err)
   377  	}
   378  	r := regexp.MustCompile(`Using existing remote.*origin`)
   379  	if !r.MatchString(output.Stderr()) {
   380  		t.Errorf("output did not match: %q", output.Stderr())
   381  		return
   382  	}
   383  	reg.Verify(t)
   384  }
   385  
   386  func TestRepoFork_in_parent(t *testing.T) {
   387  	reg := &httpmock.Registry{}
   388  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   389  	httpClient := &http.Client{Transport: reg}
   390  
   391  	_, restore := run.Stub()
   392  	defer restore(t)
   393  	defer stubSince(2 * time.Second)()
   394  
   395  	output, err := runCommand(httpClient, nil, true, "--remote=false")
   396  	if err != nil {
   397  		t.Errorf("error running command `repo fork`: %v", err)
   398  	}
   399  
   400  	assert.Equal(t, "", output.String())
   401  
   402  	r := regexp.MustCompile(`Created fork.*someone/REPO`)
   403  	if !r.MatchString(output.Stderr()) {
   404  		t.Errorf("output did not match regexp /%s/\n> output\n%s\n", r, output)
   405  		return
   406  	}
   407  	reg.Verify(t)
   408  }
   409  
   410  func TestRepoFork_outside(t *testing.T) {
   411  	tests := []struct {
   412  		name string
   413  		args string
   414  	}{
   415  		{
   416  			name: "url arg",
   417  			args: "--clone=false http://github.com/OWNER/REPO.git",
   418  		},
   419  		{
   420  			name: "full name arg",
   421  			args: "--clone=false OWNER/REPO",
   422  		},
   423  	}
   424  	for _, tt := range tests {
   425  		t.Run(tt.name, func(t *testing.T) {
   426  			defer stubSince(2 * time.Second)()
   427  			reg := &httpmock.Registry{}
   428  			defer reg.StubWithFixturePath(200, "./forkResult.json")()
   429  			httpClient := &http.Client{Transport: reg}
   430  
   431  			output, err := runCommand(httpClient, nil, true, tt.args)
   432  			if err != nil {
   433  				t.Errorf("error running command `repo fork`: %v", err)
   434  			}
   435  
   436  			assert.Equal(t, "", output.String())
   437  
   438  			r := regexp.MustCompile(`Created fork.*someone/REPO`)
   439  			if !r.MatchString(output.Stderr()) {
   440  				t.Errorf("output did not match regexp /%s/\n> output\n%s\n", r, output)
   441  				return
   442  			}
   443  			reg.Verify(t)
   444  		})
   445  	}
   446  }
   447  
   448  func TestRepoFork_in_parent_yes(t *testing.T) {
   449  	defer stubSince(2 * time.Second)()
   450  	reg := &httpmock.Registry{}
   451  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   452  	httpClient := &http.Client{Transport: reg}
   453  
   454  	cs, restore := run.Stub()
   455  	defer restore(t)
   456  
   457  	cs.Register(`git remote add -f fork https://github\.com/someone/REPO\.git`, 0, "")
   458  
   459  	output, err := runCommand(httpClient, nil, true, "--remote --remote-name=fork")
   460  	if err != nil {
   461  		t.Errorf("error running command `repo fork`: %v", err)
   462  	}
   463  
   464  	assert.Equal(t, "", output.String())
   465  	//nolint:staticcheck // prefer exact matchers over ExpectLines
   466  	test.ExpectLines(t, output.Stderr(),
   467  		"Created fork.*someone/REPO",
   468  		"Added remote.*fork")
   469  	reg.Verify(t)
   470  }
   471  
   472  func TestRepoFork_outside_yes(t *testing.T) {
   473  	defer stubSince(2 * time.Second)()
   474  	reg := &httpmock.Registry{}
   475  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   476  	httpClient := &http.Client{Transport: reg}
   477  
   478  	cs, restore := run.Stub()
   479  	defer restore(t)
   480  
   481  	cs.Register(`git clone https://github\.com/someone/REPO\.git`, 0, "")
   482  	cs.Register(`git -C REPO remote add -f upstream https://github\.com/OWNER/REPO\.git`, 0, "")
   483  
   484  	output, err := runCommand(httpClient, nil, true, "--clone OWNER/REPO")
   485  	if err != nil {
   486  		t.Errorf("error running command `repo fork`: %v", err)
   487  	}
   488  
   489  	assert.Equal(t, "", output.String())
   490  	//nolint:staticcheck // prefer exact matchers over ExpectLines
   491  	test.ExpectLines(t, output.Stderr(),
   492  		"Created fork.*someone/REPO",
   493  		"Cloned fork")
   494  	reg.Verify(t)
   495  }
   496  
   497  func TestRepoFork_ForkAlreadyExistsAndCloneNonTty(t *testing.T) {
   498  	defer stubSince(2 * time.Minute)()
   499  	reg := &httpmock.Registry{}
   500  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   501  	httpClient := &http.Client{Transport: reg}
   502  
   503  	cs, restore := run.Stub()
   504  	defer restore(t)
   505  
   506  	cs.Register(`git clone https://github\.com/someone/REPO\.git`, 0, "")
   507  	cs.Register(`git -C REPO remote add -f upstream https://github\.com/OWNER/REPO\.git`, 0, "")
   508  
   509  	output, err := runCommand(httpClient, nil, false, "--clone OWNER/REPO")
   510  	if err != nil {
   511  		t.Errorf("error running command `repo fork`: %v", err)
   512  	}
   513  
   514  	assert.Equal(t, "", output.String())
   515  	//nolint:staticcheck // prefer exact matchers over ExpectLines
   516  	test.ExpectLines(t, output.Stderr(),
   517  		"someone/REPO.*already exists")
   518  	reg.Verify(t)
   519  }
   520  
   521  func TestRepoFork_outside_survey_yes(t *testing.T) {
   522  	defer stubSince(2 * time.Second)()
   523  	reg := &httpmock.Registry{}
   524  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   525  	httpClient := &http.Client{Transport: reg}
   526  
   527  	cs, restore := run.Stub()
   528  	defer restore(t)
   529  
   530  	cs.Register(`git clone https://github\.com/someone/REPO\.git`, 0, "")
   531  	cs.Register(`git -C REPO remote add -f upstream https://github\.com/OWNER/REPO\.git`, 0, "")
   532  
   533  	defer prompt.StubConfirm(true)()
   534  
   535  	output, err := runCommand(httpClient, nil, true, "OWNER/REPO")
   536  	if err != nil {
   537  		t.Errorf("error running command `repo fork`: %v", err)
   538  	}
   539  
   540  	assert.Equal(t, "", output.String())
   541  	//nolint:staticcheck // prefer exact matchers over ExpectLines
   542  	test.ExpectLines(t, output.Stderr(),
   543  		"Created fork.*someone/REPO",
   544  		"Cloned fork")
   545  	reg.Verify(t)
   546  }
   547  
   548  func TestRepoFork_outside_survey_no(t *testing.T) {
   549  	defer stubSince(2 * time.Second)()
   550  	reg := &httpmock.Registry{}
   551  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   552  	httpClient := &http.Client{Transport: reg}
   553  
   554  	_, restore := run.Stub()
   555  	defer restore(t)
   556  
   557  	defer prompt.StubConfirm(false)()
   558  
   559  	output, err := runCommand(httpClient, nil, true, "OWNER/REPO")
   560  	if err != nil {
   561  		t.Errorf("error running command `repo fork`: %v", err)
   562  	}
   563  
   564  	assert.Equal(t, "", output.String())
   565  
   566  	r := regexp.MustCompile(`Created fork.*someone/REPO`)
   567  	if !r.MatchString(output.Stderr()) {
   568  		t.Errorf("output did not match regexp /%s/\n> output\n%s\n", r, output)
   569  		return
   570  	}
   571  	reg.Verify(t)
   572  }
   573  
   574  func TestRepoFork_in_parent_survey_yes(t *testing.T) {
   575  	reg := &httpmock.Registry{}
   576  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   577  	httpClient := &http.Client{Transport: reg}
   578  	defer stubSince(2 * time.Second)()
   579  
   580  	cs, restore := run.Stub()
   581  	defer restore(t)
   582  
   583  	cs.Register(`git remote add -f fork https://github\.com/someone/REPO\.git`, 0, "")
   584  
   585  	defer prompt.StubConfirm(true)()
   586  
   587  	output, err := runCommand(httpClient, nil, true, "--remote-name=fork")
   588  	if err != nil {
   589  		t.Errorf("error running command `repo fork`: %v", err)
   590  	}
   591  
   592  	assert.Equal(t, "", output.String())
   593  
   594  	//nolint:staticcheck // prefer exact matchers over ExpectLines
   595  	test.ExpectLines(t, output.Stderr(),
   596  		"Created fork.*someone/REPO",
   597  		"Added remote.*fork")
   598  	reg.Verify(t)
   599  }
   600  
   601  func TestRepoFork_in_parent_survey_no(t *testing.T) {
   602  	reg := &httpmock.Registry{}
   603  	defer reg.Verify(t)
   604  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   605  	httpClient := &http.Client{Transport: reg}
   606  	defer stubSince(2 * time.Second)()
   607  
   608  	_, restore := run.Stub()
   609  	defer restore(t)
   610  
   611  	defer prompt.StubConfirm(false)()
   612  
   613  	output, err := runCommand(httpClient, nil, true, "")
   614  	if err != nil {
   615  		t.Errorf("error running command `repo fork`: %v", err)
   616  	}
   617  
   618  	assert.Equal(t, "", output.String())
   619  
   620  	r := regexp.MustCompile(`Created fork.*someone/REPO`)
   621  	if !r.MatchString(output.Stderr()) {
   622  		t.Errorf("output did not match regexp /%s/\n> output\n%s\n", r, output)
   623  		return
   624  	}
   625  }
   626  
   627  func Test_RepoFork_gitFlags(t *testing.T) {
   628  	defer stubSince(2 * time.Second)()
   629  	reg := &httpmock.Registry{}
   630  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   631  	httpClient := &http.Client{Transport: reg}
   632  
   633  	cs, cmdTeardown := run.Stub()
   634  	defer cmdTeardown(t)
   635  
   636  	cs.Register(`git clone --depth 1 https://github.com/someone/REPO.git`, 0, "")
   637  	cs.Register(`git -C REPO remote add -f upstream https://github.com/OWNER/REPO.git`, 0, "")
   638  
   639  	output, err := runCommand(httpClient, nil, false, "--clone OWNER/REPO -- --depth 1")
   640  	if err != nil {
   641  		t.Errorf("error running command `repo fork`: %v", err)
   642  	}
   643  
   644  	assert.Equal(t, "", output.String())
   645  	assert.Equal(t, output.Stderr(), "")
   646  	reg.Verify(t)
   647  }
   648  
   649  func Test_RepoFork_flagError(t *testing.T) {
   650  	_, err := runCommand(nil, nil, true, "--depth 1 OWNER/REPO")
   651  	if err == nil || err.Error() != "unknown flag: --depth\nSeparate git clone flags with '--'." {
   652  		t.Errorf("unexpected error %v", err)
   653  	}
   654  }
   655  
   656  func TestRepoFork_in_parent_match_protocol(t *testing.T) {
   657  	defer stubSince(2 * time.Second)()
   658  	reg := &httpmock.Registry{}
   659  	defer reg.Verify(t)
   660  	defer reg.StubWithFixturePath(200, "./forkResult.json")()
   661  	httpClient := &http.Client{Transport: reg}
   662  
   663  	cs, restore := run.Stub()
   664  	defer restore(t)
   665  
   666  	cs.Register(`git remote add -f fork git@github\.com:someone/REPO\.git`, 0, "")
   667  
   668  	remotes := []*context.Remote{
   669  		{
   670  			Remote: &git.Remote{Name: "origin", PushURL: &url.URL{
   671  				Scheme: "ssh",
   672  			}},
   673  			Repo: ghrepo.New("OWNER", "REPO"),
   674  		},
   675  	}
   676  
   677  	output, err := runCommand(httpClient, remotes, true, "--remote --remote-name=fork")
   678  	if err != nil {
   679  		t.Errorf("error running command `repo fork`: %v", err)
   680  	}
   681  
   682  	assert.Equal(t, "", output.String())
   683  
   684  	//nolint:staticcheck // prefer exact matchers over ExpectLines
   685  	test.ExpectLines(t, output.Stderr(),
   686  		"Created fork.*someone/REPO",
   687  		"Added remote.*fork")
   688  }
   689  
   690  func stubSince(d time.Duration) func() {
   691  	originalSince := Since
   692  	Since = func(t time.Time) time.Duration {
   693  		return d
   694  	}
   695  	return func() {
   696  		Since = originalSince
   697  	}
   698  }