github.com/andrewhsu/cli/v2@v2.0.1-0.20210910131313-d4b4061f5b89/pkg/cmd/gist/list/list_test.go (about)

     1  package list
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"net/http"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/MakeNowJust/heredoc"
    11  	"github.com/andrewhsu/cli/v2/internal/config"
    12  	"github.com/andrewhsu/cli/v2/pkg/cmdutil"
    13  	"github.com/andrewhsu/cli/v2/pkg/httpmock"
    14  	"github.com/andrewhsu/cli/v2/pkg/iostreams"
    15  	"github.com/google/shlex"
    16  	"github.com/stretchr/testify/assert"
    17  )
    18  
    19  func TestNewCmdList(t *testing.T) {
    20  	tests := []struct {
    21  		name  string
    22  		cli   string
    23  		wants ListOptions
    24  	}{
    25  		{
    26  			name: "no arguments",
    27  			wants: ListOptions{
    28  				Limit:      10,
    29  				Visibility: "all",
    30  			},
    31  		},
    32  		{
    33  			name: "public",
    34  			cli:  "--public",
    35  			wants: ListOptions{
    36  				Limit:      10,
    37  				Visibility: "public",
    38  			},
    39  		},
    40  		{
    41  			name: "secret",
    42  			cli:  "--secret",
    43  			wants: ListOptions{
    44  				Limit:      10,
    45  				Visibility: "secret",
    46  			},
    47  		},
    48  		{
    49  			name: "secret with explicit false value",
    50  			cli:  "--secret=false",
    51  			wants: ListOptions{
    52  				Limit:      10,
    53  				Visibility: "all",
    54  			},
    55  		},
    56  		{
    57  			name: "public and secret",
    58  			cli:  "--secret --public",
    59  			wants: ListOptions{
    60  				Limit:      10,
    61  				Visibility: "secret",
    62  			},
    63  		},
    64  		{
    65  			name: "limit",
    66  			cli:  "--limit 30",
    67  			wants: ListOptions{
    68  				Limit:      30,
    69  				Visibility: "all",
    70  			},
    71  		},
    72  	}
    73  
    74  	for _, tt := range tests {
    75  		t.Run(tt.name, func(t *testing.T) {
    76  			f := &cmdutil.Factory{}
    77  
    78  			argv, err := shlex.Split(tt.cli)
    79  			assert.NoError(t, err)
    80  
    81  			var gotOpts *ListOptions
    82  			cmd := NewCmdList(f, func(opts *ListOptions) error {
    83  				gotOpts = opts
    84  				return nil
    85  			})
    86  			cmd.SetArgs(argv)
    87  			cmd.SetIn(&bytes.Buffer{})
    88  			cmd.SetOut(&bytes.Buffer{})
    89  			cmd.SetErr(&bytes.Buffer{})
    90  
    91  			_, err = cmd.ExecuteC()
    92  			assert.NoError(t, err)
    93  
    94  			assert.Equal(t, tt.wants.Visibility, gotOpts.Visibility)
    95  			assert.Equal(t, tt.wants.Limit, gotOpts.Limit)
    96  		})
    97  	}
    98  }
    99  
   100  func Test_listRun(t *testing.T) {
   101  	const query = `query GistList\b`
   102  	sixHours, _ := time.ParseDuration("6h")
   103  	sixHoursAgo := time.Now().Add(-sixHours)
   104  	absTime, _ := time.Parse(time.RFC3339, "2020-07-30T15:24:28Z")
   105  
   106  	tests := []struct {
   107  		name    string
   108  		opts    *ListOptions
   109  		wantOut string
   110  		stubs   func(*httpmock.Registry)
   111  		nontty  bool
   112  	}{
   113  		{
   114  			name: "no gists",
   115  			opts: &ListOptions{},
   116  			stubs: func(reg *httpmock.Registry) {
   117  				reg.Register(
   118  					httpmock.GraphQL(query),
   119  					httpmock.StringResponse(`{ "data": { "viewer": {
   120  						"gists": { "nodes": [] }
   121  					} } }`))
   122  			},
   123  			wantOut: "",
   124  		},
   125  		{
   126  			name: "default behavior",
   127  			opts: &ListOptions{},
   128  			stubs: func(reg *httpmock.Registry) {
   129  				reg.Register(
   130  					httpmock.GraphQL(query),
   131  					httpmock.StringResponse(fmt.Sprintf(
   132  						`{ "data": { "viewer": { "gists": { "nodes": [
   133  							{
   134  								"name": "1234567890",
   135  								"files": [{ "name": "cool.txt" }],
   136  								"description": "",
   137  								"updatedAt": "%[1]v",
   138  								"isPublic": true
   139  							},
   140  							{
   141  								"name": "4567890123",
   142  								"files": [{ "name": "gistfile0.txt" }],
   143  								"description": "",
   144  								"updatedAt": "%[1]v",
   145  								"isPublic": true
   146  							},
   147  							{
   148  								"name": "2345678901",
   149  								"files": [
   150  									{ "name": "gistfile0.txt" },
   151  									{ "name": "gistfile1.txt" }
   152  								],
   153  								"description": "tea leaves thwart those who court catastrophe",
   154  								"updatedAt": "%[1]v",
   155  								"isPublic": false
   156  							},
   157  							{
   158  								"name": "3456789012",
   159  								"files": [
   160  									{ "name": "gistfile0.txt" },
   161  									{ "name": "gistfile1.txt" },
   162  									{ "name": "gistfile2.txt" },
   163  									{ "name": "gistfile3.txt" },
   164  									{ "name": "gistfile4.txt" },
   165  									{ "name": "gistfile5.txt" },
   166  									{ "name": "gistfile6.txt" },
   167  									{ "name": "gistfile7.txt" },
   168  									{ "name": "gistfile9.txt" },
   169  									{ "name": "gistfile10.txt" },
   170  									{ "name": "gistfile11.txt" }
   171  								],
   172  								"description": "short desc",
   173  								"updatedAt": "%[1]v",
   174  								"isPublic": false
   175  							}
   176  						] } } } }`,
   177  						sixHoursAgo.Format(time.RFC3339),
   178  					)),
   179  				)
   180  			},
   181  			wantOut: heredoc.Doc(`
   182  				1234567890  cool.txt                         1 file    public  about 6 hours ago
   183  				4567890123                                   1 file    public  about 6 hours ago
   184  				2345678901  tea leaves thwart those who ...  2 files   secret  about 6 hours ago
   185  				3456789012  short desc                       11 files  secret  about 6 hours ago
   186  			`),
   187  		},
   188  		{
   189  			name: "with public filter",
   190  			opts: &ListOptions{Visibility: "public"},
   191  			stubs: func(reg *httpmock.Registry) {
   192  				reg.Register(
   193  					httpmock.GraphQL(query),
   194  					httpmock.StringResponse(fmt.Sprintf(
   195  						`{ "data": { "viewer": { "gists": { "nodes": [
   196  							{
   197  								"name": "1234567890",
   198  								"files": [{ "name": "cool.txt" }],
   199  								"description": "",
   200  								"updatedAt": "%[1]v",
   201  								"isPublic": true
   202  							},
   203  							{
   204  								"name": "4567890123",
   205  								"files": [{ "name": "gistfile0.txt" }],
   206  								"description": "",
   207  								"updatedAt": "%[1]v",
   208  								"isPublic": true
   209  							}
   210  						] } } } }`,
   211  						sixHoursAgo.Format(time.RFC3339),
   212  					)),
   213  				)
   214  			},
   215  			wantOut: heredoc.Doc(`
   216  				1234567890  cool.txt  1 file  public  about 6 hours ago
   217  				4567890123            1 file  public  about 6 hours ago
   218  			`),
   219  		},
   220  		{
   221  			name: "with secret filter",
   222  			opts: &ListOptions{Visibility: "secret"},
   223  			stubs: func(reg *httpmock.Registry) {
   224  				reg.Register(
   225  					httpmock.GraphQL(query),
   226  					httpmock.StringResponse(fmt.Sprintf(
   227  						`{ "data": { "viewer": { "gists": { "nodes": [
   228  							{
   229  								"name": "2345678901",
   230  								"files": [
   231  									{ "name": "gistfile0.txt" },
   232  									{ "name": "gistfile1.txt" }
   233  								],
   234  								"description": "tea leaves thwart those who court catastrophe",
   235  								"updatedAt": "%[1]v",
   236  								"isPublic": false
   237  							},
   238  							{
   239  								"name": "3456789012",
   240  								"files": [
   241  									{ "name": "gistfile0.txt" },
   242  									{ "name": "gistfile1.txt" },
   243  									{ "name": "gistfile2.txt" },
   244  									{ "name": "gistfile3.txt" },
   245  									{ "name": "gistfile4.txt" },
   246  									{ "name": "gistfile5.txt" },
   247  									{ "name": "gistfile6.txt" },
   248  									{ "name": "gistfile7.txt" },
   249  									{ "name": "gistfile9.txt" },
   250  									{ "name": "gistfile10.txt" },
   251  									{ "name": "gistfile11.txt" }
   252  								],
   253  								"description": "short desc",
   254  								"updatedAt": "%[1]v",
   255  								"isPublic": false
   256  							}
   257  						] } } } }`,
   258  						sixHoursAgo.Format(time.RFC3339),
   259  					)),
   260  				)
   261  			},
   262  			wantOut: heredoc.Doc(`
   263  				2345678901  tea leaves thwart those who ...  2 files   secret  about 6 hours ago
   264  				3456789012  short desc                       11 files  secret  about 6 hours ago
   265  			`),
   266  		},
   267  		{
   268  			name: "with limit",
   269  			opts: &ListOptions{Limit: 1},
   270  			stubs: func(reg *httpmock.Registry) {
   271  				reg.Register(
   272  					httpmock.GraphQL(query),
   273  					httpmock.StringResponse(fmt.Sprintf(
   274  						`{ "data": { "viewer": { "gists": { "nodes": [
   275  							{
   276  								"name": "1234567890",
   277  								"files": [{ "name": "cool.txt" }],
   278  								"description": "",
   279  								"updatedAt": "%v",
   280  								"isPublic": true
   281  							}
   282  						] } } } }`,
   283  						sixHoursAgo.Format(time.RFC3339),
   284  					)),
   285  				)
   286  			},
   287  			wantOut: "1234567890  cool.txt  1 file  public  about 6 hours ago\n",
   288  		},
   289  		{
   290  			name: "nontty output",
   291  			opts: &ListOptions{},
   292  			stubs: func(reg *httpmock.Registry) {
   293  				reg.Register(
   294  					httpmock.GraphQL(query),
   295  					httpmock.StringResponse(fmt.Sprintf(
   296  						`{ "data": { "viewer": { "gists": { "nodes": [
   297  							{
   298  								"name": "1234567890",
   299  								"files": [{ "name": "cool.txt" }],
   300  								"description": "",
   301  								"updatedAt": "%[1]v",
   302  								"isPublic": true
   303  							},
   304  							{
   305  								"name": "4567890123",
   306  								"files": [{ "name": "gistfile0.txt" }],
   307  								"description": "",
   308  								"updatedAt": "%[1]v",
   309  								"isPublic": true
   310  							},
   311  							{
   312  								"name": "2345678901",
   313  								"files": [
   314  									{ "name": "gistfile0.txt" },
   315  									{ "name": "gistfile1.txt" }
   316  								],
   317  								"description": "tea leaves thwart those who court catastrophe",
   318  								"updatedAt": "%[1]v",
   319  								"isPublic": false
   320  							},
   321  							{
   322  								"name": "3456789012",
   323  								"files": [
   324  									{ "name": "gistfile0.txt" },
   325  									{ "name": "gistfile1.txt" },
   326  									{ "name": "gistfile2.txt" },
   327  									{ "name": "gistfile3.txt" },
   328  									{ "name": "gistfile4.txt" },
   329  									{ "name": "gistfile5.txt" },
   330  									{ "name": "gistfile6.txt" },
   331  									{ "name": "gistfile7.txt" },
   332  									{ "name": "gistfile9.txt" },
   333  									{ "name": "gistfile10.txt" },
   334  									{ "name": "gistfile11.txt" }
   335  								],
   336  								"description": "short desc",
   337  								"updatedAt": "%[1]v",
   338  								"isPublic": false
   339  							}
   340  						] } } } }`,
   341  						absTime.Format(time.RFC3339),
   342  					)),
   343  				)
   344  			},
   345  			wantOut: heredoc.Doc(`
   346  				1234567890	cool.txt	1 file	public	2020-07-30T15:24:28Z
   347  				4567890123		1 file	public	2020-07-30T15:24:28Z
   348  				2345678901	tea leaves thwart those who court catastrophe	2 files	secret	2020-07-30T15:24:28Z
   349  				3456789012	short desc	11 files	secret	2020-07-30T15:24:28Z
   350  			`),
   351  			nontty: true,
   352  		},
   353  	}
   354  
   355  	for _, tt := range tests {
   356  		reg := &httpmock.Registry{}
   357  		tt.stubs(reg)
   358  
   359  		tt.opts.HttpClient = func() (*http.Client, error) {
   360  			return &http.Client{Transport: reg}, nil
   361  		}
   362  
   363  		tt.opts.Config = func() (config.Config, error) {
   364  			return config.NewBlankConfig(), nil
   365  		}
   366  
   367  		io, _, stdout, _ := iostreams.Test()
   368  		io.SetStdoutTTY(!tt.nontty)
   369  		tt.opts.IO = io
   370  
   371  		if tt.opts.Limit == 0 {
   372  			tt.opts.Limit = 10
   373  		}
   374  
   375  		if tt.opts.Visibility == "" {
   376  			tt.opts.Visibility = "all"
   377  		}
   378  		t.Run(tt.name, func(t *testing.T) {
   379  			err := listRun(tt.opts)
   380  			assert.NoError(t, err)
   381  
   382  			assert.Equal(t, tt.wantOut, stdout.String())
   383  			reg.Verify(t)
   384  		})
   385  	}
   386  }