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: &reg}, 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  }