github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/repo/rename/rename_test.go (about)

     1  package rename
     2  
     3  import (
     4  	"bytes"
     5  	"net/http"
     6  	"testing"
     7  
     8  	"github.com/ungtb10d/cli/v2/context"
     9  	"github.com/ungtb10d/cli/v2/git"
    10  	"github.com/ungtb10d/cli/v2/internal/config"
    11  	"github.com/ungtb10d/cli/v2/internal/ghrepo"
    12  	"github.com/ungtb10d/cli/v2/internal/run"
    13  	"github.com/ungtb10d/cli/v2/pkg/cmdutil"
    14  	"github.com/ungtb10d/cli/v2/pkg/httpmock"
    15  	"github.com/ungtb10d/cli/v2/pkg/iostreams"
    16  	"github.com/ungtb10d/cli/v2/pkg/prompt"
    17  	"github.com/google/shlex"
    18  	"github.com/stretchr/testify/assert"
    19  )
    20  
    21  func TestNewCmdRename(t *testing.T) {
    22  	testCases := []struct {
    23  		name    string
    24  		input   string
    25  		output  RenameOptions
    26  		errMsg  string
    27  		tty     bool
    28  		wantErr bool
    29  	}{
    30  		{
    31  			name:    "no arguments no tty",
    32  			input:   "",
    33  			errMsg:  "new name argument required when not running interactively",
    34  			wantErr: true,
    35  		},
    36  		{
    37  			name:  "one argument no tty confirmed",
    38  			input: "REPO --confirm",
    39  			output: RenameOptions{
    40  				newRepoSelector: "REPO",
    41  			},
    42  		},
    43  		{
    44  			name:    "one argument no tty",
    45  			input:   "REPO",
    46  			errMsg:  "--confirm required when passing a single argument",
    47  			wantErr: true,
    48  		},
    49  		{
    50  			name:  "one argument tty confirmed",
    51  			input: "REPO --confirm",
    52  			tty:   true,
    53  			output: RenameOptions{
    54  				newRepoSelector: "REPO",
    55  			},
    56  		},
    57  		{
    58  			name:  "one argument tty",
    59  			input: "REPO",
    60  			tty:   true,
    61  			output: RenameOptions{
    62  				newRepoSelector: "REPO",
    63  				DoConfirm:       true,
    64  			},
    65  		},
    66  		{
    67  			name:  "full flag argument",
    68  			input: "--repo OWNER/REPO NEW_REPO",
    69  			output: RenameOptions{
    70  				newRepoSelector: "NEW_REPO",
    71  			},
    72  		},
    73  	}
    74  	for _, tt := range testCases {
    75  		t.Run(tt.name, func(t *testing.T) {
    76  			ios, _, _, _ := iostreams.Test()
    77  			ios.SetStdinTTY(tt.tty)
    78  			ios.SetStdoutTTY(tt.tty)
    79  			f := &cmdutil.Factory{
    80  				IOStreams: ios,
    81  			}
    82  
    83  			argv, err := shlex.Split(tt.input)
    84  			assert.NoError(t, err)
    85  			var gotOpts *RenameOptions
    86  			cmd := NewCmdRename(f, func(opts *RenameOptions) error {
    87  				gotOpts = opts
    88  				return nil
    89  			})
    90  			cmd.SetArgs(argv)
    91  			cmd.SetIn(&bytes.Buffer{})
    92  			cmd.SetOut(&bytes.Buffer{})
    93  			cmd.SetErr(&bytes.Buffer{})
    94  
    95  			_, err = cmd.ExecuteC()
    96  			if tt.wantErr {
    97  				assert.EqualError(t, err, tt.errMsg)
    98  				return
    99  			}
   100  			assert.NoError(t, err)
   101  			assert.Equal(t, tt.output.newRepoSelector, gotOpts.newRepoSelector)
   102  		})
   103  	}
   104  }
   105  
   106  func TestRenameRun(t *testing.T) {
   107  	testCases := []struct {
   108  		name      string
   109  		opts      RenameOptions
   110  		httpStubs func(*httpmock.Registry)
   111  		execStubs func(*run.CommandStubber)
   112  		askStubs  func(*prompt.AskStubber)
   113  		wantOut   string
   114  		tty       bool
   115  	}{
   116  		{
   117  			name:    "none argument",
   118  			wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote\n",
   119  			askStubs: func(q *prompt.AskStubber) {
   120  				//nolint:staticcheck // SA1019: q.StubOne is deprecated: use StubPrompt
   121  				q.StubOne("NEW_REPO")
   122  			},
   123  			httpStubs: func(reg *httpmock.Registry) {
   124  				reg.Register(
   125  					httpmock.REST("PATCH", "repos/OWNER/REPO"),
   126  					httpmock.StatusStringResponse(200, `{"name":"NEW_REPO","owner":{"login":"OWNER"}}`))
   127  			},
   128  			execStubs: func(cs *run.CommandStubber) {
   129  				cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "")
   130  			},
   131  			tty: true,
   132  		},
   133  		{
   134  			name: "repo override",
   135  			opts: RenameOptions{
   136  				HasRepoOverride: true,
   137  			},
   138  			wantOut: "✓ Renamed repository OWNER/NEW_REPO\n",
   139  			askStubs: func(q *prompt.AskStubber) {
   140  				//nolint:staticcheck // SA1019: q.StubOne is deprecated: use StubPrompt
   141  				q.StubOne("NEW_REPO")
   142  			},
   143  			httpStubs: func(reg *httpmock.Registry) {
   144  				reg.Register(
   145  					httpmock.REST("PATCH", "repos/OWNER/REPO"),
   146  					httpmock.StatusStringResponse(200, `{"name":"NEW_REPO","owner":{"login":"OWNER"}}`))
   147  			},
   148  			tty: true,
   149  		},
   150  		{
   151  			name: "owner repo change name argument tty",
   152  			opts: RenameOptions{
   153  				newRepoSelector: "NEW_REPO",
   154  			},
   155  			wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote\n",
   156  			httpStubs: func(reg *httpmock.Registry) {
   157  				reg.Register(
   158  					httpmock.REST("PATCH", "repos/OWNER/REPO"),
   159  					httpmock.StatusStringResponse(200, `{"name":"NEW_REPO","owner":{"login":"OWNER"}}`))
   160  			},
   161  			execStubs: func(cs *run.CommandStubber) {
   162  				cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "")
   163  			},
   164  			tty: true,
   165  		},
   166  		{
   167  			name: "owner repo change name argument no tty",
   168  			opts: RenameOptions{
   169  				newRepoSelector: "NEW_REPO",
   170  			},
   171  			httpStubs: func(reg *httpmock.Registry) {
   172  				reg.Register(
   173  					httpmock.REST("PATCH", "repos/OWNER/REPO"),
   174  					httpmock.StatusStringResponse(200, `{"name":"NEW_REPO","owner":{"login":"OWNER"}}`))
   175  			},
   176  			execStubs: func(cs *run.CommandStubber) {
   177  				cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "")
   178  			},
   179  		},
   180  		{
   181  			name: "confirmation with yes",
   182  			tty:  true,
   183  			opts: RenameOptions{
   184  				newRepoSelector: "NEW_REPO",
   185  				DoConfirm:       true,
   186  			},
   187  			wantOut: "✓ Renamed repository OWNER/NEW_REPO\n✓ Updated the \"origin\" remote\n",
   188  			askStubs: func(q *prompt.AskStubber) {
   189  				//nolint:staticcheck // SA1019: q.StubOne is deprecated: use StubPrompt
   190  				q.StubOne(true)
   191  			},
   192  			httpStubs: func(reg *httpmock.Registry) {
   193  				reg.Register(
   194  					httpmock.REST("PATCH", "repos/OWNER/REPO"),
   195  					httpmock.StatusStringResponse(200, `{"name":"NEW_REPO","owner":{"login":"OWNER"}}`))
   196  			},
   197  			execStubs: func(cs *run.CommandStubber) {
   198  				cs.Register(`git remote set-url origin https://github.com/OWNER/NEW_REPO.git`, 0, "")
   199  			},
   200  		},
   201  
   202  		{
   203  			name: "confirmation with no",
   204  			tty:  true,
   205  			opts: RenameOptions{
   206  				newRepoSelector: "NEW_REPO",
   207  				DoConfirm:       true,
   208  			},
   209  			askStubs: func(q *prompt.AskStubber) {
   210  				//nolint:staticcheck // SA1019: q.StubOne is deprecated: use StubPrompt
   211  				q.StubOne(false)
   212  			},
   213  			wantOut: "",
   214  		},
   215  	}
   216  
   217  	for _, tt := range testCases {
   218  		//nolint:staticcheck // SA1019: prompt.InitAskStubber is deprecated: use NewAskStubber
   219  		q, teardown := prompt.InitAskStubber()
   220  		defer teardown()
   221  		if tt.askStubs != nil {
   222  			tt.askStubs(q)
   223  		}
   224  
   225  		repo, _ := ghrepo.FromFullName("OWNER/REPO")
   226  		tt.opts.BaseRepo = func() (ghrepo.Interface, error) {
   227  			return repo, nil
   228  		}
   229  
   230  		tt.opts.Config = func() (config.Config, error) {
   231  			return config.NewBlankConfig(), nil
   232  		}
   233  
   234  		tt.opts.Remotes = func() (context.Remotes, error) {
   235  			return []*context.Remote{
   236  				{
   237  					Remote: &git.Remote{Name: "origin"},
   238  					Repo:   repo,
   239  				},
   240  			}, nil
   241  		}
   242  
   243  		cs, restoreRun := run.Stub()
   244  		defer restoreRun(t)
   245  		if tt.execStubs != nil {
   246  			tt.execStubs(cs)
   247  		}
   248  
   249  		reg := &httpmock.Registry{}
   250  		if tt.httpStubs != nil {
   251  			tt.httpStubs(reg)
   252  		}
   253  		tt.opts.HttpClient = func() (*http.Client, error) {
   254  			return &http.Client{Transport: reg}, nil
   255  		}
   256  
   257  		ios, _, stdout, _ := iostreams.Test()
   258  		ios.SetStdinTTY(tt.tty)
   259  		ios.SetStdoutTTY(tt.tty)
   260  		tt.opts.IO = ios
   261  
   262  		tt.opts.GitClient = &git.Client{GitPath: "some/path/git"}
   263  
   264  		t.Run(tt.name, func(t *testing.T) {
   265  			defer reg.Verify(t)
   266  			err := renameRun(&tt.opts)
   267  			assert.NoError(t, err)
   268  			assert.Equal(t, tt.wantOut, stdout.String())
   269  		})
   270  	}
   271  }