github.com/chelnak/go-gh@v0.0.2/internal/git/url_test.go (about)

     1  package git
     2  
     3  import (
     4  	"net/url"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  )
     9  
    10  func TestIsURL(t *testing.T) {
    11  	tests := []struct {
    12  		name string
    13  		url  string
    14  		want bool
    15  	}{
    16  		{
    17  			name: "scp-like",
    18  			url:  "git@example.com:owner/repo",
    19  			want: true,
    20  		},
    21  		{
    22  			name: "scp-like with no user",
    23  			url:  "example.com:owner/repo",
    24  			want: false,
    25  		},
    26  		{
    27  			name: "ssh",
    28  			url:  "ssh://git@example.com/owner/repo",
    29  			want: true,
    30  		},
    31  		{
    32  			name: "git",
    33  			url:  "git://example.com/owner/repo",
    34  			want: true,
    35  		},
    36  		{
    37  			name: "https",
    38  			url:  "https://example.com/owner/repo.git",
    39  			want: true,
    40  		},
    41  		{
    42  			name: "no protocol",
    43  			url:  "example.com/owner/repo",
    44  			want: false,
    45  		},
    46  	}
    47  	for _, tt := range tests {
    48  		t.Run(tt.name, func(t *testing.T) {
    49  			assert.Equal(t, tt.want, isURL(tt.url))
    50  		})
    51  	}
    52  }
    53  
    54  func TestParseURL(t *testing.T) {
    55  	type url struct {
    56  		Scheme string
    57  		User   string
    58  		Host   string
    59  		Path   string
    60  	}
    61  
    62  	tests := []struct {
    63  		name    string
    64  		url     string
    65  		want    url
    66  		wantErr bool
    67  	}{
    68  		{
    69  			name: "HTTPS",
    70  			url:  "https://example.com/owner/repo.git",
    71  			want: url{
    72  				Scheme: "https",
    73  				User:   "",
    74  				Host:   "example.com",
    75  				Path:   "/owner/repo.git",
    76  			},
    77  		},
    78  		{
    79  			name: "HTTP",
    80  			url:  "http://example.com/owner/repo.git",
    81  			want: url{
    82  				Scheme: "http",
    83  				User:   "",
    84  				Host:   "example.com",
    85  				Path:   "/owner/repo.git",
    86  			},
    87  		},
    88  		{
    89  			name: "git",
    90  			url:  "git://example.com/owner/repo.git",
    91  			want: url{
    92  				Scheme: "git",
    93  				User:   "",
    94  				Host:   "example.com",
    95  				Path:   "/owner/repo.git",
    96  			},
    97  		},
    98  		{
    99  			name: "ssh",
   100  			url:  "ssh://git@example.com/owner/repo.git",
   101  			want: url{
   102  				Scheme: "ssh",
   103  				User:   "git",
   104  				Host:   "example.com",
   105  				Path:   "/owner/repo.git",
   106  			},
   107  		},
   108  		{
   109  			name: "ssh with port",
   110  			url:  "ssh://git@example.com:443/owner/repo.git",
   111  			want: url{
   112  				Scheme: "ssh",
   113  				User:   "git",
   114  				Host:   "example.com",
   115  				Path:   "/owner/repo.git",
   116  			},
   117  		},
   118  		{
   119  			name: "git+ssh",
   120  			url:  "git+ssh://example.com/owner/repo.git",
   121  			want: url{
   122  				Scheme: "ssh",
   123  				User:   "",
   124  				Host:   "example.com",
   125  				Path:   "/owner/repo.git",
   126  			},
   127  		},
   128  		{
   129  			name: "scp-like",
   130  			url:  "git@example.com:owner/repo.git",
   131  			want: url{
   132  				Scheme: "ssh",
   133  				User:   "git",
   134  				Host:   "example.com",
   135  				Path:   "/owner/repo.git",
   136  			},
   137  		},
   138  		{
   139  			name: "scp-like, leading slash",
   140  			url:  "git@example.com:/owner/repo.git",
   141  			want: url{
   142  				Scheme: "ssh",
   143  				User:   "git",
   144  				Host:   "example.com",
   145  				Path:   "/owner/repo.git",
   146  			},
   147  		},
   148  		{
   149  			name: "file protocol",
   150  			url:  "file:///example.com/owner/repo.git",
   151  			want: url{
   152  				Scheme: "file",
   153  				User:   "",
   154  				Host:   "",
   155  				Path:   "/example.com/owner/repo.git",
   156  			},
   157  		},
   158  		{
   159  			name: "file path",
   160  			url:  "/example.com/owner/repo.git",
   161  			want: url{
   162  				Scheme: "",
   163  				User:   "",
   164  				Host:   "",
   165  				Path:   "/example.com/owner/repo.git",
   166  			},
   167  		},
   168  		{
   169  			name: "Windows file path",
   170  			url:  "C:\\example.com\\owner\\repo.git",
   171  			want: url{
   172  				Scheme: "c",
   173  				User:   "",
   174  				Host:   "",
   175  				Path:   "",
   176  			},
   177  		},
   178  	}
   179  	for _, tt := range tests {
   180  		t.Run(tt.name, func(t *testing.T) {
   181  			u, err := parseURL(tt.url)
   182  			if tt.wantErr {
   183  				assert.Error(t, err)
   184  				return
   185  			}
   186  			assert.NoError(t, err)
   187  			assert.Equal(t, tt.want.Scheme, u.Scheme)
   188  			assert.Equal(t, tt.want.User, u.User.Username())
   189  			assert.Equal(t, tt.want.Host, u.Host)
   190  			assert.Equal(t, tt.want.Path, u.Path)
   191  		})
   192  	}
   193  }
   194  
   195  func TestRepoInfoFromURL(t *testing.T) {
   196  	tests := []struct {
   197  		name       string
   198  		input      string
   199  		wantHost   string
   200  		wantOwner  string
   201  		wantRepo   string
   202  		wantErr    bool
   203  		wantErrMsg string
   204  	}{
   205  		{
   206  			name:      "github.com URL",
   207  			input:     "https://github.com/monalisa/octo-cat.git",
   208  			wantHost:  "github.com",
   209  			wantOwner: "monalisa",
   210  			wantRepo:  "octo-cat",
   211  		},
   212  		{
   213  			name:      "github.com URL with trailing slash",
   214  			input:     "https://github.com/monalisa/octo-cat/",
   215  			wantHost:  "github.com",
   216  			wantOwner: "monalisa",
   217  			wantRepo:  "octo-cat",
   218  		},
   219  		{
   220  			name:      "www.github.com URL",
   221  			input:     "http://www.GITHUB.com/monalisa/octo-cat.git",
   222  			wantHost:  "github.com",
   223  			wantOwner: "monalisa",
   224  			wantRepo:  "octo-cat",
   225  		},
   226  		{
   227  			name:       "too many path components",
   228  			input:      "https://github.com/monalisa/octo-cat/pulls",
   229  			wantErr:    true,
   230  			wantErrMsg: "invalid path: /monalisa/octo-cat/pulls",
   231  		},
   232  		{
   233  			name:      "non-GitHub hostname",
   234  			input:     "https://example.com/one/two",
   235  			wantHost:  "example.com",
   236  			wantOwner: "one",
   237  			wantRepo:  "two",
   238  		},
   239  		{
   240  			name:       "filesystem path",
   241  			input:      "/path/to/file",
   242  			wantErr:    true,
   243  			wantErrMsg: "no hostname detected",
   244  		},
   245  		{
   246  			name:       "filesystem path with scheme",
   247  			input:      "file:///path/to/file",
   248  			wantErr:    true,
   249  			wantErrMsg: "no hostname detected",
   250  		},
   251  		{
   252  			name:      "github.com SSH URL",
   253  			input:     "ssh://github.com/monalisa/octo-cat.git",
   254  			wantHost:  "github.com",
   255  			wantOwner: "monalisa",
   256  			wantRepo:  "octo-cat",
   257  		},
   258  		{
   259  			name:      "github.com HTTPS+SSH URL",
   260  			input:     "https+ssh://github.com/monalisa/octo-cat.git",
   261  			wantHost:  "github.com",
   262  			wantOwner: "monalisa",
   263  			wantRepo:  "octo-cat",
   264  		},
   265  		{
   266  			name:      "github.com git URL",
   267  			input:     "git://github.com/monalisa/octo-cat.git",
   268  			wantHost:  "github.com",
   269  			wantOwner: "monalisa",
   270  			wantRepo:  "octo-cat",
   271  		},
   272  	}
   273  
   274  	for _, tt := range tests {
   275  		t.Run(tt.name, func(t *testing.T) {
   276  			u, err := url.Parse(tt.input)
   277  			assert.NoError(t, err)
   278  			host, owner, repo, err := repoInfoFromURL(u)
   279  			if tt.wantErr {
   280  				assert.EqualError(t, err, tt.wantErrMsg)
   281  				return
   282  			}
   283  			assert.NoError(t, err)
   284  			assert.Equal(t, tt.wantHost, host)
   285  			assert.Equal(t, tt.wantOwner, owner)
   286  			assert.Equal(t, tt.wantRepo, repo)
   287  		})
   288  	}
   289  }