From 49a28ba55478dec9ed98de06b3ec1ea50583f0e4 Mon Sep 17 00:00:00 2001 From: Mathieu Fenniak Date: Tue, 26 Aug 2025 21:29:22 -0600 Subject: [PATCH] add TestActionsViewViewPost to unit test Done change --- routers/web/repo/actions/view_test.go | 166 ++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) diff --git a/routers/web/repo/actions/view_test.go b/routers/web/repo/actions/view_test.go index dae1b47e6e..974906e6f3 100644 --- a/routers/web/repo/actions/view_test.go +++ b/routers/web/repo/actions/view_test.go @@ -5,14 +5,19 @@ package actions import ( "fmt" + "html/template" + "net/http" "testing" actions_model "forgejo.org/models/actions" repo_model "forgejo.org/models/repo" unittest "forgejo.org/models/unittest" + "forgejo.org/modules/json" + "forgejo.org/modules/web" "forgejo.org/services/contexttest" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_getRunByID(t *testing.T) { @@ -135,3 +140,164 @@ func Test_artifactsFindByNameOrID(t *testing.T) { }) } } + +func baseExpectedResponse() *ViewResponse { + return &ViewResponse{ + State: ViewState{ + Run: ViewRunInfo{ + Link: "/user5/repo4/actions/runs/187", + Title: "update actions", + TitleHTML: template.HTML("update actions"), + Status: "success", + CanCancel: false, + CanApprove: false, + CanRerun: false, + CanDeleteArtifact: false, + Done: true, + Jobs: []*ViewJob{ + { + ID: 192, + Name: "job_2", + Status: "success", + CanRerun: false, + Duration: "1m38s", + }, + }, + Commit: ViewCommit{ + LocaleCommit: "actions.runs.commit", + LocalePushedBy: "actions.runs.pushed_by", + LocaleWorkflow: "actions.runs.workflow", + ShortSha: "c2d72f5484", + Link: "/user5/repo4/commit/c2d72f548424103f01ee1dc02889c1e2bff816b0", + Pusher: ViewUser{ + DisplayName: "user1", + Link: "/user1", + }, + Branch: ViewBranch{ + Name: "master", + Link: "/user5/repo4/src/branch/master", + IsDeleted: false, + }, + }, + }, + CurrentJob: ViewCurrentJob{ + Title: "job_2", + Detail: "actions.status.success", + Steps: []*ViewJobStep{ + { + Summary: "Set up job", + Status: "running", + }, + { + Summary: "Complete job", + Status: "waiting", + }, + }, + }, + }, + Logs: ViewLogs{ + StepsLog: []*ViewStepLog{}, + }, + } +} + +func TestActionsViewViewPost(t *testing.T) { + unittest.PrepareTestEnv(t) + + tests := []struct { + name string + runIndex int64 + jobIndex int64 + expected *ViewResponse + expectedTweaks func(*ViewResponse) + }{ + { + name: "base case", + runIndex: 187, + jobIndex: 0, + expected: baseExpectedResponse(), + expectedTweaks: func(resp *ViewResponse) { + }, + }, + { + name: "run with waiting jobs", + runIndex: 189, + jobIndex: 0, + expected: baseExpectedResponse(), + expectedTweaks: func(resp *ViewResponse) { + // Variations from runIndex 187 -> runIndex 189 that are not the subject of this test... + resp.State.Run.Link = "/user5/repo4/actions/runs/189" + resp.State.Run.Title = "job output" + resp.State.Run.TitleHTML = "job output" + resp.State.Run.Jobs = []*ViewJob{ + { + ID: 194, + Name: "job1 (1)", + Status: "success", + }, + { + ID: 195, + Name: "job1 (2)", + Status: "success", + }, + { + ID: 196, + Name: "job2", + Status: "waiting", + }, + } + resp.State.CurrentJob.Title = "job1 (1)" + resp.State.CurrentJob.Steps = []*ViewJobStep{ + { + Summary: "Set up job", + Status: "success", + }, + { + Summary: "Complete job", + Status: "success", + }, + } + + // Under test in this case: verify that Done is set to false; in the fixture data, job.ID=195 is status + // Success, but job.ID=196 is status Waiting, and so we expect to signal Done=false to indicate to the + // UI to continue refreshing the page. + resp.State.Run.Done = false + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx, resp := contexttest.MockContext(t, "user2/repo1/actions/runs/0") + contexttest.LoadUser(t, ctx, 2) + contexttest.LoadRepo(t, ctx, 4) + ctx.SetParams(":run", fmt.Sprintf("%d", tt.runIndex)) + ctx.SetParams(":job", fmt.Sprintf("%d", tt.jobIndex)) + web.SetForm(ctx, &ViewRequest{}) + + ViewPost(ctx) + require.Equal(t, http.StatusOK, resp.Result().StatusCode) + + var actual ViewResponse + err := json.Unmarshal(resp.Body.Bytes(), &actual) + require.NoError(t, err) + + // `Duration` field is dynamic based upon current time, so eliminate it from comparison -- but check that it + // has the right format at least. + zeroDurations := func(vr *ViewResponse) { + for _, job := range vr.State.Run.Jobs { + assert.Regexp(t, `^(\d+[hms]){1,3}$`, job.Duration) + job.Duration = "" + } + for _, step := range vr.State.CurrentJob.Steps { + step.Duration = "" + } + } + zeroDurations(&actual) + zeroDurations(tt.expected) + tt.expectedTweaks(tt.expected) + + assert.Equal(t, *tt.expected, actual) + }) + } +}