Skip to content

Commit e71ff69

Browse files
committed
Add unit tests for setting a size label of a pull request
1 parent 35faae7 commit e71ff69

File tree

1 file changed

+322
-18
lines changed

1 file changed

+322
-18
lines changed

cmd/gh-actions-pr-size/github_test.go

Lines changed: 322 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"context"
5+
"encoding/json"
56
"fmt"
67
"net/http"
78
"strconv"
@@ -84,32 +85,16 @@ func TestGetPullRequestChangedLines(t *testing.T) {
8485
"GET",
8586
baseURL,
8687
func(req *http.Request) (*http.Response, error) {
87-
page := 1
88-
if v, ok := req.URL.Query()["page"]; ok && len(v) > 0 {
89-
if v, err := strconv.Atoi(v[0]); err == nil {
90-
page = v
91-
}
92-
}
88+
page := getPage(req)
9389
if page-1 >= len(tt.commitFiles) {
9490
return nil, fmt.Errorf("invalid query value")
9591
}
96-
97-
var links []string
98-
links = append(links, fmt.Sprintf(`<%s?page=%d>; rel="first"`, baseURL, 1))
99-
if page-1 >= 1 {
100-
links = append(links, fmt.Sprintf(`<%s?page=%d>; rel="prev"`, baseURL, page-1))
101-
}
102-
if page+1 <= len(tt.commitFiles) {
103-
links = append(links, fmt.Sprintf(`<%s?page=%d>; rel="next"`, baseURL, page+1))
104-
}
105-
links = append(links, fmt.Sprintf(`<%s?page=%d>; rel="last"`, baseURL, len(tt.commitFiles)))
106-
10792
resp, err := httpmock.NewJsonResponse(200, tt.commitFiles[page-1])
10893
if err != nil {
10994
return nil, err
11095
}
11196
resp.Header.Set("Content-Type", "application/json")
112-
resp.Header.Set("Link", strings.Join(links, ", "))
97+
resp.Header.Set("Link", generateLinkHeaderValue(baseURL, page, len(tt.commitFiles)))
11398
return resp, nil
11499
},
115100
)
@@ -149,3 +134,322 @@ func TestGetPullRequestChangedLinesReturnsError(t *testing.T) {
149134
assert.ErrorContains(t, err, "get all commit files: list commit files: ")
150135
assert.Zero(t, got)
151136
}
137+
138+
func TestSetLabelOnPullRequest(t *testing.T) {
139+
tcs := []struct {
140+
name string
141+
labels [][]*github.Label
142+
size size
143+
144+
wantDeletedLabels []string
145+
wantCreatedLabels []string
146+
}{
147+
{
148+
name: "The pull request doesn't have labels.",
149+
labels: [][]*github.Label{
150+
{},
151+
},
152+
size: sizeXL,
153+
wantCreatedLabels: []string{
154+
sizeXL.getLabel(),
155+
},
156+
},
157+
{
158+
name: "The pull request already has another size label.",
159+
labels: [][]*github.Label{
160+
{
161+
{
162+
Name: github.String(sizeL.getLabel()),
163+
},
164+
},
165+
},
166+
size: sizeXL,
167+
wantDeletedLabels: []string{
168+
sizeL.getLabel(),
169+
},
170+
wantCreatedLabels: []string{
171+
sizeXL.getLabel(),
172+
},
173+
},
174+
{
175+
name: "The pull request already has the target size label.",
176+
labels: [][]*github.Label{
177+
{
178+
{
179+
Name: github.String(sizeXL.getLabel()),
180+
},
181+
},
182+
},
183+
size: sizeXL,
184+
},
185+
{
186+
name: "The pull request has another size label and non-size labels.",
187+
labels: [][]*github.Label{
188+
{
189+
{
190+
Name: github.String("foo"),
191+
},
192+
},
193+
{
194+
{
195+
Name: github.String("bar"),
196+
},
197+
{
198+
Name: github.String(sizeS.getLabel()),
199+
},
200+
{
201+
Name: github.String("baz"),
202+
},
203+
},
204+
{
205+
{
206+
Name: github.String("qux"),
207+
},
208+
},
209+
},
210+
size: sizeM,
211+
wantDeletedLabels: []string{
212+
sizeS.getLabel(),
213+
},
214+
wantCreatedLabels: []string{
215+
sizeM.getLabel(),
216+
},
217+
},
218+
{
219+
name: "The pull request has multiple size labels.",
220+
labels: [][]*github.Label{
221+
{
222+
{
223+
Name: github.String(sizeL.getLabel()),
224+
},
225+
{
226+
Name: github.String(sizeM.getLabel()),
227+
},
228+
},
229+
},
230+
size: sizeXL,
231+
wantDeletedLabels: []string{
232+
sizeL.getLabel(),
233+
sizeM.getLabel(),
234+
},
235+
wantCreatedLabels: []string{
236+
sizeXL.getLabel(),
237+
},
238+
},
239+
}
240+
for _, tt := range tcs {
241+
t.Run(tt.name, func(t *testing.T) {
242+
client := &http.Client{}
243+
httpmock.ActivateNonDefault(client)
244+
defer httpmock.DeactivateAndReset()
245+
246+
var (
247+
gotDeletedLabels []string
248+
gotCreatedLabels []string
249+
)
250+
const baseURL = "https://api.github.com/repos/kkohtaka/gh-actions-pr-size/issues/42/labels"
251+
httpmock.RegisterResponder(
252+
"GET",
253+
baseURL,
254+
func(req *http.Request) (*http.Response, error) {
255+
page := getPage(req)
256+
if page-1 >= len(tt.labels) {
257+
return nil, fmt.Errorf("invalid query value")
258+
}
259+
resp, err := httpmock.NewJsonResponse(200, tt.labels[page-1])
260+
if err != nil {
261+
return nil, err
262+
}
263+
resp.Header.Set("Content-Type", "application/json")
264+
resp.Header.Set("Link", generateLinkHeaderValue(baseURL, page, len(tt.labels)))
265+
return resp, nil
266+
},
267+
)
268+
httpmock.RegisterResponder(
269+
"DELETE",
270+
fmt.Sprintf("=~^%s/(.*)$", baseURL),
271+
func(req *http.Request) (*http.Response, error) {
272+
label, err := httpmock.GetSubmatch(req, 1)
273+
if err != nil {
274+
return httpmock.NewStringResponse(400, "unable to get a label name"), nil
275+
}
276+
gotDeletedLabels = append(gotDeletedLabels, label)
277+
resp := httpmock.NewBytesResponse(200, nil)
278+
resp.Header.Set("Content-Type", "application/json")
279+
return resp, nil
280+
},
281+
)
282+
httpmock.RegisterResponder(
283+
"POST",
284+
baseURL,
285+
func(req *http.Request) (*http.Response, error) {
286+
var labels []string
287+
if err := json.NewDecoder(req.Body).Decode(&labels); err != nil {
288+
return httpmock.NewStringResponse(
289+
400,
290+
fmt.Sprintf("unable to decode request body: %v", err),
291+
), nil
292+
}
293+
gotCreatedLabels = append(gotCreatedLabels, labels...)
294+
resp := httpmock.NewBytesResponse(200, nil)
295+
resp.Header.Set("Content-Type", "application/json")
296+
return resp, nil
297+
},
298+
)
299+
300+
err := setLabelOnPullRequest(
301+
context.Background(),
302+
github.NewClient(client),
303+
"kkohtaka",
304+
"gh-actions-pr-size",
305+
42,
306+
tt.size,
307+
)
308+
require.NoError(t, err)
309+
310+
assert.Equal(t, tt.wantDeletedLabels, gotDeletedLabels)
311+
assert.Equal(t, tt.wantCreatedLabels, gotCreatedLabels)
312+
})
313+
}
314+
}
315+
316+
func TestSetLabelOnPullRequestReturnsError(t *testing.T) {
317+
const baseURL = "https://api.github.com/repos/kkohtaka/gh-actions-pr-size/issues/42/labels"
318+
319+
t.Run(
320+
"GitHub API that listing issue labels returns an error.",
321+
func(t *testing.T) {
322+
client := &http.Client{}
323+
httpmock.ActivateNonDefault(client)
324+
defer httpmock.DeactivateAndReset()
325+
326+
httpmock.RegisterResponder(
327+
"GET",
328+
baseURL,
329+
httpmock.NewErrorResponder(fmt.Errorf("test for error handling")),
330+
)
331+
332+
err := setLabelOnPullRequest(
333+
context.Background(),
334+
github.NewClient(client),
335+
"kkohtaka",
336+
"gh-actions-pr-size",
337+
42,
338+
sizeXL,
339+
)
340+
assert.ErrorContains(t, err, "list labels by issue: ")
341+
},
342+
)
343+
344+
t.Run(
345+
"GitHub API that deleting an issue label returns an error.",
346+
func(t *testing.T) {
347+
client := &http.Client{}
348+
httpmock.ActivateNonDefault(client)
349+
defer httpmock.DeactivateAndReset()
350+
351+
httpmock.RegisterResponder(
352+
"GET",
353+
baseURL,
354+
func(req *http.Request) (*http.Response, error) {
355+
resp, err := httpmock.NewJsonResponse(200, []*github.Label{
356+
{
357+
Name: github.String(sizeL.getLabel()),
358+
},
359+
})
360+
if err != nil {
361+
return nil, err
362+
}
363+
resp.Header.Set("Content-Type", "application/json")
364+
resp.Header.Set("Link", generateLinkHeaderValue(baseURL, 1, 1))
365+
return resp, nil
366+
},
367+
)
368+
httpmock.RegisterResponder(
369+
"DELETE",
370+
fmt.Sprintf("%s/%s", baseURL, sizeL.getLabel()),
371+
httpmock.NewErrorResponder(fmt.Errorf("test for error handling")),
372+
)
373+
374+
err := setLabelOnPullRequest(
375+
context.Background(),
376+
github.NewClient(client),
377+
"kkohtaka",
378+
"gh-actions-pr-size",
379+
42,
380+
sizeXL,
381+
)
382+
assert.ErrorContains(t, err, "remove a label from a pull request: ")
383+
},
384+
)
385+
386+
t.Run(
387+
"GitHub API that creating an issue label returns an error.",
388+
func(t *testing.T) {
389+
client := &http.Client{}
390+
httpmock.ActivateNonDefault(client)
391+
defer httpmock.DeactivateAndReset()
392+
393+
httpmock.RegisterResponder(
394+
"GET",
395+
baseURL,
396+
func(req *http.Request) (*http.Response, error) {
397+
resp, err := httpmock.NewJsonResponse(200, []*github.Label{
398+
{
399+
Name: github.String(sizeL.getLabel()),
400+
},
401+
})
402+
if err != nil {
403+
return nil, err
404+
}
405+
resp.Header.Set("Content-Type", "application/json")
406+
resp.Header.Set("Link", generateLinkHeaderValue(baseURL, 1, 1))
407+
return resp, nil
408+
},
409+
)
410+
httpmock.RegisterResponder(
411+
"DELETE",
412+
fmt.Sprintf("%s/%s", baseURL, sizeL.getLabel()),
413+
httpmock.NewBytesResponder(200, nil),
414+
)
415+
httpmock.RegisterResponder(
416+
"POST",
417+
baseURL,
418+
httpmock.NewErrorResponder(fmt.Errorf("test for error handling")),
419+
)
420+
421+
err := setLabelOnPullRequest(
422+
context.Background(),
423+
github.NewClient(client),
424+
"kkohtaka",
425+
"gh-actions-pr-size",
426+
42,
427+
sizeXL,
428+
)
429+
assert.ErrorContains(t, err, "add a label to a pull request: ")
430+
},
431+
)
432+
}
433+
434+
func getPage(req *http.Request) int {
435+
page := 1
436+
if v, ok := req.URL.Query()["page"]; ok && len(v) > 0 {
437+
if v, err := strconv.Atoi(v[0]); err == nil {
438+
page = v
439+
}
440+
}
441+
return page
442+
}
443+
444+
func generateLinkHeaderValue(baseURL string, page, amount int) string {
445+
var links []string
446+
links = append(links, fmt.Sprintf(`<%s?page=%d>; rel="first"`, baseURL, 1))
447+
if page-1 >= 1 {
448+
links = append(links, fmt.Sprintf(`<%s?page=%d>; rel="prev"`, baseURL, page-1))
449+
}
450+
if page+1 <= amount {
451+
links = append(links, fmt.Sprintf(`<%s?page=%d>; rel="next"`, baseURL, page+1))
452+
}
453+
links = append(links, fmt.Sprintf(`<%s?page=%d>; rel="last"`, baseURL, amount))
454+
return strings.Join(links, ", ")
455+
}

0 commit comments

Comments
 (0)