@@ -15,78 +15,191 @@ import (
15
15
"github.com/migueleliasweb/go-github-mock/src/mock"
16
16
)
17
17
18
- // TestGenerateChangelog_Mocked tests the changelog-generator logic
18
+ // TestGenerateChangelog tests the changelog-generator logic
19
19
// by mocking GitHub API calls via go-github-mock.
20
- func TestGenerateChangelog_Mocked (t * testing.T ) {
21
- // Prepare mock transport
22
- mockedHTTPClient := mock .NewMockedHTTPClient (
23
- // 1. Mock Git.GetCommit for startSHA
24
- mock .WithRequestMatchHandler (
25
- mock .GetReposGitCommitsByOwnerByRepoByCommitSha ,
26
- http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
27
- vars := mux .Vars (r )
28
- if vars ["commit_sha" ] == "start-sha" {
29
- json .NewEncoder (w ).Encode (github.Commit {
30
- Committer : & github.CommitAuthor {
31
- Date : & github.Timestamp {Time : time .Date (2025 , 4 , 1 , 12 , 0 , 0 , 0 , time .UTC )},
32
- },
33
- })
34
- return
35
- }
36
- if vars ["commit_sha" ] == "end-sha" {
37
- json .NewEncoder (w ).Encode (github.Commit {
38
- Committer : & github.CommitAuthor {
39
- Date : & github.Timestamp {Time : time .Date (2025 , 5 , 1 , 12 , 0 , 0 , 0 , time .UTC )},
40
- },
41
- })
42
- return
43
- }
44
- w .WriteHeader (http .StatusNotFound )
45
- }),
46
- ),
47
- // 3. Mock Search.Issues for merged PRs
48
- mock .WithRequestMatch (
49
- mock .GetSearchIssues ,
50
- github.IssuesSearchResult {
51
- Issues : []* github.Issue {
52
- {Number : github .Int (42 )},
53
- },
20
+ func TestGenerateChangelog (t * testing.T ) {
21
+ tt := []struct {
22
+ name string
23
+ owner string
24
+ repo string
25
+ startSHA string
26
+ startSHADate time.Time
27
+ endSHA string
28
+ endSHADate time.Time
29
+ issuesForSearch []* github.Issue
30
+ pullRequests []* github.PullRequest
31
+ expectedChangelog string
32
+ expectError bool
33
+ }{
34
+ {
35
+ name : "Valid/Feature PR with release-note" ,
36
+ owner : "foo" ,
37
+ repo : "bar" ,
38
+ startSHA : "start-sha" ,
39
+ startSHADate : time .Date (2025 , 4 , 1 , 12 , 0 , 0 , 0 , time .UTC ),
40
+ endSHA : "end-sha" ,
41
+ endSHADate : time .Date (2025 , 5 , 1 , 12 , 0 , 0 , 0 , time .UTC ),
42
+ issuesForSearch : []* github.Issue {
43
+ {Number : github .Ptr (42 )},
54
44
},
55
- ),
56
- // 4. Mock PullRequests.Get for PR #42
57
- mock .WithRequestMatch (
58
- mock .GetReposPullsByOwnerByRepoByPullNumber ,
59
- github.PullRequest {
45
+ pullRequests : []* github.PullRequest {{
60
46
Number : github .Ptr (42 ),
61
47
Title : github .Ptr ("Add new feature" ),
62
- Body : github .Ptr ("```release-note\n My note for PR42\n ```" ),
63
- Labels : []* github.Label {
64
- {Name : github .Ptr ("kind/new-feature" )},
48
+ Body : github .Ptr ("```release-note\\ nMy note for PR42\\ n```" ),
49
+ Labels : []* github.Label {{
50
+ Name : github .Ptr ("kind/new-feature" ),
51
+ }},
52
+ }},
53
+ expectedChangelog : `
54
+ ## 🚀 Features
55
+
56
+ - Add new feature (#42)
57
+ ` ,
58
+ expectError : false ,
59
+ },
60
+ {
61
+ name : "Valid/No PRs with release-note content" ,
62
+ owner : "foo" ,
63
+ repo : "bar" ,
64
+ startSHA : "start-sha" ,
65
+ startSHADate : time .Date (2025 , 4 , 1 , 12 , 0 , 0 , 0 , time .UTC ),
66
+ endSHA : "end-sha" ,
67
+ endSHADate : time .Date (2025 , 5 , 1 , 12 , 0 , 0 , 0 , time .UTC ),
68
+ issuesForSearch : []* github.Issue {
69
+ {Number : github .Ptr (43 )},
70
+ },
71
+ pullRequests : []* github.PullRequest {{
72
+ Number : github .Ptr (43 ),
73
+ Title : github .Ptr ("Refactor code" ),
74
+ Body : github .Ptr ("No release note here." ),
75
+ Labels : []* github.Label {{
76
+ Name : github .Ptr ("irrelevant-label" ),
77
+ }},
78
+ }},
79
+ expectedChangelog : "" ,
80
+ expectError : false ,
81
+ },
82
+ {
83
+ name : "Valid/Multiple PRs with different kinds" ,
84
+ owner : "foo" ,
85
+ repo : "bar" ,
86
+ startSHA : "start-sha" ,
87
+ startSHADate : time .Date (2025 , 4 , 1 , 12 , 0 , 0 , 0 , time .UTC ),
88
+ endSHA : "end-sha" ,
89
+ endSHADate : time .Date (2025 , 5 , 1 , 12 , 0 , 0 , 0 , time .UTC ),
90
+ issuesForSearch : []* github.Issue {
91
+ {Number : github .Ptr (42 )},
92
+ {Number : github .Ptr (43 )},
93
+ },
94
+ pullRequests : []* github.PullRequest {
95
+ {
96
+ Number : github .Ptr (42 ),
97
+ Title : github .Ptr ("Add new feature" ),
98
+ Body : github .Ptr ("```release-note\\ ASDF\\ n```" ),
99
+ Labels : []* github.Label {{
100
+ Name : github .Ptr ("kind/" ),
101
+ }},
102
+ },
103
+ {
104
+ Number : github .Ptr (43 ),
105
+ Title : github .Ptr ("Fix bug" ),
106
+ Body : github .Ptr ("```release-note\\ nFixed a bug\\ n```" ),
107
+ Labels : []* github.Label {{
108
+ Name : github .Ptr ("kind/bug" ),
109
+ }},
65
110
},
66
111
},
67
- ),
68
- )
112
+ expectedChangelog : `
113
+ ## 🚀 Features
69
114
70
- // Create GitHub client with mock transport
71
- ghClient := github .NewClient (mockedHTTPClient )
115
+ - Add new feature (#42)
72
116
73
- // Create changelog generator
74
- generator := generator .New (ghClient , "foo" , "bar" )
117
+ ## 🐛 Bug Fixes
75
118
76
- // Generate changelog
77
- changelog , err := generator . Generate ( context . Background (), "start-sha" , "end-sha" )
78
- if err != nil {
79
- t . Fatalf ( "Generate failed: %v" , err )
119
+ - Fix bug (#43)
120
+ ` ,
121
+ expectError : false ,
122
+ },
80
123
}
81
124
82
- // Debug output
83
- fmt .Printf ("Generated changelog:\n %s\n " , changelog )
125
+ for _ , tc := range tt {
126
+ t .Run (tc .name , func (t * testing.T ) {
127
+ currentMockHandlers := []mock.MockBackendOption {
128
+ mockGetCommitHandler (tc .startSHA , tc .startSHADate , tc .endSHA , tc .endSHADate ),
129
+ mockSearchIssuesHandler (tc .issuesForSearch ),
130
+ }
131
+ if len (tc .pullRequests ) > 0 {
132
+ currentMockHandlers = append (currentMockHandlers , mockGetPullRequestsHandler (tc .pullRequests ))
133
+ }
134
+ mockedHTTPClient := mock .NewMockedHTTPClient (currentMockHandlers ... )
84
135
85
- // Verify changelog content
86
- if ! strings .Contains (changelog , "🚀 Features" ) {
87
- t .Error ("changelog missing Features section" )
88
- }
89
- if ! strings .Contains (changelog , "#42" ) {
90
- t .Error ("changelog missing PR #42" )
136
+ g := generator .New (github .NewClient (mockedHTTPClient ), tc .owner , tc .repo )
137
+ changelog , err := g .Generate (context .Background (), tc .startSHA , tc .endSHA )
138
+ switch {
139
+ case tc .expectError && err == nil :
140
+ t .Fatalf ("Expected an error, but got nil" )
141
+ case ! tc .expectError && err != nil :
142
+ t .Fatalf ("Expected no error, but got: %v" , err )
143
+ default :
144
+ if strings .TrimSpace (changelog ) != strings .TrimSpace (tc .expectedChangelog ) {
145
+ t .Fatalf ("Generated changelog does not match expected changelog:\n want: %s\n got: %s" , tc .expectedChangelog , changelog )
146
+ }
147
+ }
148
+ })
91
149
}
92
150
}
151
+
152
+ // mockGetCommitHandler creates a mock handler for the GetCommit API call.
153
+ func mockGetCommitHandler (startSHA string , startDate time.Time , endSHA string , endDate time.Time ) mock.MockBackendOption {
154
+ return mock .WithRequestMatchHandler (
155
+ mock .GetReposGitCommitsByOwnerByRepoByCommitSha ,
156
+ http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
157
+ vars := mux .Vars (r )
158
+ commitSHA := vars ["commit_sha" ]
159
+ var commitDate time.Time
160
+ switch commitSHA {
161
+ case startSHA :
162
+ commitDate = startDate
163
+ case endSHA :
164
+ commitDate = endDate
165
+ default :
166
+ w .WriteHeader (http .StatusNotFound )
167
+ return
168
+ }
169
+ json .NewEncoder (w ).Encode (github.Commit {
170
+ Committer : & github.CommitAuthor {
171
+ Date : & github.Timestamp {Time : commitDate },
172
+ },
173
+ })
174
+ }),
175
+ )
176
+ }
177
+
178
+ // mockSearchIssuesHandler creates a mock handler for the SearchIssues API call.
179
+ func mockSearchIssuesHandler (issues []* github.Issue ) mock.MockBackendOption {
180
+ return mock .WithRequestMatch (
181
+ mock .GetSearchIssues ,
182
+ github.IssuesSearchResult {
183
+ Issues : issues ,
184
+ },
185
+ )
186
+ }
187
+
188
+ // mockGetPullRequestsHandler creates a mock handler for GetPullRequests API calls.
189
+ // It mocks responses for each PR in the provided slice based on its number.
190
+ func mockGetPullRequestsHandler (prs []* github.PullRequest ) mock.MockBackendOption {
191
+ return mock .WithRequestMatchHandler (
192
+ mock .GetReposPullsByOwnerByRepoByPullNumber ,
193
+ http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
194
+ vars := mux .Vars (r )
195
+ prNumberStr := vars ["pull_number" ]
196
+ for _ , pr := range prs {
197
+ if pr .Number != nil && fmt .Sprintf ("%d" , * pr .Number ) == prNumberStr {
198
+ json .NewEncoder (w ).Encode (pr )
199
+ return
200
+ }
201
+ }
202
+ w .WriteHeader (http .StatusNotFound )
203
+ }),
204
+ )
205
+ }
0 commit comments