github.com/andrewhsu/cli/v2@v2.0.1-0.20210910131313-d4b4061f5b89/pkg/cmd/run/rerun/rerun_test.go (about)

     1  package rerun
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"net/http"
     7  	"testing"
     8  
     9  	"github.com/andrewhsu/cli/v2/internal/ghrepo"
    10  	"github.com/andrewhsu/cli/v2/pkg/cmd/run/shared"
    11  	"github.com/andrewhsu/cli/v2/pkg/cmdutil"
    12  	"github.com/andrewhsu/cli/v2/pkg/httpmock"
    13  	"github.com/andrewhsu/cli/v2/pkg/iostreams"
    14  	"github.com/andrewhsu/cli/v2/pkg/prompt"
    15  	"github.com/google/shlex"
    16  	"github.com/stretchr/testify/assert"
    17  )
    18  
    19  func TestNewCmdRerun(t *testing.T) {
    20  	tests := []struct {
    21  		name     string
    22  		cli      string
    23  		tty      bool
    24  		wants    RerunOptions
    25  		wantsErr bool
    26  	}{
    27  		{
    28  			name:     "blank nontty",
    29  			wantsErr: true,
    30  		},
    31  		{
    32  			name: "blank tty",
    33  			tty:  true,
    34  			wants: RerunOptions{
    35  				Prompt: true,
    36  			},
    37  		},
    38  		{
    39  			name: "with arg nontty",
    40  			cli:  "1234",
    41  			wants: RerunOptions{
    42  				RunID: "1234",
    43  			},
    44  		},
    45  		{
    46  			name: "with arg tty",
    47  			tty:  true,
    48  			cli:  "1234",
    49  			wants: RerunOptions{
    50  				RunID: "1234",
    51  			},
    52  		},
    53  	}
    54  
    55  	for _, tt := range tests {
    56  		t.Run(tt.name, func(t *testing.T) {
    57  			io, _, _, _ := iostreams.Test()
    58  			io.SetStdinTTY(tt.tty)
    59  			io.SetStdoutTTY(tt.tty)
    60  
    61  			f := &cmdutil.Factory{
    62  				IOStreams: io,
    63  			}
    64  
    65  			argv, err := shlex.Split(tt.cli)
    66  			assert.NoError(t, err)
    67  
    68  			var gotOpts *RerunOptions
    69  			cmd := NewCmdRerun(f, func(opts *RerunOptions) error {
    70  				gotOpts = opts
    71  				return nil
    72  			})
    73  			cmd.SetArgs(argv)
    74  			cmd.SetIn(&bytes.Buffer{})
    75  			cmd.SetOut(ioutil.Discard)
    76  			cmd.SetErr(ioutil.Discard)
    77  
    78  			_, err = cmd.ExecuteC()
    79  			if tt.wantsErr {
    80  				assert.Error(t, err)
    81  				return
    82  			}
    83  
    84  			assert.NoError(t, err)
    85  
    86  			assert.Equal(t, tt.wants.RunID, gotOpts.RunID)
    87  			assert.Equal(t, tt.wants.Prompt, gotOpts.Prompt)
    88  		})
    89  	}
    90  
    91  }
    92  
    93  func TestRerun(t *testing.T) {
    94  	tests := []struct {
    95  		name      string
    96  		httpStubs func(*httpmock.Registry)
    97  		askStubs  func(*prompt.AskStubber)
    98  		opts      *RerunOptions
    99  		tty       bool
   100  		wantErr   bool
   101  		errOut    string
   102  		wantOut   string
   103  	}{
   104  		{
   105  			name: "arg",
   106  			tty:  true,
   107  			opts: &RerunOptions{
   108  				RunID: "1234",
   109  			},
   110  			httpStubs: func(reg *httpmock.Registry) {
   111  				reg.Register(
   112  					httpmock.REST("GET", "repos/OWNER/REPO/actions/runs/1234"),
   113  					httpmock.JSONResponse(shared.FailedRun))
   114  				reg.Register(
   115  					httpmock.REST("POST", "repos/OWNER/REPO/actions/runs/1234/rerun"),
   116  					httpmock.StringResponse("{}"))
   117  			},
   118  			wantOut: "✓ Requested rerun of run 1234\n",
   119  		},
   120  		{
   121  			name: "prompt",
   122  			tty:  true,
   123  			opts: &RerunOptions{
   124  				Prompt: true,
   125  			},
   126  			httpStubs: func(reg *httpmock.Registry) {
   127  				reg.Register(
   128  					httpmock.REST("GET", "repos/OWNER/REPO/actions/runs"),
   129  					httpmock.JSONResponse(shared.RunsPayload{
   130  						WorkflowRuns: shared.TestRuns,
   131  					}))
   132  				reg.Register(
   133  					httpmock.REST("GET", "repos/OWNER/REPO/actions/runs/1234"),
   134  					httpmock.JSONResponse(shared.FailedRun))
   135  				reg.Register(
   136  					httpmock.REST("POST", "repos/OWNER/REPO/actions/runs/1234/rerun"),
   137  					httpmock.StringResponse("{}"))
   138  			},
   139  			askStubs: func(as *prompt.AskStubber) {
   140  				as.StubOne(2)
   141  			},
   142  			wantOut: "✓ Requested rerun of run 1234\n",
   143  		},
   144  		{
   145  			name: "prompt but no failed runs",
   146  			tty:  true,
   147  			opts: &RerunOptions{
   148  				Prompt: true,
   149  			},
   150  			httpStubs: func(reg *httpmock.Registry) {
   151  				reg.Register(
   152  					httpmock.REST("GET", "repos/OWNER/REPO/actions/runs"),
   153  					httpmock.JSONResponse(shared.RunsPayload{
   154  						WorkflowRuns: []shared.Run{
   155  							shared.SuccessfulRun,
   156  							shared.TestRun("in progress", 2, shared.InProgress, ""),
   157  						}}))
   158  			},
   159  			wantErr: true,
   160  			errOut:  "no recent runs have failed; please specify a specific run ID",
   161  		},
   162  		{
   163  			name: "unrerunnable",
   164  			tty:  true,
   165  			opts: &RerunOptions{
   166  				RunID: "3",
   167  			},
   168  			httpStubs: func(reg *httpmock.Registry) {
   169  				reg.Register(
   170  					httpmock.REST("GET", "repos/OWNER/REPO/actions/runs/3"),
   171  					httpmock.JSONResponse(shared.SuccessfulRun))
   172  				reg.Register(
   173  					httpmock.REST("POST", "repos/OWNER/REPO/actions/runs/3/rerun"),
   174  					httpmock.StatusStringResponse(403, "no"))
   175  			},
   176  			wantErr: true,
   177  			errOut:  "run 3 cannot be rerun; its workflow file may be broken.",
   178  		},
   179  	}
   180  
   181  	for _, tt := range tests {
   182  		reg := &httpmock.Registry{}
   183  		tt.httpStubs(reg)
   184  		tt.opts.HttpClient = func() (*http.Client, error) {
   185  			return &http.Client{Transport: reg}, nil
   186  		}
   187  
   188  		io, _, stdout, _ := iostreams.Test()
   189  		io.SetStdinTTY(tt.tty)
   190  		io.SetStdoutTTY(tt.tty)
   191  		tt.opts.IO = io
   192  		tt.opts.BaseRepo = func() (ghrepo.Interface, error) {
   193  			return ghrepo.FromFullName("OWNER/REPO")
   194  		}
   195  
   196  		as, teardown := prompt.InitAskStubber()
   197  		defer teardown()
   198  		if tt.askStubs != nil {
   199  			tt.askStubs(as)
   200  		}
   201  
   202  		t.Run(tt.name, func(t *testing.T) {
   203  			err := runRerun(tt.opts)
   204  			if tt.wantErr {
   205  				assert.Error(t, err)
   206  				assert.Equal(t, tt.errOut, err.Error())
   207  				return
   208  			}
   209  			assert.NoError(t, err)
   210  			assert.Equal(t, tt.wantOut, stdout.String())
   211  			reg.Verify(t)
   212  		})
   213  	}
   214  }