Skip to content

Commit 833a876

Browse files
committed
mock github and fix test cases
1 parent 8b3ece5 commit 833a876

File tree

4 files changed

+216
-75
lines changed

4 files changed

+216
-75
lines changed

hack/tools/release/notes/github.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@ type githubClient struct {
3535
repo string
3636
}
3737

38+
// githubClientInterface defines the interface for GitHub client operations
39+
// to allow for mocking in tests
40+
type githubClientInterface interface {
41+
getDiffAllCommits(base, head string) (*githubDiff, error)
42+
getRef(ref string) (githubRef, error)
43+
getTag(tagSHA string) (githubTag, error)
44+
getCommit(sha string) (githubCommit, error)
45+
listMergedPRs(after, before time.Time, baseBranches ...string) ([]githubPR, error)
46+
}
47+
48+
// Ensure githubClient implements githubClientInterface
49+
var _ githubClientInterface = (*githubClient)(nil)
50+
3851
// githubDiff is the API response for the "compare" endpoint.
3952
type githubDiff struct {
4053
// MergeBaseCommit points to most recent common ancestor between two references.

hack/tools/release/notes/list.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import (
3030

3131
// githubFromToPRLister lists PRs from GitHub contained between two refs.
3232
type githubFromToPRLister struct {
33-
client *githubClient
33+
client githubClientInterface
3434
fromRef, toRef ref
3535
// branch is optional. It helps optimize the PR query by restricting
3636
// the results to PRs merged in the selected branch and in main
@@ -46,6 +46,17 @@ func newGithubFromToPRLister(repo string, fromRef, toRef ref, branch string) *gi
4646
}
4747
}
4848

49+
// newGithubFromToPRListerWithClient creates a new lister with a custom client
50+
// for testing purposes
51+
func newGithubFromToPRListerWithClient(client githubClientInterface, fromRef, toRef ref, branch string) *githubFromToPRLister {
52+
return &githubFromToPRLister{
53+
client: client,
54+
fromRef: fromRef,
55+
toRef: toRef,
56+
branch: branch,
57+
}
58+
}
59+
4960
// listPRs returns the PRs merged between `fromRef` and `toRef` (included).
5061
// It lists all PRs merged in main in the configured branch in the date
5162
// range between fromRef and toRef (we include main because minor releases

hack/tools/release/notes/list_test.go

Lines changed: 33 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ limitations under the License.
2020
package main
2121

2222
import (
23+
"fmt"
2324
"testing"
2425

2526
. "github.com/onsi/gomega"
@@ -69,26 +70,18 @@ func Test_buildSetOfPRNumbers(t *testing.T) {
6970
func Test_githubFromToPRLister_listPRs(t *testing.T) {
7071
tests := []struct {
7172
name string
72-
fields *githubFromToPRLister
73+
lister *githubFromToPRLister
7374
args ref
7475
wantErr bool
7576
}{
7677
{
7778
name: "Successful PR Listing",
78-
fields: &githubFromToPRLister{
79-
client: &githubClient{
80-
repo: "kubernetes-sigs/kind",
81-
},
82-
fromRef: ref{
83-
reType: "tags",
84-
value: "v0.26.0",
85-
},
86-
toRef: ref{
87-
reType: "tags",
88-
value: "v0.27.0",
89-
},
90-
branch: "main",
91-
},
79+
lister: newGithubFromToPRListerWithClient(
80+
newMockGithubClient(),
81+
ref{reType: "tags", value: "v0.26.0"},
82+
ref{reType: "tags", value: "v0.27.0"},
83+
"main",
84+
),
9285
args: ref{
9386
reType: "tags",
9487
value: "v0.26.0",
@@ -97,20 +90,12 @@ func Test_githubFromToPRLister_listPRs(t *testing.T) {
9790
},
9891
{
9992
name: "Setting previousReleaseRef.value blank - should use toRef and fromRef from fields",
100-
fields: &githubFromToPRLister{
101-
client: &githubClient{
102-
repo: "kubernetes-sigs/kind",
103-
},
104-
fromRef: ref{
105-
reType: "tags",
106-
value: "v0.26.0",
107-
},
108-
toRef: ref{
109-
reType: "tags",
110-
value: "v0.27.0",
111-
},
112-
branch: "main",
113-
},
93+
lister: newGithubFromToPRListerWithClient(
94+
newMockGithubClient(),
95+
ref{reType: "tags", value: "v0.26.0"},
96+
ref{reType: "tags", value: "v0.27.0"},
97+
"main",
98+
),
11499
args: ref{
115100
reType: "tags",
116101
value: "",
@@ -119,16 +104,12 @@ func Test_githubFromToPRLister_listPRs(t *testing.T) {
119104
},
120105
{
121106
name: "Create PR List when fromRef is not set",
122-
fields: &githubFromToPRLister{
123-
client: &githubClient{
124-
repo: "kubernetes-sigs/kind",
125-
},
126-
toRef: ref{
127-
reType: "tags",
128-
value: "v0.27.0",
129-
},
130-
branch: "main",
131-
},
107+
lister: newGithubFromToPRListerWithClient(
108+
newMockGithubClient(),
109+
ref{reType: "tags", value: ""},
110+
ref{reType: "tags", value: "v0.27.0"},
111+
"main",
112+
),
132113
args: ref{
133114
reType: "tags",
134115
value: "v0.26.0",
@@ -137,20 +118,12 @@ func Test_githubFromToPRLister_listPRs(t *testing.T) {
137118
},
138119
{
139120
name: "Fail when previousReleaseRef.value is set to invalid",
140-
fields: &githubFromToPRLister{
141-
client: &githubClient{
142-
repo: "kubernetes-sigs/kind",
143-
},
144-
fromRef: ref{
145-
reType: "tags",
146-
value: "v0.26.0",
147-
},
148-
toRef: ref{
149-
reType: "tags",
150-
value: "v0.27.0",
151-
},
152-
branch: "main",
153-
},
121+
lister: newGithubFromToPRListerWithClient(
122+
newMockGithubClientForInvalidRef(),
123+
ref{reType: "tags", value: "v0.26.0"},
124+
ref{reType: "tags", value: "v0.27.0"},
125+
"main",
126+
),
154127
args: ref{
155128
reType: "tags",
156129
value: "invalid",
@@ -159,20 +132,12 @@ func Test_githubFromToPRLister_listPRs(t *testing.T) {
159132
},
160133
{
161134
name: "Fail when toRef and previousReleaseRef set blank",
162-
fields: &githubFromToPRLister{
163-
client: &githubClient{
164-
repo: "kubernetes-sigs/kind",
165-
},
166-
fromRef: ref{
167-
reType: "tags",
168-
value: "v0.26.0",
169-
},
170-
toRef: ref{
171-
reType: "tags",
172-
value: "",
173-
},
174-
branch: "main",
175-
},
135+
lister: newGithubFromToPRListerWithClient(
136+
newMockGithubClientWithError("diff", fmt.Errorf("invalid ref")),
137+
ref{reType: "tags", value: "v0.26.0"},
138+
ref{reType: "tags", value: ""},
139+
"main",
140+
),
176141
args: ref{
177142
reType: "tags",
178143
value: "",
@@ -182,13 +147,7 @@ func Test_githubFromToPRLister_listPRs(t *testing.T) {
182147
}
183148
for _, tt := range tests {
184149
t.Run(tt.name, func(t *testing.T) {
185-
l := &githubFromToPRLister{
186-
client: tt.fields.client,
187-
fromRef: tt.fields.fromRef,
188-
toRef: tt.fields.toRef,
189-
branch: tt.fields.branch,
190-
}
191-
_, err := l.listPRs(tt.args)
150+
_, err := tt.lister.listPRs(tt.args)
192151
if (err != nil) != tt.wantErr {
193152
t.Errorf("githubFromToPRLister.listPRs() error = %v, wantErr %v", err, tt.wantErr)
194153
return
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
//go:build tools
2+
// +build tools
3+
4+
/*
5+
Copyright 2023 The Kubernetes Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
*/
19+
20+
package main
21+
22+
import (
23+
"fmt"
24+
"time"
25+
)
26+
27+
// mockGithubClient is a mock implementation of githubClientInterface for testing
28+
type mockGithubClient struct {
29+
// Mock responses
30+
diffResponse *githubDiff
31+
refResponse githubRef
32+
tagResponse githubTag
33+
commitResponse githubCommit
34+
prsResponse []githubPR
35+
36+
// Mock errors
37+
diffError error
38+
refError error
39+
tagError error
40+
commitError error
41+
prsError error
42+
}
43+
44+
// Ensure mockGithubClient implements githubClientInterface
45+
var _ githubClientInterface = (*mockGithubClient)(nil)
46+
47+
func (m *mockGithubClient) getDiffAllCommits(base, head string) (*githubDiff, error) {
48+
if m.diffError != nil {
49+
return nil, m.diffError
50+
}
51+
return m.diffResponse, nil
52+
}
53+
54+
func (m *mockGithubClient) getRef(ref string) (githubRef, error) {
55+
if m.refError != nil {
56+
return githubRef{}, m.refError
57+
}
58+
return m.refResponse, nil
59+
}
60+
61+
func (m *mockGithubClient) getTag(tagSHA string) (githubTag, error) {
62+
if m.tagError != nil {
63+
return githubTag{}, m.tagError
64+
}
65+
return m.tagResponse, nil
66+
}
67+
68+
func (m *mockGithubClient) getCommit(sha string) (githubCommit, error) {
69+
if m.commitError != nil {
70+
return githubCommit{}, m.commitError
71+
}
72+
return m.commitResponse, nil
73+
}
74+
75+
func (m *mockGithubClient) listMergedPRs(after, before time.Time, baseBranches ...string) ([]githubPR, error) {
76+
if m.prsError != nil {
77+
return nil, m.prsError
78+
}
79+
return m.prsResponse, nil
80+
}
81+
82+
// newMockGithubClient creates a new mock client with default responses
83+
func newMockGithubClient() *mockGithubClient {
84+
return &mockGithubClient{
85+
diffResponse: &githubDiff{
86+
MergeBaseCommit: githubCommitNode{
87+
Commit: githubCommit{
88+
Message: "Merge commit",
89+
Committer: githubCommitter{
90+
Date: time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
91+
},
92+
},
93+
},
94+
Commits: []githubCommitNode{
95+
{
96+
Commit: githubCommit{
97+
Message: "Merge pull request #1234 from test/branch",
98+
},
99+
},
100+
},
101+
},
102+
refResponse: githubRef{
103+
Object: githubObject{
104+
ObjectType: commitType,
105+
SHA: "abc123",
106+
},
107+
},
108+
tagResponse: githubTag{
109+
Object: githubObject{
110+
ObjectType: tagType,
111+
SHA: "def456",
112+
},
113+
},
114+
commitResponse: githubCommit{
115+
Message: "Test commit",
116+
Committer: githubCommitter{
117+
Date: time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
118+
},
119+
},
120+
prsResponse: []githubPR{
121+
{
122+
Number: 1234,
123+
Title: "Test PR",
124+
Labels: []githubLabel{
125+
{Name: "area/testing"},
126+
},
127+
User: githubUser{
128+
Login: "testuser",
129+
},
130+
},
131+
},
132+
}
133+
}
134+
135+
// newMockGithubClientWithError creates a mock client that returns an error for specific operations
136+
func newMockGithubClientWithError(operation string, err error) *mockGithubClient {
137+
mock := newMockGithubClient()
138+
switch operation {
139+
case "diff":
140+
mock.diffError = err
141+
case "ref":
142+
mock.refError = err
143+
case "tag":
144+
mock.tagError = err
145+
case "commit":
146+
mock.commitError = err
147+
case "prs":
148+
mock.prsError = err
149+
}
150+
return mock
151+
}
152+
153+
// newMockGithubClientForInvalidRef creates a mock client that simulates invalid ref scenarios
154+
func newMockGithubClientForInvalidRef() *mockGithubClient {
155+
mock := newMockGithubClient()
156+
mock.diffError = fmt.Errorf("invalid ref")
157+
return mock
158+
}

0 commit comments

Comments
 (0)