github.com/abdfnx/gh-api@v0.0.0-20210414084727-f5432eec23b8/pkg/cmd/repo/list/list_test.go (about)

     1  package list
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"net/http"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/MakeNowJust/heredoc"
    11  	"github.com/abdfnx/gh-api/internal/config"
    12  	"github.com/abdfnx/gh-api/pkg/cmdutil"
    13  	"github.com/abdfnx/gh-api/pkg/httpmock"
    14  	"github.com/abdfnx/gh-api/pkg/iostreams"
    15  	"github.com/abdfnx/gh-api/test"
    16  	"github.com/google/shlex"
    17  	"github.com/stretchr/testify/assert"
    18  	"github.com/stretchr/testify/require"
    19  )
    20  
    21  func TestNewCmdList(t *testing.T) {
    22  	tests := []struct {
    23  		name     string
    24  		cli      string
    25  		wants    ListOptions
    26  		wantsErr string
    27  	}{
    28  		{
    29  			name: "no arguments",
    30  			cli:  "",
    31  			wants: ListOptions{
    32  				Limit:       30,
    33  				Owner:       "",
    34  				Visibility:  "",
    35  				Fork:        false,
    36  				Source:      false,
    37  				Language:    "",
    38  				Archived:    false,
    39  				NonArchived: false,
    40  			},
    41  		},
    42  		{
    43  			name: "with owner",
    44  			cli:  "monalisa",
    45  			wants: ListOptions{
    46  				Limit:       30,
    47  				Owner:       "monalisa",
    48  				Visibility:  "",
    49  				Fork:        false,
    50  				Source:      false,
    51  				Language:    "",
    52  				Archived:    false,
    53  				NonArchived: false,
    54  			},
    55  		},
    56  		{
    57  			name: "with limit",
    58  			cli:  "-L 101",
    59  			wants: ListOptions{
    60  				Limit:       101,
    61  				Owner:       "",
    62  				Visibility:  "",
    63  				Fork:        false,
    64  				Source:      false,
    65  				Language:    "",
    66  				Archived:    false,
    67  				NonArchived: false,
    68  			},
    69  		},
    70  		{
    71  			name: "only public",
    72  			cli:  "--public",
    73  			wants: ListOptions{
    74  				Limit:       30,
    75  				Owner:       "",
    76  				Visibility:  "public",
    77  				Fork:        false,
    78  				Source:      false,
    79  				Language:    "",
    80  				Archived:    false,
    81  				NonArchived: false,
    82  			},
    83  		},
    84  		{
    85  			name: "only private",
    86  			cli:  "--private",
    87  			wants: ListOptions{
    88  				Limit:       30,
    89  				Owner:       "",
    90  				Visibility:  "private",
    91  				Fork:        false,
    92  				Source:      false,
    93  				Language:    "",
    94  				Archived:    false,
    95  				NonArchived: false,
    96  			},
    97  		},
    98  		{
    99  			name: "only forks",
   100  			cli:  "--fork",
   101  			wants: ListOptions{
   102  				Limit:       30,
   103  				Owner:       "",
   104  				Visibility:  "",
   105  				Fork:        true,
   106  				Source:      false,
   107  				Language:    "",
   108  				Archived:    false,
   109  				NonArchived: false,
   110  			},
   111  		},
   112  		{
   113  			name: "only sources",
   114  			cli:  "--source",
   115  			wants: ListOptions{
   116  				Limit:       30,
   117  				Owner:       "",
   118  				Visibility:  "",
   119  				Fork:        false,
   120  				Source:      true,
   121  				Language:    "",
   122  				Archived:    false,
   123  				NonArchived: false,
   124  			},
   125  		},
   126  		{
   127  			name: "with language",
   128  			cli:  "-l go",
   129  			wants: ListOptions{
   130  				Limit:       30,
   131  				Owner:       "",
   132  				Visibility:  "",
   133  				Fork:        false,
   134  				Source:      false,
   135  				Language:    "go",
   136  				Archived:    false,
   137  				NonArchived: false,
   138  			},
   139  		},
   140  		{
   141  			name: "only archived",
   142  			cli:  "--archived",
   143  			wants: ListOptions{
   144  				Limit:       30,
   145  				Owner:       "",
   146  				Visibility:  "",
   147  				Fork:        false,
   148  				Source:      false,
   149  				Language:    "",
   150  				Archived:    true,
   151  				NonArchived: false,
   152  			},
   153  		},
   154  		{
   155  			name: "only non-archived",
   156  			cli:  "--no-archived",
   157  			wants: ListOptions{
   158  				Limit:       30,
   159  				Owner:       "",
   160  				Visibility:  "",
   161  				Fork:        false,
   162  				Source:      false,
   163  				Language:    "",
   164  				Archived:    false,
   165  				NonArchived: true,
   166  			},
   167  		},
   168  		{
   169  			name:     "no public and private",
   170  			cli:      "--public --private",
   171  			wantsErr: "specify only one of `--public` or `--private`",
   172  		},
   173  		{
   174  			name:     "no forks with sources",
   175  			cli:      "--fork --source",
   176  			wantsErr: "specify only one of `--source` or `--fork`",
   177  		},
   178  		{
   179  			name:     "conflicting archived",
   180  			cli:      "--archived --no-archived",
   181  			wantsErr: "specify only one of `--archived` or `--no-archived`",
   182  		},
   183  		{
   184  			name:     "too many arguments",
   185  			cli:      "monalisa hubot",
   186  			wantsErr: "accepts at most 1 arg(s), received 2",
   187  		},
   188  		{
   189  			name:     "invalid limit",
   190  			cli:      "-L 0",
   191  			wantsErr: "invalid limit: 0",
   192  		},
   193  	}
   194  
   195  	for _, tt := range tests {
   196  		t.Run(tt.name, func(t *testing.T) {
   197  			f := &cmdutil.Factory{}
   198  
   199  			argv, err := shlex.Split(tt.cli)
   200  			assert.NoError(t, err)
   201  
   202  			var gotOpts *ListOptions
   203  			cmd := NewCmdList(f, func(opts *ListOptions) error {
   204  				gotOpts = opts
   205  				return nil
   206  			})
   207  			cmd.SetArgs(argv)
   208  			cmd.SetIn(&bytes.Buffer{})
   209  			cmd.SetOut(&bytes.Buffer{})
   210  			cmd.SetErr(&bytes.Buffer{})
   211  
   212  			_, err = cmd.ExecuteC()
   213  			if tt.wantsErr != "" {
   214  				assert.EqualError(t, err, tt.wantsErr)
   215  				return
   216  			}
   217  			require.NoError(t, err)
   218  
   219  			assert.Equal(t, tt.wants.Limit, gotOpts.Limit)
   220  			assert.Equal(t, tt.wants.Owner, gotOpts.Owner)
   221  			assert.Equal(t, tt.wants.Visibility, gotOpts.Visibility)
   222  			assert.Equal(t, tt.wants.Fork, gotOpts.Fork)
   223  			assert.Equal(t, tt.wants.Source, gotOpts.Source)
   224  			assert.Equal(t, tt.wants.Archived, gotOpts.Archived)
   225  			assert.Equal(t, tt.wants.NonArchived, gotOpts.NonArchived)
   226  		})
   227  	}
   228  }
   229  
   230  func runCommand(rt http.RoundTripper, isTTY bool, cli string) (*test.CmdOut, error) {
   231  	io, _, stdout, stderr := iostreams.Test()
   232  	io.SetStdoutTTY(isTTY)
   233  	io.SetStdinTTY(isTTY)
   234  	io.SetStderrTTY(isTTY)
   235  
   236  	factory := &cmdutil.Factory{
   237  		IOStreams: io,
   238  		HttpClient: func() (*http.Client, error) {
   239  			return &http.Client{Transport: rt}, nil
   240  		},
   241  		Config: func() (config.Config, error) {
   242  			return config.NewBlankConfig(), nil
   243  		},
   244  	}
   245  
   246  	cmd := NewCmdList(factory, nil)
   247  
   248  	argv, err := shlex.Split(cli)
   249  	if err != nil {
   250  		return nil, err
   251  	}
   252  	cmd.SetArgs(argv)
   253  
   254  	cmd.SetIn(&bytes.Buffer{})
   255  	cmd.SetOut(ioutil.Discard)
   256  	cmd.SetErr(ioutil.Discard)
   257  
   258  	_, err = cmd.ExecuteC()
   259  	return &test.CmdOut{
   260  		OutBuf: stdout,
   261  		ErrBuf: stderr,
   262  	}, err
   263  }
   264  
   265  func TestRepoList_nontty(t *testing.T) {
   266  	io, _, stdout, stderr := iostreams.Test()
   267  	io.SetStdoutTTY(false)
   268  	io.SetStdinTTY(false)
   269  	io.SetStderrTTY(false)
   270  
   271  	httpReg := &httpmock.Registry{}
   272  	defer httpReg.Verify(t)
   273  
   274  	httpReg.Register(
   275  		httpmock.GraphQL(`query RepositoryList\b`),
   276  		httpmock.FileResponse("./fixtures/repoList.json"),
   277  	)
   278  
   279  	opts := ListOptions{
   280  		IO: io,
   281  		HttpClient: func() (*http.Client, error) {
   282  			return &http.Client{Transport: httpReg}, nil
   283  		},
   284  		Config: func() (config.Config, error) {
   285  			return config.NewBlankConfig(), nil
   286  		},
   287  		Now: func() time.Time {
   288  			t, _ := time.Parse(time.RFC822, "19 Feb 21 15:00 UTC")
   289  			return t
   290  		},
   291  		Limit: 30,
   292  	}
   293  
   294  	err := listRun(&opts)
   295  	assert.NoError(t, err)
   296  
   297  	assert.Equal(t, "", stderr.String())
   298  
   299  	assert.Equal(t, heredoc.Doc(`
   300  		octocat/hello-world	My first repository	public	2021-02-19T06:34:58Z
   301  		octocat/cli	GitHub CLI	public, fork	2021-02-19T06:06:06Z
   302  		octocat/testing		private	2021-02-11T22:32:05Z
   303  	`), stdout.String())
   304  }
   305  
   306  func TestRepoList_tty(t *testing.T) {
   307  	io, _, stdout, stderr := iostreams.Test()
   308  	io.SetStdoutTTY(true)
   309  	io.SetStdinTTY(true)
   310  	io.SetStderrTTY(true)
   311  
   312  	httpReg := &httpmock.Registry{}
   313  	defer httpReg.Verify(t)
   314  
   315  	httpReg.Register(
   316  		httpmock.GraphQL(`query RepositoryList\b`),
   317  		httpmock.FileResponse("./fixtures/repoList.json"),
   318  	)
   319  
   320  	opts := ListOptions{
   321  		IO: io,
   322  		HttpClient: func() (*http.Client, error) {
   323  			return &http.Client{Transport: httpReg}, nil
   324  		},
   325  		Config: func() (config.Config, error) {
   326  			return config.NewBlankConfig(), nil
   327  		},
   328  		Now: func() time.Time {
   329  			t, _ := time.Parse(time.RFC822, "19 Feb 21 15:00 UTC")
   330  			return t
   331  		},
   332  		Limit: 30,
   333  	}
   334  
   335  	err := listRun(&opts)
   336  	assert.NoError(t, err)
   337  
   338  	assert.Equal(t, "", stderr.String())
   339  
   340  	assert.Equal(t, heredoc.Doc(`
   341  
   342  		Showing 3 of 3 repositories in @octocat
   343  
   344  		octocat/hello-world  My first repository  public        8h
   345  		octocat/cli          GitHub CLI           public, fork  8h
   346  		octocat/testing                           private       7d
   347  	`), stdout.String())
   348  }
   349  
   350  func TestRepoList_filtering(t *testing.T) {
   351  	http := &httpmock.Registry{}
   352  	defer http.Verify(t)
   353  
   354  	http.Register(
   355  		httpmock.GraphQL(`query RepositoryList\b`),
   356  		httpmock.GraphQLQuery(`{}`, func(_ string, params map[string]interface{}) {
   357  			assert.Equal(t, "PRIVATE", params["privacy"])
   358  			assert.Equal(t, float64(2), params["perPage"])
   359  		}),
   360  	)
   361  
   362  	output, err := runCommand(http, true, `--private --limit 2 `)
   363  	if err != nil {
   364  		t.Fatal(err)
   365  	}
   366  
   367  	assert.Equal(t, "", output.Stderr())
   368  	assert.Equal(t, "\nNo results match your search\n\n", output.String())
   369  }