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: "git with extension",
38 url: "git://example.com/owner/repo.git",
39 want: true,
40 },
41 {
42 name: "git+ssh",
43 url: "git+ssh://git@example.com/owner/repo.git",
44 want: true,
45 },
46 {
47 name: "git+https",
48 url: "git+https://example.com/owner/repo.git",
49 want: true,
50 },
51 {
52 name: "http",
53 url: "http://example.com/owner/repo.git",
54 want: true,
55 },
56 {
57 name: "https",
58 url: "https://example.com/owner/repo.git",
59 want: true,
60 },
61 {
62 name: "no protocol",
63 url: "example.com/owner/repo",
64 want: false,
65 },
66 }
67 for _, tt := range tests {
68 t.Run(tt.name, func(t *testing.T) {
69 assert.Equal(t, tt.want, IsURL(tt.url))
70 })
71 }
72 }
73
74 func TestParseURL(t *testing.T) {
75 type url struct {
76 Scheme string
77 User string
78 Host string
79 Path string
80 }
81
82 tests := []struct {
83 name string
84 url string
85 want url
86 wantErr bool
87 }{
88 {
89 name: "HTTPS",
90 url: "https://example.com/owner/repo.git",
91 want: url{
92 Scheme: "https",
93 User: "",
94 Host: "example.com",
95 Path: "/owner/repo.git",
96 },
97 },
98 {
99 name: "HTTP",
100 url: "http://example.com/owner/repo.git",
101 want: url{
102 Scheme: "http",
103 User: "",
104 Host: "example.com",
105 Path: "/owner/repo.git",
106 },
107 },
108 {
109 name: "git",
110 url: "git://example.com/owner/repo.git",
111 want: url{
112 Scheme: "git",
113 User: "",
114 Host: "example.com",
115 Path: "/owner/repo.git",
116 },
117 },
118 {
119 name: "ssh",
120 url: "ssh://git@example.com/owner/repo.git",
121 want: url{
122 Scheme: "ssh",
123 User: "git",
124 Host: "example.com",
125 Path: "/owner/repo.git",
126 },
127 },
128 {
129 name: "ssh with port",
130 url: "ssh://git@example.com:443/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: "git+ssh",
140 url: "git+ssh://example.com/owner/repo.git",
141 want: url{
142 Scheme: "ssh",
143 User: "",
144 Host: "example.com",
145 Path: "/owner/repo.git",
146 },
147 },
148 {
149 name: "git+https",
150 url: "git+https://example.com/owner/repo.git",
151 want: url{
152 Scheme: "https",
153 User: "",
154 Host: "example.com",
155 Path: "/owner/repo.git",
156 },
157 },
158 {
159 name: "scp-like",
160 url: "git@example.com:owner/repo.git",
161 want: url{
162 Scheme: "ssh",
163 User: "git",
164 Host: "example.com",
165 Path: "/owner/repo.git",
166 },
167 },
168 {
169 name: "scp-like, leading slash",
170 url: "git@example.com:/owner/repo.git",
171 want: url{
172 Scheme: "ssh",
173 User: "git",
174 Host: "example.com",
175 Path: "/owner/repo.git",
176 },
177 },
178 {
179 name: "file protocol",
180 url: "file:///example.com/owner/repo.git",
181 want: url{
182 Scheme: "file",
183 User: "",
184 Host: "",
185 Path: "/example.com/owner/repo.git",
186 },
187 },
188 {
189 name: "file path",
190 url: "/example.com/owner/repo.git",
191 want: url{
192 Scheme: "",
193 User: "",
194 Host: "",
195 Path: "/example.com/owner/repo.git",
196 },
197 },
198 {
199 name: "Windows file path",
200 url: "C:\\example.com\\owner\\repo.git",
201 want: url{
202 Scheme: "c",
203 User: "",
204 Host: "",
205 Path: "",
206 },
207 },
208 }
209 for _, tt := range tests {
210 t.Run(tt.name, func(t *testing.T) {
211 u, err := ParseURL(tt.url)
212 if tt.wantErr {
213 assert.Error(t, err)
214 return
215 }
216 assert.NoError(t, err)
217 assert.Equal(t, tt.want.Scheme, u.Scheme)
218 assert.Equal(t, tt.want.User, u.User.Username())
219 assert.Equal(t, tt.want.Host, u.Host)
220 assert.Equal(t, tt.want.Path, u.Path)
221 })
222 }
223 }
224
225 func TestRepoInfoFromURL(t *testing.T) {
226 tests := []struct {
227 name string
228 input string
229 wantHost string
230 wantOwner string
231 wantRepo string
232 wantErr bool
233 wantErrMsg string
234 }{
235 {
236 name: "github.com URL",
237 input: "https://github.com/monalisa/octo-cat.git",
238 wantHost: "github.com",
239 wantOwner: "monalisa",
240 wantRepo: "octo-cat",
241 },
242 {
243 name: "github.com URL with trailing slash",
244 input: "https://github.com/monalisa/octo-cat/",
245 wantHost: "github.com",
246 wantOwner: "monalisa",
247 wantRepo: "octo-cat",
248 },
249 {
250 name: "www.github.com URL",
251 input: "http://www.GITHUB.com/monalisa/octo-cat.git",
252 wantHost: "github.com",
253 wantOwner: "monalisa",
254 wantRepo: "octo-cat",
255 },
256 {
257 name: "too many path components",
258 input: "https://github.com/monalisa/octo-cat/pulls",
259 wantErr: true,
260 wantErrMsg: "invalid path: /monalisa/octo-cat/pulls",
261 },
262 {
263 name: "non-GitHub hostname",
264 input: "https://example.com/one/two",
265 wantHost: "example.com",
266 wantOwner: "one",
267 wantRepo: "two",
268 },
269 {
270 name: "filesystem path",
271 input: "/path/to/file",
272 wantErr: true,
273 wantErrMsg: "no hostname detected",
274 },
275 {
276 name: "filesystem path with scheme",
277 input: "file:///path/to/file",
278 wantErr: true,
279 wantErrMsg: "no hostname detected",
280 },
281 {
282 name: "github.com SSH URL",
283 input: "ssh://github.com/monalisa/octo-cat.git",
284 wantHost: "github.com",
285 wantOwner: "monalisa",
286 wantRepo: "octo-cat",
287 },
288 {
289 name: "github.com HTTPS+SSH URL",
290 input: "https+ssh://github.com/monalisa/octo-cat.git",
291 wantHost: "github.com",
292 wantOwner: "monalisa",
293 wantRepo: "octo-cat",
294 },
295 {
296 name: "github.com git URL",
297 input: "git://github.com/monalisa/octo-cat.git",
298 wantHost: "github.com",
299 wantOwner: "monalisa",
300 wantRepo: "octo-cat",
301 },
302 }
303
304 for _, tt := range tests {
305 t.Run(tt.name, func(t *testing.T) {
306 u, err := url.Parse(tt.input)
307 assert.NoError(t, err)
308 host, owner, repo, err := RepoInfoFromURL(u)
309 if tt.wantErr {
310 assert.EqualError(t, err, tt.wantErrMsg)
311 return
312 }
313 assert.NoError(t, err)
314 assert.Equal(t, tt.wantHost, host)
315 assert.Equal(t, tt.wantOwner, owner)
316 assert.Equal(t, tt.wantRepo, repo)
317 })
318 }
319 }
320
View as plain text