github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/run/list/list_test.go (about)

     1  package list
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"net/http"
     7  	"net/url"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/MakeNowJust/heredoc"
    12  	"github.com/ungtb10d/cli/v2/internal/ghrepo"
    13  	"github.com/ungtb10d/cli/v2/pkg/cmd/run/shared"
    14  	workflowShared "github.com/ungtb10d/cli/v2/pkg/cmd/workflow/shared"
    15  	"github.com/ungtb10d/cli/v2/pkg/cmdutil"
    16  	"github.com/ungtb10d/cli/v2/pkg/httpmock"
    17  	"github.com/ungtb10d/cli/v2/pkg/iostreams"
    18  	"github.com/google/shlex"
    19  	"github.com/stretchr/testify/assert"
    20  )
    21  
    22  func TestNewCmdList(t *testing.T) {
    23  	tests := []struct {
    24  		name     string
    25  		cli      string
    26  		tty      bool
    27  		wants    ListOptions
    28  		wantsErr bool
    29  	}{
    30  		{
    31  			name: "blank",
    32  			wants: ListOptions{
    33  				Limit: defaultLimit,
    34  			},
    35  		},
    36  		{
    37  			name: "limit",
    38  			cli:  "--limit 100",
    39  			wants: ListOptions{
    40  				Limit: 100,
    41  			},
    42  		},
    43  		{
    44  			name:     "bad limit",
    45  			cli:      "--limit hi",
    46  			wantsErr: true,
    47  		},
    48  		{
    49  			name: "workflow",
    50  			cli:  "--workflow foo.yml",
    51  			wants: ListOptions{
    52  				Limit:            defaultLimit,
    53  				WorkflowSelector: "foo.yml",
    54  			},
    55  		},
    56  		{
    57  			name: "branch",
    58  			cli:  "--branch new-cool-stuff",
    59  			wants: ListOptions{
    60  				Limit:  defaultLimit,
    61  				Branch: "new-cool-stuff",
    62  			},
    63  		},
    64  		{
    65  			name: "user",
    66  			cli:  "--user bak1an",
    67  			wants: ListOptions{
    68  				Limit: defaultLimit,
    69  				Actor: "bak1an",
    70  			},
    71  		},
    72  	}
    73  
    74  	for _, tt := range tests {
    75  		t.Run(tt.name, func(t *testing.T) {
    76  			ios, _, _, _ := iostreams.Test()
    77  			ios.SetStdinTTY(tt.tty)
    78  			ios.SetStdoutTTY(tt.tty)
    79  
    80  			f := &cmdutil.Factory{
    81  				IOStreams: ios,
    82  			}
    83  
    84  			argv, err := shlex.Split(tt.cli)
    85  			assert.NoError(t, err)
    86  
    87  			var gotOpts *ListOptions
    88  			cmd := NewCmdList(f, func(opts *ListOptions) error {
    89  				gotOpts = opts
    90  				return nil
    91  			})
    92  			cmd.SetArgs(argv)
    93  			cmd.SetIn(&bytes.Buffer{})
    94  			cmd.SetOut(io.Discard)
    95  			cmd.SetErr(io.Discard)
    96  
    97  			_, err = cmd.ExecuteC()
    98  			if tt.wantsErr {
    99  				assert.Error(t, err)
   100  				return
   101  			}
   102  
   103  			assert.Equal(t, tt.wants.Limit, gotOpts.Limit)
   104  			assert.Equal(t, tt.wants.WorkflowSelector, gotOpts.WorkflowSelector)
   105  			assert.Equal(t, tt.wants.Branch, gotOpts.Branch)
   106  			assert.Equal(t, tt.wants.Actor, gotOpts.Actor)
   107  		})
   108  	}
   109  }
   110  
   111  func TestListRun(t *testing.T) {
   112  	tests := []struct {
   113  		name       string
   114  		opts       *ListOptions
   115  		wantErr    bool
   116  		wantOut    string
   117  		wantErrOut string
   118  		stubs      func(*httpmock.Registry)
   119  		isTTY      bool
   120  	}{
   121  		{
   122  			name: "default arguments",
   123  			opts: &ListOptions{
   124  				Limit: defaultLimit,
   125  				now:   shared.TestRunStartTime.Add(time.Minute*4 + time.Second*34),
   126  			},
   127  			isTTY: true,
   128  			stubs: func(reg *httpmock.Registry) {
   129  				reg.Register(
   130  					httpmock.REST("GET", "repos/OWNER/REPO/actions/runs"),
   131  					httpmock.JSONResponse(shared.RunsPayload{
   132  						WorkflowRuns: shared.TestRuns,
   133  					}))
   134  				reg.Register(
   135  					httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows"),
   136  					httpmock.JSONResponse(workflowShared.WorkflowsPayload{
   137  						Workflows: []workflowShared.Workflow{
   138  							shared.TestWorkflow,
   139  						},
   140  					}))
   141  			},
   142  			wantOut: heredoc.Doc(`
   143  				STATUS  TITLE        WORKFLOW  BRANCH  EVENT  ID    ELAPSED  AGE
   144  				X       cool commit  CI        trunk   push   1     4m34s    Feb 23, 2021
   145  				*       cool commit  CI        trunk   push   2     4m34s    Feb 23, 2021
   146  				✓       cool commit  CI        trunk   push   3     4m34s    Feb 23, 2021
   147  				X       cool commit  CI        trunk   push   4     4m34s    Feb 23, 2021
   148  				X       cool commit  CI        trunk   push   1234  4m34s    Feb 23, 2021
   149  				-       cool commit  CI        trunk   push   6     4m34s    Feb 23, 2021
   150  				-       cool commit  CI        trunk   push   7     4m34s    Feb 23, 2021
   151  				*       cool commit  CI        trunk   push   8     4m34s    Feb 23, 2021
   152  				*       cool commit  CI        trunk   push   9     4m34s    Feb 23, 2021
   153  				X       cool commit  CI        trunk   push   10    4m34s    Feb 23, 2021
   154  			`),
   155  		},
   156  		{
   157  			name: "default arguments nontty",
   158  			opts: &ListOptions{
   159  				Limit: defaultLimit,
   160  				now:   shared.TestRunStartTime.Add(time.Minute*4 + time.Second*34),
   161  			},
   162  			isTTY: false,
   163  			stubs: func(reg *httpmock.Registry) {
   164  				reg.Register(
   165  					httpmock.REST("GET", "repos/OWNER/REPO/actions/runs"),
   166  					httpmock.JSONResponse(shared.RunsPayload{
   167  						WorkflowRuns: shared.TestRuns,
   168  					}))
   169  				reg.Register(
   170  					httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows"),
   171  					httpmock.JSONResponse(workflowShared.WorkflowsPayload{
   172  						Workflows: []workflowShared.Workflow{
   173  							shared.TestWorkflow,
   174  						},
   175  					}))
   176  			},
   177  			wantOut: heredoc.Doc(`
   178  				completed	timed_out	cool commit	CI	trunk	push	1	4m34s	Feb 23, 2021
   179  				in_progress		cool commit	CI	trunk	push	2	4m34s	Feb 23, 2021
   180  				completed	success	cool commit	CI	trunk	push	3	4m34s	Feb 23, 2021
   181  				completed	cancelled	cool commit	CI	trunk	push	4	4m34s	Feb 23, 2021
   182  				completed	failure	cool commit	CI	trunk	push	1234	4m34s	Feb 23, 2021
   183  				completed	neutral	cool commit	CI	trunk	push	6	4m34s	Feb 23, 2021
   184  				completed	skipped	cool commit	CI	trunk	push	7	4m34s	Feb 23, 2021
   185  				requested		cool commit	CI	trunk	push	8	4m34s	Feb 23, 2021
   186  				queued		cool commit	CI	trunk	push	9	4m34s	Feb 23, 2021
   187  				completed	stale	cool commit	CI	trunk	push	10	4m34s	Feb 23, 2021
   188  			`),
   189  		},
   190  		{
   191  			name: "pagination",
   192  			opts: &ListOptions{
   193  				Limit: 101,
   194  				now:   shared.TestRunStartTime.Add(time.Minute*4 + time.Second*34),
   195  			},
   196  			isTTY: true,
   197  			stubs: func(reg *httpmock.Registry) {
   198  				var runID int64
   199  				runs := []shared.Run{}
   200  				for runID < 103 {
   201  					runs = append(runs, shared.TestRun(runID, shared.InProgress, ""))
   202  					runID++
   203  				}
   204  				reg.Register(
   205  					httpmock.REST("GET", "repos/OWNER/REPO/actions/runs"),
   206  					httpmock.WithHeader(httpmock.JSONResponse(shared.RunsPayload{
   207  						WorkflowRuns: runs[0:100],
   208  					}), "Link", `<https://api.github.com/repositories/123/actions/runs?per_page=100&page=2>; rel="next"`))
   209  				reg.Register(
   210  					httpmock.REST("GET", "repositories/123/actions/runs"),
   211  					httpmock.JSONResponse(shared.RunsPayload{
   212  						WorkflowRuns: runs[100:],
   213  					}))
   214  				reg.Register(
   215  					httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows"),
   216  					httpmock.JSONResponse(workflowShared.WorkflowsPayload{
   217  						Workflows: []workflowShared.Workflow{
   218  							shared.TestWorkflow,
   219  						},
   220  					}))
   221  			},
   222  			wantOut: heredoc.Doc(`
   223  				STATUS  TITLE        WORKFLOW  BRANCH  EVENT  ID   ELAPSED  AGE
   224  				*       cool commit  CI        trunk   push   0    4m34s    Feb 23, 2021
   225  				*       cool commit  CI        trunk   push   1    4m34s    Feb 23, 2021
   226  				*       cool commit  CI        trunk   push   2    4m34s    Feb 23, 2021
   227  				*       cool commit  CI        trunk   push   3    4m34s    Feb 23, 2021
   228  				*       cool commit  CI        trunk   push   4    4m34s    Feb 23, 2021
   229  				*       cool commit  CI        trunk   push   5    4m34s    Feb 23, 2021
   230  				*       cool commit  CI        trunk   push   6    4m34s    Feb 23, 2021
   231  				*       cool commit  CI        trunk   push   7    4m34s    Feb 23, 2021
   232  				*       cool commit  CI        trunk   push   8    4m34s    Feb 23, 2021
   233  				*       cool commit  CI        trunk   push   9    4m34s    Feb 23, 2021
   234  				*       cool commit  CI        trunk   push   10   4m34s    Feb 23, 2021
   235  				*       cool commit  CI        trunk   push   11   4m34s    Feb 23, 2021
   236  				*       cool commit  CI        trunk   push   12   4m34s    Feb 23, 2021
   237  				*       cool commit  CI        trunk   push   13   4m34s    Feb 23, 2021
   238  				*       cool commit  CI        trunk   push   14   4m34s    Feb 23, 2021
   239  				*       cool commit  CI        trunk   push   15   4m34s    Feb 23, 2021
   240  				*       cool commit  CI        trunk   push   16   4m34s    Feb 23, 2021
   241  				*       cool commit  CI        trunk   push   17   4m34s    Feb 23, 2021
   242  				*       cool commit  CI        trunk   push   18   4m34s    Feb 23, 2021
   243  				*       cool commit  CI        trunk   push   19   4m34s    Feb 23, 2021
   244  				*       cool commit  CI        trunk   push   20   4m34s    Feb 23, 2021
   245  				*       cool commit  CI        trunk   push   21   4m34s    Feb 23, 2021
   246  				*       cool commit  CI        trunk   push   22   4m34s    Feb 23, 2021
   247  				*       cool commit  CI        trunk   push   23   4m34s    Feb 23, 2021
   248  				*       cool commit  CI        trunk   push   24   4m34s    Feb 23, 2021
   249  				*       cool commit  CI        trunk   push   25   4m34s    Feb 23, 2021
   250  				*       cool commit  CI        trunk   push   26   4m34s    Feb 23, 2021
   251  				*       cool commit  CI        trunk   push   27   4m34s    Feb 23, 2021
   252  				*       cool commit  CI        trunk   push   28   4m34s    Feb 23, 2021
   253  				*       cool commit  CI        trunk   push   29   4m34s    Feb 23, 2021
   254  				*       cool commit  CI        trunk   push   30   4m34s    Feb 23, 2021
   255  				*       cool commit  CI        trunk   push   31   4m34s    Feb 23, 2021
   256  				*       cool commit  CI        trunk   push   32   4m34s    Feb 23, 2021
   257  				*       cool commit  CI        trunk   push   33   4m34s    Feb 23, 2021
   258  				*       cool commit  CI        trunk   push   34   4m34s    Feb 23, 2021
   259  				*       cool commit  CI        trunk   push   35   4m34s    Feb 23, 2021
   260  				*       cool commit  CI        trunk   push   36   4m34s    Feb 23, 2021
   261  				*       cool commit  CI        trunk   push   37   4m34s    Feb 23, 2021
   262  				*       cool commit  CI        trunk   push   38   4m34s    Feb 23, 2021
   263  				*       cool commit  CI        trunk   push   39   4m34s    Feb 23, 2021
   264  				*       cool commit  CI        trunk   push   40   4m34s    Feb 23, 2021
   265  				*       cool commit  CI        trunk   push   41   4m34s    Feb 23, 2021
   266  				*       cool commit  CI        trunk   push   42   4m34s    Feb 23, 2021
   267  				*       cool commit  CI        trunk   push   43   4m34s    Feb 23, 2021
   268  				*       cool commit  CI        trunk   push   44   4m34s    Feb 23, 2021
   269  				*       cool commit  CI        trunk   push   45   4m34s    Feb 23, 2021
   270  				*       cool commit  CI        trunk   push   46   4m34s    Feb 23, 2021
   271  				*       cool commit  CI        trunk   push   47   4m34s    Feb 23, 2021
   272  				*       cool commit  CI        trunk   push   48   4m34s    Feb 23, 2021
   273  				*       cool commit  CI        trunk   push   49   4m34s    Feb 23, 2021
   274  				*       cool commit  CI        trunk   push   50   4m34s    Feb 23, 2021
   275  				*       cool commit  CI        trunk   push   51   4m34s    Feb 23, 2021
   276  				*       cool commit  CI        trunk   push   52   4m34s    Feb 23, 2021
   277  				*       cool commit  CI        trunk   push   53   4m34s    Feb 23, 2021
   278  				*       cool commit  CI        trunk   push   54   4m34s    Feb 23, 2021
   279  				*       cool commit  CI        trunk   push   55   4m34s    Feb 23, 2021
   280  				*       cool commit  CI        trunk   push   56   4m34s    Feb 23, 2021
   281  				*       cool commit  CI        trunk   push   57   4m34s    Feb 23, 2021
   282  				*       cool commit  CI        trunk   push   58   4m34s    Feb 23, 2021
   283  				*       cool commit  CI        trunk   push   59   4m34s    Feb 23, 2021
   284  				*       cool commit  CI        trunk   push   60   4m34s    Feb 23, 2021
   285  				*       cool commit  CI        trunk   push   61   4m34s    Feb 23, 2021
   286  				*       cool commit  CI        trunk   push   62   4m34s    Feb 23, 2021
   287  				*       cool commit  CI        trunk   push   63   4m34s    Feb 23, 2021
   288  				*       cool commit  CI        trunk   push   64   4m34s    Feb 23, 2021
   289  				*       cool commit  CI        trunk   push   65   4m34s    Feb 23, 2021
   290  				*       cool commit  CI        trunk   push   66   4m34s    Feb 23, 2021
   291  				*       cool commit  CI        trunk   push   67   4m34s    Feb 23, 2021
   292  				*       cool commit  CI        trunk   push   68   4m34s    Feb 23, 2021
   293  				*       cool commit  CI        trunk   push   69   4m34s    Feb 23, 2021
   294  				*       cool commit  CI        trunk   push   70   4m34s    Feb 23, 2021
   295  				*       cool commit  CI        trunk   push   71   4m34s    Feb 23, 2021
   296  				*       cool commit  CI        trunk   push   72   4m34s    Feb 23, 2021
   297  				*       cool commit  CI        trunk   push   73   4m34s    Feb 23, 2021
   298  				*       cool commit  CI        trunk   push   74   4m34s    Feb 23, 2021
   299  				*       cool commit  CI        trunk   push   75   4m34s    Feb 23, 2021
   300  				*       cool commit  CI        trunk   push   76   4m34s    Feb 23, 2021
   301  				*       cool commit  CI        trunk   push   77   4m34s    Feb 23, 2021
   302  				*       cool commit  CI        trunk   push   78   4m34s    Feb 23, 2021
   303  				*       cool commit  CI        trunk   push   79   4m34s    Feb 23, 2021
   304  				*       cool commit  CI        trunk   push   80   4m34s    Feb 23, 2021
   305  				*       cool commit  CI        trunk   push   81   4m34s    Feb 23, 2021
   306  				*       cool commit  CI        trunk   push   82   4m34s    Feb 23, 2021
   307  				*       cool commit  CI        trunk   push   83   4m34s    Feb 23, 2021
   308  				*       cool commit  CI        trunk   push   84   4m34s    Feb 23, 2021
   309  				*       cool commit  CI        trunk   push   85   4m34s    Feb 23, 2021
   310  				*       cool commit  CI        trunk   push   86   4m34s    Feb 23, 2021
   311  				*       cool commit  CI        trunk   push   87   4m34s    Feb 23, 2021
   312  				*       cool commit  CI        trunk   push   88   4m34s    Feb 23, 2021
   313  				*       cool commit  CI        trunk   push   89   4m34s    Feb 23, 2021
   314  				*       cool commit  CI        trunk   push   90   4m34s    Feb 23, 2021
   315  				*       cool commit  CI        trunk   push   91   4m34s    Feb 23, 2021
   316  				*       cool commit  CI        trunk   push   92   4m34s    Feb 23, 2021
   317  				*       cool commit  CI        trunk   push   93   4m34s    Feb 23, 2021
   318  				*       cool commit  CI        trunk   push   94   4m34s    Feb 23, 2021
   319  				*       cool commit  CI        trunk   push   95   4m34s    Feb 23, 2021
   320  				*       cool commit  CI        trunk   push   96   4m34s    Feb 23, 2021
   321  				*       cool commit  CI        trunk   push   97   4m34s    Feb 23, 2021
   322  				*       cool commit  CI        trunk   push   98   4m34s    Feb 23, 2021
   323  				*       cool commit  CI        trunk   push   99   4m34s    Feb 23, 2021
   324  				*       cool commit  CI        trunk   push   100  4m34s    Feb 23, 2021
   325  			`),
   326  		},
   327  		{
   328  			name: "no results",
   329  			opts: &ListOptions{
   330  				Limit: defaultLimit,
   331  			},
   332  			stubs: func(reg *httpmock.Registry) {
   333  				reg.Register(
   334  					httpmock.REST("GET", "repos/OWNER/REPO/actions/runs"),
   335  					httpmock.JSONResponse(shared.RunsPayload{}),
   336  				)
   337  			},
   338  			wantErr: true,
   339  		},
   340  		{
   341  			name: "workflow selector",
   342  			opts: &ListOptions{
   343  				Limit:            defaultLimit,
   344  				WorkflowSelector: "flow.yml",
   345  				now:              shared.TestRunStartTime.Add(time.Minute*4 + time.Second*34),
   346  			},
   347  			isTTY: true,
   348  			stubs: func(reg *httpmock.Registry) {
   349  				reg.Register(
   350  					httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows/flow.yml"),
   351  					httpmock.JSONResponse(workflowShared.AWorkflow))
   352  				reg.Register(
   353  					httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows/123/runs"),
   354  					httpmock.JSONResponse(shared.RunsPayload{
   355  						WorkflowRuns: shared.WorkflowRuns,
   356  					}))
   357  			},
   358  			wantOut: heredoc.Doc(`
   359  				STATUS  TITLE        WORKFLOW    BRANCH  EVENT  ID    ELAPSED  AGE
   360  				*       cool commit  a workflow  trunk   push   2     4m34s    Feb 23, 2021
   361  				✓       cool commit  a workflow  trunk   push   3     4m34s    Feb 23, 2021
   362  				X       cool commit  a workflow  trunk   push   1234  4m34s    Feb 23, 2021
   363  			`),
   364  		},
   365  		{
   366  			name: "branch filter applied",
   367  			opts: &ListOptions{
   368  				Limit:  defaultLimit,
   369  				Branch: "the-branch",
   370  			},
   371  			stubs: func(reg *httpmock.Registry) {
   372  				reg.Register(
   373  					httpmock.QueryMatcher("GET", "repos/OWNER/REPO/actions/runs", url.Values{
   374  						"branch": []string{"the-branch"},
   375  					}),
   376  					httpmock.JSONResponse(shared.RunsPayload{}),
   377  				)
   378  			},
   379  			wantErr: true,
   380  		},
   381  		{
   382  			name: "actor filter applied",
   383  			opts: &ListOptions{
   384  				Limit: defaultLimit,
   385  				Actor: "bak1an",
   386  			},
   387  			stubs: func(reg *httpmock.Registry) {
   388  				reg.Register(
   389  					httpmock.QueryMatcher("GET", "repos/OWNER/REPO/actions/runs", url.Values{
   390  						"actor": []string{"bak1an"},
   391  					}),
   392  					httpmock.JSONResponse(shared.RunsPayload{}),
   393  				)
   394  			},
   395  			wantErr: true,
   396  		},
   397  	}
   398  
   399  	for _, tt := range tests {
   400  		t.Run(tt.name, func(t *testing.T) {
   401  			reg := &httpmock.Registry{}
   402  			defer reg.Verify(t)
   403  			tt.stubs(reg)
   404  
   405  			tt.opts.HttpClient = func() (*http.Client, error) {
   406  				return &http.Client{Transport: reg}, nil
   407  			}
   408  
   409  			ios, _, stdout, stderr := iostreams.Test()
   410  			ios.SetStdoutTTY(tt.isTTY)
   411  			tt.opts.IO = ios
   412  			tt.opts.BaseRepo = func() (ghrepo.Interface, error) {
   413  				return ghrepo.FromFullName("OWNER/REPO")
   414  			}
   415  
   416  			err := listRun(tt.opts)
   417  			if tt.wantErr {
   418  				assert.Error(t, err)
   419  			} else {
   420  				assert.NoError(t, err)
   421  			}
   422  
   423  			assert.Equal(t, tt.wantOut, stdout.String())
   424  			assert.Equal(t, tt.wantErrOut, stderr.String())
   425  		})
   426  	}
   427  }