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 }