github.com/andrewhsu/cli/v2@v2.0.1-0.20210910131313-d4b4061f5b89/pkg/cmd/factory/default_test.go (about)

     1  package factory
     2  
     3  import (
     4  	"net/url"
     5  	"os"
     6  	"testing"
     7  
     8  	"github.com/MakeNowJust/heredoc"
     9  	"github.com/andrewhsu/cli/v2/git"
    10  	"github.com/andrewhsu/cli/v2/internal/config"
    11  	"github.com/andrewhsu/cli/v2/pkg/cmdutil"
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  func Test_BaseRepo(t *testing.T) {
    16  	orig_GH_HOST := os.Getenv("GH_HOST")
    17  	t.Cleanup(func() {
    18  		os.Setenv("GH_HOST", orig_GH_HOST)
    19  	})
    20  
    21  	tests := []struct {
    22  		name       string
    23  		remotes    git.RemoteSet
    24  		config     config.Config
    25  		override   string
    26  		wantsErr   bool
    27  		wantsName  string
    28  		wantsOwner string
    29  		wantsHost  string
    30  	}{
    31  		{
    32  			name: "matching remote",
    33  			remotes: git.RemoteSet{
    34  				git.NewRemote("origin", "https://nonsense.com/owner/repo.git"),
    35  			},
    36  			config:     defaultConfig(),
    37  			wantsName:  "repo",
    38  			wantsOwner: "owner",
    39  			wantsHost:  "nonsense.com",
    40  		},
    41  		{
    42  			name: "no matching remote",
    43  			remotes: git.RemoteSet{
    44  				git.NewRemote("origin", "https://test.com/owner/repo.git"),
    45  			},
    46  			config:   defaultConfig(),
    47  			wantsErr: true,
    48  		},
    49  		{
    50  			name: "override with matching remote",
    51  			remotes: git.RemoteSet{
    52  				git.NewRemote("origin", "https://test.com/owner/repo.git"),
    53  			},
    54  			config:     defaultConfig(),
    55  			override:   "test.com",
    56  			wantsName:  "repo",
    57  			wantsOwner: "owner",
    58  			wantsHost:  "test.com",
    59  		},
    60  		{
    61  			name: "override with no matching remote",
    62  			remotes: git.RemoteSet{
    63  				git.NewRemote("origin", "https://nonsense.com/owner/repo.git"),
    64  			},
    65  			config:   defaultConfig(),
    66  			override: "test.com",
    67  			wantsErr: true,
    68  		},
    69  	}
    70  
    71  	for _, tt := range tests {
    72  		t.Run(tt.name, func(t *testing.T) {
    73  			if tt.override != "" {
    74  				os.Setenv("GH_HOST", tt.override)
    75  			} else {
    76  				os.Unsetenv("GH_HOST")
    77  			}
    78  			f := New("1")
    79  			rr := &remoteResolver{
    80  				readRemotes: func() (git.RemoteSet, error) {
    81  					return tt.remotes, nil
    82  				},
    83  				getConfig: func() (config.Config, error) {
    84  					return tt.config, nil
    85  				},
    86  			}
    87  			f.Remotes = rr.Resolver()
    88  			f.BaseRepo = BaseRepoFunc(f)
    89  			repo, err := f.BaseRepo()
    90  			if tt.wantsErr {
    91  				assert.Error(t, err)
    92  				return
    93  			}
    94  			assert.NoError(t, err)
    95  			assert.Equal(t, tt.wantsName, repo.RepoName())
    96  			assert.Equal(t, tt.wantsOwner, repo.RepoOwner())
    97  			assert.Equal(t, tt.wantsHost, repo.RepoHost())
    98  		})
    99  	}
   100  }
   101  
   102  func Test_SmartBaseRepo(t *testing.T) {
   103  	pu, _ := url.Parse("https://test.com/newowner/newrepo.git")
   104  	orig_GH_HOST := os.Getenv("GH_HOST")
   105  	t.Cleanup(func() {
   106  		os.Setenv("GH_HOST", orig_GH_HOST)
   107  	})
   108  
   109  	tests := []struct {
   110  		name       string
   111  		remotes    git.RemoteSet
   112  		config     config.Config
   113  		override   string
   114  		wantsErr   bool
   115  		wantsName  string
   116  		wantsOwner string
   117  		wantsHost  string
   118  	}{
   119  		{
   120  			name: "override with matching remote",
   121  			remotes: git.RemoteSet{
   122  				git.NewRemote("origin", "https://test.com/owner/repo.git"),
   123  			},
   124  			config:     defaultConfig(),
   125  			override:   "test.com",
   126  			wantsName:  "repo",
   127  			wantsOwner: "owner",
   128  			wantsHost:  "test.com",
   129  		},
   130  		{
   131  			name: "override with matching remote and base resolution",
   132  			remotes: git.RemoteSet{
   133  				&git.Remote{Name: "origin",
   134  					Resolved: "base",
   135  					FetchURL: pu,
   136  					PushURL:  pu},
   137  			},
   138  			config:     defaultConfig(),
   139  			override:   "test.com",
   140  			wantsName:  "newrepo",
   141  			wantsOwner: "newowner",
   142  			wantsHost:  "test.com",
   143  		},
   144  		{
   145  			name: "override with matching remote and nonbase resolution",
   146  			remotes: git.RemoteSet{
   147  				&git.Remote{Name: "origin",
   148  					Resolved: "johnny/test",
   149  					FetchURL: pu,
   150  					PushURL:  pu},
   151  			},
   152  			config:     defaultConfig(),
   153  			override:   "test.com",
   154  			wantsName:  "test",
   155  			wantsOwner: "johnny",
   156  			wantsHost:  "test.com",
   157  		},
   158  		{
   159  			name: "override with no matching remote",
   160  			remotes: git.RemoteSet{
   161  				git.NewRemote("origin", "https://example.com/owner/repo.git"),
   162  			},
   163  			config:   defaultConfig(),
   164  			override: "test.com",
   165  			wantsErr: true,
   166  		},
   167  	}
   168  
   169  	for _, tt := range tests {
   170  		t.Run(tt.name, func(t *testing.T) {
   171  			if tt.override != "" {
   172  				os.Setenv("GH_HOST", tt.override)
   173  			} else {
   174  				os.Unsetenv("GH_HOST")
   175  			}
   176  			f := New("1")
   177  			rr := &remoteResolver{
   178  				readRemotes: func() (git.RemoteSet, error) {
   179  					return tt.remotes, nil
   180  				},
   181  				getConfig: func() (config.Config, error) {
   182  					return tt.config, nil
   183  				},
   184  			}
   185  			f.Remotes = rr.Resolver()
   186  			f.BaseRepo = SmartBaseRepoFunc(f)
   187  			repo, err := f.BaseRepo()
   188  			if tt.wantsErr {
   189  				assert.Error(t, err)
   190  				return
   191  			}
   192  			assert.NoError(t, err)
   193  			assert.Equal(t, tt.wantsName, repo.RepoName())
   194  			assert.Equal(t, tt.wantsOwner, repo.RepoOwner())
   195  			assert.Equal(t, tt.wantsHost, repo.RepoHost())
   196  		})
   197  	}
   198  }
   199  
   200  // Defined in pkg/cmdutil/repo_override.go but test it along with other BaseRepo functions
   201  func Test_OverrideBaseRepo(t *testing.T) {
   202  	orig_GH_HOST := os.Getenv("GH_REPO")
   203  	t.Cleanup(func() {
   204  		os.Setenv("GH_REPO", orig_GH_HOST)
   205  	})
   206  
   207  	tests := []struct {
   208  		name        string
   209  		remotes     git.RemoteSet
   210  		config      config.Config
   211  		envOverride string
   212  		argOverride string
   213  		wantsErr    bool
   214  		wantsName   string
   215  		wantsOwner  string
   216  		wantsHost   string
   217  	}{
   218  		{
   219  			name:        "override from argument",
   220  			argOverride: "override/test",
   221  			wantsHost:   "github.com",
   222  			wantsOwner:  "override",
   223  			wantsName:   "test",
   224  		},
   225  		{
   226  			name:        "override from environment",
   227  			envOverride: "somehost.com/override/test",
   228  			wantsHost:   "somehost.com",
   229  			wantsOwner:  "override",
   230  			wantsName:   "test",
   231  		},
   232  		{
   233  			name: "no override",
   234  			remotes: git.RemoteSet{
   235  				git.NewRemote("origin", "https://nonsense.com/owner/repo.git"),
   236  			},
   237  			config:     defaultConfig(),
   238  			wantsHost:  "nonsense.com",
   239  			wantsOwner: "owner",
   240  			wantsName:  "repo",
   241  		},
   242  	}
   243  
   244  	for _, tt := range tests {
   245  		t.Run(tt.name, func(t *testing.T) {
   246  			if tt.envOverride != "" {
   247  				os.Setenv("GH_REPO", tt.envOverride)
   248  			} else {
   249  				os.Unsetenv("GH_REPO")
   250  			}
   251  			f := New("1")
   252  			rr := &remoteResolver{
   253  				readRemotes: func() (git.RemoteSet, error) {
   254  					return tt.remotes, nil
   255  				},
   256  				getConfig: func() (config.Config, error) {
   257  					return tt.config, nil
   258  				},
   259  			}
   260  			f.Remotes = rr.Resolver()
   261  			f.BaseRepo = cmdutil.OverrideBaseRepoFunc(f, tt.argOverride)
   262  			repo, err := f.BaseRepo()
   263  			if tt.wantsErr {
   264  				assert.Error(t, err)
   265  				return
   266  			}
   267  			assert.NoError(t, err)
   268  			assert.Equal(t, tt.wantsName, repo.RepoName())
   269  			assert.Equal(t, tt.wantsOwner, repo.RepoOwner())
   270  			assert.Equal(t, tt.wantsHost, repo.RepoHost())
   271  		})
   272  	}
   273  }
   274  
   275  func Test_ioStreams_pager(t *testing.T) {
   276  	tests := []struct {
   277  		name      string
   278  		env       map[string]string
   279  		config    config.Config
   280  		wantPager string
   281  	}{
   282  		{
   283  			name: "GH_PAGER and PAGER set",
   284  			env: map[string]string{
   285  				"GH_PAGER": "GH_PAGER",
   286  				"PAGER":    "PAGER",
   287  			},
   288  			wantPager: "GH_PAGER",
   289  		},
   290  		{
   291  			name: "GH_PAGER and config pager set",
   292  			env: map[string]string{
   293  				"GH_PAGER": "GH_PAGER",
   294  			},
   295  			config:    pagerConfig(),
   296  			wantPager: "GH_PAGER",
   297  		},
   298  		{
   299  			name: "config pager and PAGER set",
   300  			env: map[string]string{
   301  				"PAGER": "PAGER",
   302  			},
   303  			config:    pagerConfig(),
   304  			wantPager: "CONFIG_PAGER",
   305  		},
   306  		{
   307  			name: "only PAGER set",
   308  			env: map[string]string{
   309  				"PAGER": "PAGER",
   310  			},
   311  			wantPager: "PAGER",
   312  		},
   313  		{
   314  			name: "GH_PAGER set to blank string",
   315  			env: map[string]string{
   316  				"GH_PAGER": "",
   317  				"PAGER":    "PAGER",
   318  			},
   319  			wantPager: "",
   320  		},
   321  	}
   322  	for _, tt := range tests {
   323  		t.Run(tt.name, func(t *testing.T) {
   324  			if tt.env != nil {
   325  				for k, v := range tt.env {
   326  					old := os.Getenv(k)
   327  					os.Setenv(k, v)
   328  					if k == "GH_PAGER" {
   329  						defer os.Unsetenv(k)
   330  					} else {
   331  						defer os.Setenv(k, old)
   332  					}
   333  				}
   334  			}
   335  			f := New("1")
   336  			f.Config = func() (config.Config, error) {
   337  				if tt.config == nil {
   338  					return config.NewBlankConfig(), nil
   339  				} else {
   340  					return tt.config, nil
   341  				}
   342  			}
   343  			io := ioStreams(f)
   344  			assert.Equal(t, tt.wantPager, io.GetPager())
   345  		})
   346  	}
   347  }
   348  
   349  func Test_ioStreams_prompt(t *testing.T) {
   350  	tests := []struct {
   351  		name           string
   352  		config         config.Config
   353  		promptDisabled bool
   354  	}{
   355  		{
   356  			name:           "default config",
   357  			promptDisabled: false,
   358  		},
   359  		{
   360  			name:           "config with prompt disabled",
   361  			config:         disablePromptConfig(),
   362  			promptDisabled: true,
   363  		},
   364  	}
   365  	for _, tt := range tests {
   366  		t.Run(tt.name, func(t *testing.T) {
   367  			f := New("1")
   368  			f.Config = func() (config.Config, error) {
   369  				if tt.config == nil {
   370  					return config.NewBlankConfig(), nil
   371  				} else {
   372  					return tt.config, nil
   373  				}
   374  			}
   375  			io := ioStreams(f)
   376  			assert.Equal(t, tt.promptDisabled, io.GetNeverPrompt())
   377  		})
   378  	}
   379  }
   380  
   381  func Test_browserLauncher(t *testing.T) {
   382  	tests := []struct {
   383  		name        string
   384  		env         map[string]string
   385  		config      config.Config
   386  		wantBrowser string
   387  	}{
   388  		{
   389  			name: "GH_BROWSER set",
   390  			env: map[string]string{
   391  				"GH_BROWSER": "GH_BROWSER",
   392  			},
   393  			wantBrowser: "GH_BROWSER",
   394  		},
   395  		{
   396  			name:        "config browser set",
   397  			config:      config.NewFromString("browser: CONFIG_BROWSER"),
   398  			wantBrowser: "CONFIG_BROWSER",
   399  		},
   400  		{
   401  			name: "BROWSER set",
   402  			env: map[string]string{
   403  				"BROWSER": "BROWSER",
   404  			},
   405  			wantBrowser: "BROWSER",
   406  		},
   407  		{
   408  			name: "GH_BROWSER and config browser set",
   409  			env: map[string]string{
   410  				"GH_BROWSER": "GH_BROWSER",
   411  			},
   412  			config:      config.NewFromString("browser: CONFIG_BROWSER"),
   413  			wantBrowser: "GH_BROWSER",
   414  		},
   415  		{
   416  			name: "config browser and BROWSER set",
   417  			env: map[string]string{
   418  				"BROWSER": "BROWSER",
   419  			},
   420  			config:      config.NewFromString("browser: CONFIG_BROWSER"),
   421  			wantBrowser: "CONFIG_BROWSER",
   422  		},
   423  		{
   424  			name: "GH_BROWSER and BROWSER set",
   425  			env: map[string]string{
   426  				"BROWSER":    "BROWSER",
   427  				"GH_BROWSER": "GH_BROWSER",
   428  			},
   429  			wantBrowser: "GH_BROWSER",
   430  		},
   431  	}
   432  	for _, tt := range tests {
   433  		t.Run(tt.name, func(t *testing.T) {
   434  			if tt.env != nil {
   435  				for k, v := range tt.env {
   436  					old := os.Getenv(k)
   437  					os.Setenv(k, v)
   438  					defer os.Setenv(k, old)
   439  				}
   440  			}
   441  			f := New("1")
   442  			f.Config = func() (config.Config, error) {
   443  				if tt.config == nil {
   444  					return config.NewBlankConfig(), nil
   445  				} else {
   446  					return tt.config, nil
   447  				}
   448  			}
   449  			browser := browserLauncher(f)
   450  			assert.Equal(t, tt.wantBrowser, browser)
   451  		})
   452  	}
   453  }
   454  
   455  func defaultConfig() config.Config {
   456  	return config.InheritEnv(config.NewFromString(heredoc.Doc(`
   457      hosts:
   458        nonsense.com:
   459          oauth_token: BLAH
   460  		`)))
   461  }
   462  
   463  func pagerConfig() config.Config {
   464  	return config.NewFromString("pager: CONFIG_PAGER")
   465  }
   466  
   467  func disablePromptConfig() config.Config {
   468  	return config.NewFromString("prompt: disabled")
   469  }