diff --git a/models/actions/run_list.go b/models/actions/run_list.go index a450212185..b296e2f477 100644 --- a/models/actions/run_list.go +++ b/models/actions/run_list.go @@ -5,6 +5,7 @@ package actions import ( "context" + "slices" "forgejo.org/models/db" repo_model "forgejo.org/models/repo" @@ -13,6 +14,8 @@ import ( "forgejo.org/modules/translation" webhook_module "forgejo.org/modules/webhook" + "golang.org/x/text/collate" + "golang.org/x/text/language" "xorm.io/builder" ) @@ -127,14 +130,18 @@ type StatusInfo struct { // GetStatusInfoList returns a slice of StatusInfo func GetStatusInfoList(ctx context.Context, lang translation.Locale) []StatusInfo { // same as those in aggregateJobStatus - allStatus := []Status{StatusSuccess, StatusFailure, StatusWaiting, StatusRunning} - statusInfoList := make([]StatusInfo, 0, 4) + allStatus := []Status{StatusBlocked, StatusCancelled, StatusFailure, StatusRunning, StatusSkipped, StatusSuccess, StatusWaiting} + statusInfoList := make([]StatusInfo, 0, 7) for _, s := range allStatus { statusInfoList = append(statusInfoList, StatusInfo{ Status: int(s), DisplayedStatus: s.LocaleString(lang), }) } + collator := collate.New(language.Und, collate.IgnoreCase) + slices.SortFunc(statusInfoList, func(a, b StatusInfo) int { + return collator.CompareString(a.DisplayedStatus, b.DisplayedStatus) + }) return statusInfoList } diff --git a/models/actions/run_list_test.go b/models/actions/run_list_test.go new file mode 100644 index 0000000000..b3d22b5155 --- /dev/null +++ b/models/actions/run_list_test.go @@ -0,0 +1,37 @@ +// Copyright 2026 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +package actions + +import ( + "testing" + + "forgejo.org/models/unittest" + "forgejo.org/modules/translation" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestActionStatusList(t *testing.T) { + require.NoError(t, unittest.PrepareTestDatabase()) + translation.InitLocales(t.Context()) + + statusInfoList := GetStatusInfoList(t.Context(), translation.NewLocale("en-US")) + assert.Len(t, statusInfoList, 7) + statuses := []string{"Blocked", "Canceled", "Failure", "Running", "Skipped", "Success", "Waiting"} + statusInts := []int{7, 3, 2, 6, 4, 1, 5} + for i, statusString := range statuses { + assert.Equal(t, statusInfoList[i].Status, statusInts[i]) + assert.Equal(t, statusInfoList[i].DisplayedStatus, statusString) + } + + statusInfoList = GetStatusInfoList(t.Context(), translation.NewLocale("de-DE")) + assert.Len(t, statusInfoList, 7) + statuses = []string{"Abgebrochen", "Blockiert", "Erfolg", "Fehler", "Laufend", "Übersprungen", "Wartend"} + statusInts = []int{3, 7, 1, 2, 6, 4, 5} + for i, statusString := range statuses { + assert.Equal(t, statusInfoList[i].Status, statusInts[i]) + assert.Equal(t, statusInfoList[i].DisplayedStatus, statusString) + } +} diff --git a/tests/e2e/actions.test.e2e.ts b/tests/e2e/actions.test.e2e.ts index 2f5d09e561..8981d037d3 100644 --- a/tests/e2e/actions.test.e2e.ts +++ b/tests/e2e/actions.test.e2e.ts @@ -203,11 +203,19 @@ test.describe('workflow list dynamic refresh', () => { await page.locator('#workflow_dispatch_dropdown>button').click(); // Status dropdown - await expect(page.getByText('Waiting')).toBeHidden(); - await expect(page.getByText('Failure')).toBeHidden(); - await page.locator('#status_dropdown').click(); - await expect(page.getByText('Waiting')).toBeVisible(); - await expect(page.getByText('Failure')).toBeVisible(); + const dropdown = page.locator('#status_dropdown'); + const dropdown_menu = dropdown.locator('.menu'); + await expect(dropdown_menu).toBeHidden(); + await dropdown.click(); + await expect(dropdown_menu).toBeVisible(); + await expect(dropdown_menu.getByText('All status')).toHaveAttribute('href', /&status=0$/); + await expect(dropdown_menu.getByText('Success')).toHaveAttribute('href', /&status=1$/); + await expect(dropdown_menu.getByText('Failure')).toHaveAttribute('href', /&status=2$/); + await expect(dropdown_menu.getByText('Waiting')).toHaveAttribute('href', /&status=5$/); + await expect(dropdown_menu.getByText('Running')).toHaveAttribute('href', /&status=6$/); + await expect(dropdown_menu.getByText('Blocked')).toHaveAttribute('href', /&status=7$/); + await expect(dropdown_menu.getByText('Canceled')).toHaveAttribute('href', /&status=3$/); + await expect(dropdown_menu.getByText('Skipped')).toHaveAttribute('href', /&status=4$/); // Actor dropdown await expect(page.getByText('All actors')).toBeHidden();