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

     1  package list
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"net/http"
     8  	"testing"
     9  
    10  	"github.com/abdfnx/gh-api/internal/ghrepo"
    11  	"github.com/abdfnx/gh-api/pkg/cmd/run/shared"
    12  	workflowShared "github.com/abdfnx/gh-api/pkg/cmd/workflow/shared"
    13  	"github.com/abdfnx/gh-api/pkg/cmdutil"
    14  	"github.com/abdfnx/gh-api/pkg/httpmock"
    15  	"github.com/abdfnx/gh-api/pkg/iostreams"
    16  	"github.com/google/shlex"
    17  	"github.com/stretchr/testify/assert"
    18  )
    19  
    20  func TestNewCmdList(t *testing.T) {
    21  	tests := []struct {
    22  		name     string
    23  		cli      string
    24  		tty      bool
    25  		wants    ListOptions
    26  		wantsErr bool
    27  	}{
    28  		{
    29  			name: "blank",
    30  			wants: ListOptions{
    31  				Limit: defaultLimit,
    32  			},
    33  		},
    34  		{
    35  			name: "limit",
    36  			cli:  "--limit 100",
    37  			wants: ListOptions{
    38  				Limit: 100,
    39  			},
    40  		},
    41  		{
    42  			name:     "bad limit",
    43  			cli:      "--limit hi",
    44  			wantsErr: true,
    45  		},
    46  		{
    47  			name: "workflow",
    48  			cli:  "--workflow foo.yml",
    49  			wants: ListOptions{
    50  				Limit:            defaultLimit,
    51  				WorkflowSelector: "foo.yml",
    52  			},
    53  		},
    54  	}
    55  
    56  	for _, tt := range tests {
    57  		t.Run(tt.name, func(t *testing.T) {
    58  			io, _, _, _ := iostreams.Test()
    59  			io.SetStdinTTY(tt.tty)
    60  			io.SetStdoutTTY(tt.tty)
    61  
    62  			f := &cmdutil.Factory{
    63  				IOStreams: io,
    64  			}
    65  
    66  			argv, err := shlex.Split(tt.cli)
    67  			assert.NoError(t, err)
    68  
    69  			var gotOpts *ListOptions
    70  			cmd := NewCmdList(f, func(opts *ListOptions) error {
    71  				gotOpts = opts
    72  				return nil
    73  			})
    74  			cmd.SetArgs(argv)
    75  			cmd.SetIn(&bytes.Buffer{})
    76  			cmd.SetOut(ioutil.Discard)
    77  			cmd.SetErr(ioutil.Discard)
    78  
    79  			_, err = cmd.ExecuteC()
    80  			if tt.wantsErr {
    81  				assert.Error(t, err)
    82  				return
    83  			}
    84  
    85  			assert.Equal(t, tt.wants.Limit, gotOpts.Limit)
    86  		})
    87  	}
    88  }
    89  
    90  func TestListRun(t *testing.T) {
    91  	tests := []struct {
    92  		name       string
    93  		opts       *ListOptions
    94  		wantOut    string
    95  		wantErrOut string
    96  		stubs      func(*httpmock.Registry)
    97  		nontty     bool
    98  	}{
    99  		{
   100  			name: "blank tty",
   101  			opts: &ListOptions{
   102  				Limit: defaultLimit,
   103  			},
   104  			stubs: func(reg *httpmock.Registry) {
   105  				reg.Register(
   106  					httpmock.REST("GET", "repos/OWNER/REPO/actions/runs"),
   107  					httpmock.JSONResponse(shared.RunsPayload{
   108  						WorkflowRuns: shared.TestRuns,
   109  					}))
   110  			},
   111  			wantOut: "X  cool commit  timed out    trunk  push  1\n-  cool commit  in progress  trunk  push  2\n✓  cool commit  successful   trunk  push  3\n✓  cool commit  cancelled    trunk  push  4\nX  cool commit  failed       trunk  push  1234\n✓  cool commit  neutral      trunk  push  6\n✓  cool commit  skipped      trunk  push  7\n-  cool commit  requested    trunk  push  8\n-  cool commit  queued       trunk  push  9\nX  cool commit  stale        trunk  push  10\n\nFor details on a run, try: gh run view <run-id>\n",
   112  		},
   113  		{
   114  			name: "blank nontty",
   115  			opts: &ListOptions{
   116  				Limit:       defaultLimit,
   117  				PlainOutput: true,
   118  			},
   119  			nontty: true,
   120  			stubs: func(reg *httpmock.Registry) {
   121  				reg.Register(
   122  					httpmock.REST("GET", "repos/OWNER/REPO/actions/runs"),
   123  					httpmock.JSONResponse(shared.RunsPayload{
   124  						WorkflowRuns: shared.TestRuns,
   125  					}))
   126  			},
   127  			wantOut: "completed\ttimed_out\tcool commit\ttimed out\ttrunk\tpush\t4m34s\t1\nin_progress\t\tcool commit\tin progress\ttrunk\tpush\t4m34s\t2\ncompleted\tsuccess\tcool commit\tsuccessful\ttrunk\tpush\t4m34s\t3\ncompleted\tcancelled\tcool commit\tcancelled\ttrunk\tpush\t4m34s\t4\ncompleted\tfailure\tcool commit\tfailed\ttrunk\tpush\t4m34s\t1234\ncompleted\tneutral\tcool commit\tneutral\ttrunk\tpush\t4m34s\t6\ncompleted\tskipped\tcool commit\tskipped\ttrunk\tpush\t4m34s\t7\nrequested\t\tcool commit\trequested\ttrunk\tpush\t4m34s\t8\nqueued\t\tcool commit\tqueued\ttrunk\tpush\t4m34s\t9\ncompleted\tstale\tcool commit\tstale\ttrunk\tpush\t4m34s\t10\n",
   128  		},
   129  		{
   130  			name: "pagination",
   131  			opts: &ListOptions{
   132  				Limit: 101,
   133  			},
   134  			stubs: func(reg *httpmock.Registry) {
   135  				runID := 0
   136  				runs := []shared.Run{}
   137  				for runID < 103 {
   138  					runs = append(runs, shared.TestRun(fmt.Sprintf("%d", runID), runID, shared.InProgress, ""))
   139  					runID++
   140  				}
   141  				reg.Register(
   142  					httpmock.REST("GET", "repos/OWNER/REPO/actions/runs"),
   143  					httpmock.JSONResponse(shared.RunsPayload{
   144  						WorkflowRuns: runs[0:100],
   145  					}))
   146  				reg.Register(
   147  					httpmock.REST("GET", "repos/OWNER/REPO/actions/runs"),
   148  					httpmock.JSONResponse(shared.RunsPayload{
   149  						WorkflowRuns: runs[100:],
   150  					}))
   151  			},
   152  			wantOut: longRunOutput,
   153  		},
   154  		{
   155  			name: "no results nontty",
   156  			opts: &ListOptions{
   157  				Limit:       defaultLimit,
   158  				PlainOutput: true,
   159  			},
   160  			stubs: func(reg *httpmock.Registry) {
   161  				reg.Register(
   162  					httpmock.REST("GET", "repos/OWNER/REPO/actions/runs"),
   163  					httpmock.JSONResponse(shared.RunsPayload{}),
   164  				)
   165  			},
   166  			nontty:  true,
   167  			wantOut: "",
   168  		},
   169  		{
   170  			name: "no results tty",
   171  			opts: &ListOptions{
   172  				Limit: defaultLimit,
   173  			},
   174  			stubs: func(reg *httpmock.Registry) {
   175  				reg.Register(
   176  					httpmock.REST("GET", "repos/OWNER/REPO/actions/runs"),
   177  					httpmock.JSONResponse(shared.RunsPayload{}),
   178  				)
   179  			},
   180  			wantOut:    "",
   181  			wantErrOut: "No runs found\n",
   182  		},
   183  		{
   184  			name: "workflow selector",
   185  			opts: &ListOptions{
   186  				Limit:            defaultLimit,
   187  				WorkflowSelector: "flow.yml",
   188  			},
   189  			stubs: func(reg *httpmock.Registry) {
   190  				reg.Register(
   191  					httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows/flow.yml"),
   192  					httpmock.JSONResponse(workflowShared.AWorkflow))
   193  				reg.Register(
   194  					httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows/123/runs"),
   195  					httpmock.JSONResponse(shared.RunsPayload{
   196  						WorkflowRuns: shared.WorkflowRuns,
   197  					}))
   198  			},
   199  			wantOut: "-  cool commit  in progress  trunk  push  2\n✓  cool commit  successful   trunk  push  3\nX  cool commit  failed       trunk  push  1234\n\nFor details on a run, try: gh run view <run-id>\n",
   200  		},
   201  	}
   202  
   203  	for _, tt := range tests {
   204  		t.Run(tt.name, func(t *testing.T) {
   205  			reg := &httpmock.Registry{}
   206  			tt.stubs(reg)
   207  
   208  			tt.opts.HttpClient = func() (*http.Client, error) {
   209  				return &http.Client{Transport: reg}, nil
   210  			}
   211  
   212  			io, _, stdout, stderr := iostreams.Test()
   213  			io.SetStdoutTTY(!tt.nontty)
   214  			tt.opts.IO = io
   215  			tt.opts.BaseRepo = func() (ghrepo.Interface, error) {
   216  				return ghrepo.FromFullName("OWNER/REPO")
   217  			}
   218  
   219  			err := listRun(tt.opts)
   220  			assert.NoError(t, err)
   221  
   222  			assert.Equal(t, tt.wantOut, stdout.String())
   223  			assert.Equal(t, tt.wantErrOut, stderr.String())
   224  			reg.Verify(t)
   225  		})
   226  	}
   227  }
   228  
   229  const longRunOutput = "-  cool commit  0    trunk  push  0\n-  cool commit  1    trunk  push  1\n-  cool commit  2    trunk  push  2\n-  cool commit  3    trunk  push  3\n-  cool commit  4    trunk  push  4\n-  cool commit  5    trunk  push  5\n-  cool commit  6    trunk  push  6\n-  cool commit  7    trunk  push  7\n-  cool commit  8    trunk  push  8\n-  cool commit  9    trunk  push  9\n-  cool commit  10   trunk  push  10\n-  cool commit  11   trunk  push  11\n-  cool commit  12   trunk  push  12\n-  cool commit  13   trunk  push  13\n-  cool commit  14   trunk  push  14\n-  cool commit  15   trunk  push  15\n-  cool commit  16   trunk  push  16\n-  cool commit  17   trunk  push  17\n-  cool commit  18   trunk  push  18\n-  cool commit  19   trunk  push  19\n-  cool commit  20   trunk  push  20\n-  cool commit  21   trunk  push  21\n-  cool commit  22   trunk  push  22\n-  cool commit  23   trunk  push  23\n-  cool commit  24   trunk  push  24\n-  cool commit  25   trunk  push  25\n-  cool commit  26   trunk  push  26\n-  cool commit  27   trunk  push  27\n-  cool commit  28   trunk  push  28\n-  cool commit  29   trunk  push  29\n-  cool commit  30   trunk  push  30\n-  cool commit  31   trunk  push  31\n-  cool commit  32   trunk  push  32\n-  cool commit  33   trunk  push  33\n-  cool commit  34   trunk  push  34\n-  cool commit  35   trunk  push  35\n-  cool commit  36   trunk  push  36\n-  cool commit  37   trunk  push  37\n-  cool commit  38   trunk  push  38\n-  cool commit  39   trunk  push  39\n-  cool commit  40   trunk  push  40\n-  cool commit  41   trunk  push  41\n-  cool commit  42   trunk  push  42\n-  cool commit  43   trunk  push  43\n-  cool commit  44   trunk  push  44\n-  cool commit  45   trunk  push  45\n-  cool commit  46   trunk  push  46\n-  cool commit  47   trunk  push  47\n-  cool commit  48   trunk  push  48\n-  cool commit  49   trunk  push  49\n-  cool commit  50   trunk  push  50\n-  cool commit  51   trunk  push  51\n-  cool commit  52   trunk  push  52\n-  cool commit  53   trunk  push  53\n-  cool commit  54   trunk  push  54\n-  cool commit  55   trunk  push  55\n-  cool commit  56   trunk  push  56\n-  cool commit  57   trunk  push  57\n-  cool commit  58   trunk  push  58\n-  cool commit  59   trunk  push  59\n-  cool commit  60   trunk  push  60\n-  cool commit  61   trunk  push  61\n-  cool commit  62   trunk  push  62\n-  cool commit  63   trunk  push  63\n-  cool commit  64   trunk  push  64\n-  cool commit  65   trunk  push  65\n-  cool commit  66   trunk  push  66\n-  cool commit  67   trunk  push  67\n-  cool commit  68   trunk  push  68\n-  cool commit  69   trunk  push  69\n-  cool commit  70   trunk  push  70\n-  cool commit  71   trunk  push  71\n-  cool commit  72   trunk  push  72\n-  cool commit  73   trunk  push  73\n-  cool commit  74   trunk  push  74\n-  cool commit  75   trunk  push  75\n-  cool commit  76   trunk  push  76\n-  cool commit  77   trunk  push  77\n-  cool commit  78   trunk  push  78\n-  cool commit  79   trunk  push  79\n-  cool commit  80   trunk  push  80\n-  cool commit  81   trunk  push  81\n-  cool commit  82   trunk  push  82\n-  cool commit  83   trunk  push  83\n-  cool commit  84   trunk  push  84\n-  cool commit  85   trunk  push  85\n-  cool commit  86   trunk  push  86\n-  cool commit  87   trunk  push  87\n-  cool commit  88   trunk  push  88\n-  cool commit  89   trunk  push  89\n-  cool commit  90   trunk  push  90\n-  cool commit  91   trunk  push  91\n-  cool commit  92   trunk  push  92\n-  cool commit  93   trunk  push  93\n-  cool commit  94   trunk  push  94\n-  cool commit  95   trunk  push  95\n-  cool commit  96   trunk  push  96\n-  cool commit  97   trunk  push  97\n-  cool commit  98   trunk  push  98\n-  cool commit  99   trunk  push  99\n-  cool commit  100  trunk  push  100\n\nFor details on a run, try: gh run view <run-id>\n"