"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "pkg/cmd/repo/fork/fork_test.go" between
gh-cli-1.11.0.tar.gz and gh-cli-1.12.0.tar.gz

About: GitHub CLI is GitHub’s official command line tool.

fork_test.go  (gh-cli-1.11.0):fork_test.go  (gh-cli-1.12.0)
package fork package fork
import ( import (
"bytes" "bytes"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"regexp" "strings"
"testing" "testing"
"time" "time"
"github.com/MakeNowJust/heredoc"
"github.com/cli/cli/context" "github.com/cli/cli/context"
"github.com/cli/cli/git" "github.com/cli/cli/git"
"github.com/cli/cli/internal/config" "github.com/cli/cli/internal/config"
"github.com/cli/cli/internal/ghrepo" "github.com/cli/cli/internal/ghrepo"
"github.com/cli/cli/internal/run" "github.com/cli/cli/internal/run"
"github.com/cli/cli/pkg/cmdutil" "github.com/cli/cli/pkg/cmdutil"
"github.com/cli/cli/pkg/httpmock" "github.com/cli/cli/pkg/httpmock"
"github.com/cli/cli/pkg/iostreams" "github.com/cli/cli/pkg/iostreams"
"github.com/cli/cli/pkg/prompt" "github.com/cli/cli/pkg/prompt"
"github.com/cli/cli/test"
"github.com/google/shlex" "github.com/google/shlex"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestNewCmdFork(t *testing.T) { func TestNewCmdFork(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
cli string cli string
tty bool tty bool
wants ForkOptions wants ForkOptions
wantErr bool wantErr bool
errMsg string
}{ }{
{ {
name: "repo with git args", name: "repo with git args",
cli: "foo/bar -- --foo=bar", cli: "foo/bar -- --foo=bar",
wants: ForkOptions{ wants: ForkOptions{
Repository: "foo/bar", Repository: "foo/bar",
GitArgs: []string{"TODO"}, GitArgs: []string{"--foo=bar"},
RemoteName: "origin", RemoteName: "origin",
Rename: true, Rename: true,
}, },
}, },
{ {
name: "git args without repo", name: "git args without repo",
cli: "-- --foo bar", cli: "-- --foo bar",
wantErr: true, wantErr: true,
errMsg: "repository argument required when passing 'git clone' flags",
}, },
{ {
name: "repo", name: "repo",
cli: "foo/bar", cli: "foo/bar",
wants: ForkOptions{ wants: ForkOptions{
Repository: "foo/bar", Repository: "foo/bar",
RemoteName: "origin", RemoteName: "origin",
Rename: true, Rename: true,
GitArgs: []string{},
}, },
}, },
{ {
name: "blank remote name", name: "blank remote name",
cli: "--remote --remote-name=''", cli: "--remote --remote-name=''",
wantErr: true, wantErr: true,
errMsg: "--remote-name cannot be blank",
}, },
{ {
name: "remote name", name: "remote name",
cli: "--remote --remote-name=foo", cli: "--remote --remote-name=foo",
wants: ForkOptions{ wants: ForkOptions{
RemoteName: "foo", RemoteName: "foo",
Rename: false, Rename: false,
Remote: true, Remote: true,
}, },
}, },
skipping to change at line 121 skipping to change at line 123
{ {
name: "to org", name: "to org",
cli: "--org batmanshome", cli: "--org batmanshome",
wants: ForkOptions{ wants: ForkOptions{
RemoteName: "origin", RemoteName: "origin",
Remote: false, Remote: false,
Rename: false, Rename: false,
Organization: "batmanshome", Organization: "batmanshome",
}, },
}, },
{
name: "empty org",
cli: " --org=''",
wantErr: true,
errMsg: "--org cannot be blank",
},
{
name: "git flags in wrong place",
cli: "--depth 1 OWNER/REPO",
wantErr: true,
errMsg: "unknown flag: --depth\nSeparate git clone flags
with '--'.",
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
io, _, _, _ := iostreams.Test() io, _, _, _ := iostreams.Test()
f := &cmdutil.Factory{ f := &cmdutil.Factory{
IOStreams: io, IOStreams: io,
} }
skipping to change at line 150 skipping to change at line 164
return nil return nil
}) })
cmd.SetArgs(argv) cmd.SetArgs(argv)
cmd.SetIn(&bytes.Buffer{}) cmd.SetIn(&bytes.Buffer{})
cmd.SetOut(&bytes.Buffer{}) cmd.SetOut(&bytes.Buffer{})
cmd.SetErr(&bytes.Buffer{}) cmd.SetErr(&bytes.Buffer{})
_, err = cmd.ExecuteC() _, err = cmd.ExecuteC()
if tt.wantErr { if tt.wantErr {
assert.Error(t, err) assert.Error(t, err)
assert.Equal(t, tt.errMsg, err.Error())
return return
} }
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, tt.wants.RemoteName, gotOpts.RemoteName) assert.Equal(t, tt.wants.RemoteName, gotOpts.RemoteName)
assert.Equal(t, tt.wants.Remote, gotOpts.Remote) assert.Equal(t, tt.wants.Remote, gotOpts.Remote)
assert.Equal(t, tt.wants.PromptRemote, gotOpts.PromptRemo te) assert.Equal(t, tt.wants.PromptRemote, gotOpts.PromptRemo te)
assert.Equal(t, tt.wants.PromptClone, gotOpts.PromptClone ) assert.Equal(t, tt.wants.PromptClone, gotOpts.PromptClone )
assert.Equal(t, tt.wants.Organization, gotOpts.Organizati on) assert.Equal(t, tt.wants.Organization, gotOpts.Organizati on)
assert.Equal(t, tt.wants.GitArgs, gotOpts.GitArgs)
}) })
} }
} }
func runCommand(httpClient *http.Client, remotes []*context.Remote, isTTY bool, func TestRepoFork(t *testing.T) {
cli string) (*test.CmdOut, error) { forkPost := func(reg *httpmock.Registry) {
io, stdin, stdout, stderr := iostreams.Test() forkResult := `{
io.SetStdoutTTY(isTTY) "node_id": "123",
io.SetStdinTTY(isTTY) "name": "REPO",
io.SetStderrTTY(isTTY) "clone_url": "https://github.com/someone/repo.git",
fac := &cmdutil.Factory{ "created_at": "2011-01-26T19:01:12Z",
IOStreams: io, "owner": {
HttpClient: func() (*http.Client, error) { "login": "someone"
return httpClient, nil }
}`
reg.Register(
httpmock.REST("POST", "repos/OWNER/REPO/forks"),
httpmock.StringResponse(forkResult))
}
tests := []struct {
name string
opts *ForkOptions
tty bool
httpStubs func(*httpmock.Registry)
execStubs func(*run.CommandStubber)
askStubs func(*prompt.AskStubber)
remotes []*context.Remote
wantOut string
wantErrOut string
wantErr bool
errMsg string
}{
// TODO implicit, override existing remote's protocol with config
ured protocol
{
name: "implicit match existing remote's protocol",
tty: true,
opts: &ForkOptions{
Remote: true,
RemoteName: "fork",
},
remotes: []*context.Remote{
{
Remote: &git.Remote{Name: "origin", PushU
RL: &url.URL{
Scheme: "ssh",
}},
Repo: ghrepo.New("OWNER", "REPO"),
},
},
httpStubs: forkPost,
execStubs: func(cs *run.CommandStubber) {
cs.Register(`git remote add -f fork git@github\.c
om:someone/REPO\.git`, 0, "")
},
wantErrOut: "✓ Created fork someone/REPO\n✓ Added remote
fork\n",
}, },
Config: func() (config.Config, error) { {
return config.NewBlankConfig(), nil name: "implicit with negative interactive choices",
tty: true,
opts: &ForkOptions{
PromptRemote: true,
Rename: true,
RemoteName: defaultRemoteName,
},
httpStubs: forkPost,
askStubs: func(as *prompt.AskStubber) {
as.StubOne(false)
},
wantErrOut: "✓ Created fork someone/REPO\n",
}, },
BaseRepo: func() (ghrepo.Interface, error) { {
return ghrepo.New("OWNER", "REPO"), nil name: "implicit with interactive choices",
tty: true,
opts: &ForkOptions{
PromptRemote: true,
Rename: true,
RemoteName: defaultRemoteName,
},
httpStubs: forkPost,
execStubs: func(cs *run.CommandStubber) {
cs.Register("git remote rename origin upstream",
0, "")
cs.Register(`git remote add -f origin https://git
hub.com/someone/REPO.git`, 0, "")
},
askStubs: func(as *prompt.AskStubber) {
as.StubOne(true)
},
wantErrOut: "✓ Created fork someone/REPO\n✓ Added remote
origin\n",
}, },
Remotes: func() (context.Remotes, error) { {
if remotes == nil { name: "implicit tty reuse existing remote",
return []*context.Remote{ tty: true,
{ opts: &ForkOptions{
Remote: &git.Remote{ Remote: true,
Name: "origin", RemoteName: defaultRemoteName,
FetchURL: &url.URL{}, },
}, remotes: []*context.Remote{
Repo: ghrepo.New("OWNER", "REPO") {
, Remote: &git.Remote{Name: "origin", Fetch
}, URL: &url.URL{}},
}, nil Repo: ghrepo.New("someone", "REPO"),
} },
{
return remotes, nil Remote: &git.Remote{Name: "upstream", Fet
chURL: &url.URL{}},
Repo: ghrepo.New("OWNER", "REPO"),
},
},
httpStubs: forkPost,
wantErrOut: "✓ Created fork someone/REPO\n✓ Using existin
g remote origin\n",
}, },
}
cmd := NewCmdFork(fac, nil)
argv, err := shlex.Split(cli)
cmd.SetArgs(argv)
cmd.SetIn(stdin)
cmd.SetOut(stdout)
cmd.SetErr(stderr)
if err != nil {
panic(err)
}
_, err = cmd.ExecuteC()
if err != nil {
return nil, err
}
return &test.CmdOut{
OutBuf: stdout,
ErrBuf: stderr}, nil
}
func TestRepoFork_nontty(t *testing.T) {
defer stubSince(2 * time.Second)()
reg := &httpmock.Registry{}
defer reg.Verify(t)
defer reg.StubWithFixturePath(200, "./forkResult.json")()
httpClient := &http.Client{Transport: reg}
_, restore := run.Stub()
defer restore(t)
output, err := runCommand(httpClient, nil, false, "")
if err != nil {
t.Fatalf("error running command `repo fork`: %v", err)
}
assert.Equal(t, "", output.String())
assert.Equal(t, "", output.Stderr())
}
func TestRepoFork_no_conflicting_remote(t *testing.T) {
remotes := []*context.Remote{
{ {
Remote: &git.Remote{ name: "implicit tty remote exists",
Name: "upstream", // gh repo fork --remote --remote-name origin | cat
FetchURL: &url.URL{}, tty: true,
opts: &ForkOptions{
Remote: true,
RemoteName: defaultRemoteName,
}, },
Repo: ghrepo.New("OWNER", "REPO"), httpStubs: forkPost,
wantErr: true,
errMsg: "a git remote named 'origin' already exists",
}, },
}
defer stubSince(2 * time.Second)()
reg := &httpmock.Registry{}
defer reg.Verify(t)
defer reg.StubWithFixturePath(200, "./forkResult.json")()
httpClient := &http.Client{Transport: reg}
cs, restore := run.Stub()
defer restore(t)
cs.Register(`git remote add -f origin https://github\.com/someone/REPO\.g
it`, 0, "")
output, err := runCommand(httpClient, remotes, false, "--remote")
if err != nil {
t.Fatalf("error running command `repo fork`: %v", err)
}
assert.Equal(t, "", output.String())
assert.Equal(t, "", output.Stderr())
}
func TestRepoFork_existing_remote_error(t *testing.T) {
defer stubSince(2 * time.Second)()
reg := &httpmock.Registry{}
defer reg.StubWithFixturePath(200, "./forkResult.json")()
httpClient := &http.Client{Transport: reg}
_, err := runCommand(httpClient, nil, true, "--remote --remote-name='orig
in'")
if err == nil {
t.Fatal("expected error running command `repo fork`")
}
assert.Equal(t, "a git remote named 'origin' already exists", err.Error()
)
reg.Verify(t)
}
func TestRepoFork_in_parent_tty(t *testing.T) {
defer stubSince(2 * time.Second)()
reg := &httpmock.Registry{}
defer reg.StubWithFixturePath(200, "./forkResult.json")()
httpClient := &http.Client{Transport: reg}
cs, restore := run.Stub()
defer restore(t)
cs.Register("git remote rename origin upstream", 0, "")
cs.Register(`git remote add -f origin https://github\.com/someone/REPO\.g
it`, 0, "")
output, err := runCommand(httpClient, nil, true, "--remote")
if err != nil {
t.Fatalf("error running command `repo fork`: %v", err)
}
assert.Equal(t, "", output.String())
assert.Equal(t, "✓ Created fork someone/REPO\n✓ Added remote origin\n", o
utput.Stderr())
reg.Verify(t)
}
func TestRepoFork_in_parent_nontty(t *testing.T) {
defer stubSince(2 * time.Second)()
reg := &httpmock.Registry{}
defer reg.StubWithFixturePath(200, "./forkResult.json")()
httpClient := &http.Client{Transport: reg}
cs, restore := run.Stub()
defer restore(t)
cs.Register("git remote rename origin upstream", 0, "")
cs.Register(`git remote add -f origin https://github\.com/someone/REPO\.g
it`, 0, "")
output, err := runCommand(httpClient, nil, false, "--remote")
if err != nil {
t.Fatalf("error running command `repo fork`: %v", err)
}
assert.Equal(t, "", output.String())
assert.Equal(t, "", output.Stderr())
reg.Verify(t)
}
func TestRepoFork_outside_parent_nontty(t *testing.T) {
defer stubSince(2 * time.Second)()
reg := &httpmock.Registry{}
reg.Verify(t)
defer reg.StubWithFixturePath(200, "./forkResult.json")()
httpClient := &http.Client{Transport: reg}
cs, restore := run.Stub()
defer restore(t)
cs.Register(`git clone https://github.com/someone/REPO\.git`, 0, "")
cs.Register(`git -C REPO remote add -f upstream https://github\.com/OWNER
/REPO\.git`, 0, "")
output, err := runCommand(httpClient, nil, false, "--clone OWNER/REPO")
if err != nil {
t.Errorf("error running command `repo fork`: %v", err)
}
assert.Equal(t, "", output.String())
assert.Equal(t, output.Stderr(), "")
}
func TestRepoFork_already_forked(t *testing.T) {
reg := &httpmock.Registry{}
defer reg.StubWithFixturePath(200, "./forkResult.json")()
httpClient := &http.Client{Transport: reg}
_, restore := run.Stub()
defer restore(t)
output, err := runCommand(httpClient, nil, true, "--remote=false")
if err != nil {
t.Errorf("got unexpected error: %v", err)
}
r := regexp.MustCompile(`someone/REPO.*already exists`)
if !r.MatchString(output.Stderr()) {
t.Errorf("output did not match regexp /%s/\n> output\n%s\n", r, o
utput.Stderr())
return
}
reg.Verify(t)
}
func TestRepoFork_reuseRemote(t *testing.T) {
remotes := []*context.Remote{
{ {
Remote: &git.Remote{Name: "origin", FetchURL: &url.URL{}} name: "implicit tty already forked",
, tty: true,
Repo: ghrepo.New("someone", "REPO"), opts: &ForkOptions{
Since: func(t time.Time) time.Duration {
return 120 * time.Second
},
},
httpStubs: forkPost,
wantErrOut: "! someone/REPO already exists\n",
}, },
{ {
Remote: &git.Remote{Name: "upstream", FetchURL: &url.URL{ name: "implicit tty --remote",
}}, tty: true,
Repo: ghrepo.New("OWNER", "REPO"), opts: &ForkOptions{
Remote: true,
RemoteName: defaultRemoteName,
Rename: true,
},
httpStubs: forkPost,
execStubs: func(cs *run.CommandStubber) {
cs.Register("git remote rename origin upstream",
0, "")
cs.Register(`git remote add -f origin https://git
hub.com/someone/REPO.git`, 0, "")
},
wantErrOut: "✓ Created fork someone/REPO\n✓ Added remote
origin\n",
}, },
}
reg := &httpmock.Registry{}
defer reg.StubWithFixturePath(200, "./forkResult.json")()
httpClient := &http.Client{Transport: reg}
output, err := runCommand(httpClient, remotes, true, "--remote")
if err != nil {
t.Errorf("got unexpected error: %v", err)
}
r := regexp.MustCompile(`Using existing remote.*origin`)
if !r.MatchString(output.Stderr()) {
t.Errorf("output did not match: %q", output.Stderr())
return
}
reg.Verify(t)
}
func TestRepoFork_in_parent(t *testing.T) {
reg := &httpmock.Registry{}
defer reg.StubWithFixturePath(200, "./forkResult.json")()
httpClient := &http.Client{Transport: reg}
_, restore := run.Stub()
defer restore(t)
defer stubSince(2 * time.Second)()
output, err := runCommand(httpClient, nil, true, "--remote=false")
if err != nil {
t.Errorf("error running command `repo fork`: %v", err)
}
assert.Equal(t, "", output.String())
r := regexp.MustCompile(`Created fork.*someone/REPO`)
if !r.MatchString(output.Stderr()) {
t.Errorf("output did not match regexp /%s/\n> output\n%s\n", r, o
utput)
return
}
reg.Verify(t)
}
func TestRepoFork_outside(t *testing.T) {
tests := []struct {
name string
args string
postBody string
responseBody string
wantStderr string
}{
{ {
name: "url arg", name: "implicit nontty reuse existing remote",
args: "--clone=false http://github.com/OWNER/REPO opts: &ForkOptions{
.git", Remote: true,
postBody: "{}\n", RemoteName: defaultRemoteName,
responseBody: `{"name":"REPO", "owner":{"login":"monalisa Rename: true,
"}}`, },
wantStderr: heredoc.Doc(` remotes: []*context.Remote{
Created fork monalisa/REPO {
`), Remote: &git.Remote{Name: "origin", Fetch
}, URL: &url.URL{}},
{ Repo: ghrepo.New("someone", "REPO"),
name: "full name arg", },
args: "--clone=false OWNER/REPO", {
postBody: "{}\n", Remote: &git.Remote{Name: "upstream", Fet
responseBody: `{"name":"REPO", "owner":{"login":"monalisa chURL: &url.URL{}},
"}}`, Repo: ghrepo.New("OWNER", "REPO"),
wantStderr: heredoc.Doc(` },
Created fork monalisa/REPO },
`), httpStubs: forkPost,
}, },
{ {
name: "fork to org without clone", name: "implicit nontty remote exists",
args: "--clone=false OWNER/REPO --org batmanshome // gh repo fork --remote --remote-name origin | cat
", opts: &ForkOptions{
postBody: "{\"organization\":\"batmanshome\"}\n", Remote: true,
responseBody: `{"name":"REPO", "owner":{"login":"BatmansH RemoteName: defaultRemoteName,
ome"}}`, },
wantStderr: heredoc.Doc(` httpStubs: forkPost,
Created fork BatmansHome/REPO wantErr: true,
`), errMsg: "a git remote named 'origin' already exists",
},
{
name: "implicit nontty already forked",
opts: &ForkOptions{
Since: func(t time.Time) time.Duration {
return 120 * time.Second
},
},
httpStubs: forkPost,
wantErrOut: "someone/REPO already exists",
},
{
name: "implicit nontty --remote",
opts: &ForkOptions{
Remote: true,
RemoteName: defaultRemoteName,
Rename: true,
},
httpStubs: forkPost,
execStubs: func(cs *run.CommandStubber) {
cs.Register("git remote rename origin upstream",
0, "")
cs.Register(`git remote add -f origin https://git
hub.com/someone/REPO.git`, 0, "")
},
},
{
name: "implicit nontty no args",
opts: &ForkOptions{},
httpStubs: forkPost,
},
{
name: "passes git flags",
tty: true,
opts: &ForkOptions{
Repository: "OWNER/REPO",
GitArgs: []string{"--depth", "1"},
Clone: true,
},
httpStubs: forkPost,
execStubs: func(cs *run.CommandStubber) {
cs.Register(`git clone --depth 1 https://github.c
om/someone/REPO\.git`, 0, "")
cs.Register(`git -C REPO remote add -f upstream h
ttps://github\.com/OWNER/REPO\.git`, 0, "")
},
wantErrOut: "✓ Created fork someone/REPO\n✓ Cloned fork\n
",
},
{
name: "repo arg fork to org",
tty: true,
opts: &ForkOptions{
Repository: "OWNER/REPO",
Organization: "gamehendge",
Clone: true,
},
httpStubs: func(reg *httpmock.Registry) {
reg.Register(
httpmock.REST("POST", "repos/OWNER/REPO/f
orks"),
func(req *http.Request) (*http.Response,
error) {
bb, err := ioutil.ReadAll(req.Bod
y)
if err != nil {
return nil, err
}
assert.Equal(t, `{"organization":
"gamehendge"}`, strings.TrimSpace(string(bb)))
return &http.Response{
Request: req,
StatusCode: 200,
Body: ioutil.NopClo
ser(bytes.NewBufferString(`{"name":"REPO", "owner":{"login":"gamehendge"}}`)),
}, nil
})
},
execStubs: func(cs *run.CommandStubber) {
cs.Register(`git clone https://github.com/gamehen
dge/REPO\.git`, 0, "")
cs.Register(`git -C REPO remote add -f upstream h
ttps://github\.com/OWNER/REPO\.git`, 0, "")
},
wantErrOut: "✓ Created fork gamehendge/REPO\n✓ Cloned for
k\n",
},
{
name: "repo arg url arg",
tty: true,
opts: &ForkOptions{
Repository: "https://github.com/OWNER/REPO.git",
Clone: true,
},
httpStubs: forkPost,
execStubs: func(cs *run.CommandStubber) {
cs.Register(`git clone https://github.com/someone
/REPO\.git`, 0, "")
cs.Register(`git -C REPO remote add -f upstream h
ttps://github\.com/OWNER/REPO\.git`, 0, "")
},
wantErrOut: "✓ Created fork someone/REPO\n✓ Cloned fork\n
",
},
{
name: "repo arg interactive no clone",
tty: true,
opts: &ForkOptions{
Repository: "OWNER/REPO",
PromptClone: true,
},
httpStubs: forkPost,
askStubs: func(as *prompt.AskStubber) {
as.StubOne(false)
},
wantErrOut: "✓ Created fork someone/REPO\n",
},
{
name: "repo arg interactive",
tty: true,
opts: &ForkOptions{
Repository: "OWNER/REPO",
PromptClone: true,
},
httpStubs: forkPost,
askStubs: func(as *prompt.AskStubber) {
as.StubOne(true)
},
execStubs: func(cs *run.CommandStubber) {
cs.Register(`git clone https://github.com/someone
/REPO\.git`, 0, "")
cs.Register(`git -C REPO remote add -f upstream h
ttps://github\.com/OWNER/REPO\.git`, 0, "")
},
wantErrOut: "✓ Created fork someone/REPO\n✓ Cloned fork\n
",
},
{
name: "repo arg interactive already forked",
tty: true,
opts: &ForkOptions{
Repository: "OWNER/REPO",
PromptClone: true,
Since: func(t time.Time) time.Duration {
return 120 * time.Second
},
},
httpStubs: forkPost,
askStubs: func(as *prompt.AskStubber) {
as.StubOne(true)
},
execStubs: func(cs *run.CommandStubber) {
cs.Register(`git clone https://github.com/someone
/REPO\.git`, 0, "")
cs.Register(`git -C REPO remote add -f upstream h
ttps://github\.com/OWNER/REPO\.git`, 0, "")
},
wantErrOut: "! someone/REPO already exists\n✓ Cloned fork
\n",
},
{
name: "repo arg nontty no flags",
opts: &ForkOptions{
Repository: "OWNER/REPO",
},
httpStubs: forkPost,
},
{
name: "repo arg nontty repo already exists",
opts: &ForkOptions{
Repository: "OWNER/REPO",
Since: func(t time.Time) time.Duration {
return 120 * time.Second
},
},
httpStubs: forkPost,
wantErrOut: "someone/REPO already exists",
},
{
name: "repo arg nontty clone arg already exists",
opts: &ForkOptions{
Repository: "OWNER/REPO",
Clone: true,
Since: func(t time.Time) time.Duration {
return 120 * time.Second
},
},
httpStubs: forkPost,
execStubs: func(cs *run.CommandStubber) {
cs.Register(`git clone https://github.com/someone
/REPO\.git`, 0, "")
cs.Register(`git -C REPO remote add -f upstream h
ttps://github\.com/OWNER/REPO\.git`, 0, "")
},
wantErrOut: "someone/REPO already exists",
},
{
name: "repo arg nontty clone arg",
opts: &ForkOptions{
Repository: "OWNER/REPO",
Clone: true,
},
httpStubs: forkPost,
execStubs: func(cs *run.CommandStubber) {
cs.Register(`git clone https://github.com/someone
/REPO\.git`, 0, "")
cs.Register(`git -C REPO remote add -f upstream h
ttps://github\.com/OWNER/REPO\.git`, 0, "")
},
}, },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defer stubSince(2 * time.Second)()
reg := &httpmock.Registry{}
reg.Register(
httpmock.REST("POST", "repos/OWNER/REPO/forks"),
func(req *http.Request) (*http.Response, error) {
bb, err := ioutil.ReadAll(req.Body)
if err != nil {
return nil, err
}
assert.Equal(t, tt.postBody, string(bb))
return &http.Response{
Request: req,
StatusCode: 200,
Body: ioutil.NopCloser(byte
s.NewBufferString(tt.responseBody)),
}, nil
})
httpClient := &http.Client{Transport: reg}
output, err := runCommand(httpClient, nil, true, tt.args)
assert.NoError(t, err)
assert.Equal(t, "", output.String())
assert.Equal(t, tt.wantStderr, output.Stderr())
reg.Verify(t)
})
}
}
func TestRepoFork_in_parent_yes(t *testing.T) {
defer stubSince(2 * time.Second)()
reg := &httpmock.Registry{}
defer reg.StubWithFixturePath(200, "./forkResult.json")()
httpClient := &http.Client{Transport: reg}
cs, restore := run.Stub()
defer restore(t)
cs.Register(`git remote add -f fork https://github\.com/someone/REPO\.git
`, 0, "")
output, err := runCommand(httpClient, nil, true, "--remote --remote-name=
fork")
if err != nil {
t.Errorf("error running command `repo fork`: %v", err)
}
assert.Equal(t, "", output.String())
//nolint:staticcheck // prefer exact matchers over ExpectLines
test.ExpectLines(t, output.Stderr(),
"Created fork.*someone/REPO",
"Added remote.*fork")
reg.Verify(t)
}
func TestRepoFork_outside_yes(t *testing.T) {
defer stubSince(2 * time.Second)()
reg := &httpmock.Registry{}
defer reg.StubWithFixturePath(200, "./forkResult.json")()
httpClient := &http.Client{Transport: reg}
cs, restore := run.Stub()
defer restore(t)
cs.Register(`git clone https://github\.com/someone/REPO\.git`, 0, "")
cs.Register(`git -C REPO remote add -f upstream https://github\.com/OWNER
/REPO\.git`, 0, "")
output, err := runCommand(httpClient, nil, true, "--clone OWNER/REPO")
if err != nil {
t.Errorf("error running command `repo fork`: %v", err)
}
assert.Equal(t, "", output.String())
//nolint:staticcheck // prefer exact matchers over ExpectLines
test.ExpectLines(t, output.Stderr(),
"Created fork.*someone/REPO",
"Cloned fork")
reg.Verify(t)
}
func TestRepoFork_ForkAlreadyExistsAndCloneNonTty(t *testing.T) {
defer stubSince(2 * time.Minute)()
reg := &httpmock.Registry{}
defer reg.StubWithFixturePath(200, "./forkResult.json")()
httpClient := &http.Client{Transport: reg}
cs, restore := run.Stub()
defer restore(t)
cs.Register(`git clone https://github\.com/someone/REPO\.git`, 0, "")
cs.Register(`git -C REPO remote add -f upstream https://github\.com/OWNER
/REPO\.git`, 0, "")
output, err := runCommand(httpClient, nil, false, "--clone OWNER/REPO")
if err != nil {
t.Errorf("error running command `repo fork`: %v", err)
}
assert.Equal(t, "", output.String())
//nolint:staticcheck // prefer exact matchers over ExpectLines
test.ExpectLines(t, output.Stderr(),
"someone/REPO.*already exists")
reg.Verify(t)
}
func TestRepoFork_outside_survey_yes(t *testing.T) {
defer stubSince(2 * time.Second)()
reg := &httpmock.Registry{}
defer reg.StubWithFixturePath(200, "./forkResult.json")()
httpClient := &http.Client{Transport: reg}
cs, restore := run.Stub()
defer restore(t)
cs.Register(`git clone https://github\.com/someone/REPO\.git`, 0, "")
cs.Register(`git -C REPO remote add -f upstream https://github\.com/OWNER
/REPO\.git`, 0, "")
defer prompt.StubConfirm(true)()
output, err := runCommand(httpClient, nil, true, "OWNER/REPO")
if err != nil {
t.Errorf("error running command `repo fork`: %v", err)
}
assert.Equal(t, "", output.String())
//nolint:staticcheck // prefer exact matchers over ExpectLines
test.ExpectLines(t, output.Stderr(),
"Created fork.*someone/REPO",
"Cloned fork")
reg.Verify(t)
}
func TestRepoFork_outside_survey_no(t *testing.T) {
defer stubSince(2 * time.Second)()
reg := &httpmock.Registry{}
defer reg.StubWithFixturePath(200, "./forkResult.json")()
httpClient := &http.Client{Transport: reg}
_, restore := run.Stub()
defer restore(t)
defer prompt.StubConfirm(false)()
output, err := runCommand(httpClient, nil, true, "OWNER/REPO")
if err != nil {
t.Errorf("error running command `repo fork`: %v", err)
}
assert.Equal(t, "", output.String())
r := regexp.MustCompile(`Created fork.*someone/REPO`)
if !r.MatchString(output.Stderr()) {
t.Errorf("output did not match regexp /%s/\n> output\n%s\n", r, o
utput)
return
}
reg.Verify(t)
}
func TestRepoFork_in_parent_survey_yes(t *testing.T) {
reg := &httpmock.Registry{}
defer reg.StubWithFixturePath(200, "./forkResult.json")()
httpClient := &http.Client{Transport: reg}
defer stubSince(2 * time.Second)()
cs, restore := run.Stub()
defer restore(t)
cs.Register(`git remote add -f fork https://github\.com/someone/REPO\.git
`, 0, "")
defer prompt.StubConfirm(true)()
output, err := runCommand(httpClient, nil, true, "--remote-name=fork")
if err != nil {
t.Errorf("error running command `repo fork`: %v", err)
}
assert.Equal(t, "", output.String())
//nolint:staticcheck // prefer exact matchers over ExpectLines
test.ExpectLines(t, output.Stderr(),
"Created fork.*someone/REPO",
"Added remote.*fork")
reg.Verify(t)
}
func TestRepoFork_in_parent_survey_no(t *testing.T) {
reg := &httpmock.Registry{}
defer reg.Verify(t)
defer reg.StubWithFixturePath(200, "./forkResult.json")()
httpClient := &http.Client{Transport: reg}
defer stubSince(2 * time.Second)()
_, restore := run.Stub()
defer restore(t)
defer prompt.StubConfirm(false)()
output, err := runCommand(httpClient, nil, true, "")
if err != nil {
t.Errorf("error running command `repo fork`: %v", err)
}
assert.Equal(t, "", output.String())
r := regexp.MustCompile(`Created fork.*someone/REPO`)
if !r.MatchString(output.Stderr()) {
t.Errorf("output did not match regexp /%s/\n> output\n%s\n", r, o
utput)
return
}
}
func Test_RepoFork_gitFlags(t *testing.T) {
defer stubSince(2 * time.Second)()
reg := &httpmock.Registry{}
defer reg.StubWithFixturePath(200, "./forkResult.json")()
httpClient := &http.Client{Transport: reg}
cs, cmdTeardown := run.Stub()
defer cmdTeardown(t)
cs.Register(`git clone --depth 1 https://github.com/someone/REPO.git`, 0,
"")
cs.Register(`git -C REPO remote add -f upstream https://github.com/OWNER/
REPO.git`, 0, "")
output, err := runCommand(httpClient, nil, false, "--clone OWNER/REPO --
--depth 1")
if err != nil {
t.Errorf("error running command `repo fork`: %v", err)
} }
assert.Equal(t, "", output.String()) for _, tt := range tests {
assert.Equal(t, output.Stderr(), "") io, _, stdout, stderr := iostreams.Test()
reg.Verify(t) io.SetStdinTTY(tt.tty)
} io.SetStdoutTTY(tt.tty)
io.SetStderrTTY(tt.tty)
tt.opts.IO = io
func Test_RepoFork_flagError(t *testing.T) { tt.opts.BaseRepo = func() (ghrepo.Interface, error) {
_, err := runCommand(nil, nil, true, "--depth 1 OWNER/REPO") return ghrepo.New("OWNER", "REPO"), nil
if err == nil || err.Error() != "unknown flag: --depth\nSeparate git clon }
e flags with '--'." {
t.Errorf("unexpected error %v", err)
}
}
func TestRepoFork_in_parent_match_protocol(t *testing.T) { reg := &httpmock.Registry{}
defer stubSince(2 * time.Second)() if tt.httpStubs != nil {
reg := &httpmock.Registry{} tt.httpStubs(reg)
defer reg.Verify(t) }
defer reg.StubWithFixturePath(200, "./forkResult.json")() tt.opts.HttpClient = func() (*http.Client, error) {
httpClient := &http.Client{Transport: reg} return &http.Client{Transport: reg}, nil
}
cs, restore := run.Stub()
defer restore(t) cfg := config.NewBlankConfig()
tt.opts.Config = func() (config.Config, error) {
cs.Register(`git remote add -f fork git@github\.com:someone/REPO\.git`, 0 return cfg, nil
, "") }
remotes := []*context.Remote{
{
Remote: &git.Remote{Name: "origin", PushURL: &url.URL{
Scheme: "ssh",
}},
Repo: ghrepo.New("OWNER", "REPO"),
},
}
output, err := runCommand(httpClient, remotes, true, "--remote --remote-n tt.opts.Remotes = func() (context.Remotes, error) {
ame=fork") if tt.remotes == nil {
if err != nil { return []*context.Remote{
t.Errorf("error running command `repo fork`: %v", err) {
} Remote: &git.Remote{
Name: "origin",
FetchURL: &url.URL{},
},
Repo: ghrepo.New("OWNER", "REPO")
,
},
}, nil
}
return tt.remotes, nil
}
assert.Equal(t, "", output.String()) as, teardown := prompt.InitAskStubber()
defer teardown()
if tt.askStubs != nil {
tt.askStubs(as)
}
cs, restoreRun := run.Stub()
defer restoreRun(t)
if tt.execStubs != nil {
tt.execStubs(cs)
}
//nolint:staticcheck // prefer exact matchers over ExpectLines t.Run(tt.name, func(t *testing.T) {
test.ExpectLines(t, output.Stderr(), if tt.opts.Since == nil {
"Created fork.*someone/REPO", tt.opts.Since = func(t time.Time) time.Duration {
"Added remote.*fork") return 2 * time.Second
} }
}
defer reg.Verify(t)
err := forkRun(tt.opts)
if tt.wantErr {
assert.Error(t, err)
assert.Equal(t, tt.errMsg, err.Error())
return
}
func stubSince(d time.Duration) func() { assert.NoError(t, err)
originalSince := Since assert.Equal(t, tt.wantOut, stdout.String())
Since = func(t time.Time) time.Duration { assert.Equal(t, tt.wantErrOut, stderr.String())
return d })
}
return func() {
Since = originalSince
} }
} }
 End of changes. 31 change blocks. 
594 lines changed or deleted 465 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)