github.com/cli/cli@v1.14.1-0.20210902173923-1af6a669e342/pkg/cmd/browse/browse_test.go (about) 1 package browse 2 3 import ( 4 "fmt" 5 "net/http" 6 "testing" 7 8 "github.com/cli/cli/internal/ghrepo" 9 "github.com/cli/cli/pkg/cmdutil" 10 "github.com/cli/cli/pkg/httpmock" 11 "github.com/cli/cli/pkg/iostreams" 12 "github.com/google/shlex" 13 "github.com/stretchr/testify/assert" 14 ) 15 16 func TestNewCmdBrowse(t *testing.T) { 17 tests := []struct { 18 name string 19 cli string 20 factory func(*cmdutil.Factory) *cmdutil.Factory 21 wants BrowseOptions 22 wantsErr bool 23 }{ 24 { 25 name: "no arguments", 26 cli: "", 27 wantsErr: false, 28 }, 29 { 30 name: "settings flag", 31 cli: "--settings", 32 wants: BrowseOptions{ 33 SettingsFlag: true, 34 }, 35 wantsErr: false, 36 }, 37 { 38 name: "projects flag", 39 cli: "--projects", 40 wants: BrowseOptions{ 41 ProjectsFlag: true, 42 }, 43 wantsErr: false, 44 }, 45 { 46 name: "wiki flag", 47 cli: "--wiki", 48 wants: BrowseOptions{ 49 WikiFlag: true, 50 }, 51 wantsErr: false, 52 }, 53 { 54 name: "no browser flag", 55 cli: "--no-browser", 56 wants: BrowseOptions{ 57 NoBrowserFlag: true, 58 }, 59 wantsErr: false, 60 }, 61 { 62 name: "branch flag", 63 cli: "--branch main", 64 wants: BrowseOptions{ 65 Branch: "main", 66 }, 67 wantsErr: false, 68 }, 69 { 70 name: "branch flag without a branch name", 71 cli: "--branch", 72 wantsErr: true, 73 }, 74 { 75 name: "combination: settings projects", 76 cli: "--settings --projects", 77 wants: BrowseOptions{ 78 SettingsFlag: true, 79 ProjectsFlag: true, 80 }, 81 wantsErr: true, 82 }, 83 { 84 name: "combination: projects wiki", 85 cli: "--projects --wiki", 86 wants: BrowseOptions{ 87 ProjectsFlag: true, 88 WikiFlag: true, 89 }, 90 wantsErr: true, 91 }, 92 { 93 name: "passed argument", 94 cli: "main.go", 95 wants: BrowseOptions{ 96 SelectorArg: "main.go", 97 }, 98 wantsErr: false, 99 }, 100 { 101 name: "passed two arguments", 102 cli: "main.go main.go", 103 wantsErr: true, 104 }, 105 } 106 for _, tt := range tests { 107 t.Run(tt.name, func(t *testing.T) { 108 f := cmdutil.Factory{} 109 var opts *BrowseOptions 110 cmd := NewCmdBrowse(&f, func(o *BrowseOptions) error { 111 opts = o 112 return nil 113 }) 114 argv, err := shlex.Split(tt.cli) 115 assert.NoError(t, err) 116 cmd.SetArgs(argv) 117 _, err = cmd.ExecuteC() 118 119 if tt.wantsErr { 120 assert.Error(t, err) 121 return 122 } else { 123 assert.NoError(t, err) 124 } 125 126 assert.Equal(t, tt.wants.Branch, opts.Branch) 127 assert.Equal(t, tt.wants.SelectorArg, opts.SelectorArg) 128 assert.Equal(t, tt.wants.ProjectsFlag, opts.ProjectsFlag) 129 assert.Equal(t, tt.wants.WikiFlag, opts.WikiFlag) 130 assert.Equal(t, tt.wants.NoBrowserFlag, opts.NoBrowserFlag) 131 assert.Equal(t, tt.wants.SettingsFlag, opts.SettingsFlag) 132 }) 133 } 134 } 135 136 func Test_runBrowse(t *testing.T) { 137 tests := []struct { 138 name string 139 opts BrowseOptions 140 baseRepo ghrepo.Interface 141 defaultBranch string 142 expectedURL string 143 wantsErr bool 144 }{ 145 { 146 name: "no arguments", 147 opts: BrowseOptions{ 148 SelectorArg: "", 149 }, 150 baseRepo: ghrepo.New("jlsestak", "cli"), 151 expectedURL: "https://github.com/jlsestak/cli", 152 }, 153 { 154 name: "settings flag", 155 opts: BrowseOptions{ 156 SettingsFlag: true, 157 }, 158 baseRepo: ghrepo.New("bchadwic", "ObscuredByClouds"), 159 expectedURL: "https://github.com/bchadwic/ObscuredByClouds/settings", 160 }, 161 { 162 name: "projects flag", 163 opts: BrowseOptions{ 164 ProjectsFlag: true, 165 }, 166 baseRepo: ghrepo.New("ttran112", "7ate9"), 167 expectedURL: "https://github.com/ttran112/7ate9/projects", 168 }, 169 { 170 name: "wiki flag", 171 opts: BrowseOptions{ 172 WikiFlag: true, 173 }, 174 baseRepo: ghrepo.New("ravocean", "ThreatLevelMidnight"), 175 expectedURL: "https://github.com/ravocean/ThreatLevelMidnight/wiki", 176 }, 177 { 178 name: "file argument", 179 opts: BrowseOptions{SelectorArg: "path/to/file.txt"}, 180 baseRepo: ghrepo.New("ken", "mrprofessor"), 181 defaultBranch: "main", 182 expectedURL: "https://github.com/ken/mrprofessor/tree/main/path/to/file.txt", 183 }, 184 { 185 name: "issue argument", 186 opts: BrowseOptions{ 187 SelectorArg: "217", 188 }, 189 baseRepo: ghrepo.New("kevin", "MinTy"), 190 expectedURL: "https://github.com/kevin/MinTy/issues/217", 191 }, 192 { 193 name: "branch flag", 194 opts: BrowseOptions{ 195 Branch: "trunk", 196 }, 197 baseRepo: ghrepo.New("jlsestak", "CouldNotThinkOfARepoName"), 198 expectedURL: "https://github.com/jlsestak/CouldNotThinkOfARepoName/tree/trunk/", 199 }, 200 { 201 name: "branch flag with file", 202 opts: BrowseOptions{ 203 Branch: "trunk", 204 SelectorArg: "main.go", 205 }, 206 baseRepo: ghrepo.New("bchadwic", "LedZeppelinIV"), 207 expectedURL: "https://github.com/bchadwic/LedZeppelinIV/tree/trunk/main.go", 208 }, 209 { 210 name: "file with line number", 211 opts: BrowseOptions{ 212 SelectorArg: "path/to/file.txt:32", 213 }, 214 baseRepo: ghrepo.New("ravocean", "angur"), 215 defaultBranch: "trunk", 216 expectedURL: "https://github.com/ravocean/angur/tree/trunk/path/to/file.txt#L32", 217 }, 218 { 219 name: "file with line range", 220 opts: BrowseOptions{ 221 SelectorArg: "path/to/file.txt:32-40", 222 }, 223 baseRepo: ghrepo.New("ravocean", "angur"), 224 defaultBranch: "trunk", 225 expectedURL: "https://github.com/ravocean/angur/tree/trunk/path/to/file.txt#L32-L40", 226 }, 227 { 228 name: "file with invalid line number", 229 opts: BrowseOptions{ 230 SelectorArg: "path/to/file.txt:32:32", 231 }, 232 baseRepo: ghrepo.New("ttran112", "ttrain211"), 233 wantsErr: true, 234 }, 235 { 236 name: "file with invalid line range", 237 opts: BrowseOptions{ 238 SelectorArg: "path/to/file.txt:32-abc", 239 }, 240 baseRepo: ghrepo.New("ttran112", "ttrain211"), 241 wantsErr: true, 242 }, 243 { 244 name: "branch with issue number", 245 opts: BrowseOptions{ 246 SelectorArg: "217", 247 Branch: "trunk", 248 }, 249 baseRepo: ghrepo.New("ken", "grc"), 250 wantsErr: false, 251 expectedURL: "https://github.com/ken/grc/issues/217", 252 }, 253 { 254 name: "opening branch file with line number", 255 opts: BrowseOptions{ 256 Branch: "first-browse-pull", 257 SelectorArg: "browse.go:32", 258 }, 259 baseRepo: ghrepo.New("github", "ThankYouGitHub"), 260 wantsErr: false, 261 expectedURL: "https://github.com/github/ThankYouGitHub/tree/first-browse-pull/browse.go#L32", 262 }, 263 { 264 name: "no browser with branch file and line number", 265 opts: BrowseOptions{ 266 Branch: "3-0-stable", 267 SelectorArg: "init.rb:6", 268 NoBrowserFlag: true, 269 }, 270 baseRepo: ghrepo.New("mislav", "will_paginate"), 271 wantsErr: false, 272 expectedURL: "https://github.com/mislav/will_paginate/tree/3-0-stable/init.rb#L6", 273 }, 274 } 275 276 for _, tt := range tests { 277 t.Run(tt.name, func(t *testing.T) { 278 io, _, stdout, stderr := iostreams.Test() 279 browser := cmdutil.TestBrowser{} 280 281 reg := httpmock.Registry{} 282 defer reg.Verify(t) 283 if tt.defaultBranch != "" { 284 reg.StubRepoInfoResponse(tt.baseRepo.RepoOwner(), tt.baseRepo.RepoName(), tt.defaultBranch) 285 } 286 287 opts := tt.opts 288 opts.IO = io 289 opts.BaseRepo = func() (ghrepo.Interface, error) { 290 return tt.baseRepo, nil 291 } 292 opts.HttpClient = func() (*http.Client, error) { 293 return &http.Client{Transport: ®}, nil 294 } 295 opts.Browser = &browser 296 297 err := runBrowse(&opts) 298 if tt.wantsErr { 299 assert.Error(t, err) 300 } else { 301 assert.NoError(t, err) 302 } 303 304 if opts.NoBrowserFlag { 305 assert.Equal(t, fmt.Sprintf("%s\n", tt.expectedURL), stdout.String()) 306 assert.Equal(t, "", stderr.String()) 307 browser.Verify(t, "") 308 } else { 309 assert.Equal(t, "", stdout.String()) 310 assert.Equal(t, "", stderr.String()) 311 browser.Verify(t, tt.expectedURL) 312 } 313 }) 314 } 315 } 316 317 func Test_parseFileArg(t *testing.T) { 318 tests := []struct { 319 name string 320 arg string 321 errorExpected bool 322 expectedFileArg string 323 stderrExpected string 324 }{ 325 { 326 name: "non line number", 327 arg: "main.go", 328 errorExpected: false, 329 expectedFileArg: "main.go", 330 }, 331 { 332 name: "line number", 333 arg: "main.go:32", 334 errorExpected: false, 335 expectedFileArg: "main.go#L32", 336 }, 337 { 338 name: "non line number error", 339 arg: "ma:in.go", 340 errorExpected: true, 341 stderrExpected: "invalid line number after colon\nUse 'gh browse --help' for more information about browse\n", 342 }, 343 } 344 for _, tt := range tests { 345 fileArg, err := parseFileArg(tt.arg) 346 if tt.errorExpected { 347 assert.Equal(t, err.Error(), tt.stderrExpected) 348 } else { 349 assert.Equal(t, err, nil) 350 assert.Equal(t, tt.expectedFileArg, fileArg) 351 } 352 } 353 }