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

     1  package clone
     2  
     3  import (
     4  	"net/http"
     5  	"strings"
     6  	"testing"
     7  
     8  	"github.com/secman-team/gh-api/core/config"
     9  	"github.com/secman-team/gh-api/core/run"
    10  	"github.com/secman-team/gh-api/pkg/cmdutil"
    11  	"github.com/secman-team/gh-api/pkg/httpmock"
    12  	"github.com/secman-team/gh-api/pkg/iostreams"
    13  	"github.com/secman-team/gh-api/test"
    14  	"github.com/google/shlex"
    15  	"github.com/stretchr/testify/assert"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  func TestNewCmdClone(t *testing.T) {
    20  	testCases := []struct {
    21  		name     string
    22  		args     string
    23  		wantOpts CloneOptions
    24  		wantErr  string
    25  	}{
    26  		{
    27  			name:    "no arguments",
    28  			args:    "",
    29  			wantErr: "cannot clone: repository argument required",
    30  		},
    31  		{
    32  			name: "repo argument",
    33  			args: "OWNER/REPO",
    34  			wantOpts: CloneOptions{
    35  				Repository: "OWNER/REPO",
    36  				GitArgs:    []string{},
    37  			},
    38  		},
    39  		{
    40  			name: "directory argument",
    41  			args: "OWNER/REPO mydir",
    42  			wantOpts: CloneOptions{
    43  				Repository: "OWNER/REPO",
    44  				GitArgs:    []string{"mydir"},
    45  			},
    46  		},
    47  		{
    48  			name: "git clone arguments",
    49  			args: "OWNER/REPO -- --depth 1 --recurse-submodules",
    50  			wantOpts: CloneOptions{
    51  				Repository: "OWNER/REPO",
    52  				GitArgs:    []string{"--depth", "1", "--recurse-submodules"},
    53  			},
    54  		},
    55  		{
    56  			name:    "unknown argument",
    57  			args:    "OWNER/REPO --depth 1",
    58  			wantErr: "unknown flag: --depth\nSeparate git clone flags with '--'.",
    59  		},
    60  	}
    61  	for _, tt := range testCases {
    62  		t.Run(tt.name, func(t *testing.T) {
    63  			io, stdin, stdout, stderr := iostreams.Test()
    64  			fac := &cmdutil.Factory{IOStreams: io}
    65  
    66  			var opts *CloneOptions
    67  			cmd := NewCmdClone(fac, func(co *CloneOptions) error {
    68  				opts = co
    69  				return nil
    70  			})
    71  
    72  			argv, err := shlex.Split(tt.args)
    73  			require.NoError(t, err)
    74  			cmd.SetArgs(argv)
    75  
    76  			cmd.SetIn(stdin)
    77  			cmd.SetOut(stdout)
    78  			cmd.SetErr(stderr)
    79  
    80  			_, err = cmd.ExecuteC()
    81  			if tt.wantErr != "" {
    82  				assert.EqualError(t, err, tt.wantErr)
    83  				return
    84  			} else {
    85  				assert.NoError(t, err)
    86  			}
    87  
    88  			assert.Equal(t, "", stdout.String())
    89  			assert.Equal(t, "", stderr.String())
    90  
    91  			assert.Equal(t, tt.wantOpts.Repository, opts.Repository)
    92  			assert.Equal(t, tt.wantOpts.GitArgs, opts.GitArgs)
    93  		})
    94  	}
    95  }
    96  
    97  func runCloneCommand(httpClient *http.Client, cli string) (*test.CmdOut, error) {
    98  	io, stdin, stdout, stderr := iostreams.Test()
    99  	fac := &cmdutil.Factory{
   100  		IOStreams: io,
   101  		HttpClient: func() (*http.Client, error) {
   102  			return httpClient, nil
   103  		},
   104  		Config: func() (config.Config, error) {
   105  			return config.NewBlankConfig(), nil
   106  		},
   107  	}
   108  
   109  	cmd := NewCmdClone(fac, nil)
   110  
   111  	argv, err := shlex.Split(cli)
   112  	cmd.SetArgs(argv)
   113  
   114  	cmd.SetIn(stdin)
   115  	cmd.SetOut(stdout)
   116  	cmd.SetErr(stderr)
   117  
   118  	if err != nil {
   119  		panic(err)
   120  	}
   121  
   122  	_, err = cmd.ExecuteC()
   123  
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  
   128  	return &test.CmdOut{OutBuf: stdout, ErrBuf: stderr}, nil
   129  }
   130  
   131  func Test_RepoClone(t *testing.T) {
   132  	tests := []struct {
   133  		name string
   134  		args string
   135  		want string
   136  	}{
   137  		{
   138  			name: "shorthand",
   139  			args: "OWNER/REPO",
   140  			want: "git clone https://github.com/OWNER/REPO.git",
   141  		},
   142  		{
   143  			name: "shorthand with directory",
   144  			args: "OWNER/REPO target_directory",
   145  			want: "git clone https://github.com/OWNER/REPO.git target_directory",
   146  		},
   147  		{
   148  			name: "clone arguments",
   149  			args: "OWNER/REPO -- -o upstream --depth 1",
   150  			want: "git clone -o upstream --depth 1 https://github.com/OWNER/REPO.git",
   151  		},
   152  		{
   153  			name: "clone arguments with directory",
   154  			args: "OWNER/REPO target_directory -- -o upstream --depth 1",
   155  			want: "git clone -o upstream --depth 1 https://github.com/OWNER/REPO.git target_directory",
   156  		},
   157  		{
   158  			name: "HTTPS URL",
   159  			args: "https://github.com/OWNER/REPO",
   160  			want: "git clone https://github.com/OWNER/REPO.git",
   161  		},
   162  		{
   163  			name: "SSH URL",
   164  			args: "git@github.com:OWNER/REPO.git",
   165  			want: "git clone git@github.com:OWNER/REPO.git",
   166  		},
   167  		{
   168  			name: "Non-canonical capitalization",
   169  			args: "Owner/Repo",
   170  			want: "git clone https://github.com/OWNER/REPO.git",
   171  		},
   172  		{
   173  			name: "clone wiki",
   174  			args: "Owner/Repo.wiki",
   175  			want: "git clone https://github.com/OWNER/REPO.wiki.git",
   176  		},
   177  		{
   178  			name: "wiki URL",
   179  			args: "https://github.com/owner/repo.wiki",
   180  			want: "git clone https://github.com/OWNER/REPO.wiki.git",
   181  		},
   182  	}
   183  	for _, tt := range tests {
   184  		t.Run(tt.name, func(t *testing.T) {
   185  			reg := &httpmock.Registry{}
   186  			defer reg.Verify(t)
   187  			reg.Register(
   188  				httpmock.GraphQL(`query RepositoryInfo\b`),
   189  				httpmock.StringResponse(`
   190  				{ "data": { "repository": {
   191  					"name": "REPO",
   192  					"owner": {
   193  						"login": "OWNER"
   194  					},
   195  					"hasWikiEnabled": true
   196  				} } }
   197  				`))
   198  
   199  			httpClient := &http.Client{Transport: reg}
   200  
   201  			cs, restore := run.Stub()
   202  			defer restore(t)
   203  			cs.Register(`git clone`, 0, "", func(s []string) {
   204  				assert.Equal(t, tt.want, strings.Join(s, " "))
   205  			})
   206  
   207  			output, err := runCloneCommand(httpClient, tt.args)
   208  			if err != nil {
   209  				t.Fatalf("error running command `repo clone`: %v", err)
   210  			}
   211  
   212  			assert.Equal(t, "", output.String())
   213  			assert.Equal(t, "", output.Stderr())
   214  		})
   215  	}
   216  }
   217  
   218  func Test_RepoClone_hasParent(t *testing.T) {
   219  	reg := &httpmock.Registry{}
   220  	reg.Register(
   221  		httpmock.GraphQL(`query RepositoryInfo\b`),
   222  		httpmock.StringResponse(`
   223  				{ "data": { "repository": {
   224  					"name": "REPO",
   225  					"owner": {
   226  						"login": "OWNER"
   227  					},
   228  					"parent": {
   229  						"name": "ORIG",
   230  						"owner": {
   231  							"login": "hubot"
   232  						},
   233  						"defaultBranchRef": {
   234  							"name": "trunk"
   235  						}
   236  					}
   237  				} } }
   238  				`))
   239  
   240  	httpClient := &http.Client{Transport: reg}
   241  
   242  	cs, cmdTeardown := run.Stub()
   243  	defer cmdTeardown(t)
   244  
   245  	cs.Register(`git clone https://github.com/OWNER/REPO.git`, 0, "")
   246  	cs.Register(`git -C REPO remote add -t trunk -f upstream https://github.com/hubot/ORIG.git`, 0, "")
   247  
   248  	_, err := runCloneCommand(httpClient, "OWNER/REPO")
   249  	if err != nil {
   250  		t.Fatalf("error running command `repo clone`: %v", err)
   251  	}
   252  }
   253  
   254  func Test_RepoClone_withoutUsername(t *testing.T) {
   255  	reg := &httpmock.Registry{}
   256  	defer reg.Verify(t)
   257  	reg.Register(
   258  		httpmock.GraphQL(`query UserCurrent\b`),
   259  		httpmock.StringResponse(`
   260  		{ "data": { "viewer": {
   261  			"login": "OWNER"
   262  		}}}`))
   263  	reg.Register(
   264  		httpmock.GraphQL(`query RepositoryInfo\b`),
   265  		httpmock.StringResponse(`
   266  				{ "data": { "repository": {
   267  					"name": "REPO",
   268  					"owner": {
   269  						"login": "OWNER"
   270  					}
   271  				} } }
   272  				`))
   273  
   274  	httpClient := &http.Client{Transport: reg}
   275  
   276  	cs, restore := run.Stub()
   277  	defer restore(t)
   278  	cs.Register(`git clone https://github\.com/OWNER/REPO\.git`, 0, "")
   279  
   280  	output, err := runCloneCommand(httpClient, "REPO")
   281  	if err != nil {
   282  		t.Fatalf("error running command `repo clone`: %v", err)
   283  	}
   284  
   285  	assert.Equal(t, "", output.String())
   286  	assert.Equal(t, "", output.Stderr())
   287  }