Skip to content

Commit 6b074cb

Browse files
committed
refactor: extract buildRunOptions for better test coverage
- Extract FindRunOptions construction logic from ListRuns into buildRunOptions function - Update TestListRunsWorkflowFiltering and related tests to use actual production code - Tests now verify production logic instead of duplicating parameter parsing - Improved error handling by returning errors instead of direct HTTP responses - Ensures future changes to parameter parsing are properly tested This addresses the issue where tests were bypassing production code logic, making them less reliable for catching regressions.
1 parent 1b9b410 commit 6b074cb

File tree

2 files changed

+35
-80
lines changed

2 files changed

+35
-80
lines changed

routers/api/v1/shared/action.go

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,8 @@ func convertToInternal(s string) ([]actions_model.Status, error) {
139139
// ownerID != 0 and repoID == 0 means all runs for the given user/org
140140
// ownerID != 0 and repoID != 0 undefined behavior
141141
// Access rights are checked at the API route level
142-
func ListRuns(ctx *context.APIContext, ownerID, repoID int64) {
143-
if ownerID != 0 && repoID != 0 {
144-
setting.PanicInDevOrTesting("ownerID and repoID should not be both set")
145-
}
142+
// buildRunOptions builds the FindRunOptions from context parameters
143+
func buildRunOptions(ctx *context.APIContext, ownerID, repoID int64) (actions_model.FindRunOptions, error) {
146144
opts := actions_model.FindRunOptions{
147145
OwnerID: ownerID,
148146
RepoID: repoID,
@@ -159,16 +157,14 @@ func ListRuns(ctx *context.APIContext, ownerID, repoID int64) {
159157
for _, status := range ctx.FormStrings("status") {
160158
values, err := convertToInternal(status)
161159
if err != nil {
162-
ctx.APIError(http.StatusBadRequest, fmt.Errorf("Invalid status %s", status))
163-
return
160+
return opts, fmt.Errorf("Invalid status %s", status)
164161
}
165162
opts.Status = append(opts.Status, values...)
166163
}
167164
if actor := ctx.FormString("actor"); actor != "" {
168165
user, err := user_model.GetUserByName(ctx, actor)
169166
if err != nil {
170-
ctx.APIErrorInternal(err)
171-
return
167+
return opts, err
172168
}
173169
opts.TriggerUserID = user.ID
174170
}
@@ -249,6 +245,20 @@ func ListRuns(ctx *context.APIContext, ownerID, repoID int64) {
249245
}
250246
}
251247

248+
return opts, nil
249+
}
250+
251+
func ListRuns(ctx *context.APIContext, ownerID, repoID int64) {
252+
if ownerID != 0 && repoID != 0 {
253+
setting.PanicInDevOrTesting("ownerID and repoID should not be both set")
254+
}
255+
256+
opts, err := buildRunOptions(ctx, ownerID, repoID)
257+
if err != nil {
258+
ctx.APIError(http.StatusBadRequest, err)
259+
return
260+
}
261+
252262
runs, total, err := db.FindAndCount[actions_model.ActionRun](ctx, opts)
253263
if err != nil {
254264
ctx.APIErrorInternal(err)

routers/api/v1/shared/action_list_runs_test.go

Lines changed: 17 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"testing"
88
"time"
99

10-
actions_model "code.gitea.io/gitea/models/actions"
1110
"code.gitea.io/gitea/models/unittest"
1211
"code.gitea.io/gitea/services/contexttest"
1312

@@ -30,12 +29,8 @@ func TestListRunsWorkflowFiltering(t *testing.T) {
3029
// Test case 1: With workflow_id parameter (simulating /workflows/{workflow_id}/runs endpoint)
3130
ctx.SetPathParam("workflow_id", "test-workflow-123")
3231

33-
// Simulate the FindRunOptions creation that happens in ListRuns
34-
opts := actions_model.FindRunOptions{
35-
OwnerID: 0,
36-
RepoID: ctx.Repo.Repository.ID,
37-
WorkflowID: ctx.PathParam("workflow_id"), // This is the key change being tested
38-
}
32+
opts, err := buildRunOptions(ctx, 0, ctx.Repo.Repository.ID)
33+
assert.NoError(t, err)
3934

4035
// Verify the WorkflowID is correctly extracted from path parameter
4136
assert.Equal(t, "test-workflow-123", opts.WorkflowID)
@@ -48,10 +43,8 @@ func TestListRunsWorkflowFiltering(t *testing.T) {
4843
contexttest.LoadUser(t, ctx2, 2)
4944
// No SetPathParam call - simulates general runs endpoint
5045

51-
opts2 := actions_model.FindRunOptions{
52-
RepoID: ctx2.Repo.Repository.ID,
53-
WorkflowID: ctx2.PathParam("workflow_id"),
54-
}
46+
opts2, err := buildRunOptions(ctx2, 0, ctx2.Repo.Repository.ID)
47+
assert.NoError(t, err)
5548

5649
// Verify WorkflowID is empty when path parameter is not set
5750
assert.Empty(t, opts2.WorkflowID)
@@ -70,14 +63,9 @@ func TestListRunsExcludePullRequestsParam(t *testing.T) {
7063
contexttest.LoadRepo(t, ctx, 1)
7164
contexttest.LoadUser(t, ctx, 2)
7265

73-
// Call the actual parsing logic from ListRuns
74-
opts := actions_model.FindRunOptions{
75-
RepoID: ctx.Repo.Repository.ID,
76-
}
77-
78-
if ctx.FormBool("exclude_pull_requests") {
79-
opts.ExcludePullRequests = true
80-
}
66+
// Call the actual production logic
67+
opts, err := buildRunOptions(ctx, 0, ctx.Repo.Repository.ID)
68+
assert.NoError(t, err)
8169

8270
// Verify the ExcludePullRequests is correctly set based on the form value
8371
assert.True(t, opts.ExcludePullRequests)
@@ -87,13 +75,8 @@ func TestListRunsExcludePullRequestsParam(t *testing.T) {
8775
contexttest.LoadRepo(t, ctx2, 1)
8876
contexttest.LoadUser(t, ctx2, 2)
8977

90-
opts2 := actions_model.FindRunOptions{
91-
RepoID: ctx2.Repo.Repository.ID,
92-
}
93-
94-
if ctx2.FormBool("exclude_pull_requests") {
95-
opts2.ExcludePullRequests = true
96-
}
78+
opts2, err := buildRunOptions(ctx2, 0, ctx2.Repo.Repository.ID)
79+
assert.NoError(t, err)
9780

9881
// Verify the ExcludePullRequests is correctly set for "1" value
9982
assert.True(t, opts2.ExcludePullRequests)
@@ -103,13 +86,8 @@ func TestListRunsExcludePullRequestsParam(t *testing.T) {
10386
contexttest.LoadRepo(t, ctx3, 1)
10487
contexttest.LoadUser(t, ctx3, 2)
10588

106-
opts3 := actions_model.FindRunOptions{
107-
RepoID: ctx3.Repo.Repository.ID,
108-
}
109-
110-
if ctx3.FormBool("exclude_pull_requests") {
111-
opts3.ExcludePullRequests = true
112-
}
89+
opts3, err := buildRunOptions(ctx3, 0, ctx3.Repo.Repository.ID)
90+
assert.NoError(t, err)
11391

11492
// Verify the ExcludePullRequests is NOT set for "false" value
11593
assert.False(t, opts3.ExcludePullRequests)
@@ -125,21 +103,8 @@ func TestListRunsCreatedParam(t *testing.T) {
125103
contexttest.LoadRepo(t, ctx, 1)
126104
contexttest.LoadUser(t, ctx, 2)
127105

128-
opts := actions_model.FindRunOptions{
129-
RepoID: ctx.Repo.Repository.ID,
130-
}
131-
132-
// Simulate the date parsing logic from ListRuns
133-
if created := ctx.FormString("created"); created != "" {
134-
if created == "2023-01-01..2023-12-31" {
135-
startDate, _ := time.Parse("2006-01-02", "2023-01-01")
136-
endDate, _ := time.Parse("2006-01-02", "2023-12-31")
137-
endDate = endDate.Add(24*time.Hour - time.Second)
138-
139-
opts.CreatedAfter = startDate
140-
opts.CreatedBefore = endDate
141-
}
142-
}
106+
opts, err := buildRunOptions(ctx, 0, ctx.Repo.Repository.ID)
107+
assert.NoError(t, err)
143108

144109
// Verify the date range is correctly parsed
145110
expectedStart, _ := time.Parse("2006-01-02", "2023-01-01")
@@ -154,18 +119,8 @@ func TestListRunsCreatedParam(t *testing.T) {
154119
contexttest.LoadRepo(t, ctx2, 1)
155120
contexttest.LoadUser(t, ctx2, 2)
156121

157-
opts2 := actions_model.FindRunOptions{
158-
RepoID: ctx2.Repo.Repository.ID,
159-
}
160-
161-
// Simulate the date parsing logic for >= format
162-
if created := ctx2.FormString("created"); created != "" {
163-
if created == ">=2023-01-01" {
164-
dateStr := "2023-01-01"
165-
startDate, _ := time.Parse("2006-01-02", dateStr)
166-
opts2.CreatedAfter = startDate
167-
}
168-
}
122+
opts2, err := buildRunOptions(ctx2, 0, ctx2.Repo.Repository.ID)
123+
assert.NoError(t, err)
169124

170125
// Verify the date is correctly parsed
171126
expectedStart2, _ := time.Parse("2006-01-02", "2023-01-01")
@@ -177,18 +132,8 @@ func TestListRunsCreatedParam(t *testing.T) {
177132
contexttest.LoadRepo(t, ctx3, 1)
178133
contexttest.LoadUser(t, ctx3, 2)
179134

180-
opts3 := actions_model.FindRunOptions{
181-
RepoID: ctx3.Repo.Repository.ID,
182-
}
183-
184-
// Simulate the date parsing logic for exact date
185-
if created := ctx3.FormString("created"); created != "" {
186-
if created == "2023-06-15" {
187-
exactDate, _ := time.Parse("2006-01-02", created)
188-
opts3.CreatedAfter = exactDate
189-
opts3.CreatedBefore = exactDate.Add(24*time.Hour - time.Second)
190-
}
191-
}
135+
opts3, err := buildRunOptions(ctx3, 0, ctx3.Repo.Repository.ID)
136+
assert.NoError(t, err)
192137

193138
// Verify the exact date is correctly parsed to a date range
194139
exactDate, _ := time.Parse("2006-01-02", "2023-06-15")

0 commit comments

Comments
 (0)