forgejo/tests/integration/actions_variables_test.go
Andreas Ahlenstorf f7873ba393 fix: normalize secrets consistently, display accurate help (#11052)
Forgejo's UI claims that whitespace is removed from the beginning and the end of the values of Forgejo Actions variables and secrets. However, that is not correct. The entered values are stored as-is. Only CRLF is replaced with LF, which is also the desired behaviour.

This PR changes the incorrect text which is also no longer displayed as placeholder but as a proper help text below the input fields. Furthermore, tests were added to verify the behaviour.

While adding tests, I discovered and fixed another inconsistency. Depending on whether secrets were managed using the UI or the HTTP API, they were treated differently. CRLF in secrets entered in the UI was correctly replaced with LF while secrets created using the HTTP API kept CRLF.

Fixes #11003.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11052
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Co-committed-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
2026-02-09 17:02:18 +01:00

147 lines
4.9 KiB
Go

// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package integration
import (
"fmt"
"net/http"
"testing"
actions_model "forgejo.org/models/actions"
repo_model "forgejo.org/models/repo"
"forgejo.org/models/unittest"
user_model "forgejo.org/models/user"
app_context "forgejo.org/services/context"
"forgejo.org/tests"
"github.com/stretchr/testify/assert"
)
func TestActionsVariablesModification(t *testing.T) {
defer unittest.OverrideFixtures("tests/integration/fixtures/TestActionVariablesModification")()
defer tests.PrepareTestEnv(t)()
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
userVariable := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{ID: 1001, OwnerID: user.ID})
userURL := "/user/settings/actions/variables"
org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3, Type: user_model.UserTypeOrganization})
orgVariable := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{ID: 1002, OwnerID: org.ID})
orgURL := "/org/" + org.Name + "/settings/actions/variables"
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1, OwnerID: user.ID})
repoVariable := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{ID: 1003, RepoID: repo.ID})
repoURL := "/" + repo.FullName() + "/settings/actions/variables"
admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{IsAdmin: true})
globalVariable := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{ID: 1004}, "owner_id = 0 AND repo_id = 0")
adminURL := "/admin/actions/variables"
adminSess := loginUser(t, admin.Name)
sess := loginUser(t, user.Name)
type errorJSON struct {
Error string `json:"errorMessage"`
}
test := func(t *testing.T, fail bool, baseURL string, id int64) {
defer tests.PrintCurrentTest(t, 1)()
t.Helper()
sess := sess
if baseURL == adminURL {
sess = adminSess
}
req := NewRequestWithValues(t, "POST", baseURL+fmt.Sprintf("/%d/edit", id), map[string]string{
"name": "glados_quote",
"data": " \r\n\tI'm fine. Two plus two is...ten, in base four, I'm fine! \r\n",
})
if fail {
resp := sess.MakeRequest(t, req, http.StatusBadRequest)
var error errorJSON
DecodeJSON(t, resp, &error)
assert.Equal(t, "Failed to find the variable.", error.Error)
} else {
sess.MakeRequest(t, req, http.StatusOK)
flashCookie := sess.GetCookie(app_context.CookieNameFlash)
assert.NotNil(t, flashCookie)
assert.Equal(t, "success%3DThe%2Bvariable%2Bhas%2Bbeen%2Bedited.", flashCookie.Value)
updatedVariable := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{ID: id})
assert.Equal(t, "GLADOS_QUOTE", updatedVariable.Name)
assert.Equal(t, " \n\tI'm fine. Two plus two is...ten, in base four, I'm fine! \n", updatedVariable.Data)
}
req = NewRequest(t, "POST", baseURL+fmt.Sprintf("/%d/delete", id))
if fail {
resp := sess.MakeRequest(t, req, http.StatusBadRequest)
var error errorJSON
DecodeJSON(t, resp, &error)
assert.Equal(t, "Failed to find the variable.", error.Error)
} else {
sess.MakeRequest(t, req, http.StatusOK)
flashCookie := sess.GetCookie(app_context.CookieNameFlash)
assert.NotNil(t, flashCookie)
assert.Equal(t, "success%3DThe%2Bvariable%2Bhas%2Bbeen%2Bremoved.", flashCookie.Value)
}
}
t.Run("User variable", func(t *testing.T) {
t.Run("Organisation", func(t *testing.T) {
test(t, true, orgURL, userVariable.ID)
})
t.Run("Repository", func(t *testing.T) {
test(t, true, repoURL, userVariable.ID)
})
t.Run("Admin", func(t *testing.T) {
test(t, true, adminURL, userVariable.ID)
})
t.Run("User", func(t *testing.T) {
test(t, false, userURL, userVariable.ID)
})
})
t.Run("Organisation variable", func(t *testing.T) {
t.Run("Repository", func(t *testing.T) {
test(t, true, repoURL, orgVariable.ID)
})
t.Run("User", func(t *testing.T) {
test(t, true, userURL, orgVariable.ID)
})
t.Run("Admin", func(t *testing.T) {
test(t, true, adminURL, userVariable.ID)
})
t.Run("Organisation", func(t *testing.T) {
test(t, false, orgURL, orgVariable.ID)
})
})
t.Run("Repository variable", func(t *testing.T) {
t.Run("Organisation", func(t *testing.T) {
test(t, true, orgURL, repoVariable.ID)
})
t.Run("User", func(t *testing.T) {
test(t, true, userURL, repoVariable.ID)
})
t.Run("Admin", func(t *testing.T) {
test(t, true, adminURL, userVariable.ID)
})
t.Run("Repository", func(t *testing.T) {
test(t, false, repoURL, repoVariable.ID)
})
})
t.Run("Global variable", func(t *testing.T) {
t.Run("Organisation", func(t *testing.T) {
test(t, true, orgURL, globalVariable.ID)
})
t.Run("User", func(t *testing.T) {
test(t, true, userURL, globalVariable.ID)
})
t.Run("Repository", func(t *testing.T) {
test(t, true, repoURL, globalVariable.ID)
})
t.Run("Admin", func(t *testing.T) {
test(t, false, adminURL, globalVariable.ID)
})
})
}