aboutsummaryrefslogtreecommitdiffstats
path: root/tests/integration
diff options
context:
space:
mode:
Diffstat (limited to 'tests/integration')
-rw-r--r--tests/integration/actions_delete_run_test.go181
-rw-r--r--tests/integration/actions_job_test.go197
-rw-r--r--tests/integration/actions_log_test.go185
-rw-r--r--tests/integration/actions_runner_modify_test.go150
-rw-r--r--tests/integration/actions_runner_test.go37
-rw-r--r--tests/integration/actions_trigger_test.go1061
-rw-r--r--tests/integration/actions_variables_test.go148
-rw-r--r--tests/integration/admin_user_test.go42
-rw-r--r--tests/integration/api_actions_artifact_v4_test.go275
-rw-r--r--tests/integration/api_actions_delete_run_test.go98
-rw-r--r--tests/integration/api_actions_runner_test.go342
-rw-r--r--tests/integration/api_activitypub_person_test.go60
-rw-r--r--tests/integration/api_admin_org_test.go53
-rw-r--r--tests/integration/api_admin_test.go14
-rw-r--r--tests/integration/api_branch_test.go18
-rw-r--r--tests/integration/api_comment_test.go8
-rw-r--r--tests/integration/api_fork_test.go41
-rw-r--r--tests/integration/api_gitignore_templates_test.go3
-rw-r--r--tests/integration/api_gpg_keys_test.go12
-rw-r--r--tests/integration/api_helper_for_declarative_test.go13
-rw-r--r--tests/integration/api_issue_label_test.go20
-rw-r--r--tests/integration/api_issue_lock_test.go74
-rw-r--r--tests/integration/api_issue_milestone_test.go2
-rw-r--r--tests/integration/api_issue_stopwatch_test.go10
-rw-r--r--tests/integration/api_issue_subscription_test.go8
-rw-r--r--tests/integration/api_issue_test.go16
-rw-r--r--tests/integration/api_issue_tracked_time_test.go6
-rw-r--r--tests/integration/api_keys_test.go4
-rw-r--r--tests/integration/api_label_templates_test.go3
-rw-r--r--tests/integration/api_license_templates_test.go3
-rw-r--r--tests/integration/api_nodeinfo_test.go34
-rw-r--r--tests/integration/api_notification_test.go8
-rw-r--r--tests/integration/api_oauth2_apps_test.go20
-rw-r--r--tests/integration/api_org_test.go232
-rw-r--r--tests/integration/api_packages_arch_test.go94
-rw-r--r--tests/integration/api_packages_cargo_test.go2
-rw-r--r--tests/integration/api_packages_chef_test.go12
-rw-r--r--tests/integration/api_packages_composer_test.go37
-rw-r--r--tests/integration/api_packages_conan_test.go54
-rw-r--r--tests/integration/api_packages_conda_test.go10
-rw-r--r--tests/integration/api_packages_container_test.go137
-rw-r--r--tests/integration/api_packages_cran_test.go8
-rw-r--r--tests/integration/api_packages_debian_test.go2
-rw-r--r--tests/integration/api_packages_generic_test.go7
-rw-r--r--tests/integration/api_packages_goproxy_test.go2
-rw-r--r--tests/integration/api_packages_helm_test.go4
-rw-r--r--tests/integration/api_packages_maven_test.go16
-rw-r--r--tests/integration/api_packages_npm_test.go2
-rw-r--r--tests/integration/api_packages_nuget_test.go121
-rw-r--r--tests/integration/api_packages_pub_test.go2
-rw-r--r--tests/integration/api_packages_pypi_test.go2
-rw-r--r--tests/integration/api_packages_rpm_test.go14
-rw-r--r--tests/integration/api_packages_rubygems_test.go8
-rw-r--r--tests/integration/api_packages_swift_test.go98
-rw-r--r--tests/integration/api_packages_test.go147
-rw-r--r--tests/integration/api_packages_vagrant_test.go4
-rw-r--r--tests/integration/api_private_serv_test.go4
-rw-r--r--tests/integration/api_pull_review_test.go38
-rw-r--r--tests/integration/api_pull_test.go169
-rw-r--r--tests/integration/api_releases_test.go10
-rw-r--r--tests/integration/api_repo_archive_test.go21
-rw-r--r--tests/integration/api_repo_branch_test.go32
-rw-r--r--tests/integration/api_repo_collaborator_test.go188
-rw-r--r--tests/integration/api_repo_file_create_test.go142
-rw-r--r--tests/integration/api_repo_file_delete_test.go32
-rw-r--r--tests/integration/api_repo_file_get_test.go2
-rw-r--r--tests/integration/api_repo_file_update_test.go89
-rw-r--r--tests/integration/api_repo_files_change_test.go118
-rw-r--r--tests/integration/api_repo_files_get_test.go157
-rw-r--r--tests/integration/api_repo_get_contents_list_test.go55
-rw-r--r--tests/integration/api_repo_get_contents_test.go184
-rw-r--r--tests/integration/api_repo_git_blobs_test.go4
-rw-r--r--tests/integration/api_repo_git_commits_test.go22
-rw-r--r--tests/integration/api_repo_git_tags_test.go4
-rw-r--r--tests/integration/api_repo_git_trees_test.go2
-rw-r--r--tests/integration/api_repo_languages_test.go5
-rw-r--r--tests/integration/api_repo_lfs_locks_test.go8
-rw-r--r--tests/integration/api_repo_lfs_migrate_test.go2
-rw-r--r--tests/integration/api_repo_lfs_test.go7
-rw-r--r--tests/integration/api_repo_license_test.go6
-rw-r--r--tests/integration/api_repo_raw_test.go4
-rw-r--r--tests/integration/api_repo_secrets_test.go27
-rw-r--r--tests/integration/api_repo_tags_test.go10
-rw-r--r--tests/integration/api_repo_teams_test.go12
-rw-r--r--tests/integration/api_repo_test.go51
-rw-r--r--tests/integration/api_repo_topic_test.go10
-rw-r--r--tests/integration/api_repo_variables_test.go8
-rw-r--r--tests/integration/api_settings_test.go7
-rw-r--r--tests/integration/api_team_test.go24
-rw-r--r--tests/integration/api_team_user_test.go52
-rw-r--r--tests/integration/api_token_test.go2
-rw-r--r--tests/integration/api_twofa_test.go2
-rw-r--r--tests/integration/api_user_block_test.go18
-rw-r--r--tests/integration/api_user_email_test.go6
-rw-r--r--tests/integration/api_user_follow_test.go8
-rw-r--r--tests/integration/api_user_info_test.go9
-rw-r--r--tests/integration/api_user_search_test.go8
-rw-r--r--tests/integration/api_user_secrets_test.go7
-rw-r--r--tests/integration/api_user_star_test.go74
-rw-r--r--tests/integration/api_user_variables_test.go17
-rw-r--r--tests/integration/api_wiki_test.go24
-rw-r--r--tests/integration/auth_ldap_test.go20
-rw-r--r--tests/integration/benchmarks_test.go69
-rw-r--r--tests/integration/change_default_branch_test.go97
-rw-r--r--tests/integration/cmd_keys_test.go17
-rw-r--r--tests/integration/compare_test.go2
-rw-r--r--tests/integration/db_collation_test.go2
-rw-r--r--tests/integration/delete_user_test.go5
-rw-r--r--tests/integration/dump_restore_test.go31
-rw-r--r--tests/integration/editor_test.go527
-rw-r--r--tests/integration/empty_repo_test.go65
-rw-r--r--tests/integration/ephemeral_actions_runner_deletion_test.go77
-rw-r--r--tests/integration/feed_repo_test.go35
-rw-r--r--tests/integration/feed_user_test.go (renamed from tests/integration/api_feed_user_test.go)25
-rw-r--r--tests/integration/git_general_test.go152
-rw-r--r--tests/integration/git_helper_for_declarative_test.go33
-rw-r--r--tests/integration/git_lfs_ssh_test.go10
-rw-r--r--tests/integration/git_misc_test.go15
-rw-r--r--tests/integration/git_push_test.go20
-rw-r--r--tests/integration/git_smart_http_test.go64
-rw-r--r--tests/integration/gpg_ssh_git_test.go (renamed from tests/integration/gpg_git_test.go)94
-rw-r--r--tests/integration/html_helper.go13
-rw-r--r--tests/integration/incoming_email_test.go4
-rw-r--r--tests/integration/integration_test.go80
-rw-r--r--tests/integration/issue_test.go73
-rw-r--r--tests/integration/lfs_local_endpoint_test.go27
-rw-r--r--tests/integration/lfs_view_test.go18
-rw-r--r--tests/integration/linguist_test.go3
-rw-r--r--tests/integration/links_test.go12
-rw-r--r--tests/integration/markup_external_test.go14
-rw-r--r--tests/integration/migrate_test.go7
-rw-r--r--tests/integration/migration-test/migration_test.go28
-rw-r--r--tests/integration/mirror_pull_test.go37
-rw-r--r--tests/integration/mirror_push_test.go22
-rw-r--r--tests/integration/nonascii_branches_test.go30
-rw-r--r--tests/integration/oauth_test.go8
-rw-r--r--tests/integration/org_count_test.go11
-rw-r--r--tests/integration/org_team_invite_test.go20
-rw-r--r--tests/integration/org_test.go45
-rw-r--r--tests/integration/org_worktime_test.go293
-rw-r--r--tests/integration/project_test.go10
-rw-r--r--tests/integration/pull_commit_test.go41
-rw-r--r--tests/integration/pull_compare_test.go64
-rw-r--r--tests/integration/pull_create_test.go8
-rw-r--r--tests/integration/pull_merge_test.go86
-rw-r--r--tests/integration/pull_review_test.go34
-rw-r--r--tests/integration/pull_status_test.go106
-rw-r--r--tests/integration/pull_update_test.go32
-rw-r--r--tests/integration/release_test.go24
-rw-r--r--tests/integration/rename_branch_test.go11
-rw-r--r--tests/integration/repo_activity_test.go13
-rw-r--r--tests/integration/repo_branch_test.go6
-rw-r--r--tests/integration/repo_commits_search_test.go2
-rw-r--r--tests/integration/repo_commits_test.go42
-rw-r--r--tests/integration/repo_fork_test.go20
-rw-r--r--tests/integration/repo_generate_test.go11
-rw-r--r--tests/integration/repo_merge_upstream_test.go83
-rw-r--r--tests/integration/repo_mergecommit_revert_test.go37
-rw-r--r--tests/integration/repo_search_test.go2
-rw-r--r--tests/integration/repo_tag_test.go22
-rw-r--r--tests/integration/repo_test.go313
-rw-r--r--tests/integration/repo_topic_test.go10
-rw-r--r--tests/integration/repo_webhook_test.go1183
-rw-r--r--tests/integration/repofiles_change_test.go306
-rw-r--r--tests/integration/session_test.go4
-rw-r--r--tests/integration/setting_test.go6
-rw-r--r--tests/integration/signin_test.go84
-rw-r--r--tests/integration/signup_test.go11
-rw-r--r--tests/integration/ssh_key_test.go6
-rw-r--r--tests/integration/timetracking_test.go18
-rw-r--r--tests/integration/user_avatar_test.go96
-rw-r--r--tests/integration/user_settings_test.go48
-rw-r--r--tests/integration/user_test.go29
-rw-r--r--tests/integration/view_test.go40
-rw-r--r--tests/integration/webfinger_test.go12
-rw-r--r--tests/integration/wiki_test.go10
-rw-r--r--tests/integration/workflow_run_api_check_test.go167
-rw-r--r--tests/integration/xss_test.go4
178 files changed, 8527 insertions, 2421 deletions
diff --git a/tests/integration/actions_delete_run_test.go b/tests/integration/actions_delete_run_test.go
new file mode 100644
index 0000000000..22f9a1f740
--- /dev/null
+++ b/tests/integration/actions_delete_run_test.go
@@ -0,0 +1,181 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package integration
+
+import (
+ "fmt"
+ "net/http"
+ "net/url"
+ "testing"
+ "time"
+
+ actions_model "code.gitea.io/gitea/models/actions"
+ auth_model "code.gitea.io/gitea/models/auth"
+ "code.gitea.io/gitea/models/unittest"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/json"
+ "code.gitea.io/gitea/routers/web/repo/actions"
+
+ runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
+ "github.com/stretchr/testify/assert"
+ "google.golang.org/protobuf/types/known/timestamppb"
+)
+
+func TestActionsDeleteRun(t *testing.T) {
+ now := time.Now()
+ testCase := struct {
+ treePath string
+ fileContent string
+ outcomes map[string]*mockTaskOutcome
+ expectedStatuses map[string]string
+ }{
+ treePath: ".gitea/workflows/test1.yml",
+ fileContent: `name: test1
+on:
+ push:
+ paths:
+ - .gitea/workflows/test1.yml
+jobs:
+ job1:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo job1
+ job2:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo job2
+ job3:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo job3
+`,
+ outcomes: map[string]*mockTaskOutcome{
+ "job1": {
+ result: runnerv1.Result_RESULT_SUCCESS,
+ logRows: []*runnerv1.LogRow{
+ {
+ Time: timestamppb.New(now.Add(4 * time.Second)),
+ Content: " \U0001F433 docker create image",
+ },
+ {
+ Time: timestamppb.New(now.Add(5 * time.Second)),
+ Content: "job1",
+ },
+ {
+ Time: timestamppb.New(now.Add(6 * time.Second)),
+ Content: "\U0001F3C1 Job succeeded",
+ },
+ },
+ },
+ "job2": {
+ result: runnerv1.Result_RESULT_SUCCESS,
+ logRows: []*runnerv1.LogRow{
+ {
+ Time: timestamppb.New(now.Add(4 * time.Second)),
+ Content: " \U0001F433 docker create image",
+ },
+ {
+ Time: timestamppb.New(now.Add(5 * time.Second)),
+ Content: "job2",
+ },
+ {
+ Time: timestamppb.New(now.Add(6 * time.Second)),
+ Content: "\U0001F3C1 Job succeeded",
+ },
+ },
+ },
+ "job3": {
+ result: runnerv1.Result_RESULT_SUCCESS,
+ logRows: []*runnerv1.LogRow{
+ {
+ Time: timestamppb.New(now.Add(4 * time.Second)),
+ Content: " \U0001F433 docker create image",
+ },
+ {
+ Time: timestamppb.New(now.Add(5 * time.Second)),
+ Content: "job3",
+ },
+ {
+ Time: timestamppb.New(now.Add(6 * time.Second)),
+ Content: "\U0001F3C1 Job succeeded",
+ },
+ },
+ },
+ },
+ expectedStatuses: map[string]string{
+ "job1": actions_model.StatusSuccess.String(),
+ "job2": actions_model.StatusSuccess.String(),
+ "job3": actions_model.StatusSuccess.String(),
+ },
+ }
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ session := loginUser(t, user2.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
+
+ apiRepo := createActionsTestRepo(t, token, "actions-delete-run-test", false)
+ runner := newMockRunner()
+ runner.registerAsRepoRunner(t, user2.Name, apiRepo.Name, "mock-runner", []string{"ubuntu-latest"}, false)
+
+ opts := getWorkflowCreateFileOptions(user2, apiRepo.DefaultBranch, "create "+testCase.treePath, testCase.fileContent)
+ createWorkflowFile(t, token, user2.Name, apiRepo.Name, testCase.treePath, opts)
+
+ runIndex := ""
+ for i := 0; i < len(testCase.outcomes); i++ {
+ task := runner.fetchTask(t)
+ jobName := getTaskJobNameByTaskID(t, token, user2.Name, apiRepo.Name, task.Id)
+ outcome := testCase.outcomes[jobName]
+ assert.NotNil(t, outcome)
+ runner.execTask(t, task, outcome)
+ runIndex = task.Context.GetFields()["run_number"].GetStringValue()
+ assert.Equal(t, "1", runIndex)
+ }
+
+ for i := 0; i < len(testCase.outcomes); i++ {
+ req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/actions/runs/%s/jobs/%d", user2.Name, apiRepo.Name, runIndex, i), map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ })
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ var listResp actions.ViewResponse
+ err := json.Unmarshal(resp.Body.Bytes(), &listResp)
+ assert.NoError(t, err)
+ assert.Len(t, listResp.State.Run.Jobs, 3)
+
+ req = NewRequest(t, "GET", fmt.Sprintf("/%s/%s/actions/runs/%s/jobs/%d/logs", user2.Name, apiRepo.Name, runIndex, i)).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusOK)
+ }
+
+ req := NewRequestWithValues(t, "GET", fmt.Sprintf("/%s/%s/actions/runs/%s", user2.Name, apiRepo.Name, runIndex), map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ })
+ session.MakeRequest(t, req, http.StatusOK)
+
+ req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/actions/runs/%s/delete", user2.Name, apiRepo.Name, runIndex), map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ })
+ session.MakeRequest(t, req, http.StatusOK)
+
+ req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/actions/runs/%s/delete", user2.Name, apiRepo.Name, runIndex), map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ })
+ session.MakeRequest(t, req, http.StatusNotFound)
+
+ req = NewRequestWithValues(t, "GET", fmt.Sprintf("/%s/%s/actions/runs/%s", user2.Name, apiRepo.Name, runIndex), map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ })
+ session.MakeRequest(t, req, http.StatusNotFound)
+
+ for i := 0; i < len(testCase.outcomes); i++ {
+ req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/actions/runs/%s/jobs/%d", user2.Name, apiRepo.Name, runIndex, i), map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ })
+ session.MakeRequest(t, req, http.StatusNotFound)
+
+ req = NewRequest(t, "GET", fmt.Sprintf("/%s/%s/actions/runs/%s/jobs/%d/logs", user2.Name, apiRepo.Name, runIndex, i)).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNotFound)
+ }
+ })
+}
diff --git a/tests/integration/actions_job_test.go b/tests/integration/actions_job_test.go
index a0c06b06fd..4f4456a4e5 100644
--- a/tests/integration/actions_job_test.go
+++ b/tests/integration/actions_job_test.go
@@ -4,12 +4,12 @@
package integration
import (
- "context"
"encoding/base64"
"fmt"
"net/http"
"net/url"
"reflect"
+ "strconv"
"testing"
"time"
@@ -22,8 +22,10 @@ import (
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ actions_service "code.gitea.io/gitea/services/actions"
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
+ "connectrpc.com/connect"
"github.com/stretchr/testify/assert"
)
@@ -37,7 +39,7 @@ func TestJobWithNeeds(t *testing.T) {
{
treePath: ".gitea/workflows/job-with-needs.yml",
fileContent: `name: job-with-needs
-on:
+on:
push:
paths:
- '.gitea/workflows/job-with-needs.yml'
@@ -68,7 +70,7 @@ jobs:
{
treePath: ".gitea/workflows/job-with-needs-fail.yml",
fileContent: `name: job-with-needs-fail
-on:
+on:
push:
paths:
- '.gitea/workflows/job-with-needs-fail.yml'
@@ -96,7 +98,7 @@ jobs:
{
treePath: ".gitea/workflows/job-with-needs-fail-if.yml",
fileContent: `name: job-with-needs-fail-if
-on:
+on:
push:
paths:
- '.gitea/workflows/job-with-needs-fail-if.yml'
@@ -133,12 +135,12 @@ jobs:
apiRepo := createActionsTestRepo(t, token, "actions-jobs-with-needs", false)
runner := newMockRunner()
- runner.registerAsRepoRunner(t, user2.Name, apiRepo.Name, "mock-runner", []string{"ubuntu-latest"})
+ runner.registerAsRepoRunner(t, user2.Name, apiRepo.Name, "mock-runner", []string{"ubuntu-latest"}, false)
for _, tc := range testCases {
- t.Run(fmt.Sprintf("test %s", tc.treePath), func(t *testing.T) {
+ t.Run("test "+tc.treePath, func(t *testing.T) {
// create the workflow file
- opts := getWorkflowCreateFileOptions(user2, apiRepo.DefaultBranch, fmt.Sprintf("create %s", tc.treePath), tc.fileContent)
+ opts := getWorkflowCreateFileOptions(user2, apiRepo.DefaultBranch, "create "+tc.treePath, tc.fileContent)
fileResp := createWorkflowFile(t, token, user2.Name, apiRepo.Name, tc.treePath, opts)
// fetch and execute task
@@ -165,9 +167,6 @@ jobs:
}
})
}
-
- httpContext := NewAPITestContext(t, user2.Name, apiRepo.Name, auth_model.AccessTokenScopeWriteRepository)
- doAPIDeleteRepository(httpContext)(t)
})
}
@@ -181,7 +180,7 @@ func TestJobNeedsMatrix(t *testing.T) {
{
treePath: ".gitea/workflows/jobs-outputs-with-matrix.yml",
fileContent: `name: jobs-outputs-with-matrix
-on:
+on:
push:
paths:
- '.gitea/workflows/jobs-outputs-with-matrix.yml'
@@ -200,7 +199,7 @@ jobs:
id: gen_output
run: |
version="${{ matrix.version }}"
- echo "output_${version}=${version}" >> "$GITHUB_OUTPUT"
+ echo "output_${version}=${version}" >> "$GITHUB_OUTPUT"
job2:
runs-on: ubuntu-latest
needs: [job1]
@@ -247,7 +246,7 @@ jobs:
{
treePath: ".gitea/workflows/jobs-outputs-with-matrix-failure.yml",
fileContent: `name: jobs-outputs-with-matrix-failure
-on:
+on:
push:
paths:
- '.gitea/workflows/jobs-outputs-with-matrix-failure.yml'
@@ -266,7 +265,7 @@ jobs:
id: gen_output
run: |
version="${{ matrix.version }}"
- echo "output_${version}=${version}" >> "$GITHUB_OUTPUT"
+ echo "output_${version}=${version}" >> "$GITHUB_OUTPUT"
job2:
runs-on: ubuntu-latest
if: ${{ always() }}
@@ -319,11 +318,11 @@ jobs:
apiRepo := createActionsTestRepo(t, token, "actions-jobs-outputs-with-matrix", false)
runner := newMockRunner()
- runner.registerAsRepoRunner(t, user2.Name, apiRepo.Name, "mock-runner", []string{"ubuntu-latest"})
+ runner.registerAsRepoRunner(t, user2.Name, apiRepo.Name, "mock-runner", []string{"ubuntu-latest"}, false)
for _, tc := range testCases {
- t.Run(fmt.Sprintf("test %s", tc.treePath), func(t *testing.T) {
- opts := getWorkflowCreateFileOptions(user2, apiRepo.DefaultBranch, fmt.Sprintf("create %s", tc.treePath), tc.fileContent)
+ t.Run("test "+tc.treePath, func(t *testing.T) {
+ opts := getWorkflowCreateFileOptions(user2, apiRepo.DefaultBranch, "create "+tc.treePath, tc.fileContent)
createWorkflowFile(t, token, user2.Name, apiRepo.Name, tc.treePath, opts)
for i := 0; i < len(tc.outcomes); i++ {
@@ -347,9 +346,6 @@ jobs:
}
})
}
-
- httpContext := NewAPITestContext(t, user2.Name, apiRepo.Name, auth_model.AccessTokenScopeWriteRepository)
- doAPIDeleteRepository(httpContext)(t)
})
}
@@ -364,7 +360,95 @@ func TestActionsGiteaContext(t *testing.T) {
user2APICtx := NewAPITestContext(t, baseRepo.OwnerName, baseRepo.Name, auth_model.AccessTokenScopeWriteRepository)
runner := newMockRunner()
- runner.registerAsRepoRunner(t, baseRepo.OwnerName, baseRepo.Name, "mock-runner", []string{"ubuntu-latest"})
+ runner.registerAsRepoRunner(t, baseRepo.OwnerName, baseRepo.Name, "mock-runner", []string{"ubuntu-latest"}, false)
+
+ // init the workflow
+ wfTreePath := ".gitea/workflows/pull.yml"
+ wfFileContent := `name: Pull Request
+on: pull_request
+jobs:
+ wf1-job:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo 'test the pull'
+`
+ opts := getWorkflowCreateFileOptions(user2, baseRepo.DefaultBranch, "create "+wfTreePath, wfFileContent)
+ createWorkflowFile(t, user2Token, baseRepo.OwnerName, baseRepo.Name, wfTreePath, opts)
+ // user2 creates a pull request
+ doAPICreateFile(user2APICtx, "user2-patch.txt", &api.CreateFileOptions{
+ FileOptions: api.FileOptions{
+ NewBranchName: "user2/patch-1",
+ Message: "create user2-patch.txt",
+ Author: api.Identity{
+ Name: user2.Name,
+ Email: user2.Email,
+ },
+ Committer: api.Identity{
+ Name: user2.Name,
+ Email: user2.Email,
+ },
+ Dates: api.CommitDateOptions{
+ Author: time.Now(),
+ Committer: time.Now(),
+ },
+ },
+ ContentBase64: base64.StdEncoding.EncodeToString([]byte("user2-fix")),
+ })(t)
+ apiPull, err := doAPICreatePullRequest(user2APICtx, baseRepo.OwnerName, baseRepo.Name, baseRepo.DefaultBranch, "user2/patch-1")(t)
+ assert.NoError(t, err)
+ task := runner.fetchTask(t)
+ gtCtx := task.Context.GetFields()
+ actionTask := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionTask{ID: task.Id})
+ actionRunJob := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunJob{ID: actionTask.JobID})
+ actionRun := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: actionRunJob.RunID})
+ assert.NoError(t, actionRun.LoadAttributes(t.Context()))
+
+ assert.Equal(t, user2.Name, gtCtx["actor"].GetStringValue())
+ assert.Equal(t, setting.AppURL+"api/v1", gtCtx["api_url"].GetStringValue())
+ assert.Equal(t, apiPull.Base.Ref, gtCtx["base_ref"].GetStringValue())
+ runEvent := map[string]any{}
+ assert.NoError(t, json.Unmarshal([]byte(actionRun.EventPayload), &runEvent))
+ assert.True(t, reflect.DeepEqual(gtCtx["event"].GetStructValue().AsMap(), runEvent))
+ assert.Equal(t, actionRun.TriggerEvent, gtCtx["event_name"].GetStringValue())
+ assert.Equal(t, apiPull.Head.Ref, gtCtx["head_ref"].GetStringValue())
+ assert.Equal(t, actionRunJob.JobID, gtCtx["job"].GetStringValue())
+ assert.Equal(t, actionRun.Ref, gtCtx["ref"].GetStringValue())
+ assert.Equal(t, (git.RefName(actionRun.Ref)).ShortName(), gtCtx["ref_name"].GetStringValue())
+ assert.False(t, gtCtx["ref_protected"].GetBoolValue())
+ assert.Equal(t, string((git.RefName(actionRun.Ref)).RefType()), gtCtx["ref_type"].GetStringValue())
+ assert.Equal(t, actionRun.Repo.OwnerName+"/"+actionRun.Repo.Name, gtCtx["repository"].GetStringValue())
+ assert.Equal(t, actionRun.Repo.OwnerName, gtCtx["repository_owner"].GetStringValue())
+ assert.Equal(t, actionRun.Repo.HTMLURL(), gtCtx["repositoryUrl"].GetStringValue())
+ assert.Equal(t, strconv.FormatInt(actionRunJob.RunID, 10), gtCtx["run_id"].GetStringValue())
+ assert.Equal(t, strconv.FormatInt(actionRun.Index, 10), gtCtx["run_number"].GetStringValue())
+ assert.Equal(t, strconv.FormatInt(actionRunJob.Attempt, 10), gtCtx["run_attempt"].GetStringValue())
+ assert.Equal(t, "Actions", gtCtx["secret_source"].GetStringValue())
+ assert.Equal(t, setting.AppURL, gtCtx["server_url"].GetStringValue())
+ assert.Equal(t, actionRun.CommitSHA, gtCtx["sha"].GetStringValue())
+ assert.Equal(t, actionRun.WorkflowID, gtCtx["workflow"].GetStringValue())
+ assert.Equal(t, setting.Actions.DefaultActionsURL.URL(), gtCtx["gitea_default_actions_url"].GetStringValue())
+ token := gtCtx["token"].GetStringValue()
+ assert.Equal(t, actionTask.TokenLastEight, token[len(token)-8:])
+ })
+}
+
+// Ephemeral
+func TestActionsGiteaContextEphemeral(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ user2Session := loginUser(t, user2.Name)
+ user2Token := getTokenForLoggedInUser(t, user2Session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
+
+ apiBaseRepo := createActionsTestRepo(t, user2Token, "actions-gitea-context", false)
+ baseRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiBaseRepo.ID})
+ user2APICtx := NewAPITestContext(t, baseRepo.OwnerName, baseRepo.Name, auth_model.AccessTokenScopeWriteRepository)
+
+ runner := newMockRunner()
+ runner.registerAsRepoRunner(t, baseRepo.OwnerName, baseRepo.Name, "mock-runner", []string{"ubuntu-latest"}, true)
+
+ // verify CleanupEphemeralRunners does not remove this runner
+ err := actions_service.CleanupEphemeralRunners(t.Context())
+ assert.NoError(t, err)
// init the workflow
wfTreePath := ".gitea/workflows/pull.yml"
@@ -375,8 +459,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- run: echo 'test the pull'
+ wf2-job:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo 'test the pull'
`
- opts := getWorkflowCreateFileOptions(user2, baseRepo.DefaultBranch, fmt.Sprintf("create %s", wfTreePath), wfFileContent)
+ opts := getWorkflowCreateFileOptions(user2, baseRepo.DefaultBranch, "create "+wfTreePath, wfFileContent)
createWorkflowFile(t, user2Token, baseRepo.OwnerName, baseRepo.Name, wfTreePath, opts)
// user2 creates a pull request
doAPICreateFile(user2APICtx, "user2-patch.txt", &api.CreateFileOptions{
@@ -405,7 +493,7 @@ jobs:
actionTask := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionTask{ID: task.Id})
actionRunJob := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunJob{ID: actionTask.JobID})
actionRun := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: actionRunJob.RunID})
- assert.NoError(t, actionRun.LoadAttributes(context.Background()))
+ assert.NoError(t, actionRun.LoadAttributes(t.Context()))
assert.Equal(t, user2.Name, gtCtx["actor"].GetStringValue())
assert.Equal(t, setting.AppURL+"api/v1", gtCtx["api_url"].GetStringValue())
@@ -423,9 +511,9 @@ jobs:
assert.Equal(t, actionRun.Repo.OwnerName+"/"+actionRun.Repo.Name, gtCtx["repository"].GetStringValue())
assert.Equal(t, actionRun.Repo.OwnerName, gtCtx["repository_owner"].GetStringValue())
assert.Equal(t, actionRun.Repo.HTMLURL(), gtCtx["repositoryUrl"].GetStringValue())
- assert.Equal(t, fmt.Sprint(actionRunJob.RunID), gtCtx["run_id"].GetStringValue())
- assert.Equal(t, fmt.Sprint(actionRun.Index), gtCtx["run_number"].GetStringValue())
- assert.Equal(t, fmt.Sprint(actionRunJob.Attempt), gtCtx["run_attempt"].GetStringValue())
+ assert.Equal(t, strconv.FormatInt(actionRunJob.RunID, 10), gtCtx["run_id"].GetStringValue())
+ assert.Equal(t, strconv.FormatInt(actionRun.Index, 10), gtCtx["run_number"].GetStringValue())
+ assert.Equal(t, strconv.FormatInt(actionRunJob.Attempt, 10), gtCtx["run_attempt"].GetStringValue())
assert.Equal(t, "Actions", gtCtx["secret_source"].GetStringValue())
assert.Equal(t, setting.AppURL, gtCtx["server_url"].GetStringValue())
assert.Equal(t, actionRun.CommitSHA, gtCtx["sha"].GetStringValue())
@@ -434,7 +522,62 @@ jobs:
token := gtCtx["token"].GetStringValue()
assert.Equal(t, actionTask.TokenLastEight, token[len(token)-8:])
- doAPIDeleteRepository(user2APICtx)(t)
+ // verify CleanupEphemeralRunners does not remove this runner
+ err = actions_service.CleanupEphemeralRunners(t.Context())
+ assert.NoError(t, err)
+
+ resp, err := runner.client.runnerServiceClient.FetchTask(t.Context(), connect.NewRequest(&runnerv1.FetchTaskRequest{
+ TasksVersion: 0,
+ }))
+ assert.NoError(t, err)
+ assert.Nil(t, resp.Msg.Task)
+
+ // verify CleanupEphemeralRunners does not remove this runner
+ err = actions_service.CleanupEphemeralRunners(t.Context())
+ assert.NoError(t, err)
+
+ _, err = runner.client.runnerServiceClient.UpdateTask(t.Context(), connect.NewRequest(&runnerv1.UpdateTaskRequest{
+ State: &runnerv1.TaskState{
+ Id: actionTask.ID,
+ Result: runnerv1.Result_RESULT_SUCCESS,
+ },
+ }))
+ assert.NoError(t, err)
+
+ resp, err = runner.client.runnerServiceClient.FetchTask(t.Context(), connect.NewRequest(&runnerv1.FetchTaskRequest{
+ TasksVersion: 0,
+ }))
+ assert.Error(t, err)
+ assert.Nil(t, resp)
+
+ resp, err = runner.client.runnerServiceClient.FetchTask(t.Context(), connect.NewRequest(&runnerv1.FetchTaskRequest{
+ TasksVersion: 0,
+ }))
+ assert.Error(t, err)
+ assert.Nil(t, resp)
+
+ // create a runner that picks a job and get force cancelled
+ runnerToBeRemoved := newMockRunner()
+ runnerToBeRemoved.registerAsRepoRunner(t, baseRepo.OwnerName, baseRepo.Name, "mock-runner-to-be-removed", []string{"ubuntu-latest"}, true)
+
+ taskToStopAPIObj := runnerToBeRemoved.fetchTask(t)
+
+ taskToStop := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionTask{ID: taskToStopAPIObj.Id})
+
+ // verify CleanupEphemeralRunners does not remove the custom crafted runner
+ err = actions_service.CleanupEphemeralRunners(t.Context())
+ assert.NoError(t, err)
+
+ runnerToRemove := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: taskToStop.RunnerID})
+
+ err = actions_model.StopTask(t.Context(), taskToStop.ID, actions_model.StatusFailure)
+ assert.NoError(t, err)
+
+ // verify CleanupEphemeralRunners does remove the custom crafted runner
+ err = actions_service.CleanupEphemeralRunners(t.Context())
+ assert.NoError(t, err)
+
+ unittest.AssertNotExistsBean(t, &actions_model.ActionRunner{ID: runnerToRemove.ID})
})
}
diff --git a/tests/integration/actions_log_test.go b/tests/integration/actions_log_test.go
index fd055fc4c4..503bda97c9 100644
--- a/tests/integration/actions_log_test.go
+++ b/tests/integration/actions_log_test.go
@@ -7,10 +7,12 @@ import (
"fmt"
"net/http"
"net/url"
+ "strconv"
"strings"
"testing"
"time"
+ actions_model "code.gitea.io/gitea/models/actions"
auth_model "code.gitea.io/gitea/models/auth"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
@@ -29,13 +31,13 @@ func TestDownloadTaskLogs(t *testing.T) {
testCases := []struct {
treePath string
fileContent string
- outcome *mockTaskOutcome
+ outcome []*mockTaskOutcome
zstdEnabled bool
}{
{
treePath: ".gitea/workflows/download-task-logs-zstd.yml",
fileContent: `name: download-task-logs-zstd
-on:
+on:
push:
paths:
- '.gitea/workflows/download-task-logs-zstd.yml'
@@ -44,21 +46,44 @@ jobs:
runs-on: ubuntu-latest
steps:
- run: echo job1 with zstd enabled
+ job2:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo job2 with zstd enabled
`,
- outcome: &mockTaskOutcome{
- result: runnerv1.Result_RESULT_SUCCESS,
- logRows: []*runnerv1.LogRow{
- {
- Time: timestamppb.New(now.Add(1 * time.Second)),
- Content: " \U0001F433 docker create image",
+ outcome: []*mockTaskOutcome{
+ {
+ result: runnerv1.Result_RESULT_SUCCESS,
+ logRows: []*runnerv1.LogRow{
+ {
+ Time: timestamppb.New(now.Add(1 * time.Second)),
+ Content: " \U0001F433 docker create image",
+ },
+ {
+ Time: timestamppb.New(now.Add(2 * time.Second)),
+ Content: "job1 zstd enabled",
+ },
+ {
+ Time: timestamppb.New(now.Add(3 * time.Second)),
+ Content: "\U0001F3C1 Job succeeded",
+ },
},
- {
- Time: timestamppb.New(now.Add(2 * time.Second)),
- Content: "job1 zstd enabled",
- },
- {
- Time: timestamppb.New(now.Add(3 * time.Second)),
- Content: "\U0001F3C1 Job succeeded",
+ },
+ {
+ result: runnerv1.Result_RESULT_SUCCESS,
+ logRows: []*runnerv1.LogRow{
+ {
+ Time: timestamppb.New(now.Add(1 * time.Second)),
+ Content: " \U0001F433 docker create image",
+ },
+ {
+ Time: timestamppb.New(now.Add(2 * time.Second)),
+ Content: "job2 zstd enabled",
+ },
+ {
+ Time: timestamppb.New(now.Add(3 * time.Second)),
+ Content: "\U0001F3C1 Job succeeded",
+ },
},
},
},
@@ -67,7 +92,7 @@ jobs:
{
treePath: ".gitea/workflows/download-task-logs-no-zstd.yml",
fileContent: `name: download-task-logs-no-zstd
-on:
+on:
push:
paths:
- '.gitea/workflows/download-task-logs-no-zstd.yml'
@@ -76,21 +101,44 @@ jobs:
runs-on: ubuntu-latest
steps:
- run: echo job1 with zstd disabled
+ job2:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo job2 with zstd disabled
`,
- outcome: &mockTaskOutcome{
- result: runnerv1.Result_RESULT_SUCCESS,
- logRows: []*runnerv1.LogRow{
- {
- Time: timestamppb.New(now.Add(4 * time.Second)),
- Content: " \U0001F433 docker create image",
- },
- {
- Time: timestamppb.New(now.Add(5 * time.Second)),
- Content: "job1 zstd disabled",
+ outcome: []*mockTaskOutcome{
+ {
+ result: runnerv1.Result_RESULT_SUCCESS,
+ logRows: []*runnerv1.LogRow{
+ {
+ Time: timestamppb.New(now.Add(4 * time.Second)),
+ Content: " \U0001F433 docker create image",
+ },
+ {
+ Time: timestamppb.New(now.Add(5 * time.Second)),
+ Content: "job1 zstd disabled",
+ },
+ {
+ Time: timestamppb.New(now.Add(6 * time.Second)),
+ Content: "\U0001F3C1 Job succeeded",
+ },
},
- {
- Time: timestamppb.New(now.Add(6 * time.Second)),
- Content: "\U0001F3C1 Job succeeded",
+ },
+ {
+ result: runnerv1.Result_RESULT_SUCCESS,
+ logRows: []*runnerv1.LogRow{
+ {
+ Time: timestamppb.New(now.Add(4 * time.Second)),
+ Content: " \U0001F433 docker create image",
+ },
+ {
+ Time: timestamppb.New(now.Add(5 * time.Second)),
+ Content: "job2 zstd disabled",
+ },
+ {
+ Time: timestamppb.New(now.Add(6 * time.Second)),
+ Content: "\U0001F3C1 Job succeeded",
+ },
},
},
},
@@ -105,10 +153,10 @@ jobs:
apiRepo := createActionsTestRepo(t, token, "actions-download-task-logs", false)
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID})
runner := newMockRunner()
- runner.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-runner", []string{"ubuntu-latest"})
+ runner.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-runner", []string{"ubuntu-latest"}, false)
for _, tc := range testCases {
- t.Run(fmt.Sprintf("test %s", tc.treePath), func(t *testing.T) {
+ t.Run("test "+tc.treePath, func(t *testing.T) {
var resetFunc func()
if tc.zstdEnabled {
resetFunc = test.MockVariableValue(&setting.Actions.LogCompression, "zstd")
@@ -119,41 +167,60 @@ jobs:
}
// create the workflow file
- opts := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, fmt.Sprintf("create %s", tc.treePath), tc.fileContent)
+ opts := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create "+tc.treePath, tc.fileContent)
createWorkflowFile(t, token, user2.Name, repo.Name, tc.treePath, opts)
- // fetch and execute task
- task := runner.fetchTask(t)
- runner.execTask(t, task, tc.outcome)
+ // fetch and execute tasks
+ for jobIndex, outcome := range tc.outcome {
+ task := runner.fetchTask(t)
+ runner.execTask(t, task, outcome)
- // check whether the log file exists
- logFileName := fmt.Sprintf("%s/%02x/%d.log", repo.FullName(), task.Id%256, task.Id)
- if setting.Actions.LogCompression.IsZstd() {
- logFileName += ".zst"
- }
- _, err := storage.Actions.Stat(logFileName)
- assert.NoError(t, err)
+ // check whether the log file exists
+ logFileName := fmt.Sprintf("%s/%02x/%d.log", repo.FullName(), task.Id%256, task.Id)
+ if setting.Actions.LogCompression.IsZstd() {
+ logFileName += ".zst"
+ }
+ _, err := storage.Actions.Stat(logFileName)
+ assert.NoError(t, err)
- // download task logs and check content
- runIndex := task.Context.GetFields()["run_number"].GetStringValue()
- req := NewRequest(t, "GET", fmt.Sprintf("/%s/%s/actions/runs/%s/jobs/0/logs", user2.Name, repo.Name, runIndex)).
- AddTokenAuth(token)
- resp := MakeRequest(t, req, http.StatusOK)
- logTextLines := strings.Split(strings.TrimSpace(resp.Body.String()), "\n")
- assert.Len(t, logTextLines, len(tc.outcome.logRows))
- for idx, lr := range tc.outcome.logRows {
- assert.Equal(
- t,
- fmt.Sprintf("%s %s", lr.Time.AsTime().Format("2006-01-02T15:04:05.0000000Z07:00"), lr.Content),
- logTextLines[idx],
- )
- }
+ // download task logs and check content
+ runIndex := task.Context.GetFields()["run_number"].GetStringValue()
+ req := NewRequest(t, "GET", fmt.Sprintf("/%s/%s/actions/runs/%s/jobs/%d/logs", user2.Name, repo.Name, runIndex, jobIndex)).
+ AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ logTextLines := strings.Split(strings.TrimSpace(resp.Body.String()), "\n")
+ assert.Len(t, logTextLines, len(outcome.logRows))
+ for idx, lr := range outcome.logRows {
+ assert.Equal(
+ t,
+ fmt.Sprintf("%s %s", lr.Time.AsTime().Format("2006-01-02T15:04:05.0000000Z07:00"), lr.Content),
+ logTextLines[idx],
+ )
+ }
+
+ runID, _ := strconv.ParseInt(task.Context.GetFields()["run_id"].GetStringValue(), 10, 64)
+ jobs, err := actions_model.GetRunJobsByRunID(t.Context(), runID)
+ assert.NoError(t, err)
+ assert.Len(t, jobs, len(tc.outcome))
+ jobID := jobs[jobIndex].ID
+
+ // download task logs from API and check content
+ req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/actions/jobs/%d/logs", user2.Name, repo.Name, jobID)).
+ AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
+ logTextLines = strings.Split(strings.TrimSpace(resp.Body.String()), "\n")
+ assert.Len(t, logTextLines, len(outcome.logRows))
+ for idx, lr := range outcome.logRows {
+ assert.Equal(
+ t,
+ fmt.Sprintf("%s %s", lr.Time.AsTime().Format("2006-01-02T15:04:05.0000000Z07:00"), lr.Content),
+ logTextLines[idx],
+ )
+ }
+ }
resetFunc()
})
}
-
- httpContext := NewAPITestContext(t, user2.Name, repo.Name, auth_model.AccessTokenScopeWriteRepository)
- doAPIDeleteRepository(httpContext)(t)
})
}
diff --git a/tests/integration/actions_runner_modify_test.go b/tests/integration/actions_runner_modify_test.go
new file mode 100644
index 0000000000..7d711bae49
--- /dev/null
+++ b/tests/integration/actions_runner_modify_test.go
@@ -0,0 +1,150 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package integration
+
+import (
+ "fmt"
+ "net/http"
+ "testing"
+
+ actions_model "code.gitea.io/gitea/models/actions"
+ "code.gitea.io/gitea/models/db"
+ repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unittest"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/tests"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestActionsRunnerModify(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ ctx := t.Context()
+
+ require.NoError(t, db.DeleteAllRecords("action_runner"))
+
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ _ = actions_model.CreateRunner(ctx, &actions_model.ActionRunner{OwnerID: user2.ID, Name: "user2-runner", TokenHash: "a", UUID: "a"})
+ user2Runner := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{OwnerID: user2.ID, Name: "user2-runner"})
+ userWebURL := "/user/settings/actions/runners"
+
+ org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3, Type: user_model.UserTypeOrganization})
+ require.NoError(t, actions_model.CreateRunner(ctx, &actions_model.ActionRunner{OwnerID: org3.ID, Name: "org3-runner", TokenHash: "b", UUID: "b"}))
+ org3Runner := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{OwnerID: org3.ID, Name: "org3-runner"})
+ orgWebURL := "/org/org3/settings/actions/runners"
+
+ repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
+ _ = actions_model.CreateRunner(ctx, &actions_model.ActionRunner{RepoID: repo1.ID, Name: "repo1-runner", TokenHash: "c", UUID: "c"})
+ repo1Runner := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{RepoID: repo1.ID, Name: "repo1-runner"})
+ repoWebURL := "/user2/repo1/settings/actions/runners"
+
+ _ = actions_model.CreateRunner(ctx, &actions_model.ActionRunner{Name: "global-runner", TokenHash: "d", UUID: "d"})
+ globalRunner := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{Name: "global-runner"})
+ adminWebURL := "/-/admin/actions/runners"
+
+ sessionAdmin := loginUser(t, "user1")
+ sessionUser2 := loginUser(t, user2.Name)
+
+ doUpdate := func(t *testing.T, sess *TestSession, baseURL string, id int64, description string, expectedStatus int) {
+ req := NewRequestWithValues(t, "POST", fmt.Sprintf("%s/%d", baseURL, id), map[string]string{
+ "_csrf": GetUserCSRFToken(t, sess),
+ "description": description,
+ })
+ sess.MakeRequest(t, req, expectedStatus)
+ }
+
+ doDelete := func(t *testing.T, sess *TestSession, baseURL string, id int64, expectedStatus int) {
+ req := NewRequestWithValues(t, "POST", fmt.Sprintf("%s/%d/delete", baseURL, id), map[string]string{
+ "_csrf": GetUserCSRFToken(t, sess),
+ })
+ sess.MakeRequest(t, req, expectedStatus)
+ }
+
+ assertDenied := func(t *testing.T, sess *TestSession, baseURL string, id int64) {
+ doUpdate(t, sess, baseURL, id, "ChangedDescription", http.StatusNotFound)
+ doDelete(t, sess, baseURL, id, http.StatusNotFound)
+ v := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: id})
+ assert.Empty(t, v.Description)
+ }
+
+ assertSuccess := func(t *testing.T, sess *TestSession, baseURL string, id int64) {
+ doUpdate(t, sess, baseURL, id, "ChangedDescription", http.StatusSeeOther)
+ v := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: id})
+ assert.Equal(t, "ChangedDescription", v.Description)
+ doDelete(t, sess, baseURL, id, http.StatusOK)
+ unittest.AssertNotExistsBean(t, &actions_model.ActionRunner{ID: id})
+ }
+
+ t.Run("UpdateUserRunner", func(t *testing.T) {
+ theRunner := user2Runner
+ t.Run("FromOrg", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, orgWebURL, theRunner.ID)
+ })
+ t.Run("FromRepo", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, repoWebURL, theRunner.ID)
+ })
+ t.Run("FromAdmin", func(t *testing.T) {
+ t.Skip("Admin can update any runner (not right but not too bad)")
+ assertDenied(t, sessionAdmin, adminWebURL, theRunner.ID)
+ })
+ })
+
+ t.Run("UpdateOrgRunner", func(t *testing.T) {
+ theRunner := org3Runner
+ t.Run("FromRepo", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, repoWebURL, theRunner.ID)
+ })
+ t.Run("FromUser", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, userWebURL, theRunner.ID)
+ })
+ t.Run("FromAdmin", func(t *testing.T) {
+ t.Skip("Admin can update any runner (not right but not too bad)")
+ assertDenied(t, sessionAdmin, adminWebURL, theRunner.ID)
+ })
+ })
+
+ t.Run("UpdateRepoRunner", func(t *testing.T) {
+ theRunner := repo1Runner
+ t.Run("FromOrg", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, orgWebURL, theRunner.ID)
+ })
+ t.Run("FromUser", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, userWebURL, theRunner.ID)
+ })
+ t.Run("FromAdmin", func(t *testing.T) {
+ t.Skip("Admin can update any runner (not right but not too bad)")
+ assertDenied(t, sessionAdmin, adminWebURL, theRunner.ID)
+ })
+ })
+
+ t.Run("UpdateGlobalRunner", func(t *testing.T) {
+ theRunner := globalRunner
+ t.Run("FromOrg", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, orgWebURL, theRunner.ID)
+ })
+ t.Run("FromUser", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, userWebURL, theRunner.ID)
+ })
+ t.Run("FromRepo", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, repoWebURL, theRunner.ID)
+ })
+ })
+
+ t.Run("UpdateSuccess", func(t *testing.T) {
+ t.Run("User", func(t *testing.T) {
+ assertSuccess(t, sessionUser2, userWebURL, user2Runner.ID)
+ })
+ t.Run("Org", func(t *testing.T) {
+ assertSuccess(t, sessionAdmin, orgWebURL, org3Runner.ID)
+ })
+ t.Run("Repo", func(t *testing.T) {
+ assertSuccess(t, sessionUser2, repoWebURL, repo1Runner.ID)
+ })
+ t.Run("Admin", func(t *testing.T) {
+ assertSuccess(t, sessionAdmin, adminWebURL, globalRunner.ID)
+ })
+ })
+}
diff --git a/tests/integration/actions_runner_test.go b/tests/integration/actions_runner_test.go
index 355ea1705e..6cc5a10e0f 100644
--- a/tests/integration/actions_runner_test.go
+++ b/tests/integration/actions_runner_test.go
@@ -37,7 +37,7 @@ func newMockRunner() *mockRunner {
}
func newMockRunnerClient(uuid, token string) *mockRunnerClient {
- baseURL := fmt.Sprintf("%sapi/actions", setting.AppURL)
+ baseURL := setting.AppURL + "api/actions"
opt := connect.WithInterceptors(connect.UnaryInterceptorFunc(func(next connect.UnaryFunc) connect.UnaryFunc {
return func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) {
@@ -60,26 +60,27 @@ func newMockRunnerClient(uuid, token string) *mockRunnerClient {
}
func (r *mockRunner) doPing(t *testing.T) {
- resp, err := r.client.pingServiceClient.Ping(context.Background(), connect.NewRequest(&pingv1.PingRequest{
+ resp, err := r.client.pingServiceClient.Ping(t.Context(), connect.NewRequest(&pingv1.PingRequest{
Data: "mock-runner",
}))
assert.NoError(t, err)
assert.Equal(t, "Hello, mock-runner!", resp.Msg.Data)
}
-func (r *mockRunner) doRegister(t *testing.T, name, token string, labels []string) {
+func (r *mockRunner) doRegister(t *testing.T, name, token string, labels []string, ephemeral bool) {
r.doPing(t)
- resp, err := r.client.runnerServiceClient.Register(context.Background(), connect.NewRequest(&runnerv1.RegisterRequest{
- Name: name,
- Token: token,
- Version: "mock-runner-version",
- Labels: labels,
+ resp, err := r.client.runnerServiceClient.Register(t.Context(), connect.NewRequest(&runnerv1.RegisterRequest{
+ Name: name,
+ Token: token,
+ Version: "mock-runner-version",
+ Labels: labels,
+ Ephemeral: ephemeral,
}))
assert.NoError(t, err)
r.client = newMockRunnerClient(resp.Msg.Runner.Uuid, resp.Msg.Runner.Token)
}
-func (r *mockRunner) registerAsRepoRunner(t *testing.T, ownerName, repoName, runnerName string, labels []string) {
+func (r *mockRunner) registerAsRepoRunner(t *testing.T, ownerName, repoName, runnerName string, labels []string, ephemeral bool) {
session := loginUser(t, ownerName)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/actions/runners/registration-token", ownerName, repoName)).AddTokenAuth(token)
@@ -88,7 +89,7 @@ func (r *mockRunner) registerAsRepoRunner(t *testing.T, ownerName, repoName, run
Token string `json:"token"`
}
DecodeJSON(t, resp, &registrationToken)
- r.doRegister(t, runnerName, registrationToken.Token, labels)
+ r.doRegister(t, runnerName, registrationToken.Token, labels, ephemeral)
}
func (r *mockRunner) fetchTask(t *testing.T, timeout ...time.Duration) *runnerv1.Task {
@@ -99,7 +100,7 @@ func (r *mockRunner) fetchTask(t *testing.T, timeout ...time.Duration) *runnerv1
ddl := time.Now().Add(fetchTimeout)
var task *runnerv1.Task
for time.Now().Before(ddl) {
- resp, err := r.client.runnerServiceClient.FetchTask(context.Background(), connect.NewRequest(&runnerv1.FetchTaskRequest{
+ resp, err := r.client.runnerServiceClient.FetchTask(t.Context(), connect.NewRequest(&runnerv1.FetchTaskRequest{
TasksVersion: 0,
}))
assert.NoError(t, err)
@@ -114,15 +115,14 @@ func (r *mockRunner) fetchTask(t *testing.T, timeout ...time.Duration) *runnerv1
}
type mockTaskOutcome struct {
- result runnerv1.Result
- outputs map[string]string
- logRows []*runnerv1.LogRow
- execTime time.Duration
+ result runnerv1.Result
+ outputs map[string]string
+ logRows []*runnerv1.LogRow
}
func (r *mockRunner) execTask(t *testing.T, task *runnerv1.Task, outcome *mockTaskOutcome) {
for idx, lr := range outcome.logRows {
- resp, err := r.client.runnerServiceClient.UpdateLog(context.Background(), connect.NewRequest(&runnerv1.UpdateLogRequest{
+ resp, err := r.client.runnerServiceClient.UpdateLog(t.Context(), connect.NewRequest(&runnerv1.UpdateLogRequest{
TaskId: task.Id,
Index: int64(idx),
Rows: []*runnerv1.LogRow{lr},
@@ -133,7 +133,7 @@ func (r *mockRunner) execTask(t *testing.T, task *runnerv1.Task, outcome *mockTa
}
sentOutputKeys := make([]string, 0, len(outcome.outputs))
for outputKey, outputValue := range outcome.outputs {
- resp, err := r.client.runnerServiceClient.UpdateTask(context.Background(), connect.NewRequest(&runnerv1.UpdateTaskRequest{
+ resp, err := r.client.runnerServiceClient.UpdateTask(t.Context(), connect.NewRequest(&runnerv1.UpdateTaskRequest{
State: &runnerv1.TaskState{
Id: task.Id,
Result: runnerv1.Result_RESULT_UNSPECIFIED,
@@ -144,8 +144,7 @@ func (r *mockRunner) execTask(t *testing.T, task *runnerv1.Task, outcome *mockTa
sentOutputKeys = append(sentOutputKeys, outputKey)
assert.ElementsMatch(t, sentOutputKeys, resp.Msg.SentOutputs)
}
- time.Sleep(outcome.execTime)
- resp, err := r.client.runnerServiceClient.UpdateTask(context.Background(), connect.NewRequest(&runnerv1.UpdateTaskRequest{
+ resp, err := r.client.runnerServiceClient.UpdateTask(t.Context(), connect.NewRequest(&runnerv1.UpdateTaskRequest{
State: &runnerv1.TaskState{
Id: task.Id,
Result: outcome.result,
diff --git a/tests/integration/actions_trigger_test.go b/tests/integration/actions_trigger_test.go
index 2c76aa826f..088491d570 100644
--- a/tests/integration/actions_trigger_test.go
+++ b/tests/integration/actions_trigger_test.go
@@ -4,7 +4,9 @@
package integration
import (
+ "encoding/base64"
"fmt"
+ "net/http"
"net/url"
"strings"
"testing"
@@ -20,12 +22,15 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
actions_module "code.gitea.io/gitea/modules/actions"
+ "code.gitea.io/gitea/modules/commitstatus"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
+ "code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/timeutil"
+ "code.gitea.io/gitea/modules/util"
issue_service "code.gitea.io/gitea/services/issue"
pull_service "code.gitea.io/gitea/services/pull"
release_service "code.gitea.io/gitea/services/release"
@@ -72,21 +77,31 @@ func TestPullRequestTargetEvent(t *testing.T) {
addWorkflowToBaseResp, err := files_service.ChangeRepoFiles(git.DefaultContext, baseRepo, user2, &files_service.ChangeRepoFilesOptions{
Files: []*files_service.ChangeRepoFile{
{
- Operation: "create",
- TreePath: ".gitea/workflows/pr.yml",
- ContentReader: strings.NewReader("name: test\non:\n pull_request_target:\n paths:\n - 'file_*.txt'\njobs:\n test:\n runs-on: ubuntu-latest\n steps:\n - run: echo helloworld\n"),
+ Operation: "create",
+ TreePath: ".gitea/workflows/pr.yml",
+ ContentReader: strings.NewReader(`name: test
+on:
+ pull_request_target:
+ paths:
+ - 'file_*.txt'
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo helloworld
+`),
},
},
Message: "add workflow",
OldBranch: "main",
NewBranch: "main",
Author: &files_service.IdentityOptions{
- Name: user2.Name,
- Email: user2.Email,
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
},
Committer: &files_service.IdentityOptions{
- Name: user2.Name,
- Email: user2.Email,
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
},
Dates: &files_service.CommitDateOptions{
Author: time.Now(),
@@ -109,12 +124,12 @@ func TestPullRequestTargetEvent(t *testing.T) {
OldBranch: "main",
NewBranch: "fork-branch-1",
Author: &files_service.IdentityOptions{
- Name: user4.Name,
- Email: user4.Email,
+ GitUserName: user4.Name,
+ GitUserEmail: user4.Email,
},
Committer: &files_service.IdentityOptions{
- Name: user4.Name,
- Email: user4.Email,
+ GitUserName: user4.Name,
+ GitUserEmail: user4.Email,
},
Dates: &files_service.CommitDateOptions{
Author: time.Now(),
@@ -164,12 +179,12 @@ func TestPullRequestTargetEvent(t *testing.T) {
OldBranch: "main",
NewBranch: "fork-branch-2",
Author: &files_service.IdentityOptions{
- Name: user4.Name,
- Email: user4.Email,
+ GitUserName: user4.Name,
+ GitUserEmail: user4.Email,
},
Committer: &files_service.IdentityOptions{
- Name: user4.Name,
- Email: user4.Email,
+ GitUserName: user4.Name,
+ GitUserEmail: user4.Email,
},
Dates: &files_service.CommitDateOptions{
Author: time.Now(),
@@ -228,21 +243,31 @@ func TestSkipCI(t *testing.T) {
addWorkflowToBaseResp, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
Files: []*files_service.ChangeRepoFile{
{
- Operation: "create",
- TreePath: ".gitea/workflows/pr.yml",
- ContentReader: strings.NewReader("name: test\non:\n push:\n branches: [master]\n pull_request:\njobs:\n test:\n runs-on: ubuntu-latest\n steps:\n - run: echo helloworld\n"),
+ Operation: "create",
+ TreePath: ".gitea/workflows/pr.yml",
+ ContentReader: strings.NewReader(`name: test
+on:
+ push:
+ branches: [master]
+ pull_request:
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo helloworld
+`),
},
},
Message: "add workflow",
OldBranch: "master",
NewBranch: "master",
Author: &files_service.IdentityOptions{
- Name: user2.Name,
- Email: user2.Email,
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
},
Committer: &files_service.IdentityOptions{
- Name: user2.Name,
- Email: user2.Email,
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
},
Dates: &files_service.CommitDateOptions{
Author: time.Now(),
@@ -264,16 +289,16 @@ func TestSkipCI(t *testing.T) {
ContentReader: strings.NewReader("bar"),
},
},
- Message: fmt.Sprintf("%s add bar", setting.Actions.SkipWorkflowStrings[0]),
+ Message: setting.Actions.SkipWorkflowStrings[0] + " add bar",
OldBranch: "master",
NewBranch: "master",
Author: &files_service.IdentityOptions{
- Name: user2.Name,
- Email: user2.Email,
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
},
Committer: &files_service.IdentityOptions{
- Name: user2.Name,
- Email: user2.Email,
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
},
Dates: &files_service.CommitDateOptions{
Author: time.Now(),
@@ -299,12 +324,12 @@ func TestSkipCI(t *testing.T) {
OldBranch: "master",
NewBranch: "test-skip-ci",
Author: &files_service.IdentityOptions{
- Name: user2.Name,
- Email: user2.Email,
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
},
Committer: &files_service.IdentityOptions{
- Name: user2.Name,
- Email: user2.Email,
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
},
Dates: &files_service.CommitDateOptions{
Author: time.Now(),
@@ -347,21 +372,29 @@ func TestCreateDeleteRefEvent(t *testing.T) {
addWorkflowToBaseResp, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
Files: []*files_service.ChangeRepoFile{
{
- Operation: "create",
- TreePath: ".gitea/workflows/createdelete.yml",
- ContentReader: strings.NewReader("name: test\non:\n [create,delete]\njobs:\n test:\n runs-on: ubuntu-latest\n steps:\n - run: echo helloworld\n"),
+ Operation: "create",
+ TreePath: ".gitea/workflows/createdelete.yml",
+ ContentReader: strings.NewReader(`name: test
+on:
+ [create,delete]
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo helloworld
+`),
},
},
Message: "add workflow",
OldBranch: "main",
NewBranch: "main",
Author: &files_service.IdentityOptions{
- Name: user2.Name,
- Email: user2.Email,
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
},
Committer: &files_service.IdentityOptions{
- Name: user2.Name,
- Email: user2.Email,
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
},
Dates: &files_service.CommitDateOptions{
Author: time.Now(),
@@ -461,21 +494,30 @@ func TestPullRequestCommitStatusEvent(t *testing.T) {
addWorkflow, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
Files: []*files_service.ChangeRepoFile{
{
- Operation: "create",
- TreePath: ".gitea/workflows/pr.yml",
- ContentReader: strings.NewReader("name: test\non:\n pull_request:\n types: [assigned, unassigned, labeled, unlabeled, opened, edited, closed, reopened, synchronize, milestoned, demilestoned, review_requested, review_request_removed]\njobs:\n test:\n runs-on: ubuntu-latest\n steps:\n - run: echo helloworld\n"),
+ Operation: "create",
+ TreePath: ".gitea/workflows/pr.yml",
+ ContentReader: strings.NewReader(`name: test
+on:
+ pull_request:
+ types: [assigned, unassigned, labeled, unlabeled, opened, edited, closed, reopened, synchronize, milestoned, demilestoned, review_requested, review_request_removed]
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo helloworld
+`),
},
},
Message: "add workflow",
OldBranch: "main",
NewBranch: "main",
Author: &files_service.IdentityOptions{
- Name: user2.Name,
- Email: user2.Email,
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
},
Committer: &files_service.IdentityOptions{
- Name: user2.Name,
- Email: user2.Email,
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
},
Dates: &files_service.CommitDateOptions{
Author: time.Now(),
@@ -576,12 +618,12 @@ func TestPullRequestCommitStatusEvent(t *testing.T) {
OldBranch: testBranch,
NewBranch: testBranch,
Author: &files_service.IdentityOptions{
- Name: user2.Name,
- Email: user2.Email,
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
},
Committer: &files_service.IdentityOptions{
- Name: user2.Name,
- Email: user2.Email,
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
},
Dates: &files_service.CommitDateOptions{
Author: time.Now(),
@@ -592,12 +634,12 @@ func TestPullRequestCommitStatusEvent(t *testing.T) {
assert.NotEmpty(t, addFileResp)
sha = addFileResp.Commit.SHA
assert.Eventually(t, func() bool {
- latestCommitStatuses, _, err := git_model.GetLatestCommitStatus(db.DefaultContext, repo.ID, sha, db.ListOptionsAll)
+ latestCommitStatuses, err := git_model.GetLatestCommitStatus(db.DefaultContext, repo.ID, sha, db.ListOptionsAll)
assert.NoError(t, err)
if len(latestCommitStatuses) == 0 {
return false
}
- if latestCommitStatuses[0].State == api.CommitStatusPending {
+ if latestCommitStatuses[0].State == commitstatus.CommitStatusPending {
insertFakeStatus(t, repo, sha, latestCommitStatuses[0].TargetURL, latestCommitStatuses[0].Context)
return true
}
@@ -635,19 +677,930 @@ func TestPullRequestCommitStatusEvent(t *testing.T) {
}
func checkCommitStatusAndInsertFakeStatus(t *testing.T, repo *repo_model.Repository, sha string) {
- latestCommitStatuses, _, err := git_model.GetLatestCommitStatus(db.DefaultContext, repo.ID, sha, db.ListOptionsAll)
+ latestCommitStatuses, err := git_model.GetLatestCommitStatus(db.DefaultContext, repo.ID, sha, db.ListOptionsAll)
assert.NoError(t, err)
assert.Len(t, latestCommitStatuses, 1)
- assert.Equal(t, api.CommitStatusPending, latestCommitStatuses[0].State)
+ assert.Equal(t, commitstatus.CommitStatusPending, latestCommitStatuses[0].State)
insertFakeStatus(t, repo, sha, latestCommitStatuses[0].TargetURL, latestCommitStatuses[0].Context)
}
func insertFakeStatus(t *testing.T, repo *repo_model.Repository, sha, targetURL, context string) {
err := commitstatus_service.CreateCommitStatus(db.DefaultContext, repo, user_model.NewActionsUser(), sha, &git_model.CommitStatus{
- State: api.CommitStatusSuccess,
+ State: commitstatus.CommitStatusSuccess,
TargetURL: targetURL,
Context: context,
})
assert.NoError(t, err)
}
+
+func TestWorkflowDispatchPublicApi(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ session := loginUser(t, user2.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // create the repo
+ repo, err := repo_service.CreateRepository(db.DefaultContext, user2, user2, repo_service.CreateRepoOptions{
+ Name: "workflow-dispatch-event",
+ Description: "test workflow-dispatch ci event",
+ AutoInit: true,
+ Gitignores: "Go",
+ License: "MIT",
+ Readme: "Default",
+ DefaultBranch: "main",
+ IsPrivate: false,
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, repo)
+
+ // add workflow file to the repo
+ addWorkflowToBaseResp, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
+ Files: []*files_service.ChangeRepoFile{
+ {
+ Operation: "create",
+ TreePath: ".gitea/workflows/dispatch.yml",
+ ContentReader: strings.NewReader(`
+on:
+ workflow_dispatch
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo helloworld
+`),
+ },
+ },
+ Message: "add workflow",
+ OldBranch: "main",
+ NewBranch: "main",
+ Author: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Committer: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Dates: &files_service.CommitDateOptions{
+ Author: time.Now(),
+ Committer: time.Now(),
+ },
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, addWorkflowToBaseResp)
+
+ // Get the commit ID of the default branch
+ gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo)
+ assert.NoError(t, err)
+ defer gitRepo.Close()
+ branch, err := git_model.GetBranch(db.DefaultContext, repo.ID, repo.DefaultBranch)
+ assert.NoError(t, err)
+ values := url.Values{}
+ values.Set("ref", "main")
+ req := NewRequestWithURLValues(t, "POST", fmt.Sprintf("/api/v1/repos/%s/actions/workflows/dispatch.yml/dispatches", repo.FullName()), values).
+ AddTokenAuth(token)
+ _ = MakeRequest(t, req, http.StatusNoContent)
+
+ run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{
+ Title: "add workflow",
+ RepoID: repo.ID,
+ Event: "workflow_dispatch",
+ Ref: "refs/heads/main",
+ WorkflowID: "dispatch.yml",
+ CommitSHA: branch.CommitID,
+ })
+ assert.NotNil(t, run)
+ })
+}
+
+func TestWorkflowDispatchPublicApiWithInputs(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ session := loginUser(t, user2.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // create the repo
+ repo, err := repo_service.CreateRepository(db.DefaultContext, user2, user2, repo_service.CreateRepoOptions{
+ Name: "workflow-dispatch-event",
+ Description: "test workflow-dispatch ci event",
+ AutoInit: true,
+ Gitignores: "Go",
+ License: "MIT",
+ Readme: "Default",
+ DefaultBranch: "main",
+ IsPrivate: false,
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, repo)
+
+ // add workflow file to the repo
+ addWorkflowToBaseResp, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
+ Files: []*files_service.ChangeRepoFile{
+ {
+ Operation: "create",
+ TreePath: ".gitea/workflows/dispatch.yml",
+ ContentReader: strings.NewReader(`
+on:
+ workflow_dispatch: { inputs: { myinput: { default: def }, myinput2: { default: def2 }, myinput3: { type: boolean, default: false } } }
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo helloworld
+`),
+ },
+ },
+ Message: "add workflow",
+ OldBranch: "main",
+ NewBranch: "main",
+ Author: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Committer: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Dates: &files_service.CommitDateOptions{
+ Author: time.Now(),
+ Committer: time.Now(),
+ },
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, addWorkflowToBaseResp)
+
+ // Get the commit ID of the default branch
+ gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo)
+ assert.NoError(t, err)
+ defer gitRepo.Close()
+ branch, err := git_model.GetBranch(db.DefaultContext, repo.ID, repo.DefaultBranch)
+ assert.NoError(t, err)
+ values := url.Values{}
+ values.Set("ref", "main")
+ values.Set("inputs[myinput]", "val0")
+ values.Set("inputs[myinput3]", "true")
+ req := NewRequestWithURLValues(t, "POST", fmt.Sprintf("/api/v1/repos/%s/actions/workflows/dispatch.yml/dispatches", repo.FullName()), values).
+ AddTokenAuth(token)
+ _ = MakeRequest(t, req, http.StatusNoContent)
+
+ run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{
+ Title: "add workflow",
+ RepoID: repo.ID,
+ Event: "workflow_dispatch",
+ Ref: "refs/heads/main",
+ WorkflowID: "dispatch.yml",
+ CommitSHA: branch.CommitID,
+ })
+ assert.NotNil(t, run)
+ dispatchPayload := &api.WorkflowDispatchPayload{}
+ err = json.Unmarshal([]byte(run.EventPayload), dispatchPayload)
+ assert.NoError(t, err)
+ assert.Contains(t, dispatchPayload.Inputs, "myinput")
+ assert.Contains(t, dispatchPayload.Inputs, "myinput2")
+ assert.Contains(t, dispatchPayload.Inputs, "myinput3")
+ assert.Equal(t, "val0", dispatchPayload.Inputs["myinput"])
+ assert.Equal(t, "def2", dispatchPayload.Inputs["myinput2"])
+ assert.Equal(t, "true", dispatchPayload.Inputs["myinput3"])
+ })
+}
+
+func TestWorkflowDispatchPublicApiJSON(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ session := loginUser(t, user2.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // create the repo
+ repo, err := repo_service.CreateRepository(db.DefaultContext, user2, user2, repo_service.CreateRepoOptions{
+ Name: "workflow-dispatch-event",
+ Description: "test workflow-dispatch ci event",
+ AutoInit: true,
+ Gitignores: "Go",
+ License: "MIT",
+ Readme: "Default",
+ DefaultBranch: "main",
+ IsPrivate: false,
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, repo)
+
+ // add workflow file to the repo
+ addWorkflowToBaseResp, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
+ Files: []*files_service.ChangeRepoFile{
+ {
+ Operation: "create",
+ TreePath: ".gitea/workflows/dispatch.yml",
+ ContentReader: strings.NewReader(`
+on:
+ workflow_dispatch: { inputs: { myinput: { default: def }, myinput2: { default: def2 }, myinput3: { type: boolean, default: false } } }
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo helloworld
+`),
+ },
+ },
+ Message: "add workflow",
+ OldBranch: "main",
+ NewBranch: "main",
+ Author: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Committer: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Dates: &files_service.CommitDateOptions{
+ Author: time.Now(),
+ Committer: time.Now(),
+ },
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, addWorkflowToBaseResp)
+
+ // Get the commit ID of the default branch
+ gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo)
+ assert.NoError(t, err)
+ defer gitRepo.Close()
+ branch, err := git_model.GetBranch(db.DefaultContext, repo.ID, repo.DefaultBranch)
+ assert.NoError(t, err)
+ inputs := &api.CreateActionWorkflowDispatch{
+ Ref: "main",
+ Inputs: map[string]string{
+ "myinput": "val0",
+ "myinput3": "true",
+ },
+ }
+
+ req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/actions/workflows/dispatch.yml/dispatches", repo.FullName()), inputs).
+ AddTokenAuth(token)
+ _ = MakeRequest(t, req, http.StatusNoContent)
+
+ run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{
+ Title: "add workflow",
+ RepoID: repo.ID,
+ Event: "workflow_dispatch",
+ Ref: "refs/heads/main",
+ WorkflowID: "dispatch.yml",
+ CommitSHA: branch.CommitID,
+ })
+ assert.NotNil(t, run)
+ })
+}
+
+func TestWorkflowDispatchPublicApiWithInputsJSON(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ session := loginUser(t, user2.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // create the repo
+ repo, err := repo_service.CreateRepository(db.DefaultContext, user2, user2, repo_service.CreateRepoOptions{
+ Name: "workflow-dispatch-event",
+ Description: "test workflow-dispatch ci event",
+ AutoInit: true,
+ Gitignores: "Go",
+ License: "MIT",
+ Readme: "Default",
+ DefaultBranch: "main",
+ IsPrivate: false,
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, repo)
+
+ // add workflow file to the repo
+ addWorkflowToBaseResp, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
+ Files: []*files_service.ChangeRepoFile{
+ {
+ Operation: "create",
+ TreePath: ".gitea/workflows/dispatch.yml",
+ ContentReader: strings.NewReader(`
+on:
+ workflow_dispatch: { inputs: { myinput: { default: def }, myinput2: { default: def2 }, myinput3: { type: boolean, default: false } } }
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo helloworld
+`),
+ },
+ },
+ Message: "add workflow",
+ OldBranch: "main",
+ NewBranch: "main",
+ Author: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Committer: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Dates: &files_service.CommitDateOptions{
+ Author: time.Now(),
+ Committer: time.Now(),
+ },
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, addWorkflowToBaseResp)
+
+ // Get the commit ID of the default branch
+ gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo)
+ assert.NoError(t, err)
+ defer gitRepo.Close()
+ branch, err := git_model.GetBranch(db.DefaultContext, repo.ID, repo.DefaultBranch)
+ assert.NoError(t, err)
+ inputs := &api.CreateActionWorkflowDispatch{
+ Ref: "main",
+ Inputs: map[string]string{
+ "myinput": "val0",
+ "myinput3": "true",
+ },
+ }
+ req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/actions/workflows/dispatch.yml/dispatches", repo.FullName()), inputs).
+ AddTokenAuth(token)
+ _ = MakeRequest(t, req, http.StatusNoContent)
+
+ run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{
+ Title: "add workflow",
+ RepoID: repo.ID,
+ Event: "workflow_dispatch",
+ Ref: "refs/heads/main",
+ WorkflowID: "dispatch.yml",
+ CommitSHA: branch.CommitID,
+ })
+ assert.NotNil(t, run)
+ dispatchPayload := &api.WorkflowDispatchPayload{}
+ err = json.Unmarshal([]byte(run.EventPayload), dispatchPayload)
+ assert.NoError(t, err)
+ assert.Contains(t, dispatchPayload.Inputs, "myinput")
+ assert.Contains(t, dispatchPayload.Inputs, "myinput2")
+ assert.Contains(t, dispatchPayload.Inputs, "myinput3")
+ assert.Equal(t, "val0", dispatchPayload.Inputs["myinput"])
+ assert.Equal(t, "def2", dispatchPayload.Inputs["myinput2"])
+ assert.Equal(t, "true", dispatchPayload.Inputs["myinput3"])
+ })
+}
+
+func TestWorkflowDispatchPublicApiWithInputsNonDefaultBranchJSON(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ session := loginUser(t, user2.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // create the repo
+ repo, err := repo_service.CreateRepository(db.DefaultContext, user2, user2, repo_service.CreateRepoOptions{
+ Name: "workflow-dispatch-event",
+ Description: "test workflow-dispatch ci event",
+ AutoInit: true,
+ Gitignores: "Go",
+ License: "MIT",
+ Readme: "Default",
+ DefaultBranch: "main",
+ IsPrivate: false,
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, repo)
+
+ // add workflow file to the repo
+ addWorkflowToBaseResp, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
+ Files: []*files_service.ChangeRepoFile{
+ {
+ Operation: "create",
+ TreePath: ".gitea/workflows/dispatch.yml",
+ ContentReader: strings.NewReader(`
+on:
+ workflow_dispatch
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo helloworld
+`),
+ },
+ },
+ Message: "add workflow",
+ OldBranch: "main",
+ NewBranch: "main",
+ Author: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Committer: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Dates: &files_service.CommitDateOptions{
+ Author: time.Now(),
+ Committer: time.Now(),
+ },
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, addWorkflowToBaseResp)
+
+ // add workflow file to the repo
+ addWorkflowToBaseResp, err = files_service.ChangeRepoFiles(git.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
+ Files: []*files_service.ChangeRepoFile{
+ {
+ Operation: "update",
+ TreePath: ".gitea/workflows/dispatch.yml",
+ ContentReader: strings.NewReader(`
+on:
+ workflow_dispatch: { inputs: { myinput: { default: def }, myinput2: { default: def2 }, myinput3: { type: boolean, default: false } } }
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo helloworld
+`),
+ },
+ },
+ Message: "add workflow",
+ OldBranch: "main",
+ NewBranch: "dispatch",
+ Author: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Committer: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Dates: &files_service.CommitDateOptions{
+ Author: time.Now(),
+ Committer: time.Now(),
+ },
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, addWorkflowToBaseResp)
+
+ // Get the commit ID of the dispatch branch
+ gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo)
+ assert.NoError(t, err)
+ defer gitRepo.Close()
+ commit, err := gitRepo.GetBranchCommit("dispatch")
+ assert.NoError(t, err)
+ inputs := &api.CreateActionWorkflowDispatch{
+ Ref: "refs/heads/dispatch",
+ Inputs: map[string]string{
+ "myinput": "val0",
+ "myinput3": "true",
+ },
+ }
+ req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/actions/workflows/dispatch.yml/dispatches", repo.FullName()), inputs).
+ AddTokenAuth(token)
+ _ = MakeRequest(t, req, http.StatusNoContent)
+
+ run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{
+ Title: "add workflow",
+ RepoID: repo.ID,
+ Repo: repo,
+ Event: "workflow_dispatch",
+ Ref: "refs/heads/dispatch",
+ WorkflowID: "dispatch.yml",
+ CommitSHA: commit.ID.String(),
+ })
+ assert.NotNil(t, run)
+ dispatchPayload := &api.WorkflowDispatchPayload{}
+ err = json.Unmarshal([]byte(run.EventPayload), dispatchPayload)
+ assert.NoError(t, err)
+ assert.Contains(t, dispatchPayload.Inputs, "myinput")
+ assert.Contains(t, dispatchPayload.Inputs, "myinput2")
+ assert.Contains(t, dispatchPayload.Inputs, "myinput3")
+ assert.Equal(t, "val0", dispatchPayload.Inputs["myinput"])
+ assert.Equal(t, "def2", dispatchPayload.Inputs["myinput2"])
+ assert.Equal(t, "true", dispatchPayload.Inputs["myinput3"])
+ })
+}
+
+func TestWorkflowApi(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ session := loginUser(t, user2.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // create the repo
+ repo, err := repo_service.CreateRepository(db.DefaultContext, user2, user2, repo_service.CreateRepoOptions{
+ Name: "workflow-api",
+ Description: "test workflow apis",
+ AutoInit: true,
+ Gitignores: "Go",
+ License: "MIT",
+ Readme: "Default",
+ DefaultBranch: "main",
+ IsPrivate: false,
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, repo)
+
+ req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/workflows", repo.FullName())).
+ AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ workflows := &api.ActionWorkflowResponse{}
+ json.NewDecoder(resp.Body).Decode(workflows)
+ assert.Empty(t, workflows.Workflows)
+
+ // add workflow file to the repo
+ addWorkflowToBaseResp, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
+ Files: []*files_service.ChangeRepoFile{
+ {
+ Operation: "create",
+ TreePath: ".gitea/workflows/dispatch.yml",
+ ContentReader: strings.NewReader(`
+on:
+ workflow_dispatch: { inputs: { myinput: { default: def }, myinput2: { default: def2 }, myinput3: { type: boolean, default: false } } }
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo helloworld
+`),
+ },
+ },
+ Message: "add workflow",
+ OldBranch: "main",
+ NewBranch: "main",
+ Author: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Committer: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Dates: &files_service.CommitDateOptions{
+ Author: time.Now(),
+ Committer: time.Now(),
+ },
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, addWorkflowToBaseResp)
+
+ req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/workflows", repo.FullName())).
+ AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
+ json.NewDecoder(resp.Body).Decode(workflows)
+ assert.Len(t, workflows.Workflows, 1)
+ assert.Equal(t, "dispatch.yml", workflows.Workflows[0].Name)
+ assert.Equal(t, ".gitea/workflows/dispatch.yml", workflows.Workflows[0].Path)
+ assert.Equal(t, ".gitea/workflows/dispatch.yml", workflows.Workflows[0].Path)
+ assert.Equal(t, "active", workflows.Workflows[0].State)
+
+ // Use a hardcoded api path
+ req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/workflows/%s", repo.FullName(), workflows.Workflows[0].ID)).
+ AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
+ workflow := &api.ActionWorkflow{}
+ json.NewDecoder(resp.Body).Decode(workflow)
+ assert.Equal(t, workflows.Workflows[0].ID, workflow.ID)
+ assert.Equal(t, workflows.Workflows[0].Path, workflow.Path)
+ assert.Equal(t, workflows.Workflows[0].URL, workflow.URL)
+ assert.Equal(t, workflows.Workflows[0].HTMLURL, workflow.HTMLURL)
+ assert.Equal(t, workflows.Workflows[0].Name, workflow.Name)
+ assert.Equal(t, workflows.Workflows[0].State, workflow.State)
+
+ // Use the provided url instead of the hardcoded one
+ req = NewRequest(t, "GET", workflows.Workflows[0].URL).
+ AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
+ workflow = &api.ActionWorkflow{}
+ json.NewDecoder(resp.Body).Decode(workflow)
+ assert.Equal(t, workflows.Workflows[0].ID, workflow.ID)
+ assert.Equal(t, workflows.Workflows[0].Path, workflow.Path)
+ assert.Equal(t, workflows.Workflows[0].URL, workflow.URL)
+ assert.Equal(t, workflows.Workflows[0].HTMLURL, workflow.HTMLURL)
+ assert.Equal(t, workflows.Workflows[0].Name, workflow.Name)
+ assert.Equal(t, workflows.Workflows[0].State, workflow.State)
+
+ // Disable the workflow
+ req = NewRequest(t, "PUT", workflows.Workflows[0].URL+"/disable").
+ AddTokenAuth(token)
+ _ = MakeRequest(t, req, http.StatusNoContent)
+
+ // Use the provided url instead of the hardcoded one
+ req = NewRequest(t, "GET", workflows.Workflows[0].URL).
+ AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
+ workflow = &api.ActionWorkflow{}
+ json.NewDecoder(resp.Body).Decode(workflow)
+ assert.Equal(t, workflows.Workflows[0].ID, workflow.ID)
+ assert.Equal(t, workflows.Workflows[0].Path, workflow.Path)
+ assert.Equal(t, workflows.Workflows[0].URL, workflow.URL)
+ assert.Equal(t, workflows.Workflows[0].HTMLURL, workflow.HTMLURL)
+ assert.Equal(t, workflows.Workflows[0].Name, workflow.Name)
+ assert.Equal(t, "disabled_manually", workflow.State)
+
+ inputs := &api.CreateActionWorkflowDispatch{
+ Ref: "main",
+ Inputs: map[string]string{
+ "myinput": "val0",
+ "myinput3": "true",
+ },
+ }
+ // Since the workflow is disabled, so the response code is 403 forbidden
+ req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/actions/workflows/dispatch.yml/dispatches", repo.FullName()), inputs).
+ AddTokenAuth(token)
+ _ = MakeRequest(t, req, http.StatusForbidden)
+
+ // Enable the workflow again
+ req = NewRequest(t, "PUT", workflows.Workflows[0].URL+"/enable").
+ AddTokenAuth(token)
+ _ = MakeRequest(t, req, http.StatusNoContent)
+
+ // Use the provided url instead of the hardcoded one
+ req = NewRequest(t, "GET", workflows.Workflows[0].URL).
+ AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
+ workflow = &api.ActionWorkflow{}
+ json.NewDecoder(resp.Body).Decode(workflow)
+ assert.Equal(t, workflows.Workflows[0].ID, workflow.ID)
+ assert.Equal(t, workflows.Workflows[0].Path, workflow.Path)
+ assert.Equal(t, workflows.Workflows[0].URL, workflow.URL)
+ assert.Equal(t, workflows.Workflows[0].HTMLURL, workflow.HTMLURL)
+ assert.Equal(t, workflows.Workflows[0].Name, workflow.Name)
+ assert.Equal(t, workflows.Workflows[0].State, workflow.State)
+
+ req = NewRequest(t, "GET", workflows.Workflows[0].URL).
+ AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
+ workflow = &api.ActionWorkflow{}
+ json.NewDecoder(resp.Body).Decode(workflow)
+ assert.Equal(t, workflows.Workflows[0].ID, workflow.ID)
+ assert.Equal(t, workflows.Workflows[0].Path, workflow.Path)
+ assert.Equal(t, workflows.Workflows[0].URL, workflow.URL)
+ assert.Equal(t, workflows.Workflows[0].HTMLURL, workflow.HTMLURL)
+ assert.Equal(t, workflows.Workflows[0].Name, workflow.Name)
+ assert.Equal(t, workflows.Workflows[0].State, workflow.State)
+
+ // Get the commit ID of the default branch
+ gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo)
+ assert.NoError(t, err)
+ defer gitRepo.Close()
+ branch, err := git_model.GetBranch(db.DefaultContext, repo.ID, repo.DefaultBranch)
+ assert.NoError(t, err)
+ inputs = &api.CreateActionWorkflowDispatch{
+ Ref: "main",
+ Inputs: map[string]string{
+ "myinput": "val0",
+ "myinput3": "true",
+ },
+ }
+ req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/actions/workflows/dispatch.yml/dispatches", repo.FullName()), inputs).
+ AddTokenAuth(token)
+ _ = MakeRequest(t, req, http.StatusNoContent)
+
+ run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{
+ Title: "add workflow",
+ RepoID: repo.ID,
+ Event: "workflow_dispatch",
+ Ref: "refs/heads/main",
+ WorkflowID: "dispatch.yml",
+ CommitSHA: branch.CommitID,
+ })
+ assert.NotNil(t, run)
+ dispatchPayload := &api.WorkflowDispatchPayload{}
+ err = json.Unmarshal([]byte(run.EventPayload), dispatchPayload)
+ assert.NoError(t, err)
+ assert.Contains(t, dispatchPayload.Inputs, "myinput")
+ assert.Contains(t, dispatchPayload.Inputs, "myinput2")
+ assert.Contains(t, dispatchPayload.Inputs, "myinput3")
+ assert.Equal(t, "val0", dispatchPayload.Inputs["myinput"])
+ assert.Equal(t, "def2", dispatchPayload.Inputs["myinput2"])
+ assert.Equal(t, "true", dispatchPayload.Inputs["myinput3"])
+ })
+}
+
+func TestClosePullRequestWithPath(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ // user2 is the owner of the base repo
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ user2Token := getTokenForLoggedInUser(t, loginUser(t, user2.Name), auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
+ // user4 is the owner of the fork repo
+ user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
+ user4Token := getTokenForLoggedInUser(t, loginUser(t, user4.Name), auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
+
+ // create the base repo
+ apiBaseRepo := createActionsTestRepo(t, user2Token, "close-pull-request-with-path", false)
+ baseRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiBaseRepo.ID})
+ user2APICtx := NewAPITestContext(t, baseRepo.OwnerName, baseRepo.Name, auth_model.AccessTokenScopeWriteRepository)
+
+ // init the workflow
+ wfTreePath := ".gitea/workflows/pull.yml"
+ wfFileContent := `name: Pull Request
+on:
+ pull_request:
+ types:
+ - closed
+ paths:
+ - 'app/**'
+jobs:
+ echo:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo 'Hello World'
+`
+ opts1 := getWorkflowCreateFileOptions(user2, baseRepo.DefaultBranch, "create "+wfTreePath, wfFileContent)
+ createWorkflowFile(t, user2Token, baseRepo.OwnerName, baseRepo.Name, wfTreePath, opts1)
+
+ // user4 forks the repo
+ req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/forks", baseRepo.OwnerName, baseRepo.Name),
+ &api.CreateForkOption{
+ Name: util.ToPointer("close-pull-request-with-path-fork"),
+ }).AddTokenAuth(user4Token)
+ resp := MakeRequest(t, req, http.StatusAccepted)
+ var apiForkRepo api.Repository
+ DecodeJSON(t, resp, &apiForkRepo)
+ forkRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiForkRepo.ID})
+ user4APICtx := NewAPITestContext(t, user4.Name, forkRepo.Name, auth_model.AccessTokenScopeWriteRepository)
+
+ // user4 creates a pull request to add file "app/main.go"
+ doAPICreateFile(user4APICtx, "app/main.go", &api.CreateFileOptions{
+ FileOptions: api.FileOptions{
+ NewBranchName: "user4/add-main",
+ Message: "create main.go",
+ Author: api.Identity{
+ Name: user4.Name,
+ Email: user4.Email,
+ },
+ Committer: api.Identity{
+ Name: user4.Name,
+ Email: user4.Email,
+ },
+ Dates: api.CommitDateOptions{
+ Author: time.Now(),
+ Committer: time.Now(),
+ },
+ },
+ ContentBase64: base64.StdEncoding.EncodeToString([]byte("// main.go")),
+ })(t)
+ apiPull, err := doAPICreatePullRequest(user4APICtx, baseRepo.OwnerName, baseRepo.Name, baseRepo.DefaultBranch, user4.Name+":user4/add-main")(t)
+ assert.NoError(t, err)
+
+ doAPIMergePullRequest(user2APICtx, baseRepo.OwnerName, baseRepo.Name, apiPull.Index)(t)
+
+ pullRequest := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: apiPull.ID})
+
+ // load and compare ActionRun
+ assert.Equal(t, 1, unittest.GetCount(t, &actions_model.ActionRun{RepoID: baseRepo.ID}))
+ actionRun := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: baseRepo.ID})
+ assert.Equal(t, actions_module.GithubEventPullRequest, actionRun.TriggerEvent)
+ assert.Equal(t, pullRequest.MergedCommitID, actionRun.CommitSHA)
+ })
+}
+
+func TestActionRunNameWithContextVariables(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+
+ // create the repo
+ repo, err := repo_service.CreateRepository(db.DefaultContext, user2, user2, repo_service.CreateRepoOptions{
+ Name: "action-run-name-with-variables",
+ Description: "test action run name",
+ AutoInit: true,
+ Gitignores: "Go",
+ License: "MIT",
+ Readme: "Default",
+ DefaultBranch: "main",
+ IsPrivate: false,
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, repo)
+
+ // add workflow file to the repo
+ addWorkflowToBaseResp, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
+ Files: []*files_service.ChangeRepoFile{
+ {
+ Operation: "create",
+ TreePath: ".gitea/workflows/runname.yml",
+ ContentReader: strings.NewReader(`name: test
+on:
+ [create,delete]
+run-name: ${{ gitea.actor }} is running this workflow
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo helloworld
+`),
+ },
+ },
+ Message: "add workflow with run-name",
+ OldBranch: "main",
+ NewBranch: "main",
+ Author: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Committer: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Dates: &files_service.CommitDateOptions{
+ Author: time.Now(),
+ Committer: time.Now(),
+ },
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, addWorkflowToBaseResp)
+
+ // Get the commit ID of the default branch
+ gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo)
+ assert.NoError(t, err)
+ defer gitRepo.Close()
+ branch, err := git_model.GetBranch(db.DefaultContext, repo.ID, repo.DefaultBranch)
+ assert.NoError(t, err)
+
+ // create a branch
+ err = repo_service.CreateNewBranchFromCommit(db.DefaultContext, user2, repo, gitRepo, branch.CommitID, "test-action-run-name-with-variables")
+ assert.NoError(t, err)
+ run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{
+ Title: user2.LoginName + " is running this workflow",
+ RepoID: repo.ID,
+ Event: "create",
+ Ref: "refs/heads/test-action-run-name-with-variables",
+ WorkflowID: "runname.yml",
+ CommitSHA: branch.CommitID,
+ })
+ assert.NotNil(t, run)
+ })
+}
+
+func TestActionRunName(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+
+ // create the repo
+ repo, err := repo_service.CreateRepository(db.DefaultContext, user2, user2, repo_service.CreateRepoOptions{
+ Name: "action-run-name",
+ Description: "test action run-name",
+ AutoInit: true,
+ Gitignores: "Go",
+ License: "MIT",
+ Readme: "Default",
+ DefaultBranch: "main",
+ IsPrivate: false,
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, repo)
+
+ // add workflow file to the repo
+ addWorkflowToBaseResp, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
+ Files: []*files_service.ChangeRepoFile{
+ {
+ Operation: "create",
+ TreePath: ".gitea/workflows/runname.yml",
+ ContentReader: strings.NewReader(`name: test
+on:
+ [create,delete]
+run-name: run name without variables
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo helloworld
+`),
+ },
+ },
+ Message: "add workflow with run name",
+ OldBranch: "main",
+ NewBranch: "main",
+ Author: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Committer: &files_service.IdentityOptions{
+ GitUserName: user2.Name,
+ GitUserEmail: user2.Email,
+ },
+ Dates: &files_service.CommitDateOptions{
+ Author: time.Now(),
+ Committer: time.Now(),
+ },
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, addWorkflowToBaseResp)
+
+ // Get the commit ID of the default branch
+ gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo)
+ assert.NoError(t, err)
+ defer gitRepo.Close()
+ branch, err := git_model.GetBranch(db.DefaultContext, repo.ID, repo.DefaultBranch)
+ assert.NoError(t, err)
+
+ // create a branch
+ err = repo_service.CreateNewBranchFromCommit(db.DefaultContext, user2, repo, gitRepo, branch.CommitID, "test-action-run-name")
+ assert.NoError(t, err)
+ run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{
+ Title: "run name without variables",
+ RepoID: repo.ID,
+ Event: "create",
+ Ref: "refs/heads/test-action-run-name",
+ WorkflowID: "runname.yml",
+ CommitSHA: branch.CommitID,
+ })
+ assert.NotNil(t, run)
+ })
+}
diff --git a/tests/integration/actions_variables_test.go b/tests/integration/actions_variables_test.go
new file mode 100644
index 0000000000..c0d0bd371b
--- /dev/null
+++ b/tests/integration/actions_variables_test.go
@@ -0,0 +1,148 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package integration
+
+import (
+ "fmt"
+ "net/http"
+ "testing"
+
+ actions_model "code.gitea.io/gitea/models/actions"
+ "code.gitea.io/gitea/models/db"
+ repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unittest"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/tests"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestActionsVariables(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ ctx := t.Context()
+
+ require.NoError(t, db.DeleteAllRecords("action_variable"))
+
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ _, _ = actions_model.InsertVariable(ctx, user2.ID, 0, "VAR", "user2-var", "user2-var-description")
+ user2Var := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{OwnerID: user2.ID, Name: "VAR"})
+ userWebURL := "/user/settings/actions/variables"
+
+ org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3, Type: user_model.UserTypeOrganization})
+ _, _ = actions_model.InsertVariable(ctx, org3.ID, 0, "VAR", "org3-var", "org3-var-description")
+ org3Var := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{OwnerID: org3.ID, Name: "VAR"})
+ orgWebURL := "/org/org3/settings/actions/variables"
+
+ repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
+ _, _ = actions_model.InsertVariable(ctx, 0, repo1.ID, "VAR", "repo1-var", "repo1-var-description")
+ repo1Var := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{RepoID: repo1.ID, Name: "VAR"})
+ repoWebURL := "/user2/repo1/settings/actions/variables"
+
+ _, _ = actions_model.InsertVariable(ctx, 0, 0, "VAR", "global-var", "global-var-description")
+ globalVar := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{Name: "VAR", Data: "global-var"})
+ adminWebURL := "/-/admin/actions/variables"
+
+ sessionAdmin := loginUser(t, "user1")
+ sessionUser2 := loginUser(t, user2.Name)
+
+ doUpdate := func(t *testing.T, sess *TestSession, baseURL string, id int64, data string, expectedStatus int) {
+ req := NewRequestWithValues(t, "POST", fmt.Sprintf("%s/%d/edit", baseURL, id), map[string]string{
+ "_csrf": GetUserCSRFToken(t, sess),
+ "name": "VAR",
+ "data": data,
+ })
+ sess.MakeRequest(t, req, expectedStatus)
+ }
+
+ doDelete := func(t *testing.T, sess *TestSession, baseURL string, id int64, expectedStatus int) {
+ req := NewRequestWithValues(t, "POST", fmt.Sprintf("%s/%d/delete", baseURL, id), map[string]string{
+ "_csrf": GetUserCSRFToken(t, sess),
+ })
+ sess.MakeRequest(t, req, expectedStatus)
+ }
+
+ assertDenied := func(t *testing.T, sess *TestSession, baseURL string, id int64) {
+ doUpdate(t, sess, baseURL, id, "ChangedData", http.StatusNotFound)
+ doDelete(t, sess, baseURL, id, http.StatusNotFound)
+ v := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{ID: id})
+ assert.Contains(t, v.Data, "-var")
+ }
+
+ assertSuccess := func(t *testing.T, sess *TestSession, baseURL string, id int64) {
+ doUpdate(t, sess, baseURL, id, "ChangedData", http.StatusOK)
+ v := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{ID: id})
+ assert.Equal(t, "ChangedData", v.Data)
+ doDelete(t, sess, baseURL, id, http.StatusOK)
+ unittest.AssertNotExistsBean(t, &actions_model.ActionVariable{ID: id})
+ }
+
+ t.Run("UpdateUserVar", func(t *testing.T) {
+ theVar := user2Var
+ t.Run("FromOrg", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, orgWebURL, theVar.ID)
+ })
+ t.Run("FromRepo", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, repoWebURL, theVar.ID)
+ })
+ t.Run("FromAdmin", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, adminWebURL, theVar.ID)
+ })
+ })
+
+ t.Run("UpdateOrgVar", func(t *testing.T) {
+ theVar := org3Var
+ t.Run("FromRepo", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, repoWebURL, theVar.ID)
+ })
+ t.Run("FromUser", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, userWebURL, theVar.ID)
+ })
+ t.Run("FromAdmin", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, adminWebURL, theVar.ID)
+ })
+ })
+
+ t.Run("UpdateRepoVar", func(t *testing.T) {
+ theVar := repo1Var
+ t.Run("FromOrg", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, orgWebURL, theVar.ID)
+ })
+ t.Run("FromUser", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, userWebURL, theVar.ID)
+ })
+ t.Run("FromAdmin", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, adminWebURL, theVar.ID)
+ })
+ })
+
+ t.Run("UpdateGlobalVar", func(t *testing.T) {
+ theVar := globalVar
+ t.Run("FromOrg", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, orgWebURL, theVar.ID)
+ })
+ t.Run("FromUser", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, userWebURL, theVar.ID)
+ })
+ t.Run("FromRepo", func(t *testing.T) {
+ assertDenied(t, sessionAdmin, repoWebURL, theVar.ID)
+ })
+ })
+
+ t.Run("UpdateSuccess", func(t *testing.T) {
+ t.Run("User", func(t *testing.T) {
+ assertSuccess(t, sessionUser2, userWebURL, user2Var.ID)
+ })
+ t.Run("Org", func(t *testing.T) {
+ assertSuccess(t, sessionAdmin, orgWebURL, org3Var.ID)
+ })
+ t.Run("Repo", func(t *testing.T) {
+ assertSuccess(t, sessionUser2, repoWebURL, repo1Var.ID)
+ })
+ t.Run("Admin", func(t *testing.T) {
+ assertSuccess(t, sessionAdmin, adminWebURL, globalVar.ID)
+ })
+ })
+}
diff --git a/tests/integration/admin_user_test.go b/tests/integration/admin_user_test.go
index d5d7e70bc7..95e03ab750 100644
--- a/tests/integration/admin_user_test.go
+++ b/tests/integration/admin_user_test.go
@@ -4,6 +4,7 @@
package integration
import (
+ "fmt"
"net/http"
"strconv"
"testing"
@@ -72,12 +73,37 @@ func TestAdminDeleteUser(t *testing.T) {
session := loginUser(t, "user1")
- csrf := GetUserCSRFToken(t, session)
- req := NewRequestWithValues(t, "POST", "/-/admin/users/8/delete", map[string]string{
- "_csrf": csrf,
- })
- session.MakeRequest(t, req, http.StatusSeeOther)
-
- assertUserDeleted(t, 8)
- unittest.CheckConsistencyFor(t, &user_model.User{})
+ usersToDelete := []struct {
+ userID int64
+ purge bool
+ }{
+ {
+ userID: 2,
+ purge: true,
+ },
+ {
+ userID: 8,
+ },
+ }
+
+ for _, entry := range usersToDelete {
+ t.Run(fmt.Sprintf("DeleteUser%d", entry.userID), func(t *testing.T) {
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: entry.userID})
+ assert.NotNil(t, user)
+
+ var query string
+ if entry.purge {
+ query = "?purge=true"
+ }
+
+ csrf := GetUserCSRFToken(t, session)
+ req := NewRequestWithValues(t, "POST", fmt.Sprintf("/-/admin/users/%d/delete%s", entry.userID, query), map[string]string{
+ "_csrf": csrf,
+ })
+ session.MakeRequest(t, req, http.StatusSeeOther)
+
+ assertUserDeleted(t, entry.userID)
+ unittest.CheckConsistencyFor(t, &user_model.User{})
+ })
+ }
}
diff --git a/tests/integration/api_actions_artifact_v4_test.go b/tests/integration/api_actions_artifact_v4_test.go
index 8821472801..3db8bbb82e 100644
--- a/tests/integration/api_actions_artifact_v4_test.go
+++ b/tests/integration/api_actions_artifact_v4_test.go
@@ -8,13 +8,20 @@ import (
"crypto/sha256"
"encoding/hex"
"encoding/xml"
+ "fmt"
"io"
"net/http"
"strings"
"testing"
"time"
+ auth_model "code.gitea.io/gitea/models/auth"
+ repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unittest"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/storage"
+ api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/api/actions"
actions_service "code.gitea.io/gitea/services/actions"
@@ -334,6 +341,206 @@ func TestActionsArtifactV4DownloadSingle(t *testing.T) {
assert.Equal(t, body, resp.Body.String())
}
+func TestActionsArtifactV4RunDownloadSinglePublicApi(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm artifact can be listed and found by name
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/runs/792/artifacts?name=artifact-v4-download", repo.FullName()), nil).
+ AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ var listResp api.ActionArtifactsResponse
+ err := json.Unmarshal(resp.Body.Bytes(), &listResp)
+ assert.NoError(t, err)
+ assert.NotEmpty(t, listResp.Entries[0].ArchiveDownloadURL)
+ assert.Equal(t, "artifact-v4-download", listResp.Entries[0].Name)
+
+ // confirm artifact blob storage url can be retrieved
+ req = NewRequestWithBody(t, "GET", listResp.Entries[0].ArchiveDownloadURL, nil).
+ AddTokenAuth(token)
+
+ resp = MakeRequest(t, req, http.StatusFound)
+
+ // confirm artifact can be downloaded and has expected content
+ req = NewRequestWithBody(t, "GET", resp.Header().Get("Location"), nil).
+ AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
+
+ body := strings.Repeat("D", 1024)
+ assert.Equal(t, body, resp.Body.String())
+}
+
+func TestActionsArtifactV4DownloadSinglePublicApi(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm artifact can be listed and found by name
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts?name=artifact-v4-download", repo.FullName()), nil).
+ AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ var listResp api.ActionArtifactsResponse
+ err := json.Unmarshal(resp.Body.Bytes(), &listResp)
+ assert.NoError(t, err)
+ assert.NotEmpty(t, listResp.Entries[0].ArchiveDownloadURL)
+ assert.Equal(t, "artifact-v4-download", listResp.Entries[0].Name)
+
+ // confirm artifact blob storage url can be retrieved
+ req = NewRequestWithBody(t, "GET", listResp.Entries[0].ArchiveDownloadURL, nil).
+ AddTokenAuth(token)
+
+ resp = MakeRequest(t, req, http.StatusFound)
+
+ blobLocation := resp.Header().Get("Location")
+
+ // confirm artifact can be downloaded without token and has expected content
+ req = NewRequestWithBody(t, "GET", blobLocation, nil)
+ resp = MakeRequest(t, req, http.StatusOK)
+ body := strings.Repeat("D", 1024)
+ assert.Equal(t, body, resp.Body.String())
+
+ // confirm artifact can not be downloaded without query
+ req = NewRequestWithBody(t, "GET", blobLocation, nil)
+ req.URL.RawQuery = ""
+ _ = MakeRequest(t, req, http.StatusUnauthorized)
+}
+
+func TestActionsArtifactV4DownloadSinglePublicApiPrivateRepo(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm artifact can be listed and found by name
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts?name=artifact-v4-download", repo.FullName()), nil).
+ AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ var listResp api.ActionArtifactsResponse
+ err := json.Unmarshal(resp.Body.Bytes(), &listResp)
+ assert.NoError(t, err)
+ assert.Equal(t, int64(23), listResp.Entries[0].ID)
+ assert.NotEmpty(t, listResp.Entries[0].ArchiveDownloadURL)
+ assert.Equal(t, "artifact-v4-download", listResp.Entries[0].Name)
+
+ // confirm artifact blob storage url can be retrieved
+ req = NewRequestWithBody(t, "GET", listResp.Entries[0].ArchiveDownloadURL, nil).
+ AddTokenAuth(token)
+
+ resp = MakeRequest(t, req, http.StatusFound)
+
+ blobLocation := resp.Header().Get("Location")
+ // confirm artifact can be downloaded without token and has expected content
+ req = NewRequestWithBody(t, "GET", blobLocation, nil)
+ resp = MakeRequest(t, req, http.StatusOK)
+ body := strings.Repeat("D", 1024)
+ assert.Equal(t, body, resp.Body.String())
+
+ // confirm artifact can not be downloaded without query
+ req = NewRequestWithBody(t, "GET", blobLocation, nil)
+ req.URL.RawQuery = ""
+ _ = MakeRequest(t, req, http.StatusUnauthorized)
+}
+
+func TestActionsArtifactV4ListAndGetPublicApi(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm artifact can be listed
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts", repo.FullName()), nil).
+ AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ var listResp api.ActionArtifactsResponse
+ err := json.Unmarshal(resp.Body.Bytes(), &listResp)
+ assert.NoError(t, err)
+
+ for _, artifact := range listResp.Entries {
+ assert.Contains(t, artifact.URL, fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), artifact.ID))
+ assert.Contains(t, artifact.ArchiveDownloadURL, fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d/zip", repo.FullName(), artifact.ID))
+ req = NewRequestWithBody(t, "GET", listResp.Entries[0].URL, nil).
+ AddTokenAuth(token)
+
+ resp = MakeRequest(t, req, http.StatusOK)
+ var artifactResp api.ActionArtifact
+ err := json.Unmarshal(resp.Body.Bytes(), &artifactResp)
+ assert.NoError(t, err)
+
+ assert.Equal(t, artifact.ID, artifactResp.ID)
+ assert.Equal(t, artifact.Name, artifactResp.Name)
+ assert.Equal(t, artifact.SizeInBytes, artifactResp.SizeInBytes)
+ assert.Equal(t, artifact.URL, artifactResp.URL)
+ assert.Equal(t, artifact.ArchiveDownloadURL, artifactResp.ArchiveDownloadURL)
+ }
+}
+
+func TestActionsArtifactV4GetArtifactMismatchedRepoNotFound(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm artifacts of wrong repo is not visible
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNotFound)
+}
+
+func TestActionsArtifactV4DownloadArtifactMismatchedRepoNotFound(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm artifacts of wrong repo is not visible
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d/zip", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNotFound)
+}
+
+func TestActionsArtifactV4DownloadArtifactCorrectRepoFound(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm artifacts of correct repo is visible
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d/zip", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusFound)
+}
+
+func TestActionsArtifactV4DownloadRawArtifactCorrectRepoMissingSignatureUnauthorized(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm cannot use the raw artifact endpoint even with a correct access token
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d/zip/raw", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusUnauthorized)
+}
+
func TestActionsArtifactV4Delete(t *testing.T) {
defer prepareTestEnvActionsArtifacts(t)()
@@ -350,4 +557,72 @@ func TestActionsArtifactV4Delete(t *testing.T) {
var deleteResp actions.DeleteArtifactResponse
protojson.Unmarshal(resp.Body.Bytes(), &deleteResp)
assert.True(t, deleteResp.Ok)
+
+ // confirm artifact is no longer accessible by GetSignedArtifactURL
+ req = NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/GetSignedArtifactURL", toProtoJSON(&actions.GetSignedArtifactURLRequest{
+ Name: "artifact-v4-download",
+ WorkflowRunBackendId: "792",
+ WorkflowJobRunBackendId: "193",
+ })).
+ AddTokenAuth(token)
+ _ = MakeRequest(t, req, http.StatusNotFound)
+
+ // confirm artifact is no longer enumerateable by ListArtifacts and returns length == 0 without error
+ req = NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/ListArtifacts", toProtoJSON(&actions.ListArtifactsRequest{
+ NameFilter: wrapperspb.String("artifact-v4-download"),
+ WorkflowRunBackendId: "792",
+ WorkflowJobRunBackendId: "193",
+ })).AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
+ var listResp actions.ListArtifactsResponse
+ protojson.Unmarshal(resp.Body.Bytes(), &listResp)
+ assert.Empty(t, listResp.Artifacts)
+}
+
+func TestActionsArtifactV4DeletePublicApi(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm artifacts exists
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusOK)
+
+ // delete artifact by id
+ req = NewRequestWithBody(t, "DELETE", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNoContent)
+
+ // confirm artifacts has been deleted
+ req = NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNotFound)
+}
+
+func TestActionsArtifactV4DeletePublicApiNotAllowedReadScope(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
+
+ // confirm artifacts exists
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusOK)
+
+ // try delete artifact by id
+ req = NewRequestWithBody(t, "DELETE", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusForbidden)
+
+ // confirm artifacts has not been deleted
+ req = NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusOK)
}
diff --git a/tests/integration/api_actions_delete_run_test.go b/tests/integration/api_actions_delete_run_test.go
new file mode 100644
index 0000000000..5b41702c57
--- /dev/null
+++ b/tests/integration/api_actions_delete_run_test.go
@@ -0,0 +1,98 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package integration
+
+import (
+ "fmt"
+ "net/http"
+ "testing"
+
+ auth_model "code.gitea.io/gitea/models/auth"
+ repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unittest"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/json"
+ api "code.gitea.io/gitea/modules/structs"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestAPIActionsDeleteRunCheckPermission(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+ testAPIActionsDeleteRun(t, repo, token, http.StatusNotFound)
+}
+
+func TestAPIActionsDeleteRun(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ testAPIActionsDeleteRunListArtifacts(t, repo, token, 2)
+ testAPIActionsDeleteRunListTasks(t, repo, token, true)
+ testAPIActionsDeleteRun(t, repo, token, http.StatusNoContent)
+
+ testAPIActionsDeleteRunListArtifacts(t, repo, token, 0)
+ testAPIActionsDeleteRunListTasks(t, repo, token, false)
+ testAPIActionsDeleteRun(t, repo, token, http.StatusNotFound)
+}
+
+func TestAPIActionsDeleteRunRunning(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/repos/%s/actions/runs/793", repo.FullName())).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusBadRequest)
+}
+
+func testAPIActionsDeleteRun(t *testing.T, repo *repo_model.Repository, token string, expected int) {
+ req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/repos/%s/actions/runs/795", repo.FullName())).
+ AddTokenAuth(token)
+ MakeRequest(t, req, expected)
+}
+
+func testAPIActionsDeleteRunListArtifacts(t *testing.T, repo *repo_model.Repository, token string, artifacts int) {
+ req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/runs/795/artifacts", repo.FullName())).
+ AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ var listResp api.ActionArtifactsResponse
+ err := json.Unmarshal(resp.Body.Bytes(), &listResp)
+ assert.NoError(t, err)
+ assert.Len(t, listResp.Entries, artifacts)
+}
+
+func testAPIActionsDeleteRunListTasks(t *testing.T, repo *repo_model.Repository, token string, expected bool) {
+ req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/tasks", repo.FullName())).
+ AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ var listResp api.ActionTaskResponse
+ err := json.Unmarshal(resp.Body.Bytes(), &listResp)
+ assert.NoError(t, err)
+ findTask1 := false
+ findTask2 := false
+ for _, entry := range listResp.Entries {
+ if entry.ID == 53 {
+ findTask1 = true
+ continue
+ }
+ if entry.ID == 54 {
+ findTask2 = true
+ continue
+ }
+ }
+ assert.Equal(t, expected, findTask1)
+ assert.Equal(t, expected, findTask2)
+}
diff --git a/tests/integration/api_actions_runner_test.go b/tests/integration/api_actions_runner_test.go
new file mode 100644
index 0000000000..fb9ba5b0c2
--- /dev/null
+++ b/tests/integration/api_actions_runner_test.go
@@ -0,0 +1,342 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package integration
+
+import (
+ "fmt"
+ "net/http"
+ "slices"
+ "testing"
+
+ auth_model "code.gitea.io/gitea/models/auth"
+ api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/tests"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestAPIActionsRunner(t *testing.T) {
+ t.Run("AdminRunner", testActionsRunnerAdmin)
+ t.Run("UserRunner", testActionsRunnerUser)
+ t.Run("OwnerRunner", testActionsRunnerOwner)
+ t.Run("RepoRunner", testActionsRunnerRepo)
+}
+
+func testActionsRunnerAdmin(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+ adminUsername := "user1"
+ token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeWriteAdmin)
+ req := NewRequest(t, "POST", "/api/v1/admin/actions/runners/registration-token").AddTokenAuth(token)
+ tokenResp := MakeRequest(t, req, http.StatusOK)
+ var registrationToken struct {
+ Token string `json:"token"`
+ }
+ DecodeJSON(t, tokenResp, &registrationToken)
+ assert.NotEmpty(t, registrationToken.Token)
+
+ req = NewRequest(t, "GET", "/api/v1/admin/actions/runners").AddTokenAuth(token)
+ runnerListResp := MakeRequest(t, req, http.StatusOK)
+ runnerList := api.ActionRunnersResponse{}
+ DecodeJSON(t, runnerListResp, &runnerList)
+
+ idx := slices.IndexFunc(runnerList.Entries, func(e *api.ActionRunner) bool { return e.ID == 34349 })
+ require.NotEqual(t, -1, idx)
+ expectedRunner := runnerList.Entries[idx]
+ assert.Equal(t, "runner_to_be_deleted", expectedRunner.Name)
+ assert.False(t, expectedRunner.Ephemeral)
+ assert.Len(t, expectedRunner.Labels, 2)
+ assert.Equal(t, "runner_to_be_deleted", expectedRunner.Labels[0].Name)
+ assert.Equal(t, "linux", expectedRunner.Labels[1].Name)
+
+ // Verify all returned runners can be requested and deleted
+ for _, runnerEntry := range runnerList.Entries {
+ // Verify get the runner by id
+ req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/admin/actions/runners/%d", runnerEntry.ID)).AddTokenAuth(token)
+ runnerResp := MakeRequest(t, req, http.StatusOK)
+
+ runner := api.ActionRunner{}
+ DecodeJSON(t, runnerResp, &runner)
+
+ assert.Equal(t, runnerEntry.Name, runner.Name)
+ assert.Equal(t, runnerEntry.ID, runner.ID)
+ assert.Equal(t, runnerEntry.Ephemeral, runner.Ephemeral)
+ assert.ElementsMatch(t, runnerEntry.Labels, runner.Labels)
+
+ req = NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/admin/actions/runners/%d", runnerEntry.ID)).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNoContent)
+
+ // Verify runner deletion
+ req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/admin/actions/runners/%d", runnerEntry.ID)).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNotFound)
+ }
+}
+
+func testActionsRunnerUser(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+ userUsername := "user1"
+ token := getUserToken(t, userUsername, auth_model.AccessTokenScopeWriteUser)
+ req := NewRequest(t, "POST", "/api/v1/user/actions/runners/registration-token").AddTokenAuth(token)
+ tokenResp := MakeRequest(t, req, http.StatusOK)
+ var registrationToken struct {
+ Token string `json:"token"`
+ }
+ DecodeJSON(t, tokenResp, &registrationToken)
+ assert.NotEmpty(t, registrationToken.Token)
+
+ req = NewRequest(t, "GET", "/api/v1/user/actions/runners").AddTokenAuth(token)
+ runnerListResp := MakeRequest(t, req, http.StatusOK)
+ runnerList := api.ActionRunnersResponse{}
+ DecodeJSON(t, runnerListResp, &runnerList)
+
+ assert.Len(t, runnerList.Entries, 1)
+ assert.Equal(t, "runner_to_be_deleted-user", runnerList.Entries[0].Name)
+ assert.Equal(t, int64(34346), runnerList.Entries[0].ID)
+ assert.False(t, runnerList.Entries[0].Ephemeral)
+ assert.Len(t, runnerList.Entries[0].Labels, 2)
+ assert.Equal(t, "runner_to_be_deleted", runnerList.Entries[0].Labels[0].Name)
+ assert.Equal(t, "linux", runnerList.Entries[0].Labels[1].Name)
+
+ // Verify get the runner by id
+ req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/actions/runners/%d", runnerList.Entries[0].ID)).AddTokenAuth(token)
+ runnerResp := MakeRequest(t, req, http.StatusOK)
+
+ runner := api.ActionRunner{}
+ DecodeJSON(t, runnerResp, &runner)
+
+ assert.Equal(t, "runner_to_be_deleted-user", runner.Name)
+ assert.Equal(t, int64(34346), runner.ID)
+ assert.False(t, runner.Ephemeral)
+ assert.Len(t, runner.Labels, 2)
+ assert.Equal(t, "runner_to_be_deleted", runner.Labels[0].Name)
+ assert.Equal(t, "linux", runner.Labels[1].Name)
+
+ // Verify delete the runner by id
+ req = NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/user/actions/runners/%d", runnerList.Entries[0].ID)).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNoContent)
+
+ // Verify runner deletion
+ req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/actions/runners/%d", runnerList.Entries[0].ID)).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNotFound)
+}
+
+func testActionsRunnerOwner(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ t.Run("GetRunner", func(t *testing.T) {
+ userUsername := "user2"
+ token := getUserToken(t, userUsername, auth_model.AccessTokenScopeReadOrganization)
+ // Verify get the runner by id with read scope
+ req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/orgs/org3/actions/runners/%d", 34347)).AddTokenAuth(token)
+ runnerResp := MakeRequest(t, req, http.StatusOK)
+
+ runner := api.ActionRunner{}
+ DecodeJSON(t, runnerResp, &runner)
+
+ assert.Equal(t, "runner_to_be_deleted-org", runner.Name)
+ assert.Equal(t, int64(34347), runner.ID)
+ assert.False(t, runner.Ephemeral)
+ assert.Len(t, runner.Labels, 2)
+ assert.Equal(t, "runner_to_be_deleted", runner.Labels[0].Name)
+ assert.Equal(t, "linux", runner.Labels[1].Name)
+ })
+
+ t.Run("Access", func(t *testing.T) {
+ userUsername := "user2"
+ token := getUserToken(t, userUsername, auth_model.AccessTokenScopeWriteOrganization)
+ req := NewRequest(t, "POST", "/api/v1/orgs/org3/actions/runners/registration-token").AddTokenAuth(token)
+ tokenResp := MakeRequest(t, req, http.StatusOK)
+ var registrationToken struct {
+ Token string `json:"token"`
+ }
+ DecodeJSON(t, tokenResp, &registrationToken)
+ assert.NotEmpty(t, registrationToken.Token)
+
+ req = NewRequest(t, "GET", "/api/v1/orgs/org3/actions/runners").AddTokenAuth(token)
+ runnerListResp := MakeRequest(t, req, http.StatusOK)
+ runnerList := api.ActionRunnersResponse{}
+ DecodeJSON(t, runnerListResp, &runnerList)
+
+ idx := slices.IndexFunc(runnerList.Entries, func(e *api.ActionRunner) bool { return e.ID == 34347 })
+ require.NotEqual(t, -1, idx)
+ expectedRunner := runnerList.Entries[idx]
+
+ require.NotNil(t, expectedRunner)
+ assert.Equal(t, "runner_to_be_deleted-org", expectedRunner.Name)
+ assert.Equal(t, int64(34347), expectedRunner.ID)
+ assert.False(t, expectedRunner.Ephemeral)
+ assert.Len(t, expectedRunner.Labels, 2)
+ assert.Equal(t, "runner_to_be_deleted", expectedRunner.Labels[0].Name)
+ assert.Equal(t, "linux", expectedRunner.Labels[1].Name)
+
+ // Verify get the runner by id
+ req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/orgs/org3/actions/runners/%d", expectedRunner.ID)).AddTokenAuth(token)
+ runnerResp := MakeRequest(t, req, http.StatusOK)
+
+ runner := api.ActionRunner{}
+ DecodeJSON(t, runnerResp, &runner)
+
+ assert.Equal(t, "runner_to_be_deleted-org", runner.Name)
+ assert.Equal(t, int64(34347), runner.ID)
+ assert.False(t, runner.Ephemeral)
+ assert.Len(t, runner.Labels, 2)
+ assert.Equal(t, "runner_to_be_deleted", runner.Labels[0].Name)
+ assert.Equal(t, "linux", runner.Labels[1].Name)
+
+ // Verify delete the runner by id
+ req = NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/orgs/org3/actions/runners/%d", expectedRunner.ID)).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNoContent)
+
+ // Verify runner deletion
+ req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/orgs/org3/actions/runners/%d", expectedRunner.ID)).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNotFound)
+ })
+
+ t.Run("DeleteReadScopeForbidden", func(t *testing.T) {
+ userUsername := "user2"
+ token := getUserToken(t, userUsername, auth_model.AccessTokenScopeReadOrganization)
+
+ // Verify delete the runner by id is forbidden with read scope
+ req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/orgs/org3/actions/runners/%d", 34347)).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusForbidden)
+ })
+
+ t.Run("GetRepoScopeForbidden", func(t *testing.T) {
+ userUsername := "user2"
+ token := getUserToken(t, userUsername, auth_model.AccessTokenScopeReadRepository)
+ // Verify get the runner by id with read scope
+ req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/orgs/org3/actions/runners/%d", 34347)).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusForbidden)
+ })
+
+ t.Run("GetAdminRunner", func(t *testing.T) {
+ userUsername := "user2"
+ token := getUserToken(t, userUsername, auth_model.AccessTokenScopeReadOrganization)
+ // Verify get a runner by id of different entity is not found
+ // runner.EditableInContext(ownerID, repoID) false
+ req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/orgs/org3/actions/runners/%d", 34349)).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNotFound)
+ })
+
+ t.Run("DeleteAdminRunner", func(t *testing.T) {
+ userUsername := "user2"
+ token := getUserToken(t, userUsername, auth_model.AccessTokenScopeWriteOrganization)
+ // Verify delete a runner by id of different entity is not found
+ // runner.EditableInContext(ownerID, repoID) false
+ req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/orgs/org3/actions/runners/%d", 34349)).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNotFound)
+ })
+}
+
+func testActionsRunnerRepo(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ t.Run("GetRunner", func(t *testing.T) {
+ userUsername := "user2"
+ token := getUserToken(t, userUsername, auth_model.AccessTokenScopeReadRepository)
+ // Verify get the runner by id with read scope
+ req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/user2/repo1/actions/runners/%d", 34348)).AddTokenAuth(token)
+ runnerResp := MakeRequest(t, req, http.StatusOK)
+
+ runner := api.ActionRunner{}
+ DecodeJSON(t, runnerResp, &runner)
+
+ assert.Equal(t, "runner_to_be_deleted-repo1", runner.Name)
+ assert.Equal(t, int64(34348), runner.ID)
+ assert.False(t, runner.Ephemeral)
+ assert.Len(t, runner.Labels, 2)
+ assert.Equal(t, "runner_to_be_deleted", runner.Labels[0].Name)
+ assert.Equal(t, "linux", runner.Labels[1].Name)
+ })
+
+ t.Run("Access", func(t *testing.T) {
+ userUsername := "user2"
+ token := getUserToken(t, userUsername, auth_model.AccessTokenScopeWriteRepository)
+ req := NewRequest(t, "POST", "/api/v1/repos/user2/repo1/actions/runners/registration-token").AddTokenAuth(token)
+ tokenResp := MakeRequest(t, req, http.StatusOK)
+ var registrationToken struct {
+ Token string `json:"token"`
+ }
+ DecodeJSON(t, tokenResp, &registrationToken)
+ assert.NotEmpty(t, registrationToken.Token)
+
+ req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/actions/runners").AddTokenAuth(token)
+ runnerListResp := MakeRequest(t, req, http.StatusOK)
+ runnerList := api.ActionRunnersResponse{}
+ DecodeJSON(t, runnerListResp, &runnerList)
+
+ assert.Len(t, runnerList.Entries, 1)
+ assert.Equal(t, "runner_to_be_deleted-repo1", runnerList.Entries[0].Name)
+ assert.Equal(t, int64(34348), runnerList.Entries[0].ID)
+ assert.False(t, runnerList.Entries[0].Ephemeral)
+ assert.Len(t, runnerList.Entries[0].Labels, 2)
+ assert.Equal(t, "runner_to_be_deleted", runnerList.Entries[0].Labels[0].Name)
+ assert.Equal(t, "linux", runnerList.Entries[0].Labels[1].Name)
+
+ // Verify get the runner by id
+ req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/user2/repo1/actions/runners/%d", runnerList.Entries[0].ID)).AddTokenAuth(token)
+ runnerResp := MakeRequest(t, req, http.StatusOK)
+
+ runner := api.ActionRunner{}
+ DecodeJSON(t, runnerResp, &runner)
+
+ assert.Equal(t, "runner_to_be_deleted-repo1", runner.Name)
+ assert.Equal(t, int64(34348), runner.ID)
+ assert.False(t, runner.Ephemeral)
+ assert.Len(t, runner.Labels, 2)
+ assert.Equal(t, "runner_to_be_deleted", runner.Labels[0].Name)
+ assert.Equal(t, "linux", runner.Labels[1].Name)
+
+ // Verify delete the runner by id
+ req = NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/repos/user2/repo1/actions/runners/%d", runnerList.Entries[0].ID)).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNoContent)
+
+ // Verify runner deletion
+ req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/user2/repo1/actions/runners/%d", runnerList.Entries[0].ID)).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNotFound)
+ })
+
+ t.Run("DeleteReadScopeForbidden", func(t *testing.T) {
+ userUsername := "user2"
+ token := getUserToken(t, userUsername, auth_model.AccessTokenScopeReadRepository)
+
+ // Verify delete the runner by id is forbidden with read scope
+ req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/repos/user2/repo1/actions/runners/%d", 34348)).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusForbidden)
+ })
+
+ t.Run("GetOrganizationScopeForbidden", func(t *testing.T) {
+ userUsername := "user2"
+ token := getUserToken(t, userUsername, auth_model.AccessTokenScopeReadOrganization)
+ // Verify get the runner by id with read scope
+ req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/user2/repo1/actions/runners/%d", 34348)).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusForbidden)
+ })
+
+ t.Run("GetAdminRunnerNotFound", func(t *testing.T) {
+ userUsername := "user2"
+ token := getUserToken(t, userUsername, auth_model.AccessTokenScopeReadRepository)
+ // Verify get a runner by id of different entity is not found
+ // runner.EditableInContext(ownerID, repoID) false
+ req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/user2/repo1/actions/runners/%d", 34349)).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNotFound)
+ })
+
+ t.Run("DeleteAdminRunnerNotFound", func(t *testing.T) {
+ userUsername := "user2"
+ token := getUserToken(t, userUsername, auth_model.AccessTokenScopeWriteRepository)
+ // Verify delete a runner by id of different entity is not found
+ // runner.EditableInContext(ownerID, repoID) false
+ req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/repos/user2/repo1/actions/runners/%d", 34349)).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNotFound)
+ })
+
+ t.Run("DeleteAdminRunnerNotFoundUnknownID", func(t *testing.T) {
+ userUsername := "user2"
+ token := getUserToken(t, userUsername, auth_model.AccessTokenScopeWriteRepository)
+ // Verify delete a runner by unknown id is not found
+ req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/repos/user2/repo1/actions/runners/%d", 4384797347934)).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNotFound)
+ })
+}
diff --git a/tests/integration/api_activitypub_person_test.go b/tests/integration/api_activitypub_person_test.go
index 42a2a09072..9bb1f2736e 100644
--- a/tests/integration/api_activitypub_person_test.go
+++ b/tests/integration/api_activitypub_person_test.go
@@ -4,32 +4,31 @@
package integration
import (
- "context"
"fmt"
"net/http"
"net/http/httptest"
- "net/url"
"testing"
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/activitypub"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/routers"
+ "code.gitea.io/gitea/tests"
ap "github.com/go-ap/activitypub"
"github.com/stretchr/testify/assert"
)
func TestActivityPubPerson(t *testing.T) {
- setting.Federation.Enabled = true
- testWebRoutes = routers.NormalRoutes()
- defer func() {
- setting.Federation.Enabled = false
- testWebRoutes = routers.NormalRoutes()
- }()
+ defer tests.PrepareTestEnv(t)()
+ defer test.MockVariableValue(&setting.Federation.Enabled, true)()
+ defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())()
+
+ t.Run("ExistingPerson", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
- onGiteaRun(t, func(*testing.T, *url.URL) {
userID := 2
username := "user2"
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/activitypub/user-id/%v", userID))
@@ -57,49 +56,26 @@ func TestActivityPubPerson(t *testing.T) {
assert.NotNil(t, pubKeyPem)
assert.Regexp(t, "^-----BEGIN PUBLIC KEY-----", pubKeyPem)
})
-}
-
-func TestActivityPubMissingPerson(t *testing.T) {
- setting.Federation.Enabled = true
- testWebRoutes = routers.NormalRoutes()
- defer func() {
- setting.Federation.Enabled = false
- testWebRoutes = routers.NormalRoutes()
- }()
-
- onGiteaRun(t, func(*testing.T, *url.URL) {
+ t.Run("MissingPerson", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", "/api/v1/activitypub/user-id/999999999")
resp := MakeRequest(t, req, http.StatusNotFound)
assert.Contains(t, resp.Body.String(), "user does not exist")
})
-}
-
-func TestActivityPubPersonInbox(t *testing.T) {
- setting.Federation.Enabled = true
- testWebRoutes = routers.NormalRoutes()
- defer func() {
- setting.Federation.Enabled = false
- testWebRoutes = routers.NormalRoutes()
- }()
-
- srv := httptest.NewServer(testWebRoutes)
- defer srv.Close()
+ t.Run("MissingPersonInbox", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+ srv := httptest.NewServer(testWebRoutes)
+ defer srv.Close()
+ defer test.MockVariableValue(&setting.AppURL, srv.URL+"/")()
- onGiteaRun(t, func(*testing.T, *url.URL) {
- appURL := setting.AppURL
- setting.AppURL = srv.URL + "/"
- defer func() {
- setting.Database.LogSQL = false
- setting.AppURL = appURL
- }()
username1 := "user1"
- ctx := context.Background()
+ ctx := t.Context()
user1, err := user_model.GetUserByName(ctx, username1)
assert.NoError(t, err)
- user1url := fmt.Sprintf("%s/api/v1/activitypub/user-id/1#main-key", srv.URL)
+ user1url := srv.URL + "/api/v1/activitypub/user-id/1#main-key"
c, err := activitypub.NewClient(db.DefaultContext, user1, user1url)
assert.NoError(t, err)
- user2inboxurl := fmt.Sprintf("%s/api/v1/activitypub/user-id/2/inbox", srv.URL)
+ user2inboxurl := srv.URL + "/api/v1/activitypub/user-id/2/inbox"
// Signed request succeeds
resp, err := c.Post([]byte{}, user2inboxurl)
diff --git a/tests/integration/api_admin_org_test.go b/tests/integration/api_admin_org_test.go
index a29d0ba1d7..b2d77456c4 100644
--- a/tests/integration/api_admin_org_test.go
+++ b/tests/integration/api_admin_org_test.go
@@ -5,7 +5,6 @@ package integration
import (
"net/http"
- "net/url"
"strings"
"testing"
@@ -19,10 +18,12 @@ import (
)
func TestAPIAdminOrgCreate(t *testing.T) {
- onGiteaRun(t, func(*testing.T, *url.URL) {
- session := loginUser(t, "user1")
- token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteAdmin)
+ defer tests.PrepareTestEnv(t)()
+ session := loginUser(t, "user1")
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteAdmin)
+ t.Run("CreateOrg", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
org := api.CreateOrgOption{
UserName: "user2_org",
FullName: "User2's organization",
@@ -51,13 +52,8 @@ func TestAPIAdminOrgCreate(t *testing.T) {
FullName: org.FullName,
})
})
-}
-
-func TestAPIAdminOrgCreateBadVisibility(t *testing.T) {
- onGiteaRun(t, func(*testing.T, *url.URL) {
- session := loginUser(t, "user1")
- token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteAdmin)
-
+ t.Run("CreateBadVisibility", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
org := api.CreateOrgOption{
UserName: "user2_org",
FullName: "User2's organization",
@@ -70,22 +66,21 @@ func TestAPIAdminOrgCreateBadVisibility(t *testing.T) {
AddTokenAuth(token)
MakeRequest(t, req, http.StatusUnprocessableEntity)
})
-}
-
-func TestAPIAdminOrgCreateNotAdmin(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
- nonAdminUsername := "user2"
- session := loginUser(t, nonAdminUsername)
- token := getTokenForLoggedInUser(t, session)
- org := api.CreateOrgOption{
- UserName: "user2_org",
- FullName: "User2's organization",
- Description: "This organization created by admin for user2",
- Website: "https://try.gitea.io",
- Location: "Shanghai",
- Visibility: "public",
- }
- req := NewRequestWithJSON(t, "POST", "/api/v1/admin/users/user2/orgs", &org).
- AddTokenAuth(token)
- MakeRequest(t, req, http.StatusForbidden)
+ t.Run("CreateNotAdmin", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+ nonAdminUsername := "user2"
+ session := loginUser(t, nonAdminUsername)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAll)
+ org := api.CreateOrgOption{
+ UserName: "user2_org",
+ FullName: "User2's organization",
+ Description: "This organization created by admin for user2",
+ Website: "https://try.gitea.io",
+ Location: "Shanghai",
+ Visibility: "public",
+ }
+ req := NewRequestWithJSON(t, "POST", "/api/v1/admin/users/user2/orgs", &org).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusForbidden)
+ })
}
diff --git a/tests/integration/api_admin_test.go b/tests/integration/api_admin_test.go
index 66209ee4e0..d28a103e59 100644
--- a/tests/integration/api_admin_test.go
+++ b/tests/integration/api_admin_test.go
@@ -76,7 +76,7 @@ func TestAPIAdminDeleteUnauthorizedKey(t *testing.T) {
var newPublicKey api.PublicKey
DecodeJSON(t, resp, &newPublicKey)
- token = getUserToken(t, normalUsername)
+ token = getUserToken(t, normalUsername, auth_model.AccessTokenScopeAll)
req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d", adminUsername, newPublicKey.ID).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusForbidden)
@@ -88,7 +88,7 @@ func TestAPISudoUser(t *testing.T) {
normalUsername := "user2"
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeReadUser)
- req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/user?sudo=%s", normalUsername)).
+ req := NewRequest(t, "GET", "/api/v1/user?sudo="+normalUsername).
AddTokenAuth(token)
resp := MakeRequest(t, req, http.StatusOK)
var user api.User
@@ -103,7 +103,7 @@ func TestAPISudoUserForbidden(t *testing.T) {
normalUsername := "user2"
token := getUserToken(t, normalUsername, auth_model.AccessTokenScopeReadAdmin)
- req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/user?sudo=%s", adminUsername)).
+ req := NewRequest(t, "GET", "/api/v1/user?sudo="+adminUsername).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusForbidden)
}
@@ -139,7 +139,7 @@ func TestAPIListUsersNotLoggedIn(t *testing.T) {
func TestAPIListUsersNonAdmin(t *testing.T) {
defer tests.PrepareTestEnv(t)()
nonAdminUsername := "user2"
- token := getUserToken(t, nonAdminUsername)
+ token := getUserToken(t, nonAdminUsername, auth_model.AccessTokenScopeAll)
req := NewRequest(t, "GET", "/api/v1/admin/users").
AddTokenAuth(token)
MakeRequest(t, req, http.StatusForbidden)
@@ -193,7 +193,7 @@ func TestAPIEditUser(t *testing.T) {
defer tests.PrepareTestEnv(t)()
adminUsername := "user1"
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeWriteAdmin)
- urlStr := fmt.Sprintf("/api/v1/admin/users/%s", "user2")
+ urlStr := "/api/v1/admin/users/" + "user2"
fullNameToChange := "Full Name User 2"
req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{
@@ -217,7 +217,7 @@ func TestAPIEditUser(t *testing.T) {
errMap := make(map[string]any)
json.Unmarshal(resp.Body.Bytes(), &errMap)
- assert.EqualValues(t, "e-mail invalid [email: ]", errMap["message"].(string))
+ assert.Equal(t, "e-mail invalid [email: ]", errMap["message"].(string))
user2 = unittest.AssertExistsAndLoadBean(t, &user_model.User{LoginName: "user2"})
assert.False(t, user2.IsRestricted)
@@ -374,7 +374,7 @@ func TestAPIEditUser_NotAllowedEmailDomain(t *testing.T) {
adminUsername := "user1"
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeWriteAdmin)
- urlStr := fmt.Sprintf("/api/v1/admin/users/%s", "user2")
+ urlStr := "/api/v1/admin/users/" + "user2"
newEmail := "user2@example1.com"
req := NewRequestWithJSON(t, "PATCH", urlStr, api.EditUserOption{
diff --git a/tests/integration/api_branch_test.go b/tests/integration/api_branch_test.go
index d64dd97f93..16e1f2812e 100644
--- a/tests/integration/api_branch_test.go
+++ b/tests/integration/api_branch_test.go
@@ -24,13 +24,13 @@ func testAPIGetBranch(t *testing.T, branchName string, exists bool) {
AddTokenAuth(token)
resp := MakeRequest(t, req, NoExpectedStatus)
if !exists {
- assert.EqualValues(t, http.StatusNotFound, resp.Code)
+ assert.Equal(t, http.StatusNotFound, resp.Code)
return
}
- assert.EqualValues(t, http.StatusOK, resp.Code)
+ assert.Equal(t, http.StatusOK, resp.Code)
var branch api.Branch
DecodeJSON(t, resp, &branch)
- assert.EqualValues(t, branchName, branch.Name)
+ assert.Equal(t, branchName, branch.Name)
assert.True(t, branch.UserCanPush)
assert.True(t, branch.UserCanMerge)
}
@@ -44,7 +44,7 @@ func testAPIGetBranchProtection(t *testing.T, branchName string, expectedHTTPSta
if resp.Code == http.StatusOK {
var branchProtection api.BranchProtection
DecodeJSON(t, resp, &branchProtection)
- assert.EqualValues(t, branchName, branchProtection.RuleName)
+ assert.Equal(t, branchName, branchProtection.RuleName)
return &branchProtection
}
return nil
@@ -60,7 +60,7 @@ func testAPICreateBranchProtection(t *testing.T, branchName string, expectedPrio
if resp.Code == http.StatusCreated {
var branchProtection api.BranchProtection
DecodeJSON(t, resp, &branchProtection)
- assert.EqualValues(t, branchName, branchProtection.RuleName)
+ assert.Equal(t, branchName, branchProtection.RuleName)
assert.EqualValues(t, expectedPriority, branchProtection.Priority)
}
}
@@ -74,7 +74,7 @@ func testAPIEditBranchProtection(t *testing.T, branchName string, body *api.Bran
if resp.Code == http.StatusOK {
var branchProtection api.BranchProtection
DecodeJSON(t, resp, &branchProtection)
- assert.EqualValues(t, branchName, branchProtection.RuleName)
+ assert.Equal(t, branchName, branchProtection.RuleName)
}
}
@@ -181,7 +181,7 @@ func testAPICreateBranch(t testing.TB, session *TestSession, user, repo, oldBran
DecodeJSON(t, resp, &branch)
if resp.Result().StatusCode == http.StatusCreated {
- assert.EqualValues(t, newBranch, branch.Name)
+ assert.Equal(t, newBranch, branch.Name)
}
return resp.Result().StatusCode == status
@@ -303,7 +303,7 @@ func TestAPICreateBranchWithSyncBranches(t *testing.T) {
RepoID: 1,
})
assert.NoError(t, err)
- assert.Len(t, branches, 4)
+ assert.Len(t, branches, 6)
// make a broke repository with no branch on database
_, err = db.DeleteByBean(db.DefaultContext, git_model.Branch{RepoID: 1})
@@ -320,7 +320,7 @@ func TestAPICreateBranchWithSyncBranches(t *testing.T) {
RepoID: 1,
})
assert.NoError(t, err)
- assert.Len(t, branches, 5)
+ assert.Len(t, branches, 7)
branches, err = db.Find[git_model.Branch](db.DefaultContext, git_model.FindBranchOptions{
RepoID: 1,
diff --git a/tests/integration/api_comment_test.go b/tests/integration/api_comment_test.go
index 255b8332b2..9842c358f6 100644
--- a/tests/integration/api_comment_test.go
+++ b/tests/integration/api_comment_test.go
@@ -106,7 +106,7 @@ func TestAPICreateComment(t *testing.T) {
var updatedComment api.Comment
DecodeJSON(t, resp, &updatedComment)
- assert.EqualValues(t, commentBody, updatedComment.Body)
+ assert.Equal(t, commentBody, updatedComment.Body)
unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: updatedComment.ID, IssueID: issue.ID, Content: commentBody})
t.Run("BlockedByRepoOwner", func(t *testing.T) {
@@ -174,7 +174,7 @@ func TestAPIGetSystemUserComment(t *testing.T) {
user_model.NewGhostUser(),
user_model.NewActionsUser(),
} {
- body := fmt.Sprintf("Hello %s", systemUser.Name)
+ body := "Hello " + systemUser.Name
comment, err := issues_model.CreateComment(db.DefaultContext, &issues_model.CreateCommentOptions{
Type: issues_model.CommentTypeComment,
Doer: systemUser,
@@ -233,8 +233,8 @@ func TestAPIEditComment(t *testing.T) {
var updatedComment api.Comment
DecodeJSON(t, resp, &updatedComment)
- assert.EqualValues(t, comment.ID, updatedComment.ID)
- assert.EqualValues(t, newCommentBody, updatedComment.Body)
+ assert.Equal(t, comment.ID, updatedComment.ID)
+ assert.Equal(t, newCommentBody, updatedComment.Body)
unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: comment.ID, IssueID: issue.ID, Content: newCommentBody})
}
diff --git a/tests/integration/api_fork_test.go b/tests/integration/api_fork_test.go
index 580bb459e7..2837c3b93e 100644
--- a/tests/integration/api_fork_test.go
+++ b/tests/integration/api_fork_test.go
@@ -10,6 +10,7 @@ import (
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
org_model "code.gitea.io/gitea/models/organization"
+ repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs"
@@ -33,7 +34,7 @@ func TestAPIForkListLimitedAndPrivateRepos(t *testing.T) {
// fork into a limited org
limitedOrg := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 22})
- assert.EqualValues(t, api.VisibleTypeLimited, limitedOrg.Visibility)
+ assert.Equal(t, api.VisibleTypeLimited, limitedOrg.Visibility)
ownerTeam1, err := org_model.OrgFromUser(limitedOrg).GetOwnerTeam(db.DefaultContext)
assert.NoError(t, err)
@@ -48,7 +49,7 @@ func TestAPIForkListLimitedAndPrivateRepos(t *testing.T) {
user4Sess := loginUser(t, "user4")
user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user4"})
privateOrg := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 23})
- assert.EqualValues(t, api.VisibleTypePrivate, privateOrg.Visibility)
+ assert.Equal(t, api.VisibleTypePrivate, privateOrg.Visibility)
ownerTeam2, err := org_model.OrgFromUser(privateOrg).GetOwnerTeam(db.DefaultContext)
assert.NoError(t, err)
@@ -69,7 +70,7 @@ func TestAPIForkListLimitedAndPrivateRepos(t *testing.T) {
DecodeJSON(t, resp, &forks)
assert.Empty(t, forks)
- assert.EqualValues(t, "0", resp.Header().Get("X-Total-Count"))
+ assert.Equal(t, "0", resp.Header().Get("X-Total-Count"))
})
t.Run("Logged in", func(t *testing.T) {
@@ -81,8 +82,8 @@ func TestAPIForkListLimitedAndPrivateRepos(t *testing.T) {
var forks []*api.Repository
DecodeJSON(t, resp, &forks)
- assert.Len(t, forks, 1)
- assert.EqualValues(t, "1", resp.Header().Get("X-Total-Count"))
+ assert.Len(t, forks, 2)
+ assert.Equal(t, "2", resp.Header().Get("X-Total-Count"))
assert.NoError(t, org_service.AddTeamMember(db.DefaultContext, ownerTeam2, user1))
@@ -93,6 +94,34 @@ func TestAPIForkListLimitedAndPrivateRepos(t *testing.T) {
DecodeJSON(t, resp, &forks)
assert.Len(t, forks, 2)
- assert.EqualValues(t, "2", resp.Header().Get("X-Total-Count"))
+ assert.Equal(t, "2", resp.Header().Get("X-Total-Count"))
})
}
+
+func TestGetPrivateReposForks(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ user1Sess := loginUser(t, "user1")
+ repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) // private repository
+ privateOrg := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 23})
+ user1Token := getTokenForLoggedInUser(t, user1Sess, auth_model.AccessTokenScopeWriteRepository)
+
+ forkedRepoName := "forked-repo"
+ // create fork from a private repository
+ req := NewRequestWithJSON(t, "POST", "/api/v1/repos/"+repo2.FullName()+"/forks", &api.CreateForkOption{
+ Organization: &privateOrg.Name,
+ Name: &forkedRepoName,
+ }).AddTokenAuth(user1Token)
+ MakeRequest(t, req, http.StatusAccepted)
+
+ // test get a private fork without clear permissions
+ req = NewRequest(t, "GET", "/api/v1/repos/"+repo2.FullName()+"/forks").AddTokenAuth(user1Token)
+ resp := MakeRequest(t, req, http.StatusOK)
+
+ forks := []*api.Repository{}
+ DecodeJSON(t, resp, &forks)
+ assert.Len(t, forks, 1)
+ assert.Equal(t, "1", resp.Header().Get("X-Total-Count"))
+ assert.Equal(t, "forked-repo", forks[0].Name)
+ assert.Equal(t, privateOrg.Name, forks[0].Owner.UserName)
+}
diff --git a/tests/integration/api_gitignore_templates_test.go b/tests/integration/api_gitignore_templates_test.go
index c58f5eebfe..1c56d51344 100644
--- a/tests/integration/api_gitignore_templates_test.go
+++ b/tests/integration/api_gitignore_templates_test.go
@@ -4,7 +4,6 @@
package integration
import (
- "fmt"
"net/http"
"testing"
@@ -38,7 +37,7 @@ func TestAPIGetGitignoreTemplateInfo(t *testing.T) {
// Use the first template for the test
templateName := repo_module.Gitignores[0]
- urlStr := fmt.Sprintf("/api/v1/gitignore/templates/%s", templateName)
+ urlStr := "/api/v1/gitignore/templates/" + templateName
req := NewRequest(t, "GET", urlStr)
resp := MakeRequest(t, req, http.StatusOK)
diff --git a/tests/integration/api_gpg_keys_test.go b/tests/integration/api_gpg_keys_test.go
index ec0dafc2d6..edfb9e6eca 100644
--- a/tests/integration/api_gpg_keys_test.go
+++ b/tests/integration/api_gpg_keys_test.go
@@ -86,13 +86,13 @@ func TestGPGKeys(t *testing.T) {
assert.Len(t, keys, 1)
primaryKey1 := keys[0] // Primary key 1
- assert.EqualValues(t, "38EA3BCED732982C", primaryKey1.KeyID)
+ assert.Equal(t, "38EA3BCED732982C", primaryKey1.KeyID)
assert.Len(t, primaryKey1.Emails, 1)
- assert.EqualValues(t, "user2@example.com", primaryKey1.Emails[0].Email)
+ assert.Equal(t, "user2@example.com", primaryKey1.Emails[0].Email)
assert.True(t, primaryKey1.Emails[0].Verified)
subKey := primaryKey1.SubsKey[0] // Subkey of 38EA3BCED732982C
- assert.EqualValues(t, "70D7C694D17D03AD", subKey.KeyID)
+ assert.Equal(t, "70D7C694D17D03AD", subKey.KeyID)
assert.Empty(t, subKey.Emails)
var key api.GPGKey
@@ -100,16 +100,16 @@ func TestGPGKeys(t *testing.T) {
AddTokenAuth(tokenWithGPGKeyScope)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &key)
- assert.EqualValues(t, "38EA3BCED732982C", key.KeyID)
+ assert.Equal(t, "38EA3BCED732982C", key.KeyID)
assert.Len(t, key.Emails, 1)
- assert.EqualValues(t, "user2@example.com", key.Emails[0].Email)
+ assert.Equal(t, "user2@example.com", key.Emails[0].Email)
assert.True(t, key.Emails[0].Verified)
req = NewRequest(t, "GET", "/api/v1/user/gpg_keys/"+strconv.FormatInt(subKey.ID, 10)). // Subkey of 38EA3BCED732982C
AddTokenAuth(tokenWithGPGKeyScope)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &key)
- assert.EqualValues(t, "70D7C694D17D03AD", key.KeyID)
+ assert.Equal(t, "70D7C694D17D03AD", key.KeyID)
assert.Empty(t, key.Emails)
})
diff --git a/tests/integration/api_helper_for_declarative_test.go b/tests/integration/api_helper_for_declarative_test.go
index 7755b9861a..b30cdfd0fc 100644
--- a/tests/integration/api_helper_for_declarative_test.go
+++ b/tests/integration/api_helper_for_declarative_test.go
@@ -4,7 +4,6 @@
package integration
import (
- "context"
"fmt"
"net/http"
"net/http/httptest"
@@ -34,6 +33,10 @@ type APITestContext struct {
func NewAPITestContext(t *testing.T, username, reponame string, scope ...auth.AccessTokenScope) APITestContext {
session := loginUser(t, username)
+ if len(scope) == 0 {
+ // FIXME: legacy logic: no scope means all
+ scope = []auth.AccessTokenScope{auth.AccessTokenScopeAll}
+ }
token := getTokenForLoggedInUser(t, session, scope...)
return APITestContext{
Session: session,
@@ -260,7 +263,7 @@ func doAPIMergePullRequest(ctx APITestContext, owner, repo string, index int64)
var req *RequestWrapper
var resp *httptest.ResponseRecorder
- for i := 0; i < 6; i++ {
+ for range 6 {
req = NewRequestWithJSON(t, http.MethodPost, urlStr, &forms.MergePullRequestForm{
MergeMessageField: "doAPIMergePullRequest Merge",
Do: string(repo_model.MergeStyleMerge),
@@ -273,8 +276,8 @@ func doAPIMergePullRequest(ctx APITestContext, owner, repo string, index int64)
}
err := api.APIError{}
DecodeJSON(t, resp, &err)
- assert.EqualValues(t, "Please try again later", err.Message)
- queue.GetManager().FlushAll(context.Background(), 5*time.Second)
+ assert.Equal(t, "Please try again later", err.Message)
+ queue.GetManager().FlushAll(t.Context(), 5*time.Second)
<-time.After(1 * time.Second)
}
@@ -283,7 +286,7 @@ func doAPIMergePullRequest(ctx APITestContext, owner, repo string, index int64)
expected = http.StatusOK
}
- if !assert.EqualValues(t, expected, resp.Code,
+ if !assert.Equal(t, expected, resp.Code,
"Request: %s %s", req.Method, req.URL.String()) {
logUnexpectedResponse(t, resp)
}
diff --git a/tests/integration/api_issue_label_test.go b/tests/integration/api_issue_label_test.go
index c9cdd46b9a..4324fd37d9 100644
--- a/tests/integration/api_issue_label_test.go
+++ b/tests/integration/api_issue_label_test.go
@@ -38,8 +38,8 @@ func TestAPIModifyLabels(t *testing.T) {
apiLabel := new(api.Label)
DecodeJSON(t, resp, &apiLabel)
dbLabel := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: apiLabel.ID, RepoID: repo.ID})
- assert.EqualValues(t, dbLabel.Name, apiLabel.Name)
- assert.EqualValues(t, strings.TrimLeft(dbLabel.Color, "#"), apiLabel.Color)
+ assert.Equal(t, dbLabel.Name, apiLabel.Name)
+ assert.Equal(t, strings.TrimLeft(dbLabel.Color, "#"), apiLabel.Color)
req = NewRequestWithJSON(t, "POST", urlStr, &api.CreateLabelOption{
Name: "TestL 2",
@@ -67,7 +67,7 @@ func TestAPIModifyLabels(t *testing.T) {
AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiLabel)
- assert.EqualValues(t, strings.TrimLeft(dbLabel.Color, "#"), apiLabel.Color)
+ assert.Equal(t, strings.TrimLeft(dbLabel.Color, "#"), apiLabel.Color)
// EditLabel
newName := "LabelNewName"
@@ -79,7 +79,7 @@ func TestAPIModifyLabels(t *testing.T) {
}).AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiLabel)
- assert.EqualValues(t, newColor, apiLabel.Color)
+ assert.Equal(t, newColor, apiLabel.Color)
req = NewRequestWithJSON(t, "PATCH", singleURLStr, &api.EditLabelOption{
Color: &newColorWrong,
}).AddTokenAuth(token)
@@ -165,7 +165,7 @@ func TestAPIReplaceIssueLabels(t *testing.T) {
var apiLabels []*api.Label
DecodeJSON(t, resp, &apiLabels)
if assert.Len(t, apiLabels, 1) {
- assert.EqualValues(t, label.ID, apiLabels[0].ID)
+ assert.Equal(t, label.ID, apiLabels[0].ID)
}
unittest.AssertCount(t, &issues_model.IssueLabel{IssueID: issue.ID}, 1)
@@ -191,7 +191,7 @@ func TestAPIReplaceIssueLabelsWithLabelNames(t *testing.T) {
var apiLabels []*api.Label
DecodeJSON(t, resp, &apiLabels)
if assert.Len(t, apiLabels, 1) {
- assert.EqualValues(t, label.Name, apiLabels[0].Name)
+ assert.Equal(t, label.Name, apiLabels[0].Name)
}
}
@@ -215,8 +215,8 @@ func TestAPIModifyOrgLabels(t *testing.T) {
apiLabel := new(api.Label)
DecodeJSON(t, resp, &apiLabel)
dbLabel := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: apiLabel.ID, OrgID: owner.ID})
- assert.EqualValues(t, dbLabel.Name, apiLabel.Name)
- assert.EqualValues(t, strings.TrimLeft(dbLabel.Color, "#"), apiLabel.Color)
+ assert.Equal(t, dbLabel.Name, apiLabel.Name)
+ assert.Equal(t, strings.TrimLeft(dbLabel.Color, "#"), apiLabel.Color)
req = NewRequestWithJSON(t, "POST", urlStr, &api.CreateLabelOption{
Name: "TestL 2",
@@ -244,7 +244,7 @@ func TestAPIModifyOrgLabels(t *testing.T) {
AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiLabel)
- assert.EqualValues(t, strings.TrimLeft(dbLabel.Color, "#"), apiLabel.Color)
+ assert.Equal(t, strings.TrimLeft(dbLabel.Color, "#"), apiLabel.Color)
// EditLabel
newName := "LabelNewName"
@@ -256,7 +256,7 @@ func TestAPIModifyOrgLabels(t *testing.T) {
}).AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiLabel)
- assert.EqualValues(t, newColor, apiLabel.Color)
+ assert.Equal(t, newColor, apiLabel.Color)
req = NewRequestWithJSON(t, "PATCH", singleURLStr, &api.EditLabelOption{
Color: &newColorWrong,
}).AddTokenAuth(token)
diff --git a/tests/integration/api_issue_lock_test.go b/tests/integration/api_issue_lock_test.go
new file mode 100644
index 0000000000..47b1f2cf0d
--- /dev/null
+++ b/tests/integration/api_issue_lock_test.go
@@ -0,0 +1,74 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package integration
+
+import (
+ "fmt"
+ "net/http"
+ "testing"
+
+ auth_model "code.gitea.io/gitea/models/auth"
+ issues_model "code.gitea.io/gitea/models/issues"
+ repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unittest"
+ user_model "code.gitea.io/gitea/models/user"
+ api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/tests"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestAPILockIssue(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ t.Run("Lock", func(t *testing.T) {
+ issueBefore := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1})
+ assert.False(t, issueBefore.IsLocked)
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issueBefore.RepoID})
+ owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/lock", owner.Name, repo.Name, issueBefore.Index)
+
+ session := loginUser(t, owner.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
+
+ // check lock issue
+ req := NewRequestWithJSON(t, "PUT", urlStr, api.LockIssueOption{Reason: "Spam"}).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNoContent)
+ issueAfter := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1})
+ assert.True(t, issueAfter.IsLocked)
+
+ // check with other user
+ user34 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 34})
+ session34 := loginUser(t, user34.Name)
+ token34 := getTokenForLoggedInUser(t, session34, auth_model.AccessTokenScopeAll)
+ req = NewRequestWithJSON(t, "PUT", urlStr, api.LockIssueOption{Reason: "Spam"}).AddTokenAuth(token34)
+ MakeRequest(t, req, http.StatusForbidden)
+ })
+
+ t.Run("Unlock", func(t *testing.T) {
+ issueBefore := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1})
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issueBefore.RepoID})
+ owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/lock", owner.Name, repo.Name, issueBefore.Index)
+
+ session := loginUser(t, owner.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
+
+ lockReq := NewRequestWithJSON(t, "PUT", urlStr, api.LockIssueOption{Reason: "Spam"}).AddTokenAuth(token)
+ MakeRequest(t, lockReq, http.StatusNoContent)
+
+ // check unlock issue
+ req := NewRequest(t, "DELETE", urlStr).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNoContent)
+ issueAfter := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1})
+ assert.False(t, issueAfter.IsLocked)
+
+ // check with other user
+ user34 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 34})
+ session34 := loginUser(t, user34.Name)
+ token34 := getTokenForLoggedInUser(t, session34, auth_model.AccessTokenScopeAll)
+ req = NewRequest(t, "DELETE", urlStr).AddTokenAuth(token34)
+ MakeRequest(t, req, http.StatusForbidden)
+ })
+}
diff --git a/tests/integration/api_issue_milestone_test.go b/tests/integration/api_issue_milestone_test.go
index 2d00752302..1196c8d358 100644
--- a/tests/integration/api_issue_milestone_test.go
+++ b/tests/integration/api_issue_milestone_test.go
@@ -73,7 +73,7 @@ func TestAPIIssuesMilestone(t *testing.T) {
AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiMilestone)
- assert.EqualValues(t, apiMilestones[2], apiMilestone)
+ assert.Equal(t, apiMilestones[2], apiMilestone)
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/milestones?state=%s&name=%s", owner.Name, repo.Name, "all", "milestone2")).
AddTokenAuth(token)
diff --git a/tests/integration/api_issue_stopwatch_test.go b/tests/integration/api_issue_stopwatch_test.go
index 4765787e6f..3606d9a228 100644
--- a/tests/integration/api_issue_stopwatch_test.go
+++ b/tests/integration/api_issue_stopwatch_test.go
@@ -35,11 +35,11 @@ func TestAPIListStopWatches(t *testing.T) {
stopwatch := unittest.AssertExistsAndLoadBean(t, &issues_model.Stopwatch{UserID: owner.ID})
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: stopwatch.IssueID})
if assert.Len(t, apiWatches, 1) {
- assert.EqualValues(t, stopwatch.CreatedUnix.AsTime().Unix(), apiWatches[0].Created.Unix())
- assert.EqualValues(t, issue.Index, apiWatches[0].IssueIndex)
- assert.EqualValues(t, issue.Title, apiWatches[0].IssueTitle)
- assert.EqualValues(t, repo.Name, apiWatches[0].RepoName)
- assert.EqualValues(t, repo.OwnerName, apiWatches[0].RepoOwnerName)
+ assert.Equal(t, stopwatch.CreatedUnix.AsTime().Unix(), apiWatches[0].Created.Unix())
+ assert.Equal(t, issue.Index, apiWatches[0].IssueIndex)
+ assert.Equal(t, issue.Title, apiWatches[0].IssueTitle)
+ assert.Equal(t, repo.Name, apiWatches[0].RepoName)
+ assert.Equal(t, repo.OwnerName, apiWatches[0].RepoOwnerName)
assert.Positive(t, apiWatches[0].Seconds)
}
}
diff --git a/tests/integration/api_issue_subscription_test.go b/tests/integration/api_issue_subscription_test.go
index 7a716301c4..74ba171c01 100644
--- a/tests/integration/api_issue_subscription_test.go
+++ b/tests/integration/api_issue_subscription_test.go
@@ -43,11 +43,11 @@ func TestAPIIssueSubscriptions(t *testing.T) {
wi := new(api.WatchInfo)
DecodeJSON(t, resp, wi)
- assert.EqualValues(t, isWatching, wi.Subscribed)
- assert.EqualValues(t, !isWatching, wi.Ignored)
- assert.EqualValues(t, issue.APIURL(db.DefaultContext)+"/subscriptions", wi.URL)
+ assert.Equal(t, isWatching, wi.Subscribed)
+ assert.Equal(t, !isWatching, wi.Ignored)
+ assert.Equal(t, issue.APIURL(db.DefaultContext)+"/subscriptions", wi.URL)
assert.EqualValues(t, issue.CreatedUnix, wi.CreatedAt.Unix())
- assert.EqualValues(t, issueRepo.APIURL(), wi.RepositoryURL)
+ assert.Equal(t, issueRepo.APIURL(), wi.RepositoryURL)
}
testSubscription(issue1, true)
diff --git a/tests/integration/api_issue_test.go b/tests/integration/api_issue_test.go
index d8394a33d9..370c90a100 100644
--- a/tests/integration/api_issue_test.go
+++ b/tests/integration/api_issue_test.go
@@ -166,7 +166,7 @@ func TestAPICreateIssueParallel(t *testing.T) {
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues", owner.Name, repoBefore.Name)
var wg sync.WaitGroup
- for i := 0; i < 10; i++ {
+ for i := range 10 {
wg.Add(1)
go func(parentT *testing.T, i int) {
parentT.Run(fmt.Sprintf("ParallelCreateIssue_%d", i), func(t *testing.T) {
@@ -267,10 +267,7 @@ func TestAPISearchIssues(t *testing.T) {
defer tests.PrepareTestEnv(t)()
// as this API was used in the frontend, it uses UI page size
- expectedIssueCount := 20 // from the fixtures
- if expectedIssueCount > setting.UI.IssuePagingNum {
- expectedIssueCount = setting.UI.IssuePagingNum
- }
+ expectedIssueCount := min(20, setting.UI.IssuePagingNum) // 20 is from the fixtures
link, _ := url.Parse("/api/v1/repos/issues/search")
token := getUserToken(t, "user1", auth_model.AccessTokenScopeReadIssue)
@@ -313,7 +310,7 @@ func TestAPISearchIssues(t *testing.T) {
req = NewRequest(t, "GET", link.String()).AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
- assert.EqualValues(t, "22", resp.Header().Get("X-Total-Count"))
+ assert.Equal(t, "22", resp.Header().Get("X-Total-Count"))
assert.Len(t, apiIssues, 20)
query.Add("limit", "10")
@@ -321,7 +318,7 @@ func TestAPISearchIssues(t *testing.T) {
req = NewRequest(t, "GET", link.String()).AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
- assert.EqualValues(t, "22", resp.Header().Get("X-Total-Count"))
+ assert.Equal(t, "22", resp.Header().Get("X-Total-Count"))
assert.Len(t, apiIssues, 10)
query = url.Values{"assigned": {"true"}, "state": {"all"}}
@@ -371,10 +368,7 @@ func TestAPISearchIssuesWithLabels(t *testing.T) {
defer tests.PrepareTestEnv(t)()
// as this API was used in the frontend, it uses UI page size
- expectedIssueCount := 20 // from the fixtures
- if expectedIssueCount > setting.UI.IssuePagingNum {
- expectedIssueCount = setting.UI.IssuePagingNum
- }
+ expectedIssueCount := min(20, setting.UI.IssuePagingNum) // 20 is from the fixtures
link, _ := url.Parse("/api/v1/repos/issues/search")
token := getUserToken(t, "user1", auth_model.AccessTokenScopeReadIssue)
diff --git a/tests/integration/api_issue_tracked_time_test.go b/tests/integration/api_issue_tracked_time_test.go
index fd2c452b20..bd562b602e 100644
--- a/tests/integration/api_issue_tracked_time_test.go
+++ b/tests/integration/api_issue_tracked_time_test.go
@@ -41,8 +41,8 @@ func TestAPIGetTrackedTimes(t *testing.T) {
for i, time := range expect {
assert.Equal(t, time.ID, apiTimes[i].ID)
- assert.EqualValues(t, issue2.Title, apiTimes[i].Issue.Title)
- assert.EqualValues(t, issue2.ID, apiTimes[i].IssueID)
+ assert.Equal(t, issue2.Title, apiTimes[i].Issue.Title)
+ assert.Equal(t, issue2.ID, apiTimes[i].IssueID)
assert.Equal(t, time.Created.Unix(), apiTimes[i].Created.Unix())
assert.Equal(t, time.Time, apiTimes[i].Time)
user, err := user_model.GetUserByID(db.DefaultContext, time.UserID)
@@ -125,6 +125,6 @@ func TestAPIAddTrackedTimes(t *testing.T) {
DecodeJSON(t, resp, &apiNewTime)
assert.EqualValues(t, 33, apiNewTime.Time)
- assert.EqualValues(t, user2.ID, apiNewTime.UserID)
+ assert.Equal(t, user2.ID, apiNewTime.UserID)
assert.EqualValues(t, 947688818, apiNewTime.Created.Unix())
}
diff --git a/tests/integration/api_keys_test.go b/tests/integration/api_keys_test.go
index 2276b955cf..3162051acc 100644
--- a/tests/integration/api_keys_test.go
+++ b/tests/integration/api_keys_test.go
@@ -143,7 +143,7 @@ func TestCreateUserKey(t *testing.T) {
})
// Search by fingerprint
- req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/keys?fingerprint=%s", newPublicKey.Fingerprint)).
+ req = NewRequest(t, "GET", "/api/v1/user/keys?fingerprint="+newPublicKey.Fingerprint).
AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
@@ -183,7 +183,7 @@ func TestCreateUserKey(t *testing.T) {
token2 := getTokenForLoggedInUser(t, session2, auth_model.AccessTokenScopeWriteUser)
// Should find key even though not ours, but we shouldn't know whose it is
- req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/keys?fingerprint=%s", newPublicKey.Fingerprint)).
+ req = NewRequest(t, "GET", "/api/v1/user/keys?fingerprint="+newPublicKey.Fingerprint).
AddTokenAuth(token2)
resp = MakeRequest(t, req, http.StatusOK)
diff --git a/tests/integration/api_label_templates_test.go b/tests/integration/api_label_templates_test.go
index 007e979011..3e637daba6 100644
--- a/tests/integration/api_label_templates_test.go
+++ b/tests/integration/api_label_templates_test.go
@@ -4,7 +4,6 @@
package integration
import (
- "fmt"
"net/http"
"net/url"
"strings"
@@ -42,7 +41,7 @@ func TestAPIGetLabelTemplateInfo(t *testing.T) {
// Use the first template for the test
templateName := repo_module.LabelTemplateFiles[0].DisplayName
- urlStr := fmt.Sprintf("/api/v1/label/templates/%s", url.PathEscape(templateName))
+ urlStr := "/api/v1/label/templates/" + url.PathEscape(templateName)
req := NewRequest(t, "GET", urlStr)
resp := MakeRequest(t, req, http.StatusOK)
diff --git a/tests/integration/api_license_templates_test.go b/tests/integration/api_license_templates_test.go
index e12aab7c2c..52e240f9a7 100644
--- a/tests/integration/api_license_templates_test.go
+++ b/tests/integration/api_license_templates_test.go
@@ -4,7 +4,6 @@
package integration
import (
- "fmt"
"net/http"
"net/url"
"testing"
@@ -39,7 +38,7 @@ func TestAPIGetLicenseTemplateInfo(t *testing.T) {
// Use the first template for the test
licenseName := repo_module.Licenses[0]
- urlStr := fmt.Sprintf("/api/v1/licenses/%s", url.PathEscape(licenseName))
+ urlStr := "/api/v1/licenses/" + url.PathEscape(licenseName)
req := NewRequest(t, "GET", urlStr)
resp := MakeRequest(t, req, http.StatusOK)
diff --git a/tests/integration/api_nodeinfo_test.go b/tests/integration/api_nodeinfo_test.go
index 75f8dbb4ba..916c2f1723 100644
--- a/tests/integration/api_nodeinfo_test.go
+++ b/tests/integration/api_nodeinfo_test.go
@@ -5,35 +5,31 @@ package integration
import (
"net/http"
- "net/url"
"testing"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/routers"
+ "code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
)
func TestNodeinfo(t *testing.T) {
- setting.Federation.Enabled = true
- testWebRoutes = routers.NormalRoutes()
- defer func() {
- setting.Federation.Enabled = false
- testWebRoutes = routers.NormalRoutes()
- }()
+ defer tests.PrepareTestEnv(t)()
+ defer test.MockVariableValue(&setting.Federation.Enabled, true)()
+ defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())()
- onGiteaRun(t, func(*testing.T, *url.URL) {
- req := NewRequest(t, "GET", "/api/v1/nodeinfo")
- resp := MakeRequest(t, req, http.StatusOK)
- VerifyJSONSchema(t, resp, "nodeinfo_2.1.json")
+ req := NewRequest(t, "GET", "/api/v1/nodeinfo")
+ resp := MakeRequest(t, req, http.StatusOK)
+ VerifyJSONSchema(t, resp, "nodeinfo_2.1.json")
- var nodeinfo api.NodeInfo
- DecodeJSON(t, resp, &nodeinfo)
- assert.True(t, nodeinfo.OpenRegistrations)
- assert.Equal(t, "gitea", nodeinfo.Software.Name)
- assert.Equal(t, 29, nodeinfo.Usage.Users.Total)
- assert.Equal(t, 22, nodeinfo.Usage.LocalPosts)
- assert.Equal(t, 3, nodeinfo.Usage.LocalComments)
- })
+ var nodeinfo api.NodeInfo
+ DecodeJSON(t, resp, &nodeinfo)
+ assert.True(t, nodeinfo.OpenRegistrations)
+ assert.Equal(t, "gitea", nodeinfo.Software.Name)
+ assert.Equal(t, 29, nodeinfo.Usage.Users.Total)
+ assert.Equal(t, 22, nodeinfo.Usage.LocalPosts)
+ assert.Equal(t, 3, nodeinfo.Usage.LocalComments)
}
diff --git a/tests/integration/api_notification_test.go b/tests/integration/api_notification_test.go
index dc4ba83ecc..e6bc142476 100644
--- a/tests/integration/api_notification_test.go
+++ b/tests/integration/api_notification_test.go
@@ -35,7 +35,7 @@ func TestAPINotification(t *testing.T) {
// -- GET /notifications --
// test filter
since := "2000-01-01T00%3A50%3A01%2B00%3A00" // 946687801
- req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?since=%s", since)).
+ req := NewRequest(t, "GET", "/api/v1/notifications?since="+since).
AddTokenAuth(token)
resp := MakeRequest(t, req, http.StatusOK)
var apiNL []api.NotificationThread
@@ -104,10 +104,10 @@ func TestAPINotification(t *testing.T) {
assert.EqualValues(t, 5, apiN.ID)
assert.False(t, apiN.Pinned)
assert.True(t, apiN.Unread)
- assert.EqualValues(t, "issue4", apiN.Subject.Title)
+ assert.Equal(t, "issue4", apiN.Subject.Title)
assert.EqualValues(t, "Issue", apiN.Subject.Type)
- assert.EqualValues(t, thread5.Issue.APIURL(db.DefaultContext), apiN.Subject.URL)
- assert.EqualValues(t, thread5.Repository.HTMLURL(), apiN.Repository.HTMLURL)
+ assert.Equal(t, thread5.Issue.APIURL(db.DefaultContext), apiN.Subject.URL)
+ assert.Equal(t, thread5.Repository.HTMLURL(), apiN.Repository.HTMLURL)
MakeRequest(t, NewRequest(t, "GET", "/api/v1/notifications/new"), http.StatusUnauthorized)
diff --git a/tests/integration/api_oauth2_apps_test.go b/tests/integration/api_oauth2_apps_test.go
index 7a17b4ca88..13f64fd69e 100644
--- a/tests/integration/api_oauth2_apps_test.go
+++ b/tests/integration/api_oauth2_apps_test.go
@@ -43,12 +43,12 @@ func testAPICreateOAuth2Application(t *testing.T) {
var createdApp *api.OAuth2Application
DecodeJSON(t, resp, &createdApp)
- assert.EqualValues(t, appBody.Name, createdApp.Name)
+ assert.Equal(t, appBody.Name, createdApp.Name)
assert.Len(t, createdApp.ClientSecret, 56)
assert.Len(t, createdApp.ClientID, 36)
assert.True(t, createdApp.ConfidentialClient)
assert.NotEmpty(t, createdApp.Created)
- assert.EqualValues(t, appBody.RedirectURIs[0], createdApp.RedirectURIs[0])
+ assert.Equal(t, appBody.RedirectURIs[0], createdApp.RedirectURIs[0])
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{UID: user.ID, Name: createdApp.Name})
}
@@ -74,12 +74,12 @@ func testAPIListOAuth2Applications(t *testing.T) {
DecodeJSON(t, resp, &appList)
expectedApp := appList[0]
- assert.EqualValues(t, expectedApp.Name, existApp.Name)
- assert.EqualValues(t, expectedApp.ClientID, existApp.ClientID)
+ assert.Equal(t, expectedApp.Name, existApp.Name)
+ assert.Equal(t, expectedApp.ClientID, existApp.ClientID)
assert.Equal(t, expectedApp.ConfidentialClient, existApp.ConfidentialClient)
assert.Len(t, expectedApp.ClientID, 36)
assert.Empty(t, expectedApp.ClientSecret)
- assert.EqualValues(t, existApp.RedirectURIs[0], expectedApp.RedirectURIs[0])
+ assert.Equal(t, existApp.RedirectURIs[0], expectedApp.RedirectURIs[0])
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: expectedApp.ID, Name: expectedApp.Name})
}
@@ -128,13 +128,13 @@ func testAPIGetOAuth2Application(t *testing.T) {
DecodeJSON(t, resp, &app)
expectedApp := app
- assert.EqualValues(t, expectedApp.Name, existApp.Name)
- assert.EqualValues(t, expectedApp.ClientID, existApp.ClientID)
+ assert.Equal(t, expectedApp.Name, existApp.Name)
+ assert.Equal(t, expectedApp.ClientID, existApp.ClientID)
assert.Equal(t, expectedApp.ConfidentialClient, existApp.ConfidentialClient)
assert.Len(t, expectedApp.ClientID, 36)
assert.Empty(t, expectedApp.ClientSecret)
assert.Len(t, expectedApp.RedirectURIs, 1)
- assert.EqualValues(t, expectedApp.RedirectURIs[0], existApp.RedirectURIs[0])
+ assert.Equal(t, expectedApp.RedirectURIs[0], existApp.RedirectURIs[0])
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: expectedApp.ID, Name: expectedApp.Name})
}
@@ -168,8 +168,8 @@ func testAPIUpdateOAuth2Application(t *testing.T) {
expectedApp := app
assert.Len(t, expectedApp.RedirectURIs, 2)
- assert.EqualValues(t, expectedApp.RedirectURIs[0], appBody.RedirectURIs[0])
- assert.EqualValues(t, expectedApp.RedirectURIs[1], appBody.RedirectURIs[1])
+ assert.Equal(t, expectedApp.RedirectURIs[0], appBody.RedirectURIs[0])
+ assert.Equal(t, expectedApp.RedirectURIs[1], appBody.RedirectURIs[1])
assert.Equal(t, expectedApp.ConfidentialClient, appBody.ConfidentialClient)
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: expectedApp.ID, Name: expectedApp.Name})
}
diff --git a/tests/integration/api_org_test.go b/tests/integration/api_org_test.go
index fff121490c..6577bd1684 100644
--- a/tests/integration/api_org_test.go
+++ b/tests/integration/api_org_test.go
@@ -6,7 +6,6 @@ package integration
import (
"fmt"
"net/http"
- "net/url"
"strings"
"testing"
@@ -19,46 +18,53 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
-func TestAPIOrgCreate(t *testing.T) {
- onGiteaRun(t, func(*testing.T, *url.URL) {
- token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrganization)
-
- org := api.CreateOrgOption{
- UserName: "user1_org",
- FullName: "User1's organization",
- Description: "This organization created by user1",
- Website: "https://try.gitea.io",
- Location: "Shanghai",
- Visibility: "limited",
- }
- req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &org).
- AddTokenAuth(token)
- resp := MakeRequest(t, req, http.StatusCreated)
-
- var apiOrg api.Organization
- DecodeJSON(t, resp, &apiOrg)
-
- assert.Equal(t, org.UserName, apiOrg.Name)
- assert.Equal(t, org.FullName, apiOrg.FullName)
- assert.Equal(t, org.Description, apiOrg.Description)
- assert.Equal(t, org.Website, apiOrg.Website)
- assert.Equal(t, org.Location, apiOrg.Location)
- assert.Equal(t, org.Visibility, apiOrg.Visibility)
+func TestAPIOrgCreateRename(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+ token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrganization)
+
+ org := api.CreateOrgOption{
+ UserName: "user1_org",
+ FullName: "User1's organization",
+ Description: "This organization created by user1",
+ Website: "https://try.gitea.io",
+ Location: "Shanghai",
+ Visibility: "limited",
+ }
+ req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &org).AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusCreated)
+
+ var apiOrg api.Organization
+ DecodeJSON(t, resp, &apiOrg)
+
+ assert.Equal(t, org.UserName, apiOrg.Name)
+ assert.Equal(t, org.FullName, apiOrg.FullName)
+ assert.Equal(t, org.Description, apiOrg.Description)
+ assert.Equal(t, org.Website, apiOrg.Website)
+ assert.Equal(t, org.Location, apiOrg.Location)
+ assert.Equal(t, org.Visibility, apiOrg.Visibility)
+
+ unittest.AssertExistsAndLoadBean(t, &user_model.User{
+ Name: org.UserName,
+ LowerName: strings.ToLower(org.UserName),
+ FullName: org.FullName,
+ })
- unittest.AssertExistsAndLoadBean(t, &user_model.User{
- Name: org.UserName,
- LowerName: strings.ToLower(org.UserName),
- FullName: org.FullName,
- })
+ // check org name
+ req = NewRequestf(t, "GET", "/api/v1/orgs/%s", org.UserName).AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
+ DecodeJSON(t, resp, &apiOrg)
+ assert.Equal(t, org.UserName, apiOrg.Name)
+ t.Run("CheckPermission", func(t *testing.T) {
// Check owner team permission
ownerTeam, _ := org_model.GetOwnerTeam(db.DefaultContext, apiOrg.ID)
-
for _, ut := range unit_model.AllRepoUnitTypes {
up := perm.AccessModeOwner
if ut == unit_model.TypeExternalTracker || ut == unit_model.TypeExternalWiki {
@@ -71,40 +77,67 @@ func TestAPIOrgCreate(t *testing.T) {
AccessMode: up,
})
}
+ })
- req = NewRequestf(t, "GET", "/api/v1/orgs/%s", org.UserName).
- AddTokenAuth(token)
+ t.Run("CheckMembers", func(t *testing.T) {
+ req = NewRequestf(t, "GET", "/api/v1/orgs/%s/members", org.UserName).AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
- DecodeJSON(t, resp, &apiOrg)
- assert.EqualValues(t, org.UserName, apiOrg.Name)
- req = NewRequestf(t, "GET", "/api/v1/orgs/%s/repos", org.UserName).
- AddTokenAuth(token)
- resp = MakeRequest(t, req, http.StatusOK)
+ // user1 on this org is public
+ var users []*api.User
+ DecodeJSON(t, resp, &users)
+ assert.Len(t, users, 1)
+ assert.Equal(t, "user1", users[0].UserName)
+ })
+ t.Run("RenameOrg", func(t *testing.T) {
+ req = NewRequestWithJSON(t, "POST", "/api/v1/orgs/user1_org/rename", &api.RenameOrgOption{
+ NewName: "renamed_org",
+ }).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNoContent)
+ unittest.AssertExistsAndLoadBean(t, &org_model.Organization{Name: "renamed_org"})
+ org.UserName = "renamed_org" // update the variable so the following tests could still use it
+ })
+
+ t.Run("ListRepos", func(t *testing.T) {
+ // FIXME: this test is wrong, there is no repository at all, so the for-loop is empty
+ req = NewRequestf(t, "GET", "/api/v1/orgs/%s/repos", org.UserName).AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
var repos []*api.Repository
DecodeJSON(t, resp, &repos)
for _, repo := range repos {
assert.False(t, repo.Private)
}
+ })
+}
+
+func TestAPIOrgGeneral(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+ user1Session := loginUser(t, "user1")
+ user1Token := getTokenForLoggedInUser(t, user1Session, auth_model.AccessTokenScopeWriteOrganization)
- req = NewRequestf(t, "GET", "/api/v1/orgs/%s/members", org.UserName).
- AddTokenAuth(token)
+ t.Run("OrgGetAll", func(t *testing.T) {
+ // accessing with a token will return all orgs
+ req := NewRequest(t, "GET", "/api/v1/orgs").AddTokenAuth(user1Token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ var apiOrgList []*api.Organization
+
+ DecodeJSON(t, resp, &apiOrgList)
+ assert.Len(t, apiOrgList, 13)
+ assert.Equal(t, "Limited Org 36", apiOrgList[1].FullName)
+ assert.Equal(t, "limited", apiOrgList[1].Visibility)
+
+ // accessing without a token will return only public orgs
+ req = NewRequest(t, "GET", "/api/v1/orgs")
resp = MakeRequest(t, req, http.StatusOK)
- // user1 on this org is public
- var users []*api.User
- DecodeJSON(t, resp, &users)
- assert.Len(t, users, 1)
- assert.EqualValues(t, "user1", users[0].UserName)
+ DecodeJSON(t, resp, &apiOrgList)
+ assert.Len(t, apiOrgList, 9)
+ assert.Equal(t, "org 17", apiOrgList[0].FullName)
+ assert.Equal(t, "public", apiOrgList[0].Visibility)
})
-}
-func TestAPIOrgEdit(t *testing.T) {
- onGiteaRun(t, func(*testing.T, *url.URL) {
- session := loginUser(t, "user1")
-
- token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization)
+ t.Run("OrgEdit", func(t *testing.T) {
org := api.EditOrgOption{
FullName: "Org3 organization new full name",
Description: "A new description",
@@ -112,8 +145,7 @@ func TestAPIOrgEdit(t *testing.T) {
Location: "Beijing",
Visibility: "private",
}
- req := NewRequestWithJSON(t, "PATCH", "/api/v1/orgs/org3", &org).
- AddTokenAuth(token)
+ req := NewRequestWithJSON(t, "PATCH", "/api/v1/orgs/org3", &org).AddTokenAuth(user1Token)
resp := MakeRequest(t, req, http.StatusOK)
var apiOrg api.Organization
@@ -126,13 +158,8 @@ func TestAPIOrgEdit(t *testing.T) {
assert.Equal(t, org.Location, apiOrg.Location)
assert.Equal(t, org.Visibility, apiOrg.Visibility)
})
-}
-func TestAPIOrgEditBadVisibility(t *testing.T) {
- onGiteaRun(t, func(*testing.T, *url.URL) {
- session := loginUser(t, "user1")
-
- token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization)
+ t.Run("OrgEditBadVisibility", func(t *testing.T) {
org := api.EditOrgOption{
FullName: "Org3 organization new full name",
Description: "A new description",
@@ -140,18 +167,12 @@ func TestAPIOrgEditBadVisibility(t *testing.T) {
Location: "Beijing",
Visibility: "badvisibility",
}
- req := NewRequestWithJSON(t, "PATCH", "/api/v1/orgs/org3", &org).
- AddTokenAuth(token)
+ req := NewRequestWithJSON(t, "PATCH", "/api/v1/orgs/org3", &org).AddTokenAuth(user1Token)
MakeRequest(t, req, http.StatusUnprocessableEntity)
})
-}
-func TestAPIOrgDeny(t *testing.T) {
- onGiteaRun(t, func(*testing.T, *url.URL) {
- setting.Service.RequireSignInView = true
- defer func() {
- setting.Service.RequireSignInView = false
- }()
+ t.Run("OrgDeny", func(t *testing.T) {
+ defer test.MockVariableValue(&setting.Service.RequireSignInViewStrict, true)()
orgName := "user1_org"
req := NewRequestf(t, "GET", "/api/v1/orgs/%s", orgName)
@@ -163,43 +184,13 @@ func TestAPIOrgDeny(t *testing.T) {
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/members", orgName)
MakeRequest(t, req, http.StatusNotFound)
})
-}
-
-func TestAPIGetAll(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
- token := getUserToken(t, "user1", auth_model.AccessTokenScopeReadOrganization)
-
- // accessing with a token will return all orgs
- req := NewRequest(t, "GET", "/api/v1/orgs").
- AddTokenAuth(token)
- resp := MakeRequest(t, req, http.StatusOK)
- var apiOrgList []*api.Organization
-
- DecodeJSON(t, resp, &apiOrgList)
- assert.Len(t, apiOrgList, 13)
- assert.Equal(t, "Limited Org 36", apiOrgList[1].FullName)
- assert.Equal(t, "limited", apiOrgList[1].Visibility)
-
- // accessing without a token will return only public orgs
- req = NewRequest(t, "GET", "/api/v1/orgs")
- resp = MakeRequest(t, req, http.StatusOK)
-
- DecodeJSON(t, resp, &apiOrgList)
- assert.Len(t, apiOrgList, 9)
- assert.Equal(t, "org 17", apiOrgList[0].FullName)
- assert.Equal(t, "public", apiOrgList[0].Visibility)
-}
-
-func TestAPIOrgSearchEmptyTeam(t *testing.T) {
- onGiteaRun(t, func(*testing.T, *url.URL) {
- token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrganization)
+ t.Run("OrgSearchEmptyTeam", func(t *testing.T) {
orgName := "org_with_empty_team"
-
// create org
req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &api.CreateOrgOption{
UserName: orgName,
- }).AddTokenAuth(token)
+ }).AddTokenAuth(user1Token)
MakeRequest(t, req, http.StatusCreated)
// create team with no member
@@ -208,12 +199,12 @@ func TestAPIOrgSearchEmptyTeam(t *testing.T) {
IncludesAllRepositories: true,
Permission: "read",
Units: []string{"repo.code", "repo.issues", "repo.ext_issues", "repo.wiki", "repo.pulls"},
- }).AddTokenAuth(token)
+ }).AddTokenAuth(user1Token)
MakeRequest(t, req, http.StatusCreated)
// case-insensitive search for teams that have no members
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/orgs/%s/teams/search?q=%s", orgName, "empty")).
- AddTokenAuth(token)
+ AddTokenAuth(user1Token)
resp := MakeRequest(t, req, http.StatusOK)
data := struct {
Ok bool
@@ -222,7 +213,40 @@ func TestAPIOrgSearchEmptyTeam(t *testing.T) {
DecodeJSON(t, resp, &data)
assert.True(t, data.Ok)
if assert.Len(t, data.Data, 1) {
- assert.EqualValues(t, "Empty", data.Data[0].Name)
+ assert.Equal(t, "Empty", data.Data[0].Name)
}
})
+
+ t.Run("User2ChangeStatus", func(t *testing.T) {
+ user2Session := loginUser(t, "user2")
+ user2Token := getTokenForLoggedInUser(t, user2Session, auth_model.AccessTokenScopeWriteOrganization)
+
+ req := NewRequest(t, "PUT", "/api/v1/orgs/org3/public_members/user2").AddTokenAuth(user2Token)
+ MakeRequest(t, req, http.StatusNoContent)
+ req = NewRequest(t, "DELETE", "/api/v1/orgs/org3/public_members/user2").AddTokenAuth(user2Token)
+ MakeRequest(t, req, http.StatusNoContent)
+
+ // non admin but org owner could also change other member's status
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user2"})
+ require.False(t, user2.IsAdmin)
+ req = NewRequest(t, "PUT", "/api/v1/orgs/org3/public_members/user1").AddTokenAuth(user2Token)
+ MakeRequest(t, req, http.StatusNoContent)
+ req = NewRequest(t, "DELETE", "/api/v1/orgs/org3/public_members/user1").AddTokenAuth(user2Token)
+ MakeRequest(t, req, http.StatusNoContent)
+ })
+
+ t.Run("User4ChangeStatus", func(t *testing.T) {
+ user4Session := loginUser(t, "user4")
+ user4Token := getTokenForLoggedInUser(t, user4Session, auth_model.AccessTokenScopeWriteOrganization)
+
+ // user4 is a normal team member, they could change their own status
+ req := NewRequest(t, "PUT", "/api/v1/orgs/org3/public_members/user4").AddTokenAuth(user4Token)
+ MakeRequest(t, req, http.StatusNoContent)
+ req = NewRequest(t, "DELETE", "/api/v1/orgs/org3/public_members/user4").AddTokenAuth(user4Token)
+ MakeRequest(t, req, http.StatusNoContent)
+ req = NewRequest(t, "PUT", "/api/v1/orgs/org3/public_members/user1").AddTokenAuth(user4Token)
+ MakeRequest(t, req, http.StatusForbidden)
+ req = NewRequest(t, "DELETE", "/api/v1/orgs/org3/public_members/user1").AddTokenAuth(user4Token)
+ MakeRequest(t, req, http.StatusForbidden)
+ })
}
diff --git a/tests/integration/api_packages_arch_test.go b/tests/integration/api_packages_arch_test.go
index 9c7a9dd19d..e5778b4203 100644
--- a/tests/integration/api_packages_arch_test.go
+++ b/tests/integration/api_packages_arch_test.go
@@ -79,6 +79,34 @@ license = MIT`)
return buf.Bytes()
}
+ readIndexContent := func(r io.Reader) (map[string]string, error) {
+ gzr, err := gzip.NewReader(r)
+ if err != nil {
+ return nil, err
+ }
+
+ content := make(map[string]string)
+
+ tr := tar.NewReader(gzr)
+ for {
+ hd, err := tr.Next()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ buf, err := io.ReadAll(tr)
+ if err != nil {
+ return nil, err
+ }
+
+ content[hd.Name] = string(buf)
+ }
+
+ return content, nil
+ }
compressions := []string{"gz", "xz", "zst"}
repositories := []string{"main", "testing", "with/slash", ""}
@@ -135,7 +163,7 @@ license = MIT`)
assert.Condition(t, func() bool {
seen := false
expectedFilename := fmt.Sprintf("%s-%s-aarch64.pkg.tar.%s", packageName, packageVersion, compression)
- expectedCompositeKey := fmt.Sprintf("%s|aarch64", repository)
+ expectedCompositeKey := repository + "|aarch64"
for _, pf := range pfs {
if pf.Name == expectedFilename && pf.CompositeKey == expectedCompositeKey {
if seen {
@@ -171,35 +199,6 @@ license = MIT`)
MakeRequest(t, req, http.StatusConflict)
})
- readIndexContent := func(r io.Reader) (map[string]string, error) {
- gzr, err := gzip.NewReader(r)
- if err != nil {
- return nil, err
- }
-
- content := make(map[string]string)
-
- tr := tar.NewReader(gzr)
- for {
- hd, err := tr.Next()
- if err == io.EOF {
- break
- }
- if err != nil {
- return nil, err
- }
-
- buf, err := io.ReadAll(tr)
- if err != nil {
- return nil, err
- }
-
- content[hd.Name] = string(buf)
- }
-
- return content, nil
- }
-
t.Run("Index", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
@@ -299,4 +298,39 @@ license = MIT`)
})
}
}
+ t.Run("KeepLastVersion", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+ pkgVer1 := createPackage("gz", "gitea-test", "1.0.0", "aarch64")
+ pkgVer2 := createPackage("gz", "gitea-test", "1.0.1", "aarch64")
+ req := NewRequestWithBody(t, "PUT", rootURL, bytes.NewReader(pkgVer1)).
+ AddBasicAuth(user.Name)
+ MakeRequest(t, req, http.StatusCreated)
+ req = NewRequestWithBody(t, "PUT", rootURL, bytes.NewReader(pkgVer2)).
+ AddBasicAuth(user.Name)
+ MakeRequest(t, req, http.StatusCreated)
+
+ req = NewRequest(t, "GET", fmt.Sprintf("%s/aarch64/%s", rootURL, arch_service.IndexArchiveFilename))
+ resp := MakeRequest(t, req, http.StatusOK)
+
+ content, err := readIndexContent(resp.Body)
+ assert.NoError(t, err)
+ assert.Len(t, content, 2)
+
+ _, has := content["gitea-test-1.0.0/desc"]
+ assert.False(t, has)
+ _, has = content["gitea-test-1.0.1/desc"]
+ assert.True(t, has)
+
+ req = NewRequest(t, "DELETE", rootURL+"/gitea-test/1.0.1/aarch64").
+ AddBasicAuth(user.Name)
+ MakeRequest(t, req, http.StatusNoContent)
+
+ req = NewRequest(t, "GET", fmt.Sprintf("%s/aarch64/%s", rootURL, arch_service.IndexArchiveFilename))
+ resp = MakeRequest(t, req, http.StatusOK)
+ content, err = readIndexContent(resp.Body)
+ assert.NoError(t, err)
+ assert.Len(t, content, 2)
+ _, has = content["gitea-test-1.0.0/desc"]
+ assert.True(t, has)
+ })
}
diff --git a/tests/integration/api_packages_cargo_test.go b/tests/integration/api_packages_cargo_test.go
index 3fb9687653..8b5caa7ea7 100644
--- a/tests/integration/api_packages_cargo_test.go
+++ b/tests/integration/api_packages_cargo_test.go
@@ -94,7 +94,7 @@ func testPackageCargo(t *testing.T, _ *neturl.URL) {
}
root := fmt.Sprintf("%sapi/packages/%s/cargo", setting.AppURL, user.Name)
- url := fmt.Sprintf("%s/api/v1/crates", root)
+ url := root + "/api/v1/crates"
t.Run("Index", func(t *testing.T) {
t.Run("Git/Config", func(t *testing.T) {
diff --git a/tests/integration/api_packages_chef_test.go b/tests/integration/api_packages_chef_test.go
index 6efb2708af..8f2c2592e7 100644
--- a/tests/integration/api_packages_chef_test.go
+++ b/tests/integration/api_packages_chef_test.go
@@ -181,7 +181,7 @@ nwIDAQAB
var data []byte
if version == "1.3" {
- data = []byte(fmt.Sprintf(
+ data = fmt.Appendf(nil,
"Method:%s\nPath:%s\nX-Ops-Content-Hash:%s\nX-Ops-Sign:version=%s\nX-Ops-Timestamp:%s\nX-Ops-UserId:%s\nX-Ops-Server-API-Version:%s",
req.Method,
path.Clean(req.URL.Path),
@@ -190,17 +190,17 @@ nwIDAQAB
req.Header.Get("X-Ops-Timestamp"),
username,
req.Header.Get("X-Ops-Server-Api-Version"),
- ))
+ )
} else {
sum := sha1.Sum([]byte(path.Clean(req.URL.Path)))
- data = []byte(fmt.Sprintf(
+ data = fmt.Appendf(nil,
"Method:%s\nHashed Path:%s\nX-Ops-Content-Hash:%s\nX-Ops-Timestamp:%s\nX-Ops-UserId:%s",
req.Method,
base64.StdEncoding.EncodeToString(sum[:]),
req.Header.Get("X-Ops-Content-Hash"),
req.Header.Get("X-Ops-Timestamp"),
username,
- ))
+ )
}
for k := range req.Header {
@@ -274,7 +274,7 @@ nwIDAQAB
uploadPackage := func(t *testing.T, version string, expectedStatus int) {
var body bytes.Buffer
mpw := multipart.NewWriter(&body)
- part, _ := mpw.CreateFormFile("tarball", fmt.Sprintf("%s.tar.gz", version))
+ part, _ := mpw.CreateFormFile("tarball", version+".tar.gz")
zw := gzip.NewWriter(part)
tw := tar.NewWriter(zw)
@@ -320,7 +320,7 @@ nwIDAQAB
pfs, err := packages.GetFilesByVersionID(db.DefaultContext, pvs[0].ID)
assert.NoError(t, err)
assert.Len(t, pfs, 1)
- assert.Equal(t, fmt.Sprintf("%s.tar.gz", packageVersion), pfs[0].Name)
+ assert.Equal(t, packageVersion+".tar.gz", pfs[0].Name)
assert.True(t, pfs[0].IsLead)
uploadPackage(t, packageVersion, http.StatusConflict)
diff --git a/tests/integration/api_packages_composer_test.go b/tests/integration/api_packages_composer_test.go
index 51b047ab41..54f61d91d9 100644
--- a/tests/integration/api_packages_composer_test.go
+++ b/tests/integration/api_packages_composer_test.go
@@ -13,6 +13,7 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/packages"
+ repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
composer_module "code.gitea.io/gitea/modules/packages/composer"
@@ -63,7 +64,7 @@ func TestPackageComposer(t *testing.T) {
t.Run("ServiceIndex", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("%s/packages.json", url)).
+ req := NewRequest(t, "GET", url+"/packages.json").
AddBasicAuth(user.Name)
resp := MakeRequest(t, req, http.StatusOK)
@@ -217,5 +218,39 @@ func TestPackageComposer(t *testing.T) {
assert.Equal(t, "4f5fa464c3cb808a1df191dbf6cb75363f8b7072", pkgs[0].Dist.Checksum)
assert.Len(t, pkgs[0].Bin, 1)
assert.Equal(t, packageBin, pkgs[0].Bin[0])
+
+ // Test package linked to repository
+ repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
+ userPkgs, err := packages.GetPackagesByType(db.DefaultContext, user.ID, packages.TypeComposer)
+ assert.NoError(t, err)
+ assert.Len(t, userPkgs, 1)
+ assert.EqualValues(t, 0, userPkgs[0].RepoID)
+
+ err = packages.SetRepositoryLink(db.DefaultContext, userPkgs[0].ID, repo1.ID)
+ assert.NoError(t, err)
+
+ req = NewRequest(t, "GET", fmt.Sprintf("%s/p2/%s/%s.json", url, vendorName, projectName)).
+ AddBasicAuth(user.Name)
+ resp = MakeRequest(t, req, http.StatusOK)
+
+ result = composer.PackageMetadataResponse{}
+ DecodeJSON(t, resp, &result)
+
+ assert.Contains(t, result.Packages, packageName)
+ pkgs = result.Packages[packageName]
+ assert.Len(t, pkgs, 1)
+ assert.Equal(t, packageName, pkgs[0].Name)
+ assert.Equal(t, packageVersion, pkgs[0].Version)
+ assert.Equal(t, packageType, pkgs[0].Type)
+ assert.Equal(t, packageDescription, pkgs[0].Description)
+ assert.Len(t, pkgs[0].Authors, 1)
+ assert.Equal(t, packageAuthor, pkgs[0].Authors[0].Name)
+ assert.Equal(t, "zip", pkgs[0].Dist.Type)
+ assert.Equal(t, "4f5fa464c3cb808a1df191dbf6cb75363f8b7072", pkgs[0].Dist.Checksum)
+ assert.Len(t, pkgs[0].Bin, 1)
+ assert.Equal(t, packageBin, pkgs[0].Bin[0])
+ assert.Equal(t, repo1.HTMLURL(), pkgs[0].Source.URL)
+ assert.Equal(t, "git", pkgs[0].Source.Type)
+ assert.Equal(t, packageVersion, pkgs[0].Source.Reference)
})
}
diff --git a/tests/integration/api_packages_conan_test.go b/tests/integration/api_packages_conan_test.go
index 3055e57a2e..4e83c998b8 100644
--- a/tests/integration/api_packages_conan_test.go
+++ b/tests/integration/api_packages_conan_test.go
@@ -91,18 +91,18 @@ func uploadConanPackageV1(t *testing.T, baseURL, token, name, version, user, cha
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNotFound)
- req = NewRequest(t, "GET", fmt.Sprintf("%s/digest", recipeURL)).
+ req = NewRequest(t, "GET", recipeURL+"/digest").
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNotFound)
- req = NewRequest(t, "GET", fmt.Sprintf("%s/download_urls", recipeURL)).
+ req = NewRequest(t, "GET", recipeURL+"/download_urls").
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNotFound)
- req = NewRequest(t, "POST", fmt.Sprintf("%s/upload_urls", recipeURL))
+ req = NewRequest(t, "POST", recipeURL+"/upload_urls")
MakeRequest(t, req, http.StatusUnauthorized)
- req = NewRequestWithJSON(t, "POST", fmt.Sprintf("%s/upload_urls", recipeURL), map[string]int64{
+ req = NewRequestWithJSON(t, "POST", recipeURL+"/upload_urls", map[string]int64{
conanfileName: int64(len(contentConanfile)),
"removed.txt": 0,
}).AddTokenAuth(token)
@@ -127,18 +127,18 @@ func uploadConanPackageV1(t *testing.T, baseURL, token, name, version, user, cha
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNotFound)
- req = NewRequest(t, "GET", fmt.Sprintf("%s/digest", packageURL)).
+ req = NewRequest(t, "GET", packageURL+"/digest").
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNotFound)
- req = NewRequest(t, "GET", fmt.Sprintf("%s/download_urls", packageURL)).
+ req = NewRequest(t, "GET", packageURL+"/download_urls").
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNotFound)
- req = NewRequest(t, "POST", fmt.Sprintf("%s/upload_urls", packageURL))
+ req = NewRequest(t, "POST", packageURL+"/upload_urls")
MakeRequest(t, req, http.StatusUnauthorized)
- req = NewRequestWithJSON(t, "POST", fmt.Sprintf("%s/upload_urls", packageURL), map[string]int64{
+ req = NewRequestWithJSON(t, "POST", packageURL+"/upload_urls", map[string]int64{
conaninfoName: int64(len(contentConaninfo)),
"removed.txt": 0,
}).AddTokenAuth(token)
@@ -167,7 +167,7 @@ func uploadConanPackageV2(t *testing.T, baseURL, token, name, version, user, cha
AddTokenAuth(token)
MakeRequest(t, req, http.StatusCreated)
- req = NewRequest(t, "GET", fmt.Sprintf("%s/files", recipeURL)).
+ req = NewRequest(t, "GET", recipeURL+"/files").
AddTokenAuth(token)
resp := MakeRequest(t, req, http.StatusOK)
@@ -180,7 +180,7 @@ func uploadConanPackageV2(t *testing.T, baseURL, token, name, version, user, cha
packageURL := fmt.Sprintf("%s/packages/%s/revisions/%s", recipeURL, conanPackageReference, packageRevision)
- req = NewRequest(t, "GET", fmt.Sprintf("%s/files", packageURL)).
+ req = NewRequest(t, "GET", packageURL+"/files").
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNotFound)
@@ -188,7 +188,7 @@ func uploadConanPackageV2(t *testing.T, baseURL, token, name, version, user, cha
AddTokenAuth(token)
MakeRequest(t, req, http.StatusCreated)
- req = NewRequest(t, "GET", fmt.Sprintf("%s/files", packageURL)).
+ req = NewRequest(t, "GET", packageURL+"/files").
AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
@@ -219,7 +219,7 @@ func TestPackageConan(t *testing.T) {
t.Run("Ping", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("%s/v1/ping", url))
+ req := NewRequest(t, "GET", url+"/v1/ping")
resp := MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "revisions", resp.Header().Get("X-Conan-Server-Capabilities"))
@@ -230,7 +230,7 @@ func TestPackageConan(t *testing.T) {
t.Run("UserName/Password Authenticate", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("%s/v1/users/authenticate", url)).
+ req := NewRequest(t, "GET", url+"/v1/users/authenticate").
AddBasicAuth(user.Name)
resp := MakeRequest(t, req, http.StatusOK)
@@ -256,7 +256,7 @@ func TestPackageConan(t *testing.T) {
token := getTokenForLoggedInUser(t, session, scope)
- req := NewRequest(t, "GET", fmt.Sprintf("%s/v1/users/authenticate", url)).
+ req := NewRequest(t, "GET", url+"/v1/users/authenticate").
AddTokenAuth(token)
resp := MakeRequest(t, req, expectedAuthStatusCode)
if expectedAuthStatusCode != http.StatusOK {
@@ -273,7 +273,7 @@ func TestPackageConan(t *testing.T) {
recipeURL := fmt.Sprintf("%s/v1/conans/%s/%s/%s/%s", url, "TestScope", version1, "testing", channel1)
- req = NewRequestWithJSON(t, "POST", fmt.Sprintf("%s/upload_urls", recipeURL), map[string]int64{
+ req = NewRequestWithJSON(t, "POST", recipeURL+"/upload_urls", map[string]int64{
conanfileName: 64,
"removed.txt": 0,
}).AddTokenAuth(token)
@@ -308,7 +308,7 @@ func TestPackageConan(t *testing.T) {
t.Run("CheckCredentials", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("%s/v1/users/check_credentials", url)).
+ req := NewRequest(t, "GET", url+"/v1/users/check_credentials").
AddTokenAuth(token)
MakeRequest(t, req, http.StatusOK)
})
@@ -356,7 +356,7 @@ func TestPackageConan(t *testing.T) {
assert.Equal(t, int64(len(contentConaninfo)), pb.Size)
} else {
- assert.FailNow(t, "unknown file: %s", pf.Name)
+ assert.FailNow(t, "unknown file", "unknown file: %s", pf.Name)
}
}
})
@@ -376,14 +376,14 @@ func TestPackageConan(t *testing.T) {
assert.Contains(t, fileHashes, conanfileName)
assert.Equal(t, "7abc52241c22090782c54731371847a8", fileHashes[conanfileName])
- req = NewRequest(t, "GET", fmt.Sprintf("%s/digest", recipeURL))
+ req = NewRequest(t, "GET", recipeURL+"/digest")
resp = MakeRequest(t, req, http.StatusOK)
downloadURLs := make(map[string]string)
DecodeJSON(t, resp, &downloadURLs)
assert.Contains(t, downloadURLs, conanfileName)
- req = NewRequest(t, "GET", fmt.Sprintf("%s/download_urls", recipeURL))
+ req = NewRequest(t, "GET", recipeURL+"/download_urls")
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &downloadURLs)
@@ -404,14 +404,14 @@ func TestPackageConan(t *testing.T) {
assert.Contains(t, fileHashes, conaninfoName)
assert.Equal(t, "7628bfcc5b17f1470c468621a78df394", fileHashes[conaninfoName])
- req = NewRequest(t, "GET", fmt.Sprintf("%s/digest", packageURL))
+ req = NewRequest(t, "GET", packageURL+"/digest")
resp = MakeRequest(t, req, http.StatusOK)
downloadURLs = make(map[string]string)
DecodeJSON(t, resp, &downloadURLs)
assert.Contains(t, downloadURLs, conaninfoName)
- req = NewRequest(t, "GET", fmt.Sprintf("%s/download_urls", packageURL))
+ req = NewRequest(t, "GET", packageURL+"/download_urls")
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &downloadURLs)
@@ -550,7 +550,7 @@ func TestPackageConan(t *testing.T) {
t.Run("Ping", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("%s/v2/ping", url))
+ req := NewRequest(t, "GET", url+"/v2/ping")
resp := MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "revisions", resp.Header().Get("X-Conan-Server-Capabilities"))
@@ -561,7 +561,7 @@ func TestPackageConan(t *testing.T) {
t.Run("UserName/Password Authenticate", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("%s/v2/users/authenticate", url)).
+ req := NewRequest(t, "GET", url+"/v2/users/authenticate").
AddBasicAuth(user.Name)
resp := MakeRequest(t, req, http.StatusOK)
@@ -573,7 +573,7 @@ func TestPackageConan(t *testing.T) {
assert.Equal(t, user.ID, pkgMeta.UserID)
assert.Equal(t, auth_model.AccessTokenScopeAll, pkgMeta.Scope)
- token = fmt.Sprintf("Bearer %s", body)
+ token = "Bearer " + body
})
badToken := ""
@@ -590,7 +590,7 @@ func TestPackageConan(t *testing.T) {
token := getTokenForLoggedInUser(t, session, scope)
- req := NewRequest(t, "GET", fmt.Sprintf("%s/v2/users/authenticate", url)).
+ req := NewRequest(t, "GET", url+"/v2/users/authenticate").
AddTokenAuth(token)
resp := MakeRequest(t, req, expectedAuthStatusCode)
if expectedAuthStatusCode != http.StatusOK {
@@ -640,7 +640,7 @@ func TestPackageConan(t *testing.T) {
t.Run("CheckCredentials", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("%s/v2/users/check_credentials", url)).
+ req := NewRequest(t, "GET", url+"/v2/users/check_credentials").
AddTokenAuth(token)
MakeRequest(t, req, http.StatusOK)
})
@@ -664,7 +664,7 @@ func TestPackageConan(t *testing.T) {
recipeURL := fmt.Sprintf("%s/v2/conans/%s/%s/%s/%s", url, name, version1, user1, channel1)
- req := NewRequest(t, "GET", fmt.Sprintf("%s/latest", recipeURL))
+ req := NewRequest(t, "GET", recipeURL+"/latest")
resp := MakeRequest(t, req, http.StatusOK)
obj := make(map[string]string)
diff --git a/tests/integration/api_packages_conda_test.go b/tests/integration/api_packages_conda_test.go
index 272a660d45..32f55e5435 100644
--- a/tests/integration/api_packages_conda_test.go
+++ b/tests/integration/api_packages_conda_test.go
@@ -193,19 +193,19 @@ func TestPackageConda(t *testing.T) {
Removed map[string]*PackageInfo `json:"removed"`
}
- req := NewRequest(t, "GET", fmt.Sprintf("%s/noarch/repodata.json", root))
+ req := NewRequest(t, "GET", root+"/noarch/repodata.json")
resp := MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "application/json", resp.Header().Get("Content-Type"))
- req = NewRequest(t, "GET", fmt.Sprintf("%s/noarch/repodata.json.bz2", root))
+ req = NewRequest(t, "GET", root+"/noarch/repodata.json.bz2")
resp = MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "application/x-bzip2", resp.Header().Get("Content-Type"))
- req = NewRequest(t, "GET", fmt.Sprintf("%s/noarch/current_repodata.json", root))
+ req = NewRequest(t, "GET", root+"/noarch/current_repodata.json")
resp = MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "application/json", resp.Header().Get("Content-Type"))
- req = NewRequest(t, "GET", fmt.Sprintf("%s/noarch/current_repodata.json.bz2", root))
+ req = NewRequest(t, "GET", root+"/noarch/current_repodata.json.bz2")
resp = MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "application/x-bzip2", resp.Header().Get("Content-Type"))
@@ -218,7 +218,7 @@ func TestPackageConda(t *testing.T) {
pd, err := packages.GetPackageDescriptor(db.DefaultContext, pv)
assert.NoError(t, err)
- req := NewRequest(t, "GET", fmt.Sprintf("%s/noarch/repodata.json", root))
+ req := NewRequest(t, "GET", root+"/noarch/repodata.json")
resp := MakeRequest(t, req, http.StatusOK)
var result RepoData
diff --git a/tests/integration/api_packages_container_test.go b/tests/integration/api_packages_container_test.go
index 3905ad1b70..204f099bbe 100644
--- a/tests/integration/api_packages_container_test.go
+++ b/tests/integration/api_packages_container_test.go
@@ -7,8 +7,10 @@ import (
"bytes"
"crypto/sha256"
"encoding/base64"
+ "encoding/hex"
"fmt"
"net/http"
+ "strconv"
"strings"
"sync"
"testing"
@@ -16,7 +18,6 @@ import (
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
packages_model "code.gitea.io/gitea/models/packages"
- container_model "code.gitea.io/gitea/models/packages/container"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
container_module "code.gitea.io/gitea/modules/packages/container"
@@ -56,7 +57,7 @@ func TestPackageContainer(t *testing.T) {
return values
}
- images := []string{"test", "te/st"}
+ images := []string{"test", "sub/name"}
tags := []string{"latest", "main"}
multiTag := "multi"
@@ -69,7 +70,8 @@ func TestPackageContainer(t *testing.T) {
configContent := `{"architecture":"amd64","config":{"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/true"],"ArgsEscaped":true,"Image":"sha256:9bd8b88dc68b80cffe126cc820e4b52c6e558eb3b37680bfee8e5f3ed7b8c257"},"container":"b89fe92a887d55c0961f02bdfbfd8ac3ddf66167db374770d2d9e9fab3311510","container_config":{"Hostname":"b89fe92a887d","Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh","-c","#(nop) ","CMD [\"/true\"]"],"ArgsEscaped":true,"Image":"sha256:9bd8b88dc68b80cffe126cc820e4b52c6e558eb3b37680bfee8e5f3ed7b8c257"},"created":"2022-01-01T00:00:00.000000000Z","docker_version":"20.10.12","history":[{"created":"2022-01-01T00:00:00.000000000Z","created_by":"/bin/sh -c #(nop) COPY file:0e7589b0c800daaf6fa460d2677101e4676dd9491980210cb345480e513f3602 in /true "},{"created":"2022-01-01T00:00:00.000000001Z","created_by":"/bin/sh -c #(nop) CMD [\"/true\"]","empty_layer":true}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:0ff3b91bdf21ecdf2f2f3d4372c2098a14dbe06cd678e8f0a85fd4902d00e2e2"]}}`
manifestDigest := "sha256:4f10484d1c1bb13e3956b4de1cd42db8e0f14a75be1617b60f2de3cd59c803c6"
- manifestContent := `{"schemaVersion":2,"mediaType":"application/vnd.docker.distribution.manifest.v2+json","config":{"mediaType":"application/vnd.docker.container.image.v1+json","digest":"sha256:4607e093bec406eaadb6f3a340f63400c9d3a7038680744c406903766b938f0d","size":1069},"layers":[{"mediaType":"application/vnd.docker.image.rootfs.diff.tar.gzip","digest":"sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4","size":32}]}`
+ manifestContent := `{"schemaVersion":2,"mediaType":"` + container_module.ContentTypeDockerDistributionManifestV2 + `","config":{"mediaType":"application/vnd.docker.container.image.v1+json","digest":"sha256:4607e093bec406eaadb6f3a340f63400c9d3a7038680744c406903766b938f0d","size":1069},"layers":[{"mediaType":"application/vnd.docker.image.rootfs.diff.tar.gzip","digest":"sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4","size":32}]}`
+ manifestContentType := container_module.ContentTypeDockerDistributionManifestV2
untaggedManifestDigest := "sha256:4305f5f5572b9a426b88909b036e52ee3cf3d7b9c1b01fac840e90747f56623d"
untaggedManifestContent := `{"schemaVersion":2,"mediaType":"` + oci.MediaTypeImageManifest + `","config":{"mediaType":"application/vnd.docker.container.image.v1+json","digest":"sha256:4607e093bec406eaadb6f3a340f63400c9d3a7038680744c406903766b938f0d","size":1069},"layers":[{"mediaType":"application/vnd.docker.image.rootfs.diff.tar.gzip","digest":"sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4","size":32}]}`
@@ -92,12 +94,12 @@ func TestPackageContainer(t *testing.T) {
t.Run("Anonymous", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("%sv2", setting.AppURL))
+ req := NewRequest(t, "GET", setting.AppURL+"v2")
resp := MakeRequest(t, req, http.StatusUnauthorized)
assert.ElementsMatch(t, defaultAuthenticateValues, resp.Header().Values("WWW-Authenticate"))
- req = NewRequest(t, "GET", fmt.Sprintf("%sv2/token", setting.AppURL))
+ req = NewRequest(t, "GET", setting.AppURL+"v2/token")
resp = MakeRequest(t, req, http.StatusOK)
tokenResponse := &TokenResponse{}
@@ -105,18 +107,18 @@ func TestPackageContainer(t *testing.T) {
assert.NotEmpty(t, tokenResponse.Token)
- anonymousToken = fmt.Sprintf("Bearer %s", tokenResponse.Token)
+ anonymousToken = "Bearer " + tokenResponse.Token
- req = NewRequest(t, "GET", fmt.Sprintf("%sv2", setting.AppURL)).
+ req = NewRequest(t, "GET", setting.AppURL+"v2").
AddTokenAuth(anonymousToken)
MakeRequest(t, req, http.StatusOK)
- defer test.MockVariableValue(&setting.Service.RequireSignInView, true)()
+ defer test.MockVariableValue(&setting.Service.RequireSignInViewStrict, true)()
- req = NewRequest(t, "GET", fmt.Sprintf("%sv2", setting.AppURL))
+ req = NewRequest(t, "GET", setting.AppURL+"v2")
MakeRequest(t, req, http.StatusUnauthorized)
- req = NewRequest(t, "GET", fmt.Sprintf("%sv2/token", setting.AppURL))
+ req = NewRequest(t, "GET", setting.AppURL+"v2/token")
MakeRequest(t, req, http.StatusUnauthorized)
defer test.MockVariableValue(&setting.AppURL, "https://domain:8443/sub-path/")()
@@ -129,12 +131,12 @@ func TestPackageContainer(t *testing.T) {
t.Run("UserName/Password", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("%sv2", setting.AppURL))
+ req := NewRequest(t, "GET", setting.AppURL+"v2")
resp := MakeRequest(t, req, http.StatusUnauthorized)
assert.ElementsMatch(t, defaultAuthenticateValues, resp.Header().Values("WWW-Authenticate"))
- req = NewRequest(t, "GET", fmt.Sprintf("%sv2/token", setting.AppURL)).
+ req = NewRequest(t, "GET", setting.AppURL+"v2/token").
AddBasicAuth(user.Name)
resp = MakeRequest(t, req, http.StatusOK)
@@ -147,9 +149,9 @@ func TestPackageContainer(t *testing.T) {
assert.Equal(t, user.ID, pkgMeta.UserID)
assert.Equal(t, auth_model.AccessTokenScopeAll, pkgMeta.Scope)
- userToken = fmt.Sprintf("Bearer %s", tokenResponse.Token)
+ userToken = "Bearer " + tokenResponse.Token
- req = NewRequest(t, "GET", fmt.Sprintf("%sv2", setting.AppURL)).
+ req = NewRequest(t, "GET", setting.AppURL+"v2").
AddTokenAuth(userToken)
MakeRequest(t, req, http.StatusOK)
})
@@ -161,23 +163,23 @@ func TestPackageContainer(t *testing.T) {
session := loginUser(t, user.Name)
readToken = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadPackage)
- req := NewRequest(t, "GET", fmt.Sprintf("%sv2/token", setting.AppURL))
+ req := NewRequest(t, "GET", setting.AppURL+"v2/token")
req.Request.SetBasicAuth(user.Name, readToken)
resp := MakeRequest(t, req, http.StatusOK)
tokenResponse := &TokenResponse{}
DecodeJSON(t, resp, &tokenResponse)
- readToken = fmt.Sprintf("Bearer %s", tokenResponse.Token)
+ readToken = "Bearer " + tokenResponse.Token
badToken = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadNotification)
- req = NewRequest(t, "GET", fmt.Sprintf("%sv2/token", setting.AppURL))
+ req = NewRequest(t, "GET", setting.AppURL+"v2/token")
req.Request.SetBasicAuth(user.Name, badToken)
MakeRequest(t, req, http.StatusUnauthorized)
testCase := func(scope auth_model.AccessTokenScope, expectedAuthStatus, expectedStatus int) {
token := getTokenForLoggedInUser(t, session, scope)
- req := NewRequest(t, "GET", fmt.Sprintf("%sv2/token", setting.AppURL))
+ req := NewRequest(t, "GET", setting.AppURL+"v2/token")
req.SetBasicAuth(user.Name, token)
resp := MakeRequest(t, req, expectedAuthStatus)
@@ -190,8 +192,8 @@ func TestPackageContainer(t *testing.T) {
assert.NotEmpty(t, tokenResponse.Token)
- req = NewRequest(t, "GET", fmt.Sprintf("%sv2", setting.AppURL)).
- AddTokenAuth(fmt.Sprintf("Bearer %s", tokenResponse.Token))
+ req = NewRequest(t, "GET", setting.AppURL+"v2").
+ AddTokenAuth("Bearer " + tokenResponse.Token)
MakeRequest(t, req, expectedStatus)
}
testCase(auth_model.AccessTokenScopeReadPackage, http.StatusOK, http.StatusOK)
@@ -204,17 +206,17 @@ func TestPackageContainer(t *testing.T) {
t.Run("DetermineSupport", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("%sv2", setting.AppURL)).
+ req := NewRequest(t, "GET", setting.AppURL+"v2").
AddTokenAuth(userToken)
resp := MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "registry/2.0", resp.Header().Get("Docker-Distribution-Api-Version"))
- req = NewRequest(t, "GET", fmt.Sprintf("%sv2", setting.AppURL)).
+ req = NewRequest(t, "GET", setting.AppURL+"v2").
AddTokenAuth(readToken)
resp = MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "registry/2.0", resp.Header().Get("Docker-Distribution-Api-Version"))
- req = NewRequest(t, "GET", fmt.Sprintf("%sv2", setting.AppURL)).
+ req = NewRequest(t, "GET", setting.AppURL+"v2").
AddTokenAuth(badToken)
MakeRequest(t, req, http.StatusUnauthorized)
})
@@ -226,15 +228,15 @@ func TestPackageContainer(t *testing.T) {
t.Run("UploadBlob/Monolithic", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "POST", fmt.Sprintf("%s/blobs/uploads", url)).
+ req := NewRequest(t, "POST", url+"/blobs/uploads").
AddTokenAuth(anonymousToken)
MakeRequest(t, req, http.StatusUnauthorized)
- req = NewRequest(t, "POST", fmt.Sprintf("%s/blobs/uploads", url)).
+ req = NewRequest(t, "POST", url+"/blobs/uploads").
AddTokenAuth(readToken)
MakeRequest(t, req, http.StatusUnauthorized)
- req = NewRequest(t, "POST", fmt.Sprintf("%s/blobs/uploads", url)).
+ req = NewRequest(t, "POST", url+"/blobs/uploads").
AddTokenAuth(badToken)
MakeRequest(t, req, http.StatusUnauthorized)
@@ -249,7 +251,7 @@ func TestPackageContainer(t *testing.T) {
assert.Equal(t, fmt.Sprintf("/v2/%s/%s/blobs/%s", user.Name, image, blobDigest), resp.Header().Get("Location"))
assert.Equal(t, blobDigest, resp.Header().Get("Docker-Content-Digest"))
- pv, err := packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, user.ID, packages_model.TypeContainer, image, container_model.UploadVersion)
+ pv, err := packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, user.ID, packages_model.TypeContainer, image, container_module.UploadVersion)
assert.NoError(t, err)
pfs, err := packages_model.GetFilesByVersionID(db.DefaultContext, pv.ID)
@@ -264,15 +266,15 @@ func TestPackageContainer(t *testing.T) {
t.Run("UploadBlob/Chunked", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "POST", fmt.Sprintf("%s/blobs/uploads", url)).
+ req := NewRequest(t, "POST", url+"/blobs/uploads").
AddTokenAuth(readToken)
MakeRequest(t, req, http.StatusUnauthorized)
- req = NewRequest(t, "POST", fmt.Sprintf("%s/blobs/uploads", url)).
+ req = NewRequest(t, "POST", url+"/blobs/uploads").
AddTokenAuth(badToken)
MakeRequest(t, req, http.StatusUnauthorized)
- req = NewRequest(t, "POST", fmt.Sprintf("%s/blobs/uploads", url)).
+ req = NewRequest(t, "POST", url+"/blobs/uploads").
AddTokenAuth(userToken)
resp := MakeRequest(t, req, http.StatusAccepted)
@@ -295,11 +297,22 @@ func TestPackageContainer(t *testing.T) {
SetHeader("Content-Range", "1-10")
MakeRequest(t, req, http.StatusRequestedRangeNotSatisfiable)
- contentRange := fmt.Sprintf("0-%d", len(blobContent)-1)
- req.SetHeader("Content-Range", contentRange)
+ // first patch without Content-Range
+ req = NewRequestWithBody(t, "PATCH", setting.AppURL+uploadURL[1:], bytes.NewReader(blobContent[:1])).
+ AddTokenAuth(userToken)
+ resp = MakeRequest(t, req, http.StatusAccepted)
+ assert.NotEmpty(t, resp.Header().Get("Location"))
+ assert.Equal(t, "0-0", resp.Header().Get("Range"))
+
+ // then send remaining content with Content-Range
+ req = NewRequestWithBody(t, "PATCH", setting.AppURL+uploadURL[1:], bytes.NewReader(blobContent[1:])).
+ SetHeader("Content-Range", fmt.Sprintf("1-%d", len(blobContent)-1)).
+ AddTokenAuth(userToken)
resp = MakeRequest(t, req, http.StatusAccepted)
+ contentRange := fmt.Sprintf("0-%d", len(blobContent)-1)
assert.Equal(t, uuid, resp.Header().Get("Docker-Upload-Uuid"))
+ assert.NotEmpty(t, resp.Header().Get("Location"))
assert.Equal(t, contentRange, resp.Header().Get("Range"))
uploadURL = resp.Header().Get("Location")
@@ -309,7 +322,8 @@ func TestPackageContainer(t *testing.T) {
resp = MakeRequest(t, req, http.StatusNoContent)
assert.Equal(t, uuid, resp.Header().Get("Docker-Upload-Uuid"))
- assert.Equal(t, fmt.Sprintf("0-%d", len(blobContent)), resp.Header().Get("Range"))
+ assert.Equal(t, uploadURL, resp.Header().Get("Location"))
+ assert.Equal(t, contentRange, resp.Header().Get("Range"))
pbu, err = packages_model.GetBlobUploadByID(db.DefaultContext, uuid)
assert.NoError(t, err)
@@ -325,7 +339,7 @@ func TestPackageContainer(t *testing.T) {
t.Run("Cancel", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "POST", fmt.Sprintf("%s/blobs/uploads", url)).
+ req := NewRequest(t, "POST", url+"/blobs/uploads").
AddTokenAuth(userToken)
resp := MakeRequest(t, req, http.StatusAccepted)
@@ -340,7 +354,8 @@ func TestPackageContainer(t *testing.T) {
resp = MakeRequest(t, req, http.StatusNoContent)
assert.Equal(t, uuid, resp.Header().Get("Docker-Upload-Uuid"))
- assert.Equal(t, "0-0", resp.Header().Get("Range"))
+ // FIXME: undefined behavior when the uploaded content is empty: https://github.com/opencontainers/distribution-spec/issues/578
+ assert.Nil(t, resp.Header().Values("Range"))
req = NewRequest(t, "DELETE", setting.AppURL+uploadURL[1:]).
AddTokenAuth(userToken)
@@ -428,7 +443,7 @@ func TestPackageContainer(t *testing.T) {
assert.Len(t, pd.Files, 3)
for _, pfd := range pd.Files {
switch pfd.File.Name {
- case container_model.ManifestFilename:
+ case container_module.ManifestFilename:
assert.True(t, pfd.File.IsLead)
assert.Equal(t, "application/vnd.docker.distribution.manifest.v2+json", pfd.Properties.GetByName(container_module.PropertyMediaType))
assert.Equal(t, manifestDigest, pfd.Properties.GetByName(container_module.PropertyDigest))
@@ -441,7 +456,7 @@ func TestPackageContainer(t *testing.T) {
assert.Equal(t, "application/vnd.docker.image.rootfs.diff.tar.gzip", pfd.Properties.GetByName(container_module.PropertyMediaType))
assert.Equal(t, blobDigest, pfd.Properties.GetByName(container_module.PropertyDigest))
default:
- assert.FailNow(t, "unknown file: %s", pfd.File.Name)
+ assert.FailNow(t, "unknown file", "unknown file: %s", pfd.File.Name)
}
}
@@ -467,7 +482,7 @@ func TestPackageContainer(t *testing.T) {
t.Run("HeadManifest", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "HEAD", fmt.Sprintf("%s/manifests/unknown-tag", url)).
+ req := NewRequest(t, "HEAD", url+"/manifests/unknown-tag").
AddTokenAuth(userToken)
MakeRequest(t, req, http.StatusNotFound)
@@ -475,14 +490,14 @@ func TestPackageContainer(t *testing.T) {
AddTokenAuth(userToken)
resp := MakeRequest(t, req, http.StatusOK)
- assert.Equal(t, fmt.Sprintf("%d", len(manifestContent)), resp.Header().Get("Content-Length"))
+ assert.Equal(t, strconv.Itoa(len(manifestContent)), resp.Header().Get("Content-Length"))
assert.Equal(t, manifestDigest, resp.Header().Get("Docker-Content-Digest"))
})
t.Run("GetManifest", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("%s/manifests/unknown-tag", url)).
+ req := NewRequest(t, "GET", url+"/manifests/unknown-tag").
AddTokenAuth(userToken)
MakeRequest(t, req, http.StatusNotFound)
@@ -490,8 +505,8 @@ func TestPackageContainer(t *testing.T) {
AddTokenAuth(userToken)
resp := MakeRequest(t, req, http.StatusOK)
- assert.Equal(t, fmt.Sprintf("%d", len(manifestContent)), resp.Header().Get("Content-Length"))
- assert.Equal(t, oci.MediaTypeImageManifest, resp.Header().Get("Content-Type"))
+ assert.Equal(t, strconv.Itoa(len(manifestContent)), resp.Header().Get("Content-Length"))
+ assert.Equal(t, manifestContentType, resp.Header().Get("Content-Type"))
assert.Equal(t, manifestDigest, resp.Header().Get("Docker-Content-Digest"))
assert.Equal(t, manifestContent, resp.Body.String())
})
@@ -512,7 +527,7 @@ func TestPackageContainer(t *testing.T) {
AddTokenAuth(userToken)
resp = MakeRequest(t, req, http.StatusOK)
- assert.Equal(t, fmt.Sprintf("%d", len(untaggedManifestContent)), resp.Header().Get("Content-Length"))
+ assert.Equal(t, strconv.Itoa(len(untaggedManifestContent)), resp.Header().Get("Content-Length"))
assert.Equal(t, untaggedManifestDigest, resp.Header().Get("Docker-Content-Digest"))
pv, err := packages_model.GetVersionByNameAndVersion(db.DefaultContext, user.ID, packages_model.TypeContainer, image, untaggedManifestDigest)
@@ -530,7 +545,7 @@ func TestPackageContainer(t *testing.T) {
assert.Len(t, pd.Files, 3)
for _, pfd := range pd.Files {
- if pfd.File.Name == container_model.ManifestFilename {
+ if pfd.File.Name == container_module.ManifestFilename {
assert.True(t, pfd.File.IsLead)
assert.Equal(t, oci.MediaTypeImageManifest, pfd.Properties.GetByName(container_module.PropertyMediaType))
assert.Equal(t, untaggedManifestDigest, pfd.Properties.GetByName(container_module.PropertyDigest))
@@ -598,7 +613,7 @@ func TestPackageContainer(t *testing.T) {
AddTokenAuth(userToken)
resp := MakeRequest(t, req, http.StatusOK)
- assert.Equal(t, fmt.Sprintf("%d", len(blobContent)), resp.Header().Get("Content-Length"))
+ assert.Equal(t, strconv.Itoa(len(blobContent)), resp.Header().Get("Content-Length"))
assert.Equal(t, blobDigest, resp.Header().Get("Docker-Content-Digest"))
req = NewRequest(t, "HEAD", fmt.Sprintf("%s/blobs/%s", url, blobDigest)).
@@ -617,11 +632,27 @@ func TestPackageContainer(t *testing.T) {
AddTokenAuth(userToken)
resp := MakeRequest(t, req, http.StatusOK)
- assert.Equal(t, fmt.Sprintf("%d", len(blobContent)), resp.Header().Get("Content-Length"))
+ assert.Equal(t, strconv.Itoa(len(blobContent)), resp.Header().Get("Content-Length"))
assert.Equal(t, blobDigest, resp.Header().Get("Docker-Content-Digest"))
assert.Equal(t, blobContent, resp.Body.Bytes())
})
+ t.Run("GetBlob/Empty", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+ emptyDigestBuf := sha256.Sum256(nil)
+ emptyDigest := "sha256:" + hex.EncodeToString(emptyDigestBuf[:])
+ req := NewRequestWithBody(t, "POST", fmt.Sprintf("%s/blobs/uploads?digest=%s", url, emptyDigest), strings.NewReader("")).AddTokenAuth(userToken)
+ MakeRequest(t, req, http.StatusCreated)
+
+ req = NewRequest(t, "HEAD", fmt.Sprintf("%s/blobs/%s", url, emptyDigest)).AddTokenAuth(userToken)
+ resp := MakeRequest(t, req, http.StatusOK)
+ assert.Equal(t, "0", resp.Header().Get("Content-Length"))
+
+ req = NewRequest(t, "GET", fmt.Sprintf("%s/blobs/%s", url, emptyDigest)).AddTokenAuth(userToken)
+ resp = MakeRequest(t, req, http.StatusOK)
+ assert.Equal(t, "0", resp.Header().Get("Content-Length"))
+ })
+
t.Run("GetTagList", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
@@ -631,27 +662,27 @@ func TestPackageContainer(t *testing.T) {
ExpectedLink string
}{
{
- URL: fmt.Sprintf("%s/tags/list", url),
+ URL: url + "/tags/list",
ExpectedTags: []string{"latest", "main", "multi"},
ExpectedLink: fmt.Sprintf(`</v2/%s/%s/tags/list?last=multi>; rel="next"`, user.Name, image),
},
{
- URL: fmt.Sprintf("%s/tags/list?n=0", url),
+ URL: url + "/tags/list?n=0",
ExpectedTags: []string{},
ExpectedLink: "",
},
{
- URL: fmt.Sprintf("%s/tags/list?n=2", url),
+ URL: url + "/tags/list?n=2",
ExpectedTags: []string{"latest", "main"},
ExpectedLink: fmt.Sprintf(`</v2/%s/%s/tags/list?last=main&n=2>; rel="next"`, user.Name, image),
},
{
- URL: fmt.Sprintf("%s/tags/list?last=main", url),
+ URL: url + "/tags/list?last=main",
ExpectedTags: []string{"multi"},
ExpectedLink: fmt.Sprintf(`</v2/%s/%s/tags/list?last=multi>; rel="next"`, user.Name, image),
},
{
- URL: fmt.Sprintf("%s/tags/list?n=1&last=latest", url),
+ URL: url + "/tags/list?n=1&last=latest",
ExpectedTags: []string{"main"},
ExpectedLink: fmt.Sprintf(`</v2/%s/%s/tags/list?last=main&n=1>; rel="next"`, user.Name, image),
},
@@ -731,7 +762,7 @@ func TestPackageContainer(t *testing.T) {
url := fmt.Sprintf("%sv2/%s/parallel", setting.AppURL, user.Name)
var wg sync.WaitGroup
- for i := 0; i < 10; i++ {
+ for i := range 10 {
wg.Add(1)
content := []byte{byte(i)}
@@ -757,7 +788,7 @@ func TestPackageContainer(t *testing.T) {
return func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("%sv2/_catalog", setting.AppURL)).
+ req := NewRequest(t, "GET", setting.AppURL+"v2/_catalog").
AddTokenAuth(userToken)
resp := MakeRequest(t, req, http.StatusOK)
diff --git a/tests/integration/api_packages_cran_test.go b/tests/integration/api_packages_cran_test.go
index 667ba0908c..bd4a99f331 100644
--- a/tests/integration/api_packages_cran_test.go
+++ b/tests/integration/api_packages_cran_test.go
@@ -133,8 +133,8 @@ func TestPackageCran(t *testing.T) {
assert.Contains(t, resp.Header().Get("Content-Type"), "text/plain")
body := resp.Body.String()
- assert.Contains(t, body, fmt.Sprintf("Package: %s", packageName))
- assert.Contains(t, body, fmt.Sprintf("Version: %s", packageVersion))
+ assert.Contains(t, body, "Package: "+packageName)
+ assert.Contains(t, body, "Version: "+packageVersion)
req = NewRequest(t, "GET", url+"/src/contrib/PACKAGES.gz").
AddBasicAuth(user.Name)
@@ -230,8 +230,8 @@ func TestPackageCran(t *testing.T) {
assert.Contains(t, resp.Header().Get("Content-Type"), "text/plain")
body := resp.Body.String()
- assert.Contains(t, body, fmt.Sprintf("Package: %s", packageName))
- assert.Contains(t, body, fmt.Sprintf("Version: %s", packageVersion))
+ assert.Contains(t, body, "Package: "+packageName)
+ assert.Contains(t, body, "Version: "+packageVersion)
req = NewRequest(t, "GET", url+"/bin/windows/contrib/4.2/PACKAGES.gz").
AddBasicAuth(user.Name)
diff --git a/tests/integration/api_packages_debian_test.go b/tests/integration/api_packages_debian_test.go
index 98027d774c..3ae60d2aa2 100644
--- a/tests/integration/api_packages_debian_test.go
+++ b/tests/integration/api_packages_debian_test.go
@@ -284,7 +284,7 @@ func TestPackageDebian(t *testing.T) {
// because "Iterate" keeps a dangling SQL session but the callback function still uses the same session to execute statements.
// The "Iterate" problem has been checked by TestContextSafety now, so here we only need to check the cleanup logic with a small number
packagesCount := 2
- for i := 0; i < packagesCount; i++ {
+ for i := range packagesCount {
uploadURL := fmt.Sprintf("%s/pool/%s/%s/upload", rootURL, "test", "main")
req := NewRequestWithBody(t, "PUT", uploadURL, createArchive(packageName, "1.0."+strconv.Itoa(i), "all")).AddBasicAuth(user.Name)
MakeRequest(t, req, http.StatusCreated)
diff --git a/tests/integration/api_packages_generic_test.go b/tests/integration/api_packages_generic_test.go
index baa8dd66c8..5f410fc470 100644
--- a/tests/integration/api_packages_generic_test.go
+++ b/tests/integration/api_packages_generic_test.go
@@ -15,6 +15,7 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
@@ -131,11 +132,7 @@ func TestPackageGeneric(t *testing.T) {
t.Run("RequireSignInView", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
-
- setting.Service.RequireSignInView = true
- defer func() {
- setting.Service.RequireSignInView = false
- }()
+ defer test.MockVariableValue(&setting.Service.RequireSignInViewStrict, true)()
req = NewRequest(t, "GET", url+"/dummy.bin")
MakeRequest(t, req, http.StatusUnauthorized)
diff --git a/tests/integration/api_packages_goproxy_test.go b/tests/integration/api_packages_goproxy_test.go
index dab9fefc5e..fa0ee5b901 100644
--- a/tests/integration/api_packages_goproxy_test.go
+++ b/tests/integration/api_packages_goproxy_test.go
@@ -87,7 +87,7 @@ func TestPackageGo(t *testing.T) {
AddBasicAuth(user.Name)
MakeRequest(t, req, http.StatusConflict)
- time.Sleep(time.Second)
+ time.Sleep(time.Second) // Ensure the timestamp is different, then the "list" below can have stable order
content = createArchive(map[string][]byte{
packageName + "@" + packageVersion2 + "/go.mod": []byte(goModContent),
diff --git a/tests/integration/api_packages_helm_test.go b/tests/integration/api_packages_helm_test.go
index 76285add11..8f5c6ac571 100644
--- a/tests/integration/api_packages_helm_test.go
+++ b/tests/integration/api_packages_helm_test.go
@@ -52,7 +52,7 @@ dependencies:
zw := gzip.NewWriter(&buf)
archive := tar.NewWriter(zw)
archive.WriteHeader(&tar.Header{
- Name: fmt.Sprintf("%s/Chart.yaml", packageName),
+ Name: packageName + "/Chart.yaml",
Mode: 0o600,
Size: int64(len(chartContent)),
})
@@ -122,7 +122,7 @@ dependencies:
t.Run("Index", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("%s/index.yaml", url)).
+ req := NewRequest(t, "GET", url+"/index.yaml").
AddBasicAuth(user.Name)
resp := MakeRequest(t, req, http.StatusOK)
diff --git a/tests/integration/api_packages_maven_test.go b/tests/integration/api_packages_maven_test.go
index 486a5af93e..30ef1884cd 100644
--- a/tests/integration/api_packages_maven_test.go
+++ b/tests/integration/api_packages_maven_test.go
@@ -80,6 +80,7 @@ func TestPackageMaven(t *testing.T) {
t.Run("UploadLegacy", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
+ // try to upload a package with legacy package name (will be saved as "GroupID-ArtifactID")
legacyRootLink := "/api/packages/user2/maven/com/gitea/legacy-project"
req := NewRequestWithBody(t, "PUT", legacyRootLink+"/1.0.2/any-file-name?use_legacy_package_name=1", strings.NewReader("test-content")).AddBasicAuth(user.Name)
MakeRequest(t, req, http.StatusCreated)
@@ -97,6 +98,13 @@ func TestPackageMaven(t *testing.T) {
req = NewRequest(t, "GET", "/user2/-/packages/maven/com.gitea%3Alegacy-project/1.0.2")
MakeRequest(t, req, http.StatusNotFound)
+ // legacy package names should also be able to be listed
+ req = NewRequest(t, "GET", legacyRootLink+"/maven-metadata.xml").AddBasicAuth(user.Name)
+ resp := MakeRequest(t, req, http.StatusOK)
+ respBody := resp.Body.String()
+ assert.Contains(t, respBody, "<version>1.0.2</version>")
+
+ // then upload a package with correct package name (will be saved as "GroupID:ArtifactID")
req = NewRequestWithBody(t, "PUT", legacyRootLink+"/1.0.3/any-file-name", strings.NewReader("test-content")).AddBasicAuth(user.Name)
MakeRequest(t, req, http.StatusCreated)
_, err = packages.GetPackageByName(db.DefaultContext, user.ID, packages.TypeMaven, "com.gitea-legacy-project")
@@ -114,6 +122,12 @@ func TestPackageMaven(t *testing.T) {
req = NewRequest(t, "GET", "/user2/-/packages/maven/com.gitea%3Alegacy-project/1.0.2")
MakeRequest(t, req, http.StatusOK)
+ // now 2 packages should be listed
+ req = NewRequest(t, "GET", legacyRootLink+"/maven-metadata.xml").AddBasicAuth(user.Name)
+ resp = MakeRequest(t, req, http.StatusOK)
+ respBody = resp.Body.String()
+ assert.Contains(t, respBody, "<version>1.0.2</version>")
+ assert.Contains(t, respBody, "<version>1.0.3</version>")
require.NoError(t, packages.DeletePackageByID(db.DefaultContext, p.ID))
})
@@ -307,7 +321,7 @@ func TestPackageMavenConcurrent(t *testing.T) {
defer tests.PrintCurrentTest(t)()
var wg sync.WaitGroup
- for i := 0; i < 10; i++ {
+ for i := range 10 {
wg.Add(1)
go func(i int) {
putFile(t, fmt.Sprintf("/%s/%s.jar", packageVersion, strconv.Itoa(i)), "test", http.StatusCreated)
diff --git a/tests/integration/api_packages_npm_test.go b/tests/integration/api_packages_npm_test.go
index ae1dd876f7..a190ed679d 100644
--- a/tests/integration/api_packages_npm_test.go
+++ b/tests/integration/api_packages_npm_test.go
@@ -28,7 +28,7 @@ func TestPackageNpm(t *testing.T) {
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
- token := fmt.Sprintf("Bearer %s", getTokenForLoggedInUser(t, loginUser(t, user.Name), auth_model.AccessTokenScopeWritePackage))
+ token := "Bearer " + getTokenForLoggedInUser(t, loginUser(t, user.Name), auth_model.AccessTokenScopeWritePackage)
packageName := "@scope/test-package"
packageVersion := "1.0.1-pre"
diff --git a/tests/integration/api_packages_nuget_test.go b/tests/integration/api_packages_nuget_test.go
index 622c2c4394..65b1b9845a 100644
--- a/tests/integration/api_packages_nuget_test.go
+++ b/tests/integration/api_packages_nuget_test.go
@@ -46,21 +46,30 @@ func TestPackageNuGet(t *testing.T) {
defer tests.PrepareTestEnv(t)()
type FeedEntryProperties struct {
- Version string `xml:"Version"`
- NormalizedVersion string `xml:"NormalizedVersion"`
Authors string `xml:"Authors"`
+ Copyright string `xml:"Copyright,omitempty"`
+ Created nuget.TypedValue[time.Time] `xml:"Created"`
Dependencies string `xml:"Dependencies"`
Description string `xml:"Description"`
- VersionDownloadCount nuget.TypedValue[int64] `xml:"VersionDownloadCount"`
+ DevelopmentDependency nuget.TypedValue[bool] `xml:"DevelopmentDependency"`
DownloadCount nuget.TypedValue[int64] `xml:"DownloadCount"`
- PackageSize nuget.TypedValue[int64] `xml:"PackageSize"`
- Created nuget.TypedValue[time.Time] `xml:"Created"`
+ ID string `xml:"Id"`
+ IconURL string `xml:"IconUrl,omitempty"`
+ Language string `xml:"Language,omitempty"`
LastUpdated nuget.TypedValue[time.Time] `xml:"LastUpdated"`
- Published nuget.TypedValue[time.Time] `xml:"Published"`
+ LicenseURL string `xml:"LicenseUrl,omitempty"`
+ MinClientVersion string `xml:"MinClientVersion,omitempty"`
+ NormalizedVersion string `xml:"NormalizedVersion"`
+ Owners string `xml:"Owners,omitempty"`
+ PackageSize nuget.TypedValue[int64] `xml:"PackageSize"`
ProjectURL string `xml:"ProjectUrl,omitempty"`
+ Published nuget.TypedValue[time.Time] `xml:"Published"`
ReleaseNotes string `xml:"ReleaseNotes,omitempty"`
RequireLicenseAcceptance nuget.TypedValue[bool] `xml:"RequireLicenseAcceptance"`
+ Tags string `xml:"Tags,omitempty"`
Title string `xml:"Title"`
+ Version string `xml:"Version"`
+ VersionDownloadCount nuget.TypedValue[int64] `xml:"VersionDownloadCount"`
}
type FeedEntry struct {
@@ -86,28 +95,54 @@ func TestPackageNuGet(t *testing.T) {
readToken := getUserToken(t, user.Name, auth_model.AccessTokenScopeReadPackage)
badToken := getUserToken(t, user.Name, auth_model.AccessTokenScopeReadNotification)
- packageName := "test.package"
+ packageName := "test.package" // id
+ packageID := packageName
packageVersion := "1.0.3"
packageAuthors := "KN4CK3R"
packageDescription := "Gitea Test Package"
+
symbolFilename := "test.pdb"
symbolID := "d910bb6948bd4c6cb40155bcf52c3c94"
+ packageCopyright := "Package Copyright"
+ packageIconURL := "https://gitea.io/favicon.png"
+ packageLanguage := "Package Language"
+ packageLicenseURL := "https://gitea.io/license"
+ packageMinClientVersion := "1.0.0.0"
+ packageOwners := "Package Owners"
+ packageProjectURL := "https://gitea.io"
+ packageReleaseNotes := "Package Release Notes"
+ packageTags := "tag_1 tag_2 tag_3"
+ packageTitle := "Package Title"
+ packageDevelopmentDependency := true
+ packageRequireLicenseAcceptance := true
+
createNuspec := func(id, version string) string {
return `<?xml version="1.0" encoding="utf-8"?>
-<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
- <metadata>
- <id>` + id + `</id>
- <version>` + version + `</version>
- <authors>` + packageAuthors + `</authors>
- <description>` + packageDescription + `</description>
- <dependencies>
- <group targetFramework=".NETStandard2.0">
- <dependency id="Microsoft.CSharp" version="4.5.0" />
- </group>
- </dependencies>
- </metadata>
-</package>`
+ <package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
+ <metadata minClientVersion="` + packageMinClientVersion + `">
+ <authors>` + packageAuthors + `</authors>
+ <copyright>` + packageCopyright + `</copyright>
+ <description>` + packageDescription + `</description>
+ <developmentDependency>true</developmentDependency>
+ <iconUrl>` + packageIconURL + `</iconUrl>
+ <id>` + id + `</id>
+ <language>` + packageLanguage + `</language>
+ <licenseUrl>` + packageLicenseURL + `</licenseUrl>
+ <owners>` + packageOwners + `</owners>
+ <projectUrl>` + packageProjectURL + `</projectUrl>
+ <releaseNotes>` + packageReleaseNotes + `</releaseNotes>
+ <requireLicenseAcceptance>true</requireLicenseAcceptance>
+ <tags>` + packageTags + `</tags>
+ <title>` + packageTitle + `</title>
+ <version>` + version + `</version>
+ <dependencies>
+ <group targetFramework=".NETStandard2.0">
+ <dependency id="Microsoft.CSharp" version="4.5.0" />
+ </group>
+ </dependencies>
+ </metadata>
+ </package>`
}
createPackage := func(id, version string) *bytes.Buffer {
@@ -198,7 +233,7 @@ func TestPackageNuGet(t *testing.T) {
t.Run(c.Owner, func(t *testing.T) {
url := fmt.Sprintf("/api/packages/%s/nuget", c.Owner)
- req := NewRequest(t, "GET", fmt.Sprintf("%s/index.json", url))
+ req := NewRequest(t, "GET", url+"/index.json")
if c.UseBasicAuth {
req.AddBasicAuth(user.Name)
} else if c.token != "" {
@@ -273,10 +308,10 @@ func TestPackageNuGet(t *testing.T) {
pb, err := packages.GetBlobByID(db.DefaultContext, pf.BlobID)
assert.NoError(t, err)
assert.Equal(t, int64(len(content)), pb.Size)
- case fmt.Sprintf("%s.nuspec", packageName):
+ case packageName + ".nuspec":
assert.False(t, pf.IsLead)
default:
- assert.Fail(t, "unexpected filename: %v", pf.Name)
+ assert.Fail(t, "unexpected filename", "unexpected filename: %v", pf.Name)
}
}
@@ -319,10 +354,10 @@ func TestPackageNuGet(t *testing.T) {
pb, err := packages.GetBlobByID(db.DefaultContext, pf.BlobID)
assert.NoError(t, err)
assert.Equal(t, int64(len(content)), pb.Size)
- case fmt.Sprintf("%s.nuspec", packageName):
+ case packageName + ".nuspec":
assert.False(t, pf.IsLead)
default:
- assert.Fail(t, "unexpected filename: %v", pf.Name)
+ assert.Fail(t, "unexpected filename", "unexpected filename: %v", pf.Name)
}
}
@@ -360,15 +395,15 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
return &buf
}
- req := NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/symbolpackage", url), createSymbolPackage("unknown-package", "SymbolsPackage")).
+ req := NewRequestWithBody(t, "PUT", url+"/symbolpackage", createSymbolPackage("unknown-package", "SymbolsPackage")).
AddBasicAuth(user.Name)
MakeRequest(t, req, http.StatusNotFound)
- req = NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/symbolpackage", url), createSymbolPackage(packageName, "DummyPackage")).
+ req = NewRequestWithBody(t, "PUT", url+"/symbolpackage", createSymbolPackage(packageName, "DummyPackage")).
AddBasicAuth(user.Name)
MakeRequest(t, req, http.StatusBadRequest)
- req = NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/symbolpackage", url), createSymbolPackage(packageName, "SymbolsPackage")).
+ req = NewRequestWithBody(t, "PUT", url+"/symbolpackage", createSymbolPackage(packageName, "SymbolsPackage")).
AddBasicAuth(user.Name)
MakeRequest(t, req, http.StatusCreated)
@@ -393,19 +428,19 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
pb, err := packages.GetBlobByID(db.DefaultContext, pf.BlobID)
assert.NoError(t, err)
- assert.Equal(t, int64(412), pb.Size)
+ assert.Equal(t, int64(610), pb.Size)
case fmt.Sprintf("%s.%s.snupkg", packageName, packageVersion):
assert.False(t, pf.IsLead)
pb, err := packages.GetBlobByID(db.DefaultContext, pf.BlobID)
assert.NoError(t, err)
assert.Equal(t, int64(616), pb.Size)
- case fmt.Sprintf("%s.nuspec", packageName):
+ case packageName + ".nuspec":
assert.False(t, pf.IsLead)
pb, err := packages.GetBlobByID(db.DefaultContext, pf.BlobID)
assert.NoError(t, err)
- assert.Equal(t, int64(427), pb.Size)
+ assert.Equal(t, int64(996), pb.Size)
case symbolFilename:
assert.False(t, pf.IsLead)
@@ -419,11 +454,11 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
assert.Equal(t, nuget_module.PropertySymbolID, pps[0].Name)
assert.Equal(t, symbolID, pps[0].Value)
default:
- assert.FailNow(t, "unexpected file: %v", pf.Name)
+ assert.FailNow(t, "unexpected file", "unexpected file: %v", pf.Name)
}
}
- req = NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/symbolpackage", url), createSymbolPackage(packageName, "SymbolsPackage")).
+ req = NewRequestWithBody(t, "PUT", url+"/symbolpackage", createSymbolPackage(packageName, "SymbolsPackage")).
AddBasicAuth(user.Name)
MakeRequest(t, req, http.StatusConflict)
})
@@ -631,7 +666,7 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
})
t.Run("Next", func(t *testing.T) {
- req := NewRequest(t, "GET", fmt.Sprintf("%s/Search()?searchTerm='test'&$skip=0&$top=1", url)).
+ req := NewRequest(t, "GET", url+"/Search()?searchTerm='test'&$skip=0&$top=1").
AddBasicAuth(user.Name)
resp := MakeRequest(t, req, http.StatusOK)
@@ -736,10 +771,24 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
var result FeedEntry
decodeXML(t, resp, &result)
- assert.Equal(t, packageName, result.Properties.Title)
- assert.Equal(t, packageVersion, result.Properties.Version)
assert.Equal(t, packageAuthors, result.Properties.Authors)
assert.Equal(t, packageDescription, result.Properties.Description)
+ assert.Equal(t, packageID, result.Properties.ID)
+ assert.Equal(t, packageVersion, result.Properties.Version)
+
+ assert.Equal(t, packageCopyright, result.Properties.Copyright)
+ assert.Equal(t, packageDevelopmentDependency, result.Properties.DevelopmentDependency.Value)
+ assert.Equal(t, packageIconURL, result.Properties.IconURL)
+ assert.Equal(t, packageLanguage, result.Properties.Language)
+ assert.Equal(t, packageLicenseURL, result.Properties.LicenseURL)
+ assert.Equal(t, packageMinClientVersion, result.Properties.MinClientVersion)
+ assert.Equal(t, packageOwners, result.Properties.Owners)
+ assert.Equal(t, packageProjectURL, result.Properties.ProjectURL)
+ assert.Equal(t, packageReleaseNotes, result.Properties.ReleaseNotes)
+ assert.Equal(t, packageRequireLicenseAcceptance, result.Properties.RequireLicenseAcceptance.Value)
+ assert.Equal(t, packageTags, result.Properties.Tags)
+ assert.Equal(t, packageTitle, result.Properties.Title)
+
assert.Equal(t, "Microsoft.CSharp:4.5.0:.NETStandard2.0", result.Properties.Dependencies)
})
diff --git a/tests/integration/api_packages_pub_test.go b/tests/integration/api_packages_pub_test.go
index 11da894ddf..3c1bca908e 100644
--- a/tests/integration/api_packages_pub_test.go
+++ b/tests/integration/api_packages_pub_test.go
@@ -37,7 +37,7 @@ func TestPackagePub(t *testing.T) {
packageVersion := "1.0.1"
packageDescription := "Test Description"
- filename := fmt.Sprintf("%s.tar.gz", packageVersion)
+ filename := packageVersion + ".tar.gz"
pubspecContent := `name: ` + packageName + `
version: ` + packageVersion + `
diff --git a/tests/integration/api_packages_pypi_test.go b/tests/integration/api_packages_pypi_test.go
index 2dabb5005b..54db45f1ac 100644
--- a/tests/integration/api_packages_pypi_test.go
+++ b/tests/integration/api_packages_pypi_test.go
@@ -67,7 +67,7 @@ func TestPackagePyPI(t *testing.T) {
body, writer, closeFunc := createBasicMultipartFile(filename, packageName, content)
writer.WriteField("project_urls", "DOCUMENTATION , https://readthedocs.org")
- writer.WriteField("project_urls", fmt.Sprintf("Home-page, %s", projectURL))
+ writer.WriteField("project_urls", "Home-page, "+projectURL)
_ = closeFunc()
diff --git a/tests/integration/api_packages_rpm_test.go b/tests/integration/api_packages_rpm_test.go
index 6feceaeb78..bd1959f64e 100644
--- a/tests/integration/api_packages_rpm_test.go
+++ b/tests/integration/api_packages_rpm_test.go
@@ -157,9 +157,14 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`,
t.Run("Download", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
+ // download the package without the file name
req := NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/%s/%s", groupURL, packageName, packageVersion, packageArchitecture))
resp := MakeRequest(t, req, http.StatusOK)
+ assert.Equal(t, content, resp.Body.Bytes())
+ // download the package with a file name (it can be anything)
+ req = NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/%s/%s/any-file-name", groupURL, packageName, packageVersion, packageArchitecture))
+ resp = MakeRequest(t, req, http.StatusOK)
assert.Equal(t, content, resp.Body.Bytes())
})
@@ -317,7 +322,7 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`,
var result Metadata
decodeGzipXML(t, resp, &result)
- assert.EqualValues(t, 1, result.PackageCount)
+ assert.Equal(t, 1, result.PackageCount)
assert.Len(t, result.Packages, 1)
p := result.Packages[0]
assert.Equal(t, "rpm", p.Type)
@@ -366,7 +371,7 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`,
var result Filelists
decodeGzipXML(t, resp, &result)
- assert.EqualValues(t, 1, result.PackageCount)
+ assert.Equal(t, 1, result.PackageCount)
assert.Len(t, result.Packages, 1)
p := result.Packages[0]
assert.NotEmpty(t, p.Pkgid)
@@ -403,7 +408,7 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`,
var result Other
decodeGzipXML(t, resp, &result)
- assert.EqualValues(t, 1, result.PackageCount)
+ assert.Equal(t, 1, result.PackageCount)
assert.Len(t, result.Packages, 1)
p := result.Packages[0]
assert.NotEmpty(t, p.Pkgid)
@@ -447,7 +452,8 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`,
pub, err := openpgp.ReadArmoredKeyRing(gpgResp.Body)
require.NoError(t, err)
- req = NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/%s/%s", groupURL, packageName, packageVersion, packageArchitecture))
+ rpmFileName := fmt.Sprintf("%s-%s.%s.rpm", packageName, packageVersion, packageArchitecture)
+ req = NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/%s/%s/%s", groupURL, packageName, packageVersion, packageArchitecture, rpmFileName))
resp := MakeRequest(t, req, http.StatusOK)
_, sigs, err := rpmutils.Verify(resp.Body, pub)
diff --git a/tests/integration/api_packages_rubygems_test.go b/tests/integration/api_packages_rubygems_test.go
index fe9283df4d..ab76c52440 100644
--- a/tests/integration/api_packages_rubygems_test.go
+++ b/tests/integration/api_packages_rubygems_test.go
@@ -185,7 +185,7 @@ func TestPackageRubyGems(t *testing.T) {
root := fmt.Sprintf("/api/packages/%s/rubygems", user.Name)
uploadFile := func(t *testing.T, content []byte, expectedStatus int) {
- req := NewRequestWithBody(t, "POST", fmt.Sprintf("%s/api/v1/gems", root), bytes.NewReader(content)).
+ req := NewRequestWithBody(t, "POST", root+"/api/v1/gems", bytes.NewReader(content)).
AddBasicAuth(user.Name)
MakeRequest(t, req, expectedStatus)
}
@@ -293,7 +293,7 @@ gAAAAP//MS06Gw==`)
t.Run("Versions", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("%s/versions", root)).AddBasicAuth(user.Name)
+ req := NewRequest(t, "GET", root+"/versions").AddBasicAuth(user.Name)
resp := MakeRequest(t, req, http.StatusOK)
assert.Equal(t, `---
gitea 1.0.5 08843c2dd0ea19910e6b056b98e38f1c
@@ -307,7 +307,7 @@ gitea-another 0.99 8b639e4048d282941485368ec42609be
_ = writer.WriteField("gem_name", packageName)
_ = writer.WriteField("version", packageVersion)
_ = writer.Close()
- req := NewRequestWithBody(t, "DELETE", fmt.Sprintf("%s/api/v1/gems/yank", root), &body).
+ req := NewRequestWithBody(t, "DELETE", root+"/api/v1/gems/yank", &body).
SetHeader("Content-Type", writer.FormDataContentType()).
AddBasicAuth(user.Name)
MakeRequest(t, req, http.StatusOK)
@@ -330,7 +330,7 @@ gitea-another 0.99 8b639e4048d282941485368ec42609be
t.Run("VersionsAfterDelete", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("%s/versions", root)).AddBasicAuth(user.Name)
+ req := NewRequest(t, "GET", root+"/versions").AddBasicAuth(user.Name)
resp := MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "---\n", resp.Body.String())
})
diff --git a/tests/integration/api_packages_swift_test.go b/tests/integration/api_packages_swift_test.go
index c0e0dccfab..b29e8459ff 100644
--- a/tests/integration/api_packages_swift_test.go
+++ b/tests/integration/api_packages_swift_test.go
@@ -23,6 +23,7 @@ import (
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
func TestPackageSwift(t *testing.T) {
@@ -34,6 +35,7 @@ func TestPackageSwift(t *testing.T) {
packageName := "test_package"
packageID := packageScope + "." + packageName
packageVersion := "1.0.3"
+ packageVersion2 := "1.0.4"
packageAuthor := "KN4CK3R"
packageDescription := "Gitea Test Package"
packageRepositoryURL := "https://gitea.io/gitea/gitea"
@@ -183,6 +185,94 @@ func TestPackageSwift(t *testing.T) {
)
})
+ t.Run("UploadMultipart", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ uploadPackage := func(t *testing.T, url string, expectedStatus int, sr io.Reader, metadata string) {
+ var body bytes.Buffer
+ mpw := multipart.NewWriter(&body)
+
+ // Read the source archive content
+ sourceContent, err := io.ReadAll(sr)
+ assert.NoError(t, err)
+ mpw.WriteField("source-archive", string(sourceContent))
+
+ if metadata != "" {
+ mpw.WriteField("metadata", metadata)
+ }
+
+ mpw.Close()
+
+ req := NewRequestWithBody(t, "PUT", url, &body).
+ SetHeader("Content-Type", mpw.FormDataContentType()).
+ SetHeader("Accept", swift_router.AcceptJSON).
+ AddBasicAuth(user.Name)
+ MakeRequest(t, req, expectedStatus)
+ }
+
+ createArchive := func(files map[string]string) *bytes.Buffer {
+ var buf bytes.Buffer
+ zw := zip.NewWriter(&buf)
+ for filename, content := range files {
+ w, _ := zw.Create(filename)
+ w.Write([]byte(content))
+ }
+ zw.Close()
+ return &buf
+ }
+
+ uploadURL := fmt.Sprintf("%s/%s/%s/%s", url, packageScope, packageName, packageVersion2)
+
+ req := NewRequestWithBody(t, "PUT", uploadURL, bytes.NewReader([]byte{}))
+ MakeRequest(t, req, http.StatusUnauthorized)
+
+ // Test with metadata as form field
+ uploadPackage(
+ t,
+ uploadURL,
+ http.StatusCreated,
+ createArchive(map[string]string{
+ "Package.swift": contentManifest1,
+ "Package@swift-5.6.swift": contentManifest2,
+ }),
+ `{"name":"`+packageName+`","version":"`+packageVersion2+`","description":"`+packageDescription+`","codeRepository":"`+packageRepositoryURL+`","author":{"givenName":"`+packageAuthor+`"},"repositoryURLs":["`+packageRepositoryURL+`"]}`,
+ )
+
+ pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeSwift)
+ assert.NoError(t, err)
+ require.Len(t, pvs, 2) // ATTENTION: many subtests are unable to run separately, they depend on the results of previous tests
+ thisPackageVersion := pvs[0]
+ pd, err := packages.GetPackageDescriptor(db.DefaultContext, thisPackageVersion)
+ assert.NoError(t, err)
+ assert.NotNil(t, pd.SemVer)
+ assert.Equal(t, packageID, pd.Package.Name)
+ assert.Equal(t, packageVersion2, pd.Version.Version)
+ assert.IsType(t, &swift_module.Metadata{}, pd.Metadata)
+ metadata := pd.Metadata.(*swift_module.Metadata)
+ assert.Equal(t, packageDescription, metadata.Description)
+ assert.Len(t, metadata.Manifests, 2)
+ assert.Equal(t, contentManifest1, metadata.Manifests[""].Content)
+ assert.Equal(t, contentManifest2, metadata.Manifests["5.6"].Content)
+ assert.Len(t, pd.VersionProperties, 1)
+ assert.Equal(t, packageRepositoryURL, pd.VersionProperties.GetByName(swift_module.PropertyRepositoryURL))
+
+ pfs, err := packages.GetFilesByVersionID(db.DefaultContext, thisPackageVersion.ID)
+ assert.NoError(t, err)
+ assert.Len(t, pfs, 1)
+ assert.Equal(t, fmt.Sprintf("%s-%s.zip", packageName, packageVersion2), pfs[0].Name)
+ assert.True(t, pfs[0].IsLead)
+
+ uploadPackage(
+ t,
+ uploadURL,
+ http.StatusConflict,
+ createArchive(map[string]string{
+ "Package.swift": contentManifest1,
+ }),
+ "",
+ )
+ })
+
t.Run("Download", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
@@ -211,7 +301,7 @@ func TestPackageSwift(t *testing.T) {
SetHeader("Accept", swift_router.AcceptJSON)
resp := MakeRequest(t, req, http.StatusOK)
- versionURL := setting.AppURL + url[1:] + fmt.Sprintf("/%s/%s/%s", packageScope, packageName, packageVersion)
+ versionURL := setting.AppURL + url[1:] + fmt.Sprintf("/%s/%s/%s", packageScope, packageName, packageVersion2)
assert.Equal(t, "1", resp.Header().Get("Content-Version"))
assert.Equal(t, fmt.Sprintf(`<%s>; rel="latest-version"`, versionURL), resp.Header().Get("Link"))
@@ -221,9 +311,9 @@ func TestPackageSwift(t *testing.T) {
var result *swift_router.EnumeratePackageVersionsResponse
DecodeJSON(t, resp, &result)
- assert.Len(t, result.Releases, 1)
- assert.Contains(t, result.Releases, packageVersion)
- assert.Equal(t, versionURL, result.Releases[packageVersion].URL)
+ assert.Len(t, result.Releases, 2)
+ assert.Contains(t, result.Releases, packageVersion2)
+ assert.Equal(t, versionURL, result.Releases[packageVersion2].URL)
req = NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s.json", url, packageScope, packageName)).
AddBasicAuth(user.Name)
diff --git a/tests/integration/api_packages_test.go b/tests/integration/api_packages_test.go
index daf32e82f9..f10b098885 100644
--- a/tests/integration/api_packages_test.go
+++ b/tests/integration/api_packages_test.go
@@ -15,14 +15,15 @@ import (
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
packages_model "code.gitea.io/gitea/models/packages"
- container_model "code.gitea.io/gitea/models/packages/container"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
+ container_module "code.gitea.io/gitea/modules/packages/container"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
packages_service "code.gitea.io/gitea/services/packages"
packages_cleanup_service "code.gitea.io/gitea/services/packages/cleanup"
+ repo_service "code.gitea.io/gitea/services/repository"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
@@ -34,7 +35,7 @@ func TestPackageAPI(t *testing.T) {
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
session := loginUser(t, user.Name)
tokenReadPackage := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadPackage)
- tokenDeletePackage := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWritePackage)
+ tokenWritePackage := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWritePackage)
packageName := "test-package"
packageVersion := "1.0.3"
@@ -48,7 +49,7 @@ func TestPackageAPI(t *testing.T) {
t.Run("ListPackages", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s", user.Name)).
+ req := NewRequest(t, "GET", "/api/v1/packages/"+user.Name).
AddTokenAuth(tokenReadPackage)
resp := MakeRequest(t, req, http.StatusOK)
@@ -82,47 +83,101 @@ func TestPackageAPI(t *testing.T) {
assert.Equal(t, packageVersion, p.Version)
assert.NotNil(t, p.Creator)
assert.Equal(t, user.Name, p.Creator.UserName)
+ })
- t.Run("RepositoryLink", func(t *testing.T) {
- defer tests.PrintCurrentTest(t)()
+ t.Run("ListPackageVersions", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
- p, err := packages_model.GetPackageByName(db.DefaultContext, user.ID, packages_model.TypeGeneric, packageName)
- assert.NoError(t, err)
+ req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s", user.Name, packageName)).
+ AddTokenAuth(tokenReadPackage)
+ resp := MakeRequest(t, req, http.StatusOK)
- // no repository link
- req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s", user.Name, packageName, packageVersion)).
- AddTokenAuth(tokenReadPackage)
- resp := MakeRequest(t, req, http.StatusOK)
+ var apiPackages []*api.Package
+ DecodeJSON(t, resp, &apiPackages)
+
+ assert.Len(t, apiPackages, 1)
+ assert.Equal(t, string(packages_model.TypeGeneric), apiPackages[0].Type)
+ assert.Equal(t, packageName, apiPackages[0].Name)
+ assert.Equal(t, packageVersion, apiPackages[0].Version)
+ })
+
+ t.Run("LatestPackageVersion", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
- var ap1 *api.Package
- DecodeJSON(t, resp, &ap1)
- assert.Nil(t, ap1.Repository)
+ req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/-/latest", user.Name, packageName)).
+ AddTokenAuth(tokenReadPackage)
+ resp := MakeRequest(t, req, http.StatusOK)
- // link to public repository
- assert.NoError(t, packages_model.SetRepositoryLink(db.DefaultContext, p.ID, 1))
+ var apiPackage *api.Package
+ DecodeJSON(t, resp, &apiPackage)
- req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s", user.Name, packageName, packageVersion)).
- AddTokenAuth(tokenReadPackage)
- resp = MakeRequest(t, req, http.StatusOK)
+ assert.Equal(t, string(packages_model.TypeGeneric), apiPackage.Type)
+ assert.Equal(t, packageName, apiPackage.Name)
+ assert.Equal(t, packageVersion, apiPackage.Version)
+ })
- var ap2 *api.Package
- DecodeJSON(t, resp, &ap2)
- assert.NotNil(t, ap2.Repository)
- assert.EqualValues(t, 1, ap2.Repository.ID)
+ t.Run("RepositoryLink", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
- // link to private repository
- assert.NoError(t, packages_model.SetRepositoryLink(db.DefaultContext, p.ID, 2))
+ _, err := packages_model.GetPackageByName(db.DefaultContext, user.ID, packages_model.TypeGeneric, packageName)
+ assert.NoError(t, err)
- req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s", user.Name, packageName, packageVersion)).
- AddTokenAuth(tokenReadPackage)
- resp = MakeRequest(t, req, http.StatusOK)
+ // no repository link
+ req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s", user.Name, packageName, packageVersion)).
+ AddTokenAuth(tokenReadPackage)
+ resp := MakeRequest(t, req, http.StatusOK)
- var ap3 *api.Package
- DecodeJSON(t, resp, &ap3)
- assert.Nil(t, ap3.Repository)
+ var ap1 *api.Package
+ DecodeJSON(t, resp, &ap1)
+ assert.Nil(t, ap1.Repository)
- assert.NoError(t, packages_model.UnlinkRepositoryFromAllPackages(db.DefaultContext, 2))
+ // create a repository
+ newRepo, err := repo_service.CreateRepository(db.DefaultContext, user, user, repo_service.CreateRepoOptions{
+ Name: "repo4",
})
+ assert.NoError(t, err)
+
+ // link to public repository
+ req = NewRequest(t, "POST", fmt.Sprintf("/api/v1/packages/%s/generic/%s/-/link/%s", user.Name, packageName, newRepo.Name)).AddTokenAuth(tokenWritePackage)
+ MakeRequest(t, req, http.StatusCreated)
+
+ req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s", user.Name, packageName, packageVersion)).
+ AddTokenAuth(tokenReadPackage)
+ resp = MakeRequest(t, req, http.StatusOK)
+
+ var ap2 *api.Package
+ DecodeJSON(t, resp, &ap2)
+ assert.NotNil(t, ap2.Repository)
+ assert.Equal(t, newRepo.ID, ap2.Repository.ID)
+
+ // link to repository without write access, should fail
+ req = NewRequest(t, "POST", fmt.Sprintf("/api/v1/packages/%s/generic/%s/-/link/%s", user.Name, packageName, "repo3")).AddTokenAuth(tokenWritePackage)
+ MakeRequest(t, req, http.StatusNotFound)
+
+ // remove link
+ req = NewRequest(t, "POST", fmt.Sprintf("/api/v1/packages/%s/generic/%s/-/unlink", user.Name, packageName)).AddTokenAuth(tokenWritePackage)
+ MakeRequest(t, req, http.StatusNoContent)
+
+ req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s", user.Name, packageName, packageVersion)).
+ AddTokenAuth(tokenReadPackage)
+ resp = MakeRequest(t, req, http.StatusOK)
+
+ var ap3 *api.Package
+ DecodeJSON(t, resp, &ap3)
+ assert.Nil(t, ap3.Repository)
+
+ // force link to a repository the currently logged-in user doesn't have access to
+ privateRepoID := int64(6)
+ assert.NoError(t, packages_model.SetRepositoryLink(db.DefaultContext, ap1.ID, privateRepoID))
+
+ req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s", user.Name, packageName, packageVersion)).AddTokenAuth(tokenReadPackage)
+ resp = MakeRequest(t, req, http.StatusOK)
+
+ var ap4 *api.Package
+ DecodeJSON(t, resp, &ap4)
+ assert.Nil(t, ap4.Repository)
+
+ assert.NoError(t, packages_model.UnlinkRepositoryFromAllPackages(db.DefaultContext, privateRepoID))
})
t.Run("ListPackageFiles", func(t *testing.T) {
@@ -152,11 +207,11 @@ func TestPackageAPI(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/packages/%s/dummy/%s/%s", user.Name, packageName, packageVersion)).
- AddTokenAuth(tokenDeletePackage)
+ AddTokenAuth(tokenWritePackage)
MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s", user.Name, packageName, packageVersion)).
- AddTokenAuth(tokenDeletePackage)
+ AddTokenAuth(tokenWritePackage)
MakeRequest(t, req, http.StatusNoContent)
})
}
@@ -384,7 +439,7 @@ func TestPackageAccess(t *testing.T) {
{limitedOrgNoMember, http.StatusOK},
{publicOrgNoMember, http.StatusOK},
} {
- req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s", target.Owner.Name)).
+ req := NewRequest(t, "GET", "/api/v1/packages/"+target.Owner.Name).
AddTokenAuth(tokenReadPackage)
MakeRequest(t, req, target.ExpectedStatus)
}
@@ -483,7 +538,7 @@ func TestPackageCleanup(t *testing.T) {
assert.NoError(t, err)
assert.NotEmpty(t, pbs)
- _, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, user.ID, packages_model.TypeContainer, "cleanup-test", container_model.UploadVersion)
+ _, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, user.ID, packages_model.TypeContainer, "cleanup-test", container_module.UploadVersion)
assert.NoError(t, err)
err = packages_cleanup_service.CleanupTask(db.DefaultContext, duration)
@@ -493,7 +548,7 @@ func TestPackageCleanup(t *testing.T) {
assert.NoError(t, err)
assert.Empty(t, pbs)
- _, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, user.ID, packages_model.TypeContainer, "cleanup-test", container_model.UploadVersion)
+ _, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, user.ID, packages_model.TypeContainer, "cleanup-test", container_module.UploadVersion)
assert.ErrorIs(t, err, packages_model.ErrPackageNotExist)
})
@@ -581,12 +636,16 @@ func TestPackageCleanup(t *testing.T) {
},
{
Name: "Mixed",
- Versions: []version{
- {Version: "keep", ShouldExist: true, Created: time.Now().Add(time.Duration(10000)).Unix()},
- {Version: "dummy", ShouldExist: true, Created: 1},
- {Version: "test-3", ShouldExist: true},
- {Version: "test-4", ShouldExist: false, Created: 1},
- },
+ Versions: func(limit, removeDays int) []version {
+ aa := []version{
+ {Version: "keep", ShouldExist: true, Created: time.Now().Add(time.Duration(10000)).Unix()},
+ {Version: "dummy", ShouldExist: true, Created: 1},
+ }
+ for i := range limit {
+ aa = append(aa, version{Version: fmt.Sprintf("test-%v", i+3), ShouldExist: util.Iif(i < removeDays, true, false), Created: time.Now().AddDate(0, 0, -i).Unix()})
+ }
+ return aa
+ }(220, 7),
Rule: &packages_model.PackageCleanupRule{
Enabled: true,
KeepCount: 1,
@@ -631,7 +690,7 @@ func TestPackageCleanup(t *testing.T) {
err = packages_service.DeletePackageVersionAndReferences(db.DefaultContext, pv)
assert.NoError(t, err)
} else {
- assert.ErrorIs(t, err, packages_model.ErrPackageNotExist)
+ assert.ErrorIs(t, err, packages_model.ErrPackageNotExist, v.Version)
}
}
diff --git a/tests/integration/api_packages_vagrant_test.go b/tests/integration/api_packages_vagrant_test.go
index a5e954f3a2..1743e37222 100644
--- a/tests/integration/api_packages_vagrant_test.go
+++ b/tests/integration/api_packages_vagrant_test.go
@@ -35,7 +35,7 @@ func TestPackageVagrant(t *testing.T) {
packageDescription := "Test Description"
packageProvider := "virtualbox"
- filename := fmt.Sprintf("%s.box", packageProvider)
+ filename := packageProvider + ".box"
infoContent, _ := json.Marshal(map[string]string{
"description": packageDescription,
@@ -59,7 +59,7 @@ func TestPackageVagrant(t *testing.T) {
t.Run("Authenticate", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- authenticateURL := fmt.Sprintf("%s/authenticate", root)
+ authenticateURL := root + "/authenticate"
req := NewRequest(t, "GET", authenticateURL)
MakeRequest(t, req, http.StatusUnauthorized)
diff --git a/tests/integration/api_private_serv_test.go b/tests/integration/api_private_serv_test.go
index 2001bb1fad..b0dd0cf049 100644
--- a/tests/integration/api_private_serv_test.go
+++ b/tests/integration/api_private_serv_test.go
@@ -17,7 +17,7 @@ import (
func TestAPIPrivateNoServ(t *testing.T) {
onGiteaRun(t, func(*testing.T, *url.URL) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := context.WithCancel(t.Context())
defer cancel()
key, user, err := private.ServNoCommand(ctx, 1)
assert.NoError(t, err)
@@ -39,7 +39,7 @@ func TestAPIPrivateNoServ(t *testing.T) {
func TestAPIPrivateServ(t *testing.T) {
onGiteaRun(t, func(*testing.T, *url.URL) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := context.WithCancel(t.Context())
defer cancel()
// Can push to a repo we own
diff --git a/tests/integration/api_pull_review_test.go b/tests/integration/api_pull_review_test.go
index b85882a510..1fc65ddea8 100644
--- a/tests/integration/api_pull_review_test.go
+++ b/tests/integration/api_pull_review_test.go
@@ -43,17 +43,17 @@ func TestAPIPullReview(t *testing.T) {
require.Len(t, reviews, 8)
for _, r := range reviews {
- assert.EqualValues(t, pullIssue.HTMLURL(), r.HTMLPullURL)
+ assert.Equal(t, pullIssue.HTMLURL(), r.HTMLPullURL)
}
assert.EqualValues(t, 8, reviews[3].ID)
assert.EqualValues(t, "APPROVED", reviews[3].State)
- assert.EqualValues(t, 0, reviews[3].CodeCommentsCount)
+ assert.Equal(t, 0, reviews[3].CodeCommentsCount)
assert.True(t, reviews[3].Stale)
assert.False(t, reviews[3].Official)
assert.EqualValues(t, 10, reviews[5].ID)
assert.EqualValues(t, "REQUEST_CHANGES", reviews[5].State)
- assert.EqualValues(t, 1, reviews[5].CodeCommentsCount)
+ assert.Equal(t, 1, reviews[5].CodeCommentsCount)
assert.EqualValues(t, -1, reviews[5].Reviewer.ID) // ghost user
assert.False(t, reviews[5].Stale)
assert.True(t, reviews[5].Official)
@@ -64,13 +64,13 @@ func TestAPIPullReview(t *testing.T) {
resp = MakeRequest(t, req, http.StatusOK)
var review api.PullReview
DecodeJSON(t, resp, &review)
- assert.EqualValues(t, *reviews[3], review)
+ assert.Equal(t, *reviews[3], review)
req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/pulls/%d/reviews/%d", repo.OwnerName, repo.Name, pullIssue.Index, reviews[5].ID).
AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &review)
- assert.EqualValues(t, *reviews[5], review)
+ assert.Equal(t, *reviews[5], review)
// test GetPullReviewComments
comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 7})
@@ -80,11 +80,11 @@ func TestAPIPullReview(t *testing.T) {
var reviewComments []*api.PullReviewComment
DecodeJSON(t, resp, &reviewComments)
assert.Len(t, reviewComments, 1)
- assert.EqualValues(t, "Ghost", reviewComments[0].Poster.UserName)
- assert.EqualValues(t, "a review from a deleted user", reviewComments[0].Body)
- assert.EqualValues(t, comment.ID, reviewComments[0].ID)
+ assert.Equal(t, "Ghost", reviewComments[0].Poster.UserName)
+ assert.Equal(t, "a review from a deleted user", reviewComments[0].Body)
+ assert.Equal(t, comment.ID, reviewComments[0].ID)
assert.EqualValues(t, comment.UpdatedUnix, reviewComments[0].Updated.Unix())
- assert.EqualValues(t, comment.HTMLURL(db.DefaultContext), reviewComments[0].HTMLURL)
+ assert.Equal(t, comment.HTMLURL(db.DefaultContext), reviewComments[0].HTMLURL)
// test CreatePullReview
req = NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d/reviews", repo.OwnerName, repo.Name, pullIssue.Index), &api.CreatePullReviewOptions{
@@ -113,7 +113,7 @@ func TestAPIPullReview(t *testing.T) {
DecodeJSON(t, resp, &review)
assert.EqualValues(t, 6, review.ID)
assert.EqualValues(t, "PENDING", review.State)
- assert.EqualValues(t, 3, review.CodeCommentsCount)
+ assert.Equal(t, 3, review.CodeCommentsCount)
// test SubmitPullReview
req = NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d/reviews/%d", repo.OwnerName, repo.Name, pullIssue.Index, review.ID), &api.SubmitPullReviewOptions{
@@ -124,7 +124,7 @@ func TestAPIPullReview(t *testing.T) {
DecodeJSON(t, resp, &review)
assert.EqualValues(t, 6, review.ID)
assert.EqualValues(t, "APPROVED", review.State)
- assert.EqualValues(t, 3, review.CodeCommentsCount)
+ assert.Equal(t, 3, review.CodeCommentsCount)
// test dismiss review
req = NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d/reviews/%d/dismissals", repo.OwnerName, repo.Name, pullIssue.Index, review.ID), &api.DismissPullReviewOptions{
@@ -151,7 +151,7 @@ func TestAPIPullReview(t *testing.T) {
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &review)
assert.EqualValues(t, "COMMENT", review.State)
- assert.EqualValues(t, 0, review.CodeCommentsCount)
+ assert.Equal(t, 0, review.CodeCommentsCount)
req = NewRequestf(t, http.MethodDelete, "/api/v1/repos/%s/%s/pulls/%d/reviews/%d", repo.OwnerName, repo.Name, pullIssue.Index, review.ID).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNoContent)
@@ -179,7 +179,7 @@ func TestAPIPullReview(t *testing.T) {
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &commentReview)
assert.EqualValues(t, "COMMENT", commentReview.State)
- assert.EqualValues(t, 2, commentReview.CodeCommentsCount)
+ assert.Equal(t, 2, commentReview.CodeCommentsCount)
assert.Empty(t, commentReview.Body)
assert.False(t, commentReview.Dismissed)
@@ -194,8 +194,8 @@ func TestAPIPullReview(t *testing.T) {
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &commentReview)
assert.EqualValues(t, "COMMENT", commentReview.State)
- assert.EqualValues(t, 0, commentReview.CodeCommentsCount)
- assert.EqualValues(t, commentBody, commentReview.Body)
+ assert.Equal(t, 0, commentReview.CodeCommentsCount)
+ assert.Equal(t, commentBody, commentReview.Body)
assert.False(t, commentReview.Dismissed)
// test CreatePullReview Comment without body and no comments
@@ -207,7 +207,7 @@ func TestAPIPullReview(t *testing.T) {
resp = MakeRequest(t, req, http.StatusUnprocessableEntity)
errMap := make(map[string]any)
json.Unmarshal(resp.Body.Bytes(), &errMap)
- assert.EqualValues(t, "review event COMMENT requires a body or a comment", errMap["message"].(string))
+ assert.Equal(t, "review event COMMENT requires a body or a comment", errMap["message"].(string))
// test get review requests
// to make it simple, use same api with get review
@@ -221,14 +221,14 @@ func TestAPIPullReview(t *testing.T) {
DecodeJSON(t, resp, &reviews)
assert.EqualValues(t, 11, reviews[0].ID)
assert.EqualValues(t, "REQUEST_REVIEW", reviews[0].State)
- assert.EqualValues(t, 0, reviews[0].CodeCommentsCount)
+ assert.Equal(t, 0, reviews[0].CodeCommentsCount)
assert.False(t, reviews[0].Stale)
assert.True(t, reviews[0].Official)
- assert.EqualValues(t, "test_team", reviews[0].ReviewerTeam.Name)
+ assert.Equal(t, "test_team", reviews[0].ReviewerTeam.Name)
assert.EqualValues(t, 12, reviews[1].ID)
assert.EqualValues(t, "REQUEST_REVIEW", reviews[1].State)
- assert.EqualValues(t, 0, reviews[0].CodeCommentsCount)
+ assert.Equal(t, 0, reviews[0].CodeCommentsCount)
assert.False(t, reviews[1].Stale)
assert.True(t, reviews[1].Official)
assert.EqualValues(t, 1, reviews[1].Reviewer.ID)
diff --git a/tests/integration/api_pull_test.go b/tests/integration/api_pull_test.go
index 969e110895..f2df6021e1 100644
--- a/tests/integration/api_pull_test.go
+++ b/tests/integration/api_pull_test.go
@@ -5,11 +5,13 @@ package integration
import (
"bytes"
- "context"
"fmt"
"io"
"net/http"
+ "net/url"
+ "strings"
"testing"
+ "time"
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
@@ -18,11 +20,15 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/convert"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/gitdiff"
issue_service "code.gitea.io/gitea/services/issue"
+ pull_service "code.gitea.io/gitea/services/pull"
+ files_service "code.gitea.io/gitea/services/repository/files"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
@@ -51,30 +57,30 @@ func TestAPIViewPulls(t *testing.T) {
assert.Empty(t, pull.RequestedReviewersTeams)
assert.EqualValues(t, 5, pull.RequestedReviewers[0].ID)
assert.EqualValues(t, 6, pull.RequestedReviewers[1].ID)
- assert.EqualValues(t, 1, pull.ChangedFiles)
if assert.EqualValues(t, 5, pull.ID) {
resp = ctx.Session.MakeRequest(t, NewRequest(t, "GET", pull.DiffURL), http.StatusOK)
bs, err := io.ReadAll(resp.Body)
assert.NoError(t, err)
- patch, err := gitdiff.ParsePatch(context.Background(), 1000, 5000, 10, bytes.NewReader(bs), "")
+ patch, err := gitdiff.ParsePatch(t.Context(), 1000, 5000, 10, bytes.NewReader(bs), "")
assert.NoError(t, err)
- if assert.Len(t, patch.Files, pull.ChangedFiles) {
+ if assert.Len(t, patch.Files, 1) {
assert.Equal(t, "File-WoW", patch.Files[0].Name)
// FIXME: The old name should be empty if it's a file add type
assert.Equal(t, "File-WoW", patch.Files[0].OldName)
- assert.EqualValues(t, pull.Additions, patch.Files[0].Addition)
- assert.EqualValues(t, pull.Deletions, patch.Files[0].Deletion)
+ assert.Equal(t, 1, patch.Files[0].Addition)
+ assert.Equal(t, 0, patch.Files[0].Deletion)
assert.Equal(t, gitdiff.DiffFileAdd, patch.Files[0].Type)
}
t.Run(fmt.Sprintf("APIGetPullFiles_%d", pull.ID),
doAPIGetPullFiles(ctx, pull, func(t *testing.T, files []*api.ChangedFile) {
- if assert.Len(t, files, pull.ChangedFiles) {
+ if assert.Len(t, files, 1) {
assert.Equal(t, "File-WoW", files[0].Filename)
assert.Empty(t, files[0].PreviousFilename)
- assert.EqualValues(t, pull.Additions, files[0].Additions)
- assert.EqualValues(t, pull.Deletions, files[0].Deletions)
+ assert.Equal(t, 1, files[0].Additions)
+ assert.Equal(t, 1, files[0].Changes)
+ assert.Equal(t, 0, files[0].Deletions)
assert.Equal(t, "added", files[0].Status)
}
}))
@@ -88,53 +94,51 @@ func TestAPIViewPulls(t *testing.T) {
assert.EqualValues(t, 4, pull.RequestedReviewers[1].ID)
assert.EqualValues(t, 2, pull.RequestedReviewers[2].ID)
assert.EqualValues(t, 5, pull.RequestedReviewers[3].ID)
- assert.EqualValues(t, 1, pull.ChangedFiles)
if assert.EqualValues(t, 2, pull.ID) {
resp = ctx.Session.MakeRequest(t, NewRequest(t, "GET", pull.DiffURL), http.StatusOK)
bs, err := io.ReadAll(resp.Body)
assert.NoError(t, err)
- patch, err := gitdiff.ParsePatch(context.Background(), 1000, 5000, 10, bytes.NewReader(bs), "")
+ patch, err := gitdiff.ParsePatch(t.Context(), 1000, 5000, 10, bytes.NewReader(bs), "")
assert.NoError(t, err)
- if assert.Len(t, patch.Files, pull.ChangedFiles) {
+ if assert.Len(t, patch.Files, 1) {
assert.Equal(t, "README.md", patch.Files[0].Name)
assert.Equal(t, "README.md", patch.Files[0].OldName)
- assert.EqualValues(t, pull.Additions, patch.Files[0].Addition)
- assert.EqualValues(t, pull.Deletions, patch.Files[0].Deletion)
+ assert.Equal(t, 4, patch.Files[0].Addition)
+ assert.Equal(t, 1, patch.Files[0].Deletion)
assert.Equal(t, gitdiff.DiffFileChange, patch.Files[0].Type)
}
t.Run(fmt.Sprintf("APIGetPullFiles_%d", pull.ID),
doAPIGetPullFiles(ctx, pull, func(t *testing.T, files []*api.ChangedFile) {
- if assert.Len(t, files, pull.ChangedFiles) {
+ if assert.Len(t, files, 1) {
assert.Equal(t, "README.md", files[0].Filename)
// FIXME: The PreviousFilename name should be the same as Filename if it's a file change
- assert.Equal(t, "", files[0].PreviousFilename)
- assert.EqualValues(t, pull.Additions, files[0].Additions)
- assert.EqualValues(t, pull.Deletions, files[0].Deletions)
+ assert.Empty(t, files[0].PreviousFilename)
+ assert.Equal(t, 4, files[0].Additions)
+ assert.Equal(t, 1, files[0].Deletions)
assert.Equal(t, "changed", files[0].Status)
}
}))
}
- pull = pulls[2]
+ pull = pulls[0]
assert.EqualValues(t, 1, pull.Poster.ID)
- assert.Len(t, pull.RequestedReviewers, 1)
+ assert.Len(t, pull.RequestedReviewers, 2)
assert.Empty(t, pull.RequestedReviewersTeams)
- assert.EqualValues(t, 1, pull.RequestedReviewers[0].ID)
- assert.EqualValues(t, 0, pull.ChangedFiles)
+ assert.EqualValues(t, 5, pull.RequestedReviewers[0].ID)
- if assert.EqualValues(t, 1, pull.ID) {
+ if assert.EqualValues(t, 5, pull.ID) {
resp = ctx.Session.MakeRequest(t, NewRequest(t, "GET", pull.DiffURL), http.StatusOK)
bs, err := io.ReadAll(resp.Body)
assert.NoError(t, err)
- patch, err := gitdiff.ParsePatch(context.Background(), 1000, 5000, 10, bytes.NewReader(bs), "")
+ patch, err := gitdiff.ParsePatch(t.Context(), 1000, 5000, 10, bytes.NewReader(bs), "")
assert.NoError(t, err)
- assert.EqualValues(t, pull.ChangedFiles, patch.NumFiles)
+ assert.Len(t, patch.Files, 1)
t.Run(fmt.Sprintf("APIGetPullFiles_%d", pull.ID),
doAPIGetPullFiles(ctx, pull, func(t *testing.T, files []*api.ChangedFile) {
- assert.Len(t, files, pull.ChangedFiles)
+ assert.Len(t, files, 1)
}))
}
}
@@ -196,7 +200,7 @@ func TestAPICreatePullSuccess(t *testing.T) {
session := loginUser(t, owner11.Name)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls", owner10.Name, repo10.Name), &api.CreatePullRequestOption{
- Head: fmt.Sprintf("%s:master", owner11.Name),
+ Head: owner11.Name + ":master",
Base: "master",
Title: "create a failure pr",
}).AddTokenAuth(token)
@@ -216,7 +220,7 @@ func TestAPICreatePullBasePermission(t *testing.T) {
session := loginUser(t, user4.Name)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
opts := &api.CreatePullRequestOption{
- Head: fmt.Sprintf("%s:master", repo11.OwnerName),
+ Head: repo11.OwnerName + ":master",
Base: "master",
Title: "create a failure pr",
}
@@ -244,7 +248,7 @@ func TestAPICreatePullHeadPermission(t *testing.T) {
session := loginUser(t, user4.Name)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
opts := &api.CreatePullRequestOption{
- Head: fmt.Sprintf("%s:master", repo11.OwnerName),
+ Head: repo11.OwnerName + ":master",
Base: "master",
Title: "create a failure pr",
}
@@ -272,7 +276,7 @@ func TestAPICreatePullSameRepoSuccess(t *testing.T) {
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls", owner.Name, repo.Name), &api.CreatePullRequestOption{
- Head: fmt.Sprintf("%s:pr-to-update", owner.Name),
+ Head: owner.Name + ":pr-to-update",
Base: "master",
Title: "successfully create a PR between branches of the same repository",
}).AddTokenAuth(token)
@@ -293,7 +297,7 @@ func TestAPICreatePullWithFieldsSuccess(t *testing.T) {
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
opts := &api.CreatePullRequestOption{
- Head: fmt.Sprintf("%s:master", owner11.Name),
+ Head: owner11.Name + ":master",
Base: "master",
Title: "create a failure pr",
Body: "foobaaar",
@@ -310,12 +314,12 @@ func TestAPICreatePullWithFieldsSuccess(t *testing.T) {
DecodeJSON(t, res, pull)
assert.NotNil(t, pull.Milestone)
- assert.EqualValues(t, opts.Milestone, pull.Milestone.ID)
+ assert.Equal(t, opts.Milestone, pull.Milestone.ID)
if assert.Len(t, pull.Assignees, 1) {
- assert.EqualValues(t, opts.Assignees[0], owner10.Name)
+ assert.Equal(t, opts.Assignees[0], owner10.Name)
}
assert.NotNil(t, pull.Labels)
- assert.EqualValues(t, opts.Labels[0], pull.Labels[0].ID)
+ assert.Equal(t, opts.Labels[0], pull.Labels[0].ID)
}
func TestAPICreatePullWithFieldsFailure(t *testing.T) {
@@ -331,7 +335,7 @@ func TestAPICreatePullWithFieldsFailure(t *testing.T) {
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
opts := &api.CreatePullRequestOption{
- Head: fmt.Sprintf("%s:master", owner11.Name),
+ Head: owner11.Name + ":master",
Base: "master",
}
@@ -369,7 +373,7 @@ func TestAPIEditPull(t *testing.T) {
apiPull := new(api.PullRequest)
resp := MakeRequest(t, req, http.StatusCreated)
DecodeJSON(t, resp, apiPull)
- assert.EqualValues(t, "master", apiPull.Base.Name)
+ assert.Equal(t, "master", apiPull.Base.Name)
newTitle := "edit a this pr"
newBody := "edited body"
@@ -380,7 +384,7 @@ func TestAPIEditPull(t *testing.T) {
}).AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusCreated)
DecodeJSON(t, resp, apiPull)
- assert.EqualValues(t, "feature/1", apiPull.Base.Name)
+ assert.Equal(t, "feature/1", apiPull.Base.Name)
// check comment history
pull := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: apiPull.ID})
err := pull.LoadIssue(db.DefaultContext)
@@ -427,3 +431,94 @@ func TestAPICommitPullRequest(t *testing.T) {
req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/commits/%s/pull", owner.Name, repo.Name, invalidCommitSHA).AddTokenAuth(ctx.Token)
ctx.Session.MakeRequest(t, req, http.StatusNotFound)
}
+
+func TestAPIViewPullFilesWithHeadRepoDeleted(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ baseRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
+ user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
+
+ ctx := NewAPITestContext(t, "user1", baseRepo.Name, auth_model.AccessTokenScopeAll)
+
+ doAPIForkRepository(ctx, "user2")(t)
+
+ forkedRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ForkID: baseRepo.ID, OwnerName: "user1"})
+
+ // add a new file to the forked repo
+ addFileToForkedResp, err := files_service.ChangeRepoFiles(git.DefaultContext, forkedRepo, user1, &files_service.ChangeRepoFilesOptions{
+ Files: []*files_service.ChangeRepoFile{
+ {
+ Operation: "create",
+ TreePath: "file_1.txt",
+ ContentReader: strings.NewReader("file1"),
+ },
+ },
+ Message: "add file1",
+ OldBranch: "master",
+ NewBranch: "fork-branch-1",
+ Author: &files_service.IdentityOptions{
+ GitUserName: user1.Name,
+ GitUserEmail: user1.Email,
+ },
+ Committer: &files_service.IdentityOptions{
+ GitUserName: user1.Name,
+ GitUserEmail: user1.Email,
+ },
+ Dates: &files_service.CommitDateOptions{
+ Author: time.Now(),
+ Committer: time.Now(),
+ },
+ })
+ assert.NoError(t, err)
+ assert.NotEmpty(t, addFileToForkedResp)
+
+ // create Pull
+ pullIssue := &issues_model.Issue{
+ RepoID: baseRepo.ID,
+ Title: "Test pull-request-target-event",
+ PosterID: user1.ID,
+ Poster: user1,
+ IsPull: true,
+ }
+ pullRequest := &issues_model.PullRequest{
+ HeadRepoID: forkedRepo.ID,
+ BaseRepoID: baseRepo.ID,
+ HeadBranch: "fork-branch-1",
+ BaseBranch: "master",
+ HeadRepo: forkedRepo,
+ BaseRepo: baseRepo,
+ Type: issues_model.PullRequestGitea,
+ }
+
+ prOpts := &pull_service.NewPullRequestOptions{Repo: baseRepo, Issue: pullIssue, PullRequest: pullRequest}
+ err = pull_service.NewPullRequest(git.DefaultContext, prOpts)
+ assert.NoError(t, err)
+ pr := convert.ToAPIPullRequest(t.Context(), pullRequest, user1)
+
+ ctx = NewAPITestContext(t, "user2", baseRepo.Name, auth_model.AccessTokenScopeAll)
+ doAPIGetPullFiles(ctx, pr, func(t *testing.T, files []*api.ChangedFile) {
+ if assert.Len(t, files, 1) {
+ assert.Equal(t, "file_1.txt", files[0].Filename)
+ assert.Empty(t, files[0].PreviousFilename)
+ assert.Equal(t, 1, files[0].Additions)
+ assert.Equal(t, 1, files[0].Changes)
+ assert.Equal(t, 0, files[0].Deletions)
+ assert.Equal(t, "added", files[0].Status)
+ }
+ })(t)
+
+ // delete the head repository of the pull request
+ forkCtx := NewAPITestContext(t, "user1", forkedRepo.Name, auth_model.AccessTokenScopeAll)
+ doAPIDeleteRepository(forkCtx)(t)
+
+ doAPIGetPullFiles(ctx, pr, func(t *testing.T, files []*api.ChangedFile) {
+ if assert.Len(t, files, 1) {
+ assert.Equal(t, "file_1.txt", files[0].Filename)
+ assert.Empty(t, files[0].PreviousFilename)
+ assert.Equal(t, 1, files[0].Additions)
+ assert.Equal(t, 1, files[0].Changes)
+ assert.Equal(t, 0, files[0].Deletions)
+ assert.Equal(t, "added", files[0].Status)
+ }
+ })(t)
+ })
+}
diff --git a/tests/integration/api_releases_test.go b/tests/integration/api_releases_test.go
index b3d4928b7b..a3dbc0363b 100644
--- a/tests/integration/api_releases_test.go
+++ b/tests/integration/api_releases_test.go
@@ -97,7 +97,7 @@ func createNewReleaseUsingAPI(t *testing.T, token string, owner *user_model.User
Title: newRelease.Title,
}
unittest.AssertExistsAndLoadBean(t, rel)
- assert.EqualValues(t, newRelease.Note, rel.Note)
+ assert.Equal(t, newRelease.Note, rel.Note)
return &newRelease
}
@@ -151,7 +151,7 @@ func TestAPICreateAndUpdateRelease(t *testing.T) {
Title: newRelease.Title,
}
unittest.AssertExistsAndLoadBean(t, rel)
- assert.EqualValues(t, rel.Note, newRelease.Note)
+ assert.Equal(t, rel.Note, newRelease.Note)
}
func TestAPICreateProtectedTagRelease(t *testing.T) {
@@ -329,7 +329,7 @@ func TestAPIUploadAssetRelease(t *testing.T) {
var attachment *api.Attachment
DecodeJSON(t, resp, &attachment)
- assert.EqualValues(t, filename, attachment.Name)
+ assert.Equal(t, filename, attachment.Name)
assert.EqualValues(t, 104, attachment.Size)
req = NewRequestWithBody(t, http.MethodPost, assetURL+"?name=test-asset", bytes.NewReader(body.Bytes())).
@@ -340,7 +340,7 @@ func TestAPIUploadAssetRelease(t *testing.T) {
var attachment2 *api.Attachment
DecodeJSON(t, resp, &attachment2)
- assert.EqualValues(t, "test-asset", attachment2.Name)
+ assert.Equal(t, "test-asset", attachment2.Name)
assert.EqualValues(t, 104, attachment2.Size)
})
@@ -358,7 +358,7 @@ func TestAPIUploadAssetRelease(t *testing.T) {
var attachment *api.Attachment
DecodeJSON(t, resp, &attachment)
- assert.EqualValues(t, "stream.bin", attachment.Name)
+ assert.Equal(t, "stream.bin", attachment.Name)
assert.EqualValues(t, 104, attachment.Size)
})
}
diff --git a/tests/integration/api_repo_archive_test.go b/tests/integration/api_repo_archive_test.go
index 8589199da3..97c2c0d54b 100644
--- a/tests/integration/api_repo_archive_test.go
+++ b/tests/integration/api_repo_archive_test.go
@@ -12,7 +12,9 @@ import (
"testing"
auth_model "code.gitea.io/gitea/models/auth"
+ "code.gitea.io/gitea/models/perm"
repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/tests"
@@ -48,7 +50,7 @@ func TestAPIDownloadArchive(t *testing.T) {
bs2, err := io.ReadAll(resp.Body)
assert.NoError(t, err)
// The locked URL should give the same bytes as the non-locked one
- assert.EqualValues(t, bs, bs2)
+ assert.Equal(t, bs, bs2)
link, _ = url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/archive/master.bundle", user2.Name, repo.Name))
resp = MakeRequest(t, NewRequest(t, "GET", link.String()).AddTokenAuth(token), http.StatusOK)
@@ -58,9 +60,12 @@ func TestAPIDownloadArchive(t *testing.T) {
link, _ = url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/archive/master", user2.Name, repo.Name))
MakeRequest(t, NewRequest(t, "GET", link.String()).AddTokenAuth(token), http.StatusBadRequest)
+
+ t.Run("GitHubStyle", testAPIDownloadArchiveGitHubStyle)
+ t.Run("PrivateRepo", testAPIDownloadArchivePrivateRepo)
}
-func TestAPIDownloadArchive2(t *testing.T) {
+func testAPIDownloadArchiveGitHubStyle(t *testing.T) {
defer tests.PrepareTestEnv(t)()
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
@@ -88,14 +93,20 @@ func TestAPIDownloadArchive2(t *testing.T) {
bs2, err := io.ReadAll(resp.Body)
assert.NoError(t, err)
// The locked URL should give the same bytes as the non-locked one
- assert.EqualValues(t, bs, bs2)
+ assert.Equal(t, bs, bs2)
link, _ = url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/bundle/master", user2.Name, repo.Name))
resp = MakeRequest(t, NewRequest(t, "GET", link.String()).AddTokenAuth(token), http.StatusOK)
bs, err = io.ReadAll(resp.Body)
assert.NoError(t, err)
assert.Len(t, bs, 382)
+}
- link, _ = url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/archive/master", user2.Name, repo.Name))
- MakeRequest(t, NewRequest(t, "GET", link.String()).AddTokenAuth(token), http.StatusBadRequest)
+func testAPIDownloadArchivePrivateRepo(t *testing.T) {
+ _ = repo_model.UpdateRepositoryColsNoAutoTime(t.Context(), &repo_model.Repository{ID: 1, IsPrivate: true}, "is_private")
+ MakeRequest(t, NewRequest(t, "HEAD", "/api/v1/repos/user2/repo1/archive/master.zip"), http.StatusNotFound)
+ MakeRequest(t, NewRequest(t, "HEAD", "/api/v1/repos/user2/repo1/zipball/master"), http.StatusNotFound)
+ _ = repo_model.UpdateRepoUnitPublicAccess(t.Context(), &repo_model.RepoUnit{RepoID: 1, Type: unit.TypeCode, AnonymousAccessMode: perm.AccessModeRead})
+ MakeRequest(t, NewRequest(t, "HEAD", "/api/v1/repos/user2/repo1/archive/master.zip"), http.StatusOK)
+ MakeRequest(t, NewRequest(t, "HEAD", "/api/v1/repos/user2/repo1/zipball/master"), http.StatusOK)
}
diff --git a/tests/integration/api_repo_branch_test.go b/tests/integration/api_repo_branch_test.go
index 63080b308c..066eb366b1 100644
--- a/tests/integration/api_repo_branch_test.go
+++ b/tests/integration/api_repo_branch_test.go
@@ -4,11 +4,11 @@
package integration
import (
- "bytes"
"fmt"
"io"
"net/http"
"net/url"
+ "strings"
"testing"
auth_model "code.gitea.io/gitea/models/auth"
@@ -42,8 +42,8 @@ func TestAPIRepoBranchesPlain(t *testing.T) {
var branches []*api.Branch
assert.NoError(t, json.Unmarshal(bs, &branches))
assert.Len(t, branches, 2)
- assert.EqualValues(t, "test_branch", branches[0].Name)
- assert.EqualValues(t, "master", branches[1].Name)
+ assert.Equal(t, "test_branch", branches[0].Name)
+ assert.Equal(t, "master", branches[1].Name)
link2, _ := url.Parse(fmt.Sprintf("/api/v1/repos/org3/%s/branches/test_branch", repo3.Name))
MakeRequest(t, NewRequest(t, "GET", link2.String()).AddTokenAuth(publicOnlyToken), http.StatusForbidden)
@@ -53,20 +53,20 @@ func TestAPIRepoBranchesPlain(t *testing.T) {
assert.NoError(t, err)
var branch api.Branch
assert.NoError(t, json.Unmarshal(bs, &branch))
- assert.EqualValues(t, "test_branch", branch.Name)
+ assert.Equal(t, "test_branch", branch.Name)
MakeRequest(t, NewRequest(t, "POST", link.String()).AddTokenAuth(publicOnlyToken), http.StatusForbidden)
req := NewRequest(t, "POST", link.String()).AddTokenAuth(token)
req.Header.Add("Content-Type", "application/json")
- req.Body = io.NopCloser(bytes.NewBufferString(`{"new_branch_name":"test_branch2", "old_branch_name": "test_branch", "old_ref_name":"refs/heads/test_branch"}`))
+ req.Body = io.NopCloser(strings.NewReader(`{"new_branch_name":"test_branch2", "old_branch_name": "test_branch", "old_ref_name":"refs/heads/test_branch"}`))
resp = MakeRequest(t, req, http.StatusCreated)
bs, err = io.ReadAll(resp.Body)
assert.NoError(t, err)
var branch2 api.Branch
assert.NoError(t, json.Unmarshal(bs, &branch2))
- assert.EqualValues(t, "test_branch2", branch2.Name)
- assert.EqualValues(t, branch.Commit.ID, branch2.Commit.ID)
+ assert.Equal(t, "test_branch2", branch2.Name)
+ assert.Equal(t, branch.Commit.ID, branch2.Commit.ID)
resp = MakeRequest(t, NewRequest(t, "GET", link.String()).AddTokenAuth(token), http.StatusOK)
bs, err = io.ReadAll(resp.Body)
@@ -75,9 +75,9 @@ func TestAPIRepoBranchesPlain(t *testing.T) {
branches = []*api.Branch{}
assert.NoError(t, json.Unmarshal(bs, &branches))
assert.Len(t, branches, 3)
- assert.EqualValues(t, "test_branch", branches[0].Name)
- assert.EqualValues(t, "test_branch2", branches[1].Name)
- assert.EqualValues(t, "master", branches[2].Name)
+ assert.Equal(t, "test_branch", branches[0].Name)
+ assert.Equal(t, "test_branch2", branches[1].Name)
+ assert.Equal(t, "master", branches[2].Name)
link3, _ := url.Parse(fmt.Sprintf("/api/v1/repos/org3/%s/branches/test_branch2", repo3.Name))
MakeRequest(t, NewRequest(t, "DELETE", link3.String()), http.StatusNotFound)
@@ -104,8 +104,8 @@ func TestAPIRepoBranchesMirror(t *testing.T) {
var branches []*api.Branch
assert.NoError(t, json.Unmarshal(bs, &branches))
assert.Len(t, branches, 2)
- assert.EqualValues(t, "test_branch", branches[0].Name)
- assert.EqualValues(t, "master", branches[1].Name)
+ assert.Equal(t, "test_branch", branches[0].Name)
+ assert.Equal(t, "master", branches[1].Name)
link2, _ := url.Parse(fmt.Sprintf("/api/v1/repos/org3/%s/branches/test_branch", repo5.Name))
resp = MakeRequest(t, NewRequest(t, "GET", link2.String()).AddTokenAuth(token), http.StatusOK)
@@ -113,18 +113,18 @@ func TestAPIRepoBranchesMirror(t *testing.T) {
assert.NoError(t, err)
var branch api.Branch
assert.NoError(t, json.Unmarshal(bs, &branch))
- assert.EqualValues(t, "test_branch", branch.Name)
+ assert.Equal(t, "test_branch", branch.Name)
req := NewRequest(t, "POST", link.String()).AddTokenAuth(token)
req.Header.Add("Content-Type", "application/json")
- req.Body = io.NopCloser(bytes.NewBufferString(`{"new_branch_name":"test_branch2", "old_branch_name": "test_branch", "old_ref_name":"refs/heads/test_branch"}`))
+ req.Body = io.NopCloser(strings.NewReader(`{"new_branch_name":"test_branch2", "old_branch_name": "test_branch", "old_ref_name":"refs/heads/test_branch"}`))
resp = MakeRequest(t, req, http.StatusForbidden)
bs, err = io.ReadAll(resp.Body)
assert.NoError(t, err)
- assert.EqualValues(t, "{\"message\":\"Git Repository is a mirror.\",\"url\":\""+setting.AppURL+"api/swagger\"}\n", string(bs))
+ assert.Equal(t, "{\"message\":\"Git Repository is a mirror.\",\"url\":\""+setting.AppURL+"api/swagger\"}\n", string(bs))
resp = MakeRequest(t, NewRequest(t, "DELETE", link2.String()).AddTokenAuth(token), http.StatusForbidden)
bs, err = io.ReadAll(resp.Body)
assert.NoError(t, err)
- assert.EqualValues(t, "{\"message\":\"Git Repository is a mirror.\",\"url\":\""+setting.AppURL+"api/swagger\"}\n", string(bs))
+ assert.Equal(t, "{\"message\":\"Git Repository is a mirror.\",\"url\":\""+setting.AppURL+"api/swagger\"}\n", string(bs))
}
diff --git a/tests/integration/api_repo_collaborator_test.go b/tests/integration/api_repo_collaborator_test.go
index 463db1dfb1..11e2924e84 100644
--- a/tests/integration/api_repo_collaborator_test.go
+++ b/tests/integration/api_repo_collaborator_test.go
@@ -5,7 +5,6 @@ package integration
import (
"net/http"
- "net/url"
"testing"
auth_model "code.gitea.io/gitea/models/auth"
@@ -14,132 +13,145 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
)
func TestAPIRepoCollaboratorPermission(t *testing.T) {
- onGiteaRun(t, func(t *testing.T, u *url.URL) {
- repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
- repo2Owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo2.OwnerID})
+ defer tests.PrepareTestEnv(t)()
+ repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
+ repo2Owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo2.OwnerID})
- user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
- user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
- user10 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 10})
- user11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 11})
- user34 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 34})
+ user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
+ user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
+ user10 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 10})
+ user11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 11})
+ user34 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 34})
- testCtx := NewAPITestContext(t, repo2Owner.Name, repo2.Name, auth_model.AccessTokenScopeWriteRepository)
+ testCtx := NewAPITestContext(t, repo2Owner.Name, repo2.Name, auth_model.AccessTokenScopeWriteRepository)
- t.Run("RepoOwnerShouldBeOwner", func(t *testing.T) {
- req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, repo2Owner.Name).
- AddTokenAuth(testCtx.Token)
- resp := MakeRequest(t, req, http.StatusOK)
+ t.Run("RepoOwnerShouldBeOwner", func(t *testing.T) {
+ req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, repo2Owner.Name).
+ AddTokenAuth(testCtx.Token)
+ resp := MakeRequest(t, req, http.StatusOK)
- var repoPermission api.RepoCollaboratorPermission
- DecodeJSON(t, resp, &repoPermission)
+ var repoPermission api.RepoCollaboratorPermission
+ DecodeJSON(t, resp, &repoPermission)
- assert.Equal(t, "owner", repoPermission.Permission)
- })
+ assert.Equal(t, "owner", repoPermission.Permission)
+ })
- t.Run("CollaboratorWithReadAccess", func(t *testing.T) {
- t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user4.Name, perm.AccessModeRead))
+ t.Run("CollaboratorWithReadAccess", func(t *testing.T) {
+ t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user4.Name, perm.AccessModeRead))
- req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, user4.Name).
- AddTokenAuth(testCtx.Token)
- resp := MakeRequest(t, req, http.StatusOK)
+ req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, user4.Name).
+ AddTokenAuth(testCtx.Token)
+ resp := MakeRequest(t, req, http.StatusOK)
- var repoPermission api.RepoCollaboratorPermission
- DecodeJSON(t, resp, &repoPermission)
+ var repoPermission api.RepoCollaboratorPermission
+ DecodeJSON(t, resp, &repoPermission)
- assert.Equal(t, "read", repoPermission.Permission)
- })
+ assert.Equal(t, "read", repoPermission.Permission)
+ })
- t.Run("CollaboratorWithWriteAccess", func(t *testing.T) {
- t.Run("AddUserAsCollaboratorWithWriteAccess", doAPIAddCollaborator(testCtx, user4.Name, perm.AccessModeWrite))
+ t.Run("CollaboratorWithWriteAccess", func(t *testing.T) {
+ t.Run("AddUserAsCollaboratorWithWriteAccess", doAPIAddCollaborator(testCtx, user4.Name, perm.AccessModeWrite))
- req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, user4.Name).
- AddTokenAuth(testCtx.Token)
- resp := MakeRequest(t, req, http.StatusOK)
+ req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, user4.Name).
+ AddTokenAuth(testCtx.Token)
+ resp := MakeRequest(t, req, http.StatusOK)
- var repoPermission api.RepoCollaboratorPermission
- DecodeJSON(t, resp, &repoPermission)
+ var repoPermission api.RepoCollaboratorPermission
+ DecodeJSON(t, resp, &repoPermission)
- assert.Equal(t, "write", repoPermission.Permission)
- })
+ assert.Equal(t, "write", repoPermission.Permission)
+ })
- t.Run("CollaboratorWithAdminAccess", func(t *testing.T) {
- t.Run("AddUserAsCollaboratorWithAdminAccess", doAPIAddCollaborator(testCtx, user4.Name, perm.AccessModeAdmin))
+ t.Run("CollaboratorWithAdminAccess", func(t *testing.T) {
+ t.Run("AddUserAsCollaboratorWithAdminAccess", doAPIAddCollaborator(testCtx, user4.Name, perm.AccessModeAdmin))
- req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, user4.Name).
- AddTokenAuth(testCtx.Token)
- resp := MakeRequest(t, req, http.StatusOK)
+ req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, user4.Name).
+ AddTokenAuth(testCtx.Token)
+ resp := MakeRequest(t, req, http.StatusOK)
- var repoPermission api.RepoCollaboratorPermission
- DecodeJSON(t, resp, &repoPermission)
+ var repoPermission api.RepoCollaboratorPermission
+ DecodeJSON(t, resp, &repoPermission)
- assert.Equal(t, "admin", repoPermission.Permission)
- })
+ assert.Equal(t, "admin", repoPermission.Permission)
+ })
- t.Run("CollaboratorNotFound", func(t *testing.T) {
- req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, "non-existent-user").
- AddTokenAuth(testCtx.Token)
- MakeRequest(t, req, http.StatusNotFound)
- })
+ t.Run("CollaboratorNotFound", func(t *testing.T) {
+ req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, "non-existent-user").
+ AddTokenAuth(testCtx.Token)
+ MakeRequest(t, req, http.StatusNotFound)
+ })
- t.Run("CollaboratorBlocked", func(t *testing.T) {
- ctx := NewAPITestContext(t, repo2Owner.Name, repo2.Name, auth_model.AccessTokenScopeWriteRepository)
- ctx.ExpectedCode = http.StatusForbidden
- doAPIAddCollaborator(ctx, user34.Name, perm.AccessModeAdmin)(t)
- })
+ t.Run("CollaboratorBlocked", func(t *testing.T) {
+ ctx := NewAPITestContext(t, repo2Owner.Name, repo2.Name, auth_model.AccessTokenScopeWriteRepository)
+ ctx.ExpectedCode = http.StatusForbidden
+ doAPIAddCollaborator(ctx, user34.Name, perm.AccessModeAdmin)(t)
+ })
+
+ t.Run("CollaboratorCanQueryItsPermissions", func(t *testing.T) {
+ t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user5.Name, perm.AccessModeRead))
+
+ _session := loginUser(t, user5.Name)
+ _testCtx := NewAPITestContext(t, user5.Name, repo2.Name, auth_model.AccessTokenScopeReadRepository)
+
+ req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, user5.Name).
+ AddTokenAuth(_testCtx.Token)
+ resp := _session.MakeRequest(t, req, http.StatusOK)
- t.Run("CollaboratorCanQueryItsPermissions", func(t *testing.T) {
- t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user5.Name, perm.AccessModeRead))
+ var repoPermission api.RepoCollaboratorPermission
+ DecodeJSON(t, resp, &repoPermission)
- _session := loginUser(t, user5.Name)
- _testCtx := NewAPITestContext(t, user5.Name, repo2.Name, auth_model.AccessTokenScopeReadRepository)
+ assert.Equal(t, "read", repoPermission.Permission)
- req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, user5.Name).
- AddTokenAuth(_testCtx.Token)
- resp := _session.MakeRequest(t, req, http.StatusOK)
+ t.Run("CollaboratorCanReadOwnPermission", func(t *testing.T) {
+ session := loginUser(t, user5.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
- var repoPermission api.RepoCollaboratorPermission
- DecodeJSON(t, resp, &repoPermission)
+ req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, user5.Name).AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
- assert.Equal(t, "read", repoPermission.Permission)
+ repoCollPerm := api.RepoCollaboratorPermission{}
+ DecodeJSON(t, resp, &repoCollPerm)
+
+ assert.Equal(t, "read", repoCollPerm.Permission)
})
+ })
- t.Run("CollaboratorCanQueryItsPermissions", func(t *testing.T) {
- t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user5.Name, perm.AccessModeRead))
+ t.Run("CollaboratorCanQueryItsPermissions", func(t *testing.T) {
+ t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user5.Name, perm.AccessModeRead))
- _session := loginUser(t, user5.Name)
- _testCtx := NewAPITestContext(t, user5.Name, repo2.Name, auth_model.AccessTokenScopeReadRepository)
+ _session := loginUser(t, user5.Name)
+ _testCtx := NewAPITestContext(t, user5.Name, repo2.Name, auth_model.AccessTokenScopeReadRepository)
- req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, user5.Name).
- AddTokenAuth(_testCtx.Token)
- resp := _session.MakeRequest(t, req, http.StatusOK)
+ req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, user5.Name).
+ AddTokenAuth(_testCtx.Token)
+ resp := _session.MakeRequest(t, req, http.StatusOK)
- var repoPermission api.RepoCollaboratorPermission
- DecodeJSON(t, resp, &repoPermission)
+ var repoPermission api.RepoCollaboratorPermission
+ DecodeJSON(t, resp, &repoPermission)
- assert.Equal(t, "read", repoPermission.Permission)
- })
+ assert.Equal(t, "read", repoPermission.Permission)
+ })
- t.Run("RepoAdminCanQueryACollaboratorsPermissions", func(t *testing.T) {
- t.Run("AddUserAsCollaboratorWithAdminAccess", doAPIAddCollaborator(testCtx, user10.Name, perm.AccessModeAdmin))
- t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user11.Name, perm.AccessModeRead))
+ t.Run("RepoAdminCanQueryACollaboratorsPermissions", func(t *testing.T) {
+ t.Run("AddUserAsCollaboratorWithAdminAccess", doAPIAddCollaborator(testCtx, user10.Name, perm.AccessModeAdmin))
+ t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user11.Name, perm.AccessModeRead))
- _session := loginUser(t, user10.Name)
- _testCtx := NewAPITestContext(t, user10.Name, repo2.Name, auth_model.AccessTokenScopeReadRepository)
+ _session := loginUser(t, user10.Name)
+ _testCtx := NewAPITestContext(t, user10.Name, repo2.Name, auth_model.AccessTokenScopeReadRepository)
- req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, user11.Name).
- AddTokenAuth(_testCtx.Token)
- resp := _session.MakeRequest(t, req, http.StatusOK)
+ req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, user11.Name).
+ AddTokenAuth(_testCtx.Token)
+ resp := _session.MakeRequest(t, req, http.StatusOK)
- var repoPermission api.RepoCollaboratorPermission
- DecodeJSON(t, resp, &repoPermission)
+ var repoPermission api.RepoCollaboratorPermission
+ DecodeJSON(t, resp, &repoPermission)
- assert.Equal(t, "read", repoPermission.Permission)
- })
+ assert.Equal(t, "read", repoPermission.Permission)
})
}
diff --git a/tests/integration/api_repo_file_create_test.go b/tests/integration/api_repo_file_create_test.go
index 41ad7211ff..af3bc54680 100644
--- a/tests/integration/api_repo_file_create_test.go
+++ b/tests/integration/api_repo_file_create_test.go
@@ -4,12 +4,11 @@
package integration
import (
- stdCtx "context"
"encoding/base64"
"fmt"
"net/http"
"net/url"
- "path/filepath"
+ "path"
"testing"
"time"
@@ -20,6 +19,7 @@ import (
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/context"
"github.com/stretchr/testify/assert"
@@ -50,28 +50,42 @@ func getCreateFileOptions() api.CreateFileOptions {
}
}
-func getExpectedFileResponseForCreate(repoFullName, commitID, treePath, latestCommitSHA string) *api.FileResponse {
+func normalizeFileContentResponseCommitTime(c *api.ContentsResponse) {
+ // decoded JSON response may contain different timezone from the one parsed by git commit
+ // so we need to normalize the time to UTC to make "assert.Equal" pass
+ c.LastCommitterDate = util.ToPointer(c.LastCommitterDate.UTC())
+ c.LastAuthorDate = util.ToPointer(c.LastAuthorDate.UTC())
+}
+
+type apiFileResponseInfo struct {
+ repoFullName, commitID, treePath, lastCommitSHA string
+ lastCommitterWhen, lastAuthorWhen time.Time
+}
+
+func getExpectedFileResponseForCreate(info apiFileResponseInfo) *api.FileResponse {
sha := "a635aa942442ddfdba07468cf9661c08fbdf0ebf"
encoding := "base64"
content := "VGhpcyBpcyBuZXcgdGV4dA=="
- selfURL := setting.AppURL + "api/v1/repos/" + repoFullName + "/contents/" + treePath + "?ref=master"
- htmlURL := setting.AppURL + repoFullName + "/src/branch/master/" + treePath
- gitURL := setting.AppURL + "api/v1/repos/" + repoFullName + "/git/blobs/" + sha
- downloadURL := setting.AppURL + repoFullName + "/raw/branch/master/" + treePath
- return &api.FileResponse{
+ selfURL := setting.AppURL + "api/v1/repos/" + info.repoFullName + "/contents/" + info.treePath + "?ref=master"
+ htmlURL := setting.AppURL + info.repoFullName + "/src/branch/master/" + info.treePath
+ gitURL := setting.AppURL + "api/v1/repos/" + info.repoFullName + "/git/blobs/" + sha
+ downloadURL := setting.AppURL + info.repoFullName + "/raw/branch/master/" + info.treePath
+ ret := &api.FileResponse{
Content: &api.ContentsResponse{
- Name: filepath.Base(treePath),
- Path: treePath,
- SHA: sha,
- LastCommitSHA: latestCommitSHA,
- Size: 16,
- Type: "file",
- Encoding: &encoding,
- Content: &content,
- URL: &selfURL,
- HTMLURL: &htmlURL,
- GitURL: &gitURL,
- DownloadURL: &downloadURL,
+ Name: path.Base(info.treePath),
+ Path: info.treePath,
+ SHA: sha,
+ LastCommitSHA: util.ToPointer(info.lastCommitSHA),
+ LastCommitterDate: util.ToPointer(info.lastCommitterWhen),
+ LastAuthorDate: util.ToPointer(info.lastAuthorWhen),
+ Size: 16,
+ Type: "file",
+ Encoding: &encoding,
+ Content: &content,
+ URL: &selfURL,
+ HTMLURL: &htmlURL,
+ GitURL: &gitURL,
+ DownloadURL: &downloadURL,
Links: &api.FileLinksResponse{
Self: &selfURL,
GitURL: &gitURL,
@@ -80,10 +94,10 @@ func getExpectedFileResponseForCreate(repoFullName, commitID, treePath, latestCo
},
Commit: &api.FileCommitResponse{
CommitMeta: api.CommitMeta{
- URL: setting.AppURL + "api/v1/repos/" + repoFullName + "/git/commits/" + commitID,
- SHA: commitID,
+ URL: setting.AppURL + "api/v1/repos/" + info.repoFullName + "/git/commits/" + info.commitID,
+ SHA: info.commitID,
},
- HTMLURL: setting.AppURL + repoFullName + "/commit/" + commitID,
+ HTMLURL: setting.AppURL + info.repoFullName + "/commit/" + info.commitID,
Author: &api.CommitUser{
Identity: api.Identity{
Name: "Anne Doe",
@@ -107,6 +121,8 @@ func getExpectedFileResponseForCreate(repoFullName, commitID, treePath, latestCo
Payload: "",
},
}
+ normalizeFileContentResponseCommitTime(ret.Content)
+ return ret
}
func BenchmarkAPICreateFileSmall(b *testing.B) {
@@ -115,7 +131,7 @@ func BenchmarkAPICreateFileSmall(b *testing.B) {
repo1 := unittest.AssertExistsAndLoadBean(b, &repo_model.Repository{ID: 1}) // public repo
b.ResetTimer()
- for n := 0; n < b.N; n++ {
+ for n := 0; b.Loop(); n++ {
treePath := fmt.Sprintf("update/file%d.txt", n)
_, _ = createFileInBranch(user2, repo1, treePath, repo1.DefaultBranch, treePath)
}
@@ -130,7 +146,7 @@ func BenchmarkAPICreateFileMedium(b *testing.B) {
repo1 := unittest.AssertExistsAndLoadBean(b, &repo_model.Repository{ID: 1}) // public repo
b.ResetTimer()
- for n := 0; n < b.N; n++ {
+ for n := 0; b.Loop(); n++ {
treePath := fmt.Sprintf("update/file%d.txt", n)
copy(data, treePath)
_, _ = createFileInBranch(user2, repo1, treePath, repo1.DefaultBranch, treePath)
@@ -167,22 +183,30 @@ func TestAPICreateFile(t *testing.T) {
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user2.Name, repo1.Name, treePath), &createFileOptions).
AddTokenAuth(token2)
resp := MakeRequest(t, req, http.StatusCreated)
- gitRepo, _ := gitrepo.OpenRepository(stdCtx.Background(), repo1)
+ gitRepo, _ := gitrepo.OpenRepository(t.Context(), repo1)
+ defer gitRepo.Close()
commitID, _ := gitRepo.GetBranchCommitID(createFileOptions.NewBranchName)
- latestCommit, _ := gitRepo.GetCommitByPath(treePath)
- expectedFileResponse := getExpectedFileResponseForCreate("user2/repo1", commitID, treePath, latestCommit.ID.String())
+ lastCommit, _ := gitRepo.GetCommitByPath(treePath)
+ expectedFileResponse := getExpectedFileResponseForCreate(apiFileResponseInfo{
+ repoFullName: "user2/repo1",
+ commitID: commitID,
+ treePath: treePath,
+ lastCommitSHA: lastCommit.ID.String(),
+ lastCommitterWhen: lastCommit.Committer.When,
+ lastAuthorWhen: lastCommit.Author.When,
+ })
var fileResponse api.FileResponse
DecodeJSON(t, resp, &fileResponse)
- assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content)
- assert.EqualValues(t, expectedFileResponse.Commit.SHA, fileResponse.Commit.SHA)
- assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL)
- assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, fileResponse.Commit.Author.Email)
- assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, fileResponse.Commit.Author.Name)
- assert.EqualValues(t, expectedFileResponse.Commit.Author.Date, fileResponse.Commit.Author.Date)
- assert.EqualValues(t, expectedFileResponse.Commit.Committer.Email, fileResponse.Commit.Committer.Email)
- assert.EqualValues(t, expectedFileResponse.Commit.Committer.Name, fileResponse.Commit.Committer.Name)
- assert.EqualValues(t, expectedFileResponse.Commit.Committer.Date, fileResponse.Commit.Committer.Date)
- gitRepo.Close()
+ normalizeFileContentResponseCommitTime(fileResponse.Content)
+ assert.Equal(t, expectedFileResponse.Content, fileResponse.Content)
+ assert.Equal(t, expectedFileResponse.Commit.SHA, fileResponse.Commit.SHA)
+ assert.Equal(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL)
+ assert.Equal(t, expectedFileResponse.Commit.Author.Email, fileResponse.Commit.Author.Email)
+ assert.Equal(t, expectedFileResponse.Commit.Author.Name, fileResponse.Commit.Author.Name)
+ assert.Equal(t, expectedFileResponse.Commit.Author.Date, fileResponse.Commit.Author.Date)
+ assert.Equal(t, expectedFileResponse.Commit.Committer.Email, fileResponse.Commit.Committer.Email)
+ assert.Equal(t, expectedFileResponse.Commit.Committer.Name, fileResponse.Commit.Committer.Name)
+ assert.Equal(t, expectedFileResponse.Commit.Committer.Date, fileResponse.Commit.Committer.Date)
}
// Test creating a file in a new branch
@@ -199,10 +223,10 @@ func TestAPICreateFile(t *testing.T) {
expectedSHA := "a635aa942442ddfdba07468cf9661c08fbdf0ebf"
expectedHTMLURL := fmt.Sprintf(setting.AppURL+"user2/repo1/src/branch/new_branch/new/file%d.txt", fileID)
expectedDownloadURL := fmt.Sprintf(setting.AppURL+"user2/repo1/raw/branch/new_branch/new/file%d.txt", fileID)
- assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA)
- assert.EqualValues(t, expectedHTMLURL, *fileResponse.Content.HTMLURL)
- assert.EqualValues(t, expectedDownloadURL, *fileResponse.Content.DownloadURL)
- assert.EqualValues(t, createFileOptions.Message+"\n", fileResponse.Commit.Message)
+ assert.Equal(t, expectedSHA, fileResponse.Content.SHA)
+ assert.Equal(t, expectedHTMLURL, *fileResponse.Content.HTMLURL)
+ assert.Equal(t, expectedDownloadURL, *fileResponse.Content.DownloadURL)
+ assert.Equal(t, createFileOptions.Message+"\n", fileResponse.Commit.Message)
// Test creating a file without a message
createFileOptions = getCreateFileOptions()
@@ -214,7 +238,7 @@ func TestAPICreateFile(t *testing.T) {
resp = MakeRequest(t, req, http.StatusCreated)
DecodeJSON(t, resp, &fileResponse)
expectedMessage := "Add " + treePath + "\n"
- assert.EqualValues(t, expectedMessage, fileResponse.Commit.Message)
+ assert.Equal(t, expectedMessage, fileResponse.Commit.Message)
// Test trying to create a file that already exists, should fail
createFileOptions = getCreateFileOptions()
@@ -285,20 +309,28 @@ func TestAPICreateFile(t *testing.T) {
AddTokenAuth(token2)
resp = MakeRequest(t, req, http.StatusCreated)
emptyRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user2", Name: "empty-repo"}) // public repo
- gitRepo, _ := gitrepo.OpenRepository(stdCtx.Background(), emptyRepo)
+ gitRepo, _ := gitrepo.OpenRepository(t.Context(), emptyRepo)
+ defer gitRepo.Close()
commitID, _ := gitRepo.GetBranchCommitID(createFileOptions.NewBranchName)
latestCommit, _ := gitRepo.GetCommitByPath(treePath)
- expectedFileResponse := getExpectedFileResponseForCreate("user2/empty-repo", commitID, treePath, latestCommit.ID.String())
+ expectedFileResponse := getExpectedFileResponseForCreate(apiFileResponseInfo{
+ repoFullName: "user2/empty-repo",
+ commitID: commitID,
+ treePath: treePath,
+ lastCommitSHA: latestCommit.ID.String(),
+ lastCommitterWhen: latestCommit.Committer.When,
+ lastAuthorWhen: latestCommit.Author.When,
+ })
DecodeJSON(t, resp, &fileResponse)
- assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content)
- assert.EqualValues(t, expectedFileResponse.Commit.SHA, fileResponse.Commit.SHA)
- assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL)
- assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, fileResponse.Commit.Author.Email)
- assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, fileResponse.Commit.Author.Name)
- assert.EqualValues(t, expectedFileResponse.Commit.Author.Date, fileResponse.Commit.Author.Date)
- assert.EqualValues(t, expectedFileResponse.Commit.Committer.Email, fileResponse.Commit.Committer.Email)
- assert.EqualValues(t, expectedFileResponse.Commit.Committer.Name, fileResponse.Commit.Committer.Name)
- assert.EqualValues(t, expectedFileResponse.Commit.Committer.Date, fileResponse.Commit.Committer.Date)
- gitRepo.Close()
+ normalizeFileContentResponseCommitTime(fileResponse.Content)
+ assert.Equal(t, expectedFileResponse.Content, fileResponse.Content)
+ assert.Equal(t, expectedFileResponse.Commit.SHA, fileResponse.Commit.SHA)
+ assert.Equal(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL)
+ assert.Equal(t, expectedFileResponse.Commit.Author.Email, fileResponse.Commit.Author.Email)
+ assert.Equal(t, expectedFileResponse.Commit.Author.Name, fileResponse.Commit.Author.Name)
+ assert.Equal(t, expectedFileResponse.Commit.Author.Date, fileResponse.Commit.Author.Date)
+ assert.Equal(t, expectedFileResponse.Commit.Committer.Email, fileResponse.Commit.Committer.Email)
+ assert.Equal(t, expectedFileResponse.Commit.Committer.Name, fileResponse.Commit.Committer.Name)
+ assert.Equal(t, expectedFileResponse.Commit.Committer.Date, fileResponse.Commit.Committer.Date)
})
}
diff --git a/tests/integration/api_repo_file_delete_test.go b/tests/integration/api_repo_file_delete_test.go
index 7c93307e19..9dd47f93e6 100644
--- a/tests/integration/api_repo_file_delete_test.go
+++ b/tests/integration/api_repo_file_delete_test.go
@@ -20,20 +20,22 @@ import (
func getDeleteFileOptions() *api.DeleteFileOptions {
return &api.DeleteFileOptions{
- FileOptions: api.FileOptions{
- BranchName: "master",
- NewBranchName: "master",
- Message: "Removing the file new/file.txt",
- Author: api.Identity{
- Name: "John Doe",
- Email: "johndoe@example.com",
- },
- Committer: api.Identity{
- Name: "Jane Doe",
- Email: "janedoe@example.com",
+ FileOptionsWithSHA: api.FileOptionsWithSHA{
+ FileOptions: api.FileOptions{
+ BranchName: "master",
+ NewBranchName: "master",
+ Message: "Removing the file new/file.txt",
+ Author: api.Identity{
+ Name: "John Doe",
+ Email: "johndoe@example.com",
+ },
+ Committer: api.Identity{
+ Name: "Jane Doe",
+ Email: "janedoe@example.com",
+ },
},
+ SHA: "103ff9234cefeee5ec5361d22b49fbb04d385885",
},
- SHA: "103ff9234cefeee5ec5361d22b49fbb04d385885",
}
}
@@ -87,7 +89,7 @@ func TestAPIDeleteFile(t *testing.T) {
DecodeJSON(t, resp, &fileResponse)
assert.NotNil(t, fileResponse)
assert.Nil(t, fileResponse.Content)
- assert.EqualValues(t, deleteFileOptions.Message+"\n", fileResponse.Commit.Message)
+ assert.Equal(t, deleteFileOptions.Message+"\n", fileResponse.Commit.Message)
// Test deleting file without a message
fileID++
@@ -100,7 +102,7 @@ func TestAPIDeleteFile(t *testing.T) {
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &fileResponse)
expectedMessage := "Delete " + treePath + "\n"
- assert.EqualValues(t, expectedMessage, fileResponse.Commit.Message)
+ assert.Equal(t, expectedMessage, fileResponse.Commit.Message)
// Test deleting a file with the wrong SHA
fileID++
@@ -110,7 +112,7 @@ func TestAPIDeleteFile(t *testing.T) {
deleteFileOptions.SHA = "badsha"
req = NewRequestWithJSON(t, "DELETE", fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user2.Name, repo1.Name, treePath), &deleteFileOptions).
AddTokenAuth(token2)
- MakeRequest(t, req, http.StatusBadRequest)
+ MakeRequest(t, req, http.StatusUnprocessableEntity)
// Test creating a file in repo16 by user4 who does not have write access
fileID++
diff --git a/tests/integration/api_repo_file_get_test.go b/tests/integration/api_repo_file_get_test.go
index 2f897093ee..379851b689 100644
--- a/tests/integration/api_repo_file_get_test.go
+++ b/tests/integration/api_repo_file_get_test.go
@@ -44,8 +44,6 @@ func TestAPIGetRawFileOrLFS(t *testing.T) {
reqLFS := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/media/"+lfs)
respLFS := MakeRequestNilResponseRecorder(t, reqLFS, http.StatusOK)
assert.Equal(t, testFileSizeSmall, respLFS.Length)
-
- doAPIDeleteRepository(httpContext)
})
})
}
diff --git a/tests/integration/api_repo_file_update_test.go b/tests/integration/api_repo_file_update_test.go
index ac28e0c0a2..9a56711da6 100644
--- a/tests/integration/api_repo_file_update_test.go
+++ b/tests/integration/api_repo_file_update_test.go
@@ -4,12 +4,11 @@
package integration
import (
- stdCtx "context"
"encoding/base64"
"fmt"
"net/http"
"net/url"
- "path/filepath"
+ "path"
"testing"
auth_model "code.gitea.io/gitea/models/auth"
@@ -19,6 +18,7 @@ import (
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/context"
"github.com/stretchr/testify/assert"
@@ -28,7 +28,7 @@ func getUpdateFileOptions() *api.UpdateFileOptions {
content := "This is updated text"
contentEncoded := base64.StdEncoding.EncodeToString([]byte(content))
return &api.UpdateFileOptions{
- DeleteFileOptions: api.DeleteFileOptions{
+ FileOptionsWithSHA: api.FileOptionsWithSHA{
FileOptions: api.FileOptions{
BranchName: "master",
NewBranchName: "master",
@@ -48,28 +48,30 @@ func getUpdateFileOptions() *api.UpdateFileOptions {
}
}
-func getExpectedFileResponseForUpdate(commitID, treePath, lastCommitSHA string) *api.FileResponse {
+func getExpectedFileResponseForUpdate(info apiFileResponseInfo) *api.FileResponse {
sha := "08bd14b2e2852529157324de9c226b3364e76136"
encoding := "base64"
content := "VGhpcyBpcyB1cGRhdGVkIHRleHQ="
- selfURL := setting.AppURL + "api/v1/repos/user2/repo1/contents/" + treePath + "?ref=master"
- htmlURL := setting.AppURL + "user2/repo1/src/branch/master/" + treePath
+ selfURL := setting.AppURL + "api/v1/repos/user2/repo1/contents/" + info.treePath + "?ref=master"
+ htmlURL := setting.AppURL + "user2/repo1/src/branch/master/" + info.treePath
gitURL := setting.AppURL + "api/v1/repos/user2/repo1/git/blobs/" + sha
- downloadURL := setting.AppURL + "user2/repo1/raw/branch/master/" + treePath
- return &api.FileResponse{
+ downloadURL := setting.AppURL + "user2/repo1/raw/branch/master/" + info.treePath
+ ret := &api.FileResponse{
Content: &api.ContentsResponse{
- Name: filepath.Base(treePath),
- Path: treePath,
- SHA: sha,
- LastCommitSHA: lastCommitSHA,
- Type: "file",
- Size: 20,
- Encoding: &encoding,
- Content: &content,
- URL: &selfURL,
- HTMLURL: &htmlURL,
- GitURL: &gitURL,
- DownloadURL: &downloadURL,
+ Name: path.Base(info.treePath),
+ Path: info.treePath,
+ SHA: sha,
+ LastCommitSHA: util.ToPointer(info.lastCommitSHA),
+ LastCommitterDate: util.ToPointer(info.lastCommitterWhen),
+ LastAuthorDate: util.ToPointer(info.lastAuthorWhen),
+ Type: "file",
+ Size: 20,
+ Encoding: &encoding,
+ Content: &content,
+ URL: &selfURL,
+ HTMLURL: &htmlURL,
+ GitURL: &gitURL,
+ DownloadURL: &downloadURL,
Links: &api.FileLinksResponse{
Self: &selfURL,
GitURL: &gitURL,
@@ -78,10 +80,10 @@ func getExpectedFileResponseForUpdate(commitID, treePath, lastCommitSHA string)
},
Commit: &api.FileCommitResponse{
CommitMeta: api.CommitMeta{
- URL: setting.AppURL + "api/v1/repos/user2/repo1/git/commits/" + commitID,
- SHA: commitID,
+ URL: setting.AppURL + "api/v1/repos/user2/repo1/git/commits/" + info.commitID,
+ SHA: info.commitID,
},
- HTMLURL: setting.AppURL + "user2/repo1/commit/" + commitID,
+ HTMLURL: setting.AppURL + "user2/repo1/commit/" + info.commitID,
Author: &api.CommitUser{
Identity: api.Identity{
Name: "John Doe",
@@ -103,6 +105,8 @@ func getExpectedFileResponseForUpdate(commitID, treePath, lastCommitSHA string)
Payload: "",
},
}
+ normalizeFileContentResponseCommitTime(ret.Content)
+ return ret
}
func TestAPIUpdateFile(t *testing.T) {
@@ -135,18 +139,25 @@ func TestAPIUpdateFile(t *testing.T) {
req := NewRequestWithJSON(t, "PUT", fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user2.Name, repo1.Name, treePath), &updateFileOptions).
AddTokenAuth(token2)
resp := MakeRequest(t, req, http.StatusOK)
- gitRepo, _ := gitrepo.OpenRepository(stdCtx.Background(), repo1)
+ gitRepo, _ := gitrepo.OpenRepository(t.Context(), repo1)
+ defer gitRepo.Close()
commitID, _ := gitRepo.GetBranchCommitID(updateFileOptions.NewBranchName)
lasCommit, _ := gitRepo.GetCommitByPath(treePath)
- expectedFileResponse := getExpectedFileResponseForUpdate(commitID, treePath, lasCommit.ID.String())
+ expectedFileResponse := getExpectedFileResponseForUpdate(apiFileResponseInfo{
+ commitID: commitID,
+ treePath: treePath,
+ lastCommitSHA: lasCommit.ID.String(),
+ lastCommitterWhen: lasCommit.Committer.When,
+ lastAuthorWhen: lasCommit.Author.When,
+ })
var fileResponse api.FileResponse
DecodeJSON(t, resp, &fileResponse)
- assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content)
- assert.EqualValues(t, expectedFileResponse.Commit.SHA, fileResponse.Commit.SHA)
- assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL)
- assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, fileResponse.Commit.Author.Email)
- assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, fileResponse.Commit.Author.Name)
- gitRepo.Close()
+ normalizeFileContentResponseCommitTime(fileResponse.Content)
+ assert.Equal(t, expectedFileResponse.Content, fileResponse.Content)
+ assert.Equal(t, expectedFileResponse.Commit.SHA, fileResponse.Commit.SHA)
+ assert.Equal(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL)
+ assert.Equal(t, expectedFileResponse.Commit.Author.Email, fileResponse.Commit.Author.Email)
+ assert.Equal(t, expectedFileResponse.Commit.Author.Name, fileResponse.Commit.Author.Name)
}
// Test updating a file in a new branch
@@ -164,10 +175,10 @@ func TestAPIUpdateFile(t *testing.T) {
expectedSHA := "08bd14b2e2852529157324de9c226b3364e76136"
expectedHTMLURL := fmt.Sprintf(setting.AppURL+"user2/repo1/src/branch/new_branch/update/file%d.txt", fileID)
expectedDownloadURL := fmt.Sprintf(setting.AppURL+"user2/repo1/raw/branch/new_branch/update/file%d.txt", fileID)
- assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA)
- assert.EqualValues(t, expectedHTMLURL, *fileResponse.Content.HTMLURL)
- assert.EqualValues(t, expectedDownloadURL, *fileResponse.Content.DownloadURL)
- assert.EqualValues(t, updateFileOptions.Message+"\n", fileResponse.Commit.Message)
+ assert.Equal(t, expectedSHA, fileResponse.Content.SHA)
+ assert.Equal(t, expectedHTMLURL, *fileResponse.Content.HTMLURL)
+ assert.Equal(t, expectedDownloadURL, *fileResponse.Content.DownloadURL)
+ assert.Equal(t, updateFileOptions.Message+"\n", fileResponse.Commit.Message)
// Test updating a file and renaming it
updateFileOptions = getUpdateFileOptions()
@@ -184,9 +195,9 @@ func TestAPIUpdateFile(t *testing.T) {
expectedSHA = "08bd14b2e2852529157324de9c226b3364e76136"
expectedHTMLURL = fmt.Sprintf(setting.AppURL+"user2/repo1/src/branch/master/rename/update/file%d.txt", fileID)
expectedDownloadURL = fmt.Sprintf(setting.AppURL+"user2/repo1/raw/branch/master/rename/update/file%d.txt", fileID)
- assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA)
- assert.EqualValues(t, expectedHTMLURL, *fileResponse.Content.HTMLURL)
- assert.EqualValues(t, expectedDownloadURL, *fileResponse.Content.DownloadURL)
+ assert.Equal(t, expectedSHA, fileResponse.Content.SHA)
+ assert.Equal(t, expectedHTMLURL, *fileResponse.Content.HTMLURL)
+ assert.Equal(t, expectedDownloadURL, *fileResponse.Content.DownloadURL)
// Test updating a file without a message
updateFileOptions = getUpdateFileOptions()
@@ -200,7 +211,7 @@ func TestAPIUpdateFile(t *testing.T) {
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &fileResponse)
expectedMessage := "Update " + treePath + "\n"
- assert.EqualValues(t, expectedMessage, fileResponse.Commit.Message)
+ assert.Equal(t, expectedMessage, fileResponse.Commit.Message)
// Test updating a file with the wrong SHA
fileID++
diff --git a/tests/integration/api_repo_files_change_test.go b/tests/integration/api_repo_files_change_test.go
index fb3ae5e4dd..999bcdc680 100644
--- a/tests/integration/api_repo_files_change_test.go
+++ b/tests/integration/api_repo_files_change_test.go
@@ -4,7 +4,6 @@
package integration
import (
- stdCtx "context"
"encoding/base64"
"fmt"
"net/http"
@@ -78,51 +77,56 @@ func TestAPIChangeFiles(t *testing.T) {
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
// Test changing files in repo1 which user2 owns, try both with branch and empty branch
- for _, branch := range [...]string{
- "master", // Branch
- "", // Empty branch
- } {
- fileID++
- createTreePath := fmt.Sprintf("new/file%d.txt", fileID)
- updateTreePath := fmt.Sprintf("update/file%d.txt", fileID)
- deleteTreePath := fmt.Sprintf("delete/file%d.txt", fileID)
- createFile(user2, repo1, updateTreePath)
- createFile(user2, repo1, deleteTreePath)
- changeFilesOptions := getChangeFilesOptions()
- changeFilesOptions.BranchName = branch
- changeFilesOptions.Files[0].Path = createTreePath
- changeFilesOptions.Files[1].Path = updateTreePath
- changeFilesOptions.Files[2].Path = deleteTreePath
- req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/contents", user2.Name, repo1.Name), &changeFilesOptions).
- AddTokenAuth(token2)
- resp := MakeRequest(t, req, http.StatusCreated)
- gitRepo, _ := gitrepo.OpenRepository(stdCtx.Background(), repo1)
- commitID, _ := gitRepo.GetBranchCommitID(changeFilesOptions.NewBranchName)
- createLasCommit, _ := gitRepo.GetCommitByPath(createTreePath)
- updateLastCommit, _ := gitRepo.GetCommitByPath(updateTreePath)
- expectedCreateFileResponse := getExpectedFileResponseForCreate(fmt.Sprintf("%v/%v", user2.Name, repo1.Name), commitID, createTreePath, createLasCommit.ID.String())
- expectedUpdateFileResponse := getExpectedFileResponseForUpdate(commitID, updateTreePath, updateLastCommit.ID.String())
- var filesResponse api.FilesResponse
- DecodeJSON(t, resp, &filesResponse)
-
- // check create file
- assert.EqualValues(t, expectedCreateFileResponse.Content, filesResponse.Files[0])
-
- // check update file
- assert.EqualValues(t, expectedUpdateFileResponse.Content, filesResponse.Files[1])
-
- // test commit info
- assert.EqualValues(t, expectedCreateFileResponse.Commit.SHA, filesResponse.Commit.SHA)
- assert.EqualValues(t, expectedCreateFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL)
- assert.EqualValues(t, expectedCreateFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email)
- assert.EqualValues(t, expectedCreateFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name)
- assert.EqualValues(t, expectedCreateFileResponse.Commit.Committer.Email, filesResponse.Commit.Committer.Email)
- assert.EqualValues(t, expectedCreateFileResponse.Commit.Committer.Name, filesResponse.Commit.Committer.Name)
-
- // test delete file
- assert.Nil(t, filesResponse.Files[2])
-
- gitRepo.Close()
+ for _, branch := range []string{"master", ""} {
+ t.Run("Branch-"+branch, func(t *testing.T) {
+ fileID++
+ createTreePath := fmt.Sprintf("new/file%d.txt", fileID)
+ updateTreePath := fmt.Sprintf("update/file%d.txt", fileID)
+ deleteTreePath := fmt.Sprintf("delete/file%d.txt", fileID)
+ _, _ = createFile(user2, repo1, updateTreePath)
+ _, _ = createFile(user2, repo1, deleteTreePath)
+ changeFilesOptions := getChangeFilesOptions()
+ changeFilesOptions.BranchName = branch
+ changeFilesOptions.Files[0].Path = createTreePath
+ changeFilesOptions.Files[1].Path = updateTreePath
+ changeFilesOptions.Files[2].Path = deleteTreePath
+ req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/contents", user2.Name, repo1.Name), &changeFilesOptions).
+ AddTokenAuth(token2)
+ resp := MakeRequest(t, req, http.StatusCreated)
+ gitRepo, _ := gitrepo.OpenRepository(t.Context(), repo1)
+ defer gitRepo.Close()
+ commitID, _ := gitRepo.GetBranchCommitID(changeFilesOptions.NewBranchName)
+ createLasCommit, _ := gitRepo.GetCommitByPath(createTreePath)
+ updateLastCommit, _ := gitRepo.GetCommitByPath(updateTreePath)
+ expectedCreateFileResponse := getExpectedFileResponseForCreate(apiFileResponseInfo{
+ repoFullName: fmt.Sprintf("%s/%s", user2.Name, repo1.Name),
+ commitID: commitID,
+ treePath: createTreePath,
+ lastCommitSHA: createLasCommit.ID.String(),
+ lastCommitterWhen: createLasCommit.Committer.When,
+ lastAuthorWhen: createLasCommit.Author.When,
+ })
+ expectedUpdateFileResponse := getExpectedFileResponseForUpdate(apiFileResponseInfo{
+ commitID: commitID,
+ treePath: updateTreePath,
+ lastCommitSHA: updateLastCommit.ID.String(),
+ lastCommitterWhen: updateLastCommit.Committer.When,
+ lastAuthorWhen: updateLastCommit.Author.When,
+ })
+ var filesResponse api.FilesResponse
+ DecodeJSON(t, resp, &filesResponse)
+ normalizeFileContentResponseCommitTime(filesResponse.Files[0])
+ normalizeFileContentResponseCommitTime(filesResponse.Files[1])
+ assert.Equal(t, expectedCreateFileResponse.Content, filesResponse.Files[0]) // check create file
+ assert.Equal(t, expectedUpdateFileResponse.Content, filesResponse.Files[1]) // check update file
+ assert.Equal(t, expectedCreateFileResponse.Commit.SHA, filesResponse.Commit.SHA)
+ assert.Equal(t, expectedCreateFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL)
+ assert.Equal(t, expectedCreateFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email)
+ assert.Equal(t, expectedCreateFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name)
+ assert.Equal(t, expectedCreateFileResponse.Commit.Committer.Email, filesResponse.Commit.Committer.Email)
+ assert.Equal(t, expectedCreateFileResponse.Commit.Committer.Name, filesResponse.Commit.Committer.Name)
+ assert.Nil(t, filesResponse.Files[2]) // test delete file
+ })
}
// Test changing files in a new branch
@@ -150,15 +154,15 @@ func TestAPIChangeFiles(t *testing.T) {
expectedUpdateSHA := "08bd14b2e2852529157324de9c226b3364e76136"
expectedUpdateHTMLURL := fmt.Sprintf(setting.AppURL+"user2/repo1/src/branch/new_branch/update/file%d.txt", fileID)
expectedUpdateDownloadURL := fmt.Sprintf(setting.AppURL+"user2/repo1/raw/branch/new_branch/update/file%d.txt", fileID)
- assert.EqualValues(t, expectedCreateSHA, filesResponse.Files[0].SHA)
- assert.EqualValues(t, expectedCreateHTMLURL, *filesResponse.Files[0].HTMLURL)
- assert.EqualValues(t, expectedCreateDownloadURL, *filesResponse.Files[0].DownloadURL)
- assert.EqualValues(t, expectedUpdateSHA, filesResponse.Files[1].SHA)
- assert.EqualValues(t, expectedUpdateHTMLURL, *filesResponse.Files[1].HTMLURL)
- assert.EqualValues(t, expectedUpdateDownloadURL, *filesResponse.Files[1].DownloadURL)
+ assert.Equal(t, expectedCreateSHA, filesResponse.Files[0].SHA)
+ assert.Equal(t, expectedCreateHTMLURL, *filesResponse.Files[0].HTMLURL)
+ assert.Equal(t, expectedCreateDownloadURL, *filesResponse.Files[0].DownloadURL)
+ assert.Equal(t, expectedUpdateSHA, filesResponse.Files[1].SHA)
+ assert.Equal(t, expectedUpdateHTMLURL, *filesResponse.Files[1].HTMLURL)
+ assert.Equal(t, expectedUpdateDownloadURL, *filesResponse.Files[1].DownloadURL)
assert.Nil(t, filesResponse.Files[2])
- assert.EqualValues(t, changeFilesOptions.Message+"\n", filesResponse.Commit.Message)
+ assert.Equal(t, changeFilesOptions.Message+"\n", filesResponse.Commit.Message)
// Test updating a file and renaming it
changeFilesOptions = getChangeFilesOptions()
@@ -176,9 +180,9 @@ func TestAPIChangeFiles(t *testing.T) {
expectedUpdateSHA = "08bd14b2e2852529157324de9c226b3364e76136"
expectedUpdateHTMLURL = fmt.Sprintf(setting.AppURL+"user2/repo1/src/branch/master/rename/update/file%d.txt", fileID)
expectedUpdateDownloadURL = fmt.Sprintf(setting.AppURL+"user2/repo1/raw/branch/master/rename/update/file%d.txt", fileID)
- assert.EqualValues(t, expectedUpdateSHA, filesResponse.Files[0].SHA)
- assert.EqualValues(t, expectedUpdateHTMLURL, *filesResponse.Files[0].HTMLURL)
- assert.EqualValues(t, expectedUpdateDownloadURL, *filesResponse.Files[0].DownloadURL)
+ assert.Equal(t, expectedUpdateSHA, filesResponse.Files[0].SHA)
+ assert.Equal(t, expectedUpdateHTMLURL, *filesResponse.Files[0].HTMLURL)
+ assert.Equal(t, expectedUpdateDownloadURL, *filesResponse.Files[0].DownloadURL)
// Test updating a file without a message
changeFilesOptions = getChangeFilesOptions()
@@ -198,7 +202,7 @@ func TestAPIChangeFiles(t *testing.T) {
resp = MakeRequest(t, req, http.StatusCreated)
DecodeJSON(t, resp, &filesResponse)
expectedMessage := fmt.Sprintf("Add %v\nUpdate %v\nDelete %v\n", createTreePath, updateTreePath, deleteTreePath)
- assert.EqualValues(t, expectedMessage, filesResponse.Commit.Message)
+ assert.Equal(t, expectedMessage, filesResponse.Commit.Message)
// Test updating a file with the wrong SHA
fileID++
diff --git a/tests/integration/api_repo_files_get_test.go b/tests/integration/api_repo_files_get_test.go
new file mode 100644
index 0000000000..a4ded7da3f
--- /dev/null
+++ b/tests/integration/api_repo_files_get_test.go
@@ -0,0 +1,157 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package integration
+
+import (
+ "fmt"
+ "net/http"
+ "net/url"
+ "testing"
+
+ auth_model "code.gitea.io/gitea/models/auth"
+ repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unittest"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/gitrepo"
+ "code.gitea.io/gitea/modules/json"
+ "code.gitea.io/gitea/modules/setting"
+ api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/test"
+ "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/tests"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestAPIGetRequestedFiles(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo1 & repo16
+ org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}) // owner of the repo3, is an org
+ user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) // owner of neither repos
+ repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) // public repo
+ repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) // public repo
+ repo16 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) // private repo
+
+ // Get user2's token
+ session := loginUser(t, user2.Name)
+ token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+ // Get user4's token
+ session = loginUser(t, user4.Name)
+ token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo1)
+ assert.NoError(t, err)
+ defer gitRepo.Close()
+ lastCommit, _ := gitRepo.GetCommitByPath("README.md")
+
+ requestFiles := func(t *testing.T, url string, files []string, expectedStatusCode ...int) (ret []*api.ContentsResponse) {
+ req := NewRequestWithJSON(t, "POST", url, &api.GetFilesOptions{Files: files})
+ resp := MakeRequest(t, req, util.OptionalArg(expectedStatusCode, http.StatusOK))
+ if resp.Code != http.StatusOK {
+ return nil
+ }
+ DecodeJSON(t, resp, &ret)
+ return ret
+ }
+
+ t.Run("User2Get", func(t *testing.T) {
+ reqBodyOpt := &api.GetFilesOptions{Files: []string{"README.md"}}
+ reqBodyParam, _ := json.Marshal(reqBodyOpt)
+ req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/file-contents?body="+url.QueryEscape(string(reqBodyParam)))
+ resp := MakeRequest(t, req, http.StatusOK)
+ var ret []*api.ContentsResponse
+ DecodeJSON(t, resp, &ret)
+ expected := []*api.ContentsResponse{getExpectedContentsResponseForContents(repo1.DefaultBranch, "branch", lastCommit.ID.String())}
+ assert.Equal(t, expected, ret)
+ })
+ t.Run("User2NoRef", func(t *testing.T) {
+ ret := requestFiles(t, "/api/v1/repos/user2/repo1/file-contents", []string{"README.md"})
+ expected := []*api.ContentsResponse{getExpectedContentsResponseForContents(repo1.DefaultBranch, "branch", lastCommit.ID.String())}
+ assert.Equal(t, expected, ret)
+ })
+ t.Run("User2RefBranch", func(t *testing.T) {
+ ret := requestFiles(t, "/api/v1/repos/user2/repo1/file-contents?ref=master", []string{"README.md"})
+ expected := []*api.ContentsResponse{getExpectedContentsResponseForContents(repo1.DefaultBranch, "branch", lastCommit.ID.String())}
+ assert.Equal(t, expected, ret)
+ })
+ t.Run("User2RefTag", func(t *testing.T) {
+ ret := requestFiles(t, "/api/v1/repos/user2/repo1/file-contents?ref=v1.1", []string{"README.md"})
+ expected := []*api.ContentsResponse{getExpectedContentsResponseForContents("v1.1", "tag", lastCommit.ID.String())}
+ assert.Equal(t, expected, ret)
+ })
+ t.Run("User2RefCommit", func(t *testing.T) {
+ ret := requestFiles(t, "/api/v1/repos/user2/repo1/file-contents?ref=65f1bf27bc3bf70f64657658635e66094edbcb4d", []string{"README.md"})
+ expected := []*api.ContentsResponse{getExpectedContentsResponseForContents("65f1bf27bc3bf70f64657658635e66094edbcb4d", "commit", lastCommit.ID.String())}
+ assert.Equal(t, expected, ret)
+ })
+ t.Run("User2RefNotExist", func(t *testing.T) {
+ ret := requestFiles(t, "/api/v1/repos/user2/repo1/file-contents?ref=not-exist", []string{"README.md"}, http.StatusNotFound)
+ assert.Empty(t, ret)
+ })
+
+ t.Run("PermissionCheck", func(t *testing.T) {
+ filesOptions := &api.GetFilesOptions{Files: []string{"README.md"}}
+ // Test accessing private ref with user token that does not have access - should fail
+ req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/file-contents", user2.Name, repo16.Name), &filesOptions).AddTokenAuth(token4)
+ MakeRequest(t, req, http.StatusNotFound)
+ // Test access private ref of owner of token
+ req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/file-contents", user2.Name, repo16.Name), &filesOptions).AddTokenAuth(token2)
+ MakeRequest(t, req, http.StatusOK)
+ // Test access of org org3 private repo file by owner user2
+ req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/file-contents", org3.Name, repo3.Name), &filesOptions).AddTokenAuth(token2)
+ MakeRequest(t, req, http.StatusOK)
+ })
+
+ t.Run("ResponseList", func(t *testing.T) {
+ defer test.MockVariableValue(&setting.API.DefaultPagingNum)()
+ defer test.MockVariableValue(&setting.API.DefaultMaxBlobSize)()
+ defer test.MockVariableValue(&setting.API.DefaultMaxResponseSize)()
+
+ type expected struct {
+ Name string
+ HasContent bool
+ }
+ assertResponse := func(t *testing.T, expected []*expected, ret []*api.ContentsResponse) {
+ require.Len(t, ret, len(expected))
+ for i, e := range expected {
+ if e == nil {
+ assert.Nil(t, ret[i], "item %d", i)
+ continue
+ }
+ assert.Equal(t, e.Name, ret[i].Name, "item %d name", i)
+ if e.HasContent {
+ require.NotNil(t, ret[i].Content, "item %d content", i)
+ assert.NotEmpty(t, *ret[i].Content, "item %d content", i)
+ } else {
+ assert.Nil(t, ret[i].Content, "item %d content", i)
+ }
+ }
+ }
+
+ // repo1 "DefaultBranch" has 2 files: LICENSE (1064 bytes), README.md (30 bytes)
+ ret := requestFiles(t, "/api/v1/repos/user2/repo1/file-contents?ref=DefaultBranch", []string{"no-such.txt", "LICENSE", "README.md"})
+ assertResponse(t, []*expected{nil, {"LICENSE", true}, {"README.md", true}}, ret)
+
+ // the returned file list is limited by the DefaultPagingNum
+ setting.API.DefaultPagingNum = 2
+ ret = requestFiles(t, "/api/v1/repos/user2/repo1/file-contents?ref=DefaultBranch", []string{"no-such.txt", "LICENSE", "README.md"})
+ assertResponse(t, []*expected{nil, {"LICENSE", true}}, ret)
+ setting.API.DefaultPagingNum = 100
+
+ // if a file exceeds the DefaultMaxBlobSize, the content is not returned
+ setting.API.DefaultMaxBlobSize = 200
+ ret = requestFiles(t, "/api/v1/repos/user2/repo1/file-contents?ref=DefaultBranch", []string{"no-such.txt", "LICENSE", "README.md"})
+ assertResponse(t, []*expected{nil, {"LICENSE", false}, {"README.md", true}}, ret)
+ setting.API.DefaultMaxBlobSize = 20000
+
+ // if the total response size would exceed the DefaultMaxResponseSize, then the list stops
+ setting.API.DefaultMaxResponseSize = ret[1].Size*4/3 + 10
+ ret = requestFiles(t, "/api/v1/repos/user2/repo1/file-contents?ref=DefaultBranch", []string{"no-such.txt", "LICENSE", "README.md"})
+ assertResponse(t, []*expected{nil, {"LICENSE", true}}, ret)
+ setting.API.DefaultMaxBlobSize = 20000
+ })
+}
diff --git a/tests/integration/api_repo_get_contents_list_test.go b/tests/integration/api_repo_get_contents_list_test.go
index 1ba74490a3..563d6fcc10 100644
--- a/tests/integration/api_repo_get_contents_list_test.go
+++ b/tests/integration/api_repo_get_contents_list_test.go
@@ -6,8 +6,9 @@ package integration
import (
"net/http"
"net/url"
- "path/filepath"
+ "path"
"testing"
+ "time"
auth_model "code.gitea.io/gitea/models/auth"
repo_model "code.gitea.io/gitea/models/repo"
@@ -17,6 +18,7 @@ import (
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/util"
repo_service "code.gitea.io/gitea/services/repository"
"github.com/stretchr/testify/assert"
@@ -31,16 +33,18 @@ func getExpectedContentsListResponseForContents(ref, refType, lastCommitSHA stri
downloadURL := setting.AppURL + "user2/repo1/raw/" + refType + "/" + ref + "/" + treePath
return []*api.ContentsResponse{
{
- Name: filepath.Base(treePath),
- Path: treePath,
- SHA: sha,
- LastCommitSHA: lastCommitSHA,
- Type: "file",
- Size: 30,
- URL: &selfURL,
- HTMLURL: &htmlURL,
- GitURL: &gitURL,
- DownloadURL: &downloadURL,
+ Name: path.Base(treePath),
+ Path: treePath,
+ SHA: sha,
+ LastCommitSHA: util.ToPointer(lastCommitSHA),
+ LastCommitterDate: util.ToPointer(time.Date(2017, time.March, 19, 16, 47, 59, 0, time.FixedZone("", -14400))),
+ LastAuthorDate: util.ToPointer(time.Date(2017, time.March, 19, 16, 47, 59, 0, time.FixedZone("", -14400))),
+ Type: "file",
+ Size: 30,
+ URL: &selfURL,
+ HTMLURL: &htmlURL,
+ GitURL: &gitURL,
+ DownloadURL: &downloadURL,
Links: &api.FileLinksResponse{
Self: &selfURL,
GitURL: &gitURL,
@@ -62,7 +66,6 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) {
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) // public repo
repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) // public repo
repo16 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) // private repo
- treePath := "" // root dir
// Get user2's token
session := loginUser(t, user2.Name)
@@ -91,7 +94,7 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) {
// ref is default ref
ref := repo1.DefaultBranch
refType := "branch"
- req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref)
+ req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents?ref=%s", user2.Name, repo1.Name, ref)
resp := MakeRequest(t, req, http.StatusOK)
var contentsListResponse []*api.ContentsResponse
DecodeJSON(t, resp, &contentsListResponse)
@@ -99,22 +102,22 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) {
lastCommit, err := gitRepo.GetCommitByPath("README.md")
assert.NoError(t, err)
expectedContentsListResponse := getExpectedContentsListResponseForContents(ref, refType, lastCommit.ID.String())
- assert.EqualValues(t, expectedContentsListResponse, contentsListResponse)
+ assert.Equal(t, expectedContentsListResponse, contentsListResponse)
// No ref
refType = "branch"
- req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s", user2.Name, repo1.Name, treePath)
+ req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/", user2.Name, repo1.Name)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &contentsListResponse)
assert.NotNil(t, contentsListResponse)
expectedContentsListResponse = getExpectedContentsListResponseForContents(repo1.DefaultBranch, refType, lastCommit.ID.String())
- assert.EqualValues(t, expectedContentsListResponse, contentsListResponse)
+ assert.Equal(t, expectedContentsListResponse, contentsListResponse)
// ref is the branch we created above in setup
ref = newBranch
refType = "branch"
- req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref)
+ req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents?ref=%s", user2.Name, repo1.Name, ref)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &contentsListResponse)
assert.NotNil(t, contentsListResponse)
@@ -123,12 +126,12 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) {
lastCommit, err = branchCommit.GetCommitByPath("README.md")
assert.NoError(t, err)
expectedContentsListResponse = getExpectedContentsListResponseForContents(ref, refType, lastCommit.ID.String())
- assert.EqualValues(t, expectedContentsListResponse, contentsListResponse)
+ assert.Equal(t, expectedContentsListResponse, contentsListResponse)
// ref is the new tag we created above in setup
ref = newTag
refType = "tag"
- req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref)
+ req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/?ref=%s", user2.Name, repo1.Name, ref)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &contentsListResponse)
assert.NotNil(t, contentsListResponse)
@@ -137,35 +140,35 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) {
lastCommit, err = tagCommit.GetCommitByPath("README.md")
assert.NoError(t, err)
expectedContentsListResponse = getExpectedContentsListResponseForContents(ref, refType, lastCommit.ID.String())
- assert.EqualValues(t, expectedContentsListResponse, contentsListResponse)
+ assert.Equal(t, expectedContentsListResponse, contentsListResponse)
// ref is a commit
ref = commitID
refType = "commit"
- req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref)
+ req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/?ref=%s", user2.Name, repo1.Name, ref)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &contentsListResponse)
assert.NotNil(t, contentsListResponse)
expectedContentsListResponse = getExpectedContentsListResponseForContents(ref, refType, commitID)
- assert.EqualValues(t, expectedContentsListResponse, contentsListResponse)
+ assert.Equal(t, expectedContentsListResponse, contentsListResponse)
// Test file contents a file with a bad ref
ref = "badref"
- req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref)
+ req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/?ref=%s", user2.Name, repo1.Name, ref)
MakeRequest(t, req, http.StatusNotFound)
// Test accessing private ref with user token that does not have access - should fail
- req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s", user2.Name, repo16.Name, treePath).
+ req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/", user2.Name, repo16.Name).
AddTokenAuth(token4)
MakeRequest(t, req, http.StatusNotFound)
// Test access private ref of owner of token
- req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/readme.md", user2.Name, repo16.Name).
+ req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/", user2.Name, repo16.Name).
AddTokenAuth(token2)
MakeRequest(t, req, http.StatusOK)
// Test access of org org3 private repo file by owner user2
- req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s", org3.Name, repo3.Name, treePath).
+ req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/", org3.Name, repo3.Name).
AddTokenAuth(token2)
MakeRequest(t, req, http.StatusOK)
}
diff --git a/tests/integration/api_repo_get_contents_test.go b/tests/integration/api_repo_get_contents_test.go
index d0f61da0c0..33df74f6ee 100644
--- a/tests/integration/api_repo_get_contents_test.go
+++ b/tests/integration/api_repo_get_contents_test.go
@@ -7,7 +7,9 @@ import (
"io"
"net/http"
"net/url"
+ "slices"
"testing"
+ "time"
auth_model "code.gitea.io/gitea/models/auth"
repo_model "code.gitea.io/gitea/models/repo"
@@ -17,34 +19,33 @@ import (
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/util"
repo_service "code.gitea.io/gitea/services/repository"
- "code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
func getExpectedContentsResponseForContents(ref, refType, lastCommitSHA string) *api.ContentsResponse {
treePath := "README.md"
- sha := "4b4851ad51df6a7d9f25c979345979eaeb5b349f"
- encoding := "base64"
- content := "IyByZXBvMQoKRGVzY3JpcHRpb24gZm9yIHJlcG8x"
selfURL := setting.AppURL + "api/v1/repos/user2/repo1/contents/" + treePath + "?ref=" + ref
htmlURL := setting.AppURL + "user2/repo1/src/" + refType + "/" + ref + "/" + treePath
- gitURL := setting.AppURL + "api/v1/repos/user2/repo1/git/blobs/" + sha
- downloadURL := setting.AppURL + "user2/repo1/raw/" + refType + "/" + ref + "/" + treePath
+ gitURL := setting.AppURL + "api/v1/repos/user2/repo1/git/blobs/4b4851ad51df6a7d9f25c979345979eaeb5b349f"
return &api.ContentsResponse{
- Name: treePath,
- Path: treePath,
- SHA: sha,
- LastCommitSHA: lastCommitSHA,
- Type: "file",
- Size: 30,
- Encoding: &encoding,
- Content: &content,
- URL: &selfURL,
- HTMLURL: &htmlURL,
- GitURL: &gitURL,
- DownloadURL: &downloadURL,
+ Name: treePath,
+ Path: treePath,
+ SHA: "4b4851ad51df6a7d9f25c979345979eaeb5b349f",
+ LastCommitSHA: util.ToPointer(lastCommitSHA),
+ LastCommitterDate: util.ToPointer(time.Date(2017, time.March, 19, 16, 47, 59, 0, time.FixedZone("", -14400))),
+ LastAuthorDate: util.ToPointer(time.Date(2017, time.March, 19, 16, 47, 59, 0, time.FixedZone("", -14400))),
+ Type: "file",
+ Size: 30,
+ Encoding: util.ToPointer("base64"),
+ Content: util.ToPointer("IyByZXBvMQoKRGVzY3JpcHRpb24gZm9yIHJlcG8x"),
+ URL: &selfURL,
+ HTMLURL: &htmlURL,
+ GitURL: &gitURL,
+ DownloadURL: util.ToPointer(setting.AppURL + "user2/repo1/raw/" + refType + "/" + ref + "/" + treePath),
Links: &api.FileLinksResponse{
Self: &selfURL,
GitURL: &gitURL,
@@ -54,7 +55,11 @@ func getExpectedContentsResponseForContents(ref, refType, lastCommitSHA string)
}
func TestAPIGetContents(t *testing.T) {
- onGiteaRun(t, testAPIGetContents)
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ testAPIGetContentsRefFormats(t)
+ testAPIGetContents(t, u)
+ testAPIGetContentsExt(t)
+ })
}
func testAPIGetContents(t *testing.T, u *url.URL) {
@@ -76,54 +81,56 @@ func testAPIGetContents(t *testing.T, u *url.URL) {
// Get the commit ID of the default branch
gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo1)
- assert.NoError(t, err)
+ require.NoError(t, err)
defer gitRepo.Close()
// Make a new branch in repo1
newBranch := "test_branch"
err = repo_service.CreateNewBranch(git.DefaultContext, user2, repo1, gitRepo, repo1.DefaultBranch, newBranch)
- assert.NoError(t, err)
+ require.NoError(t, err)
commitID, err := gitRepo.GetBranchCommitID(repo1.DefaultBranch)
- assert.NoError(t, err)
+ require.NoError(t, err)
// Make a new tag in repo1
newTag := "test_tag"
err = gitRepo.CreateTag(newTag, commitID)
- assert.NoError(t, err)
+ require.NoError(t, err)
/*** END SETUP ***/
+ // not found
+ req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/no-such/file.md", user2.Name, repo1.Name)
+ resp := MakeRequest(t, req, http.StatusNotFound)
+ assert.Contains(t, resp.Body.String(), "object does not exist [id: , rel_path: no-such]")
+
// ref is default ref
ref := repo1.DefaultBranch
refType := "branch"
- req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref)
- resp := MakeRequest(t, req, http.StatusOK)
+ req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref)
+ resp = MakeRequest(t, req, http.StatusOK)
var contentsResponse api.ContentsResponse
DecodeJSON(t, resp, &contentsResponse)
- assert.NotNil(t, contentsResponse)
lastCommit, _ := gitRepo.GetCommitByPath("README.md")
expectedContentsResponse := getExpectedContentsResponseForContents(ref, refType, lastCommit.ID.String())
- assert.EqualValues(t, *expectedContentsResponse, contentsResponse)
+ assert.Equal(t, *expectedContentsResponse, contentsResponse)
// No ref
refType = "branch"
req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s", user2.Name, repo1.Name, treePath)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &contentsResponse)
- assert.NotNil(t, contentsResponse)
expectedContentsResponse = getExpectedContentsResponseForContents(repo1.DefaultBranch, refType, lastCommit.ID.String())
- assert.EqualValues(t, *expectedContentsResponse, contentsResponse)
+ assert.Equal(t, *expectedContentsResponse, contentsResponse)
- // ref is the branch we created above in setup
+ // ref is the branch we created above in setup
ref = newBranch
refType = "branch"
req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &contentsResponse)
- assert.NotNil(t, contentsResponse)
branchCommit, _ := gitRepo.GetBranchCommit(ref)
lastCommit, _ = branchCommit.GetCommitByPath("README.md")
expectedContentsResponse = getExpectedContentsResponseForContents(ref, refType, lastCommit.ID.String())
- assert.EqualValues(t, *expectedContentsResponse, contentsResponse)
+ assert.Equal(t, *expectedContentsResponse, contentsResponse)
// ref is the new tag we created above in setup
ref = newTag
@@ -131,11 +138,10 @@ func testAPIGetContents(t *testing.T, u *url.URL) {
req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &contentsResponse)
- assert.NotNil(t, contentsResponse)
tagCommit, _ := gitRepo.GetTagCommit(ref)
lastCommit, _ = tagCommit.GetCommitByPath("README.md")
expectedContentsResponse = getExpectedContentsResponseForContents(ref, refType, lastCommit.ID.String())
- assert.EqualValues(t, *expectedContentsResponse, contentsResponse)
+ assert.Equal(t, *expectedContentsResponse, contentsResponse)
// ref is a commit
ref = commitID
@@ -143,9 +149,8 @@ func testAPIGetContents(t *testing.T, u *url.URL) {
req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &contentsResponse)
- assert.NotNil(t, contentsResponse)
expectedContentsResponse = getExpectedContentsResponseForContents(ref, refType, commitID)
- assert.EqualValues(t, *expectedContentsResponse, contentsResponse)
+ assert.Equal(t, *expectedContentsResponse, contentsResponse)
// Test file contents a file with a bad ref
ref = "badref"
@@ -168,9 +173,7 @@ func testAPIGetContents(t *testing.T, u *url.URL) {
MakeRequest(t, req, http.StatusOK)
}
-func TestAPIGetContentsRefFormats(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
-
+func testAPIGetContentsRefFormats(t *testing.T) {
file := "README.md"
sha := "65f1bf27bc3bf70f64657658635e66094edbcb4d"
content := "# repo1\n\nDescription for repo1"
@@ -178,22 +181,22 @@ func TestAPIGetContentsRefFormats(t *testing.T) {
resp := MakeRequest(t, NewRequest(t, http.MethodGet, "/api/v1/repos/user2/repo1/raw/"+file), http.StatusOK)
raw, err := io.ReadAll(resp.Body)
assert.NoError(t, err)
- assert.EqualValues(t, content, string(raw))
+ assert.Equal(t, content, string(raw))
resp = MakeRequest(t, NewRequest(t, http.MethodGet, "/api/v1/repos/user2/repo1/raw/"+sha+"/"+file), http.StatusOK)
raw, err = io.ReadAll(resp.Body)
assert.NoError(t, err)
- assert.EqualValues(t, content, string(raw))
+ assert.Equal(t, content, string(raw))
resp = MakeRequest(t, NewRequest(t, http.MethodGet, "/api/v1/repos/user2/repo1/raw/"+file+"?ref="+sha), http.StatusOK)
raw, err = io.ReadAll(resp.Body)
assert.NoError(t, err)
- assert.EqualValues(t, content, string(raw))
+ assert.Equal(t, content, string(raw))
resp = MakeRequest(t, NewRequest(t, http.MethodGet, "/api/v1/repos/user2/repo1/raw/"+file+"?ref=master"), http.StatusOK)
raw, err = io.ReadAll(resp.Body)
assert.NoError(t, err)
- assert.EqualValues(t, content, string(raw))
+ assert.Equal(t, content, string(raw))
_ = MakeRequest(t, NewRequest(t, http.MethodGet, "/api/v1/repos/user2/repo1/raw/docs/README.md?ref=main"), http.StatusNotFound)
_ = MakeRequest(t, NewRequest(t, http.MethodGet, "/api/v1/repos/user2/repo1/raw/README.md?ref=main"), http.StatusOK)
@@ -203,3 +206,98 @@ func TestAPIGetContentsRefFormats(t *testing.T) {
// FIXME: this is an incorrect behavior, non-existing branch falls back to default branch
_ = MakeRequest(t, NewRequest(t, http.MethodGet, "/api/v1/repos/user2/repo1/raw/README.md?ref=no-such"), http.StatusOK)
}
+
+func testAPIGetContentsExt(t *testing.T) {
+ session := loginUser(t, "user2")
+ token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+ t.Run("DirContents", func(t *testing.T) {
+ req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/contents-ext?ref=sub-home-md-img-check")
+ resp := MakeRequest(t, req, http.StatusOK)
+ var contentsResponse api.ContentsExtResponse
+ DecodeJSON(t, resp, &contentsResponse)
+ assert.Nil(t, contentsResponse.FileContents)
+ assert.NotNil(t, contentsResponse.DirContents)
+
+ req = NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/contents-ext/.?ref=sub-home-md-img-check")
+ resp = MakeRequest(t, req, http.StatusOK)
+ contentsResponse = api.ContentsExtResponse{}
+ DecodeJSON(t, resp, &contentsResponse)
+ assert.Nil(t, contentsResponse.FileContents)
+ assert.NotNil(t, contentsResponse.DirContents)
+
+ req = NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/contents-ext/docs?ref=sub-home-md-img-check")
+ resp = MakeRequest(t, req, http.StatusOK)
+ contentsResponse = api.ContentsExtResponse{}
+ DecodeJSON(t, resp, &contentsResponse)
+ assert.Nil(t, contentsResponse.FileContents)
+ assert.Equal(t, "README.md", contentsResponse.DirContents[0].Name)
+ assert.Nil(t, contentsResponse.DirContents[0].Encoding)
+ assert.Nil(t, contentsResponse.DirContents[0].Content)
+ assert.Nil(t, contentsResponse.DirContents[0].LastCommitSHA)
+ assert.Nil(t, contentsResponse.DirContents[0].LastCommitMessage)
+
+ // "includes=file_content" shouldn't affect directory listing
+ req = NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/contents-ext/docs?ref=sub-home-md-img-check&includes=file_content")
+ resp = MakeRequest(t, req, http.StatusOK)
+ contentsResponse = api.ContentsExtResponse{}
+ DecodeJSON(t, resp, &contentsResponse)
+ assert.Nil(t, contentsResponse.FileContents)
+ assert.Equal(t, "README.md", contentsResponse.DirContents[0].Name)
+ assert.Nil(t, contentsResponse.DirContents[0].Encoding)
+ assert.Nil(t, contentsResponse.DirContents[0].Content)
+
+ req = NewRequestf(t, "GET", "/api/v1/repos/user2/lfs/contents-ext?includes=file_content,lfs_metadata").AddTokenAuth(token2)
+ resp = session.MakeRequest(t, req, http.StatusOK)
+ contentsResponse = api.ContentsExtResponse{}
+ DecodeJSON(t, resp, &contentsResponse)
+ assert.Nil(t, contentsResponse.FileContents)
+ respFileIdx := slices.IndexFunc(contentsResponse.DirContents, func(response *api.ContentsResponse) bool { return response.Name == "jpeg.jpg" })
+ require.NotEqual(t, -1, respFileIdx)
+ respFile := contentsResponse.DirContents[respFileIdx]
+ assert.Equal(t, "jpeg.jpg", respFile.Name)
+ assert.Nil(t, respFile.Encoding)
+ assert.Nil(t, respFile.Content)
+ assert.Equal(t, util.ToPointer(int64(107)), respFile.LfsSize)
+ assert.Equal(t, util.ToPointer("0b8d8b5f15046343fd32f451df93acc2bdd9e6373be478b968e4cad6b6647351"), respFile.LfsOid)
+ })
+ t.Run("FileContents", func(t *testing.T) {
+ // by default, no file content or commit info is returned
+ req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/contents-ext/docs/README.md?ref=sub-home-md-img-check")
+ resp := MakeRequest(t, req, http.StatusOK)
+ var contentsResponse api.ContentsExtResponse
+ DecodeJSON(t, resp, &contentsResponse)
+ assert.Nil(t, contentsResponse.DirContents)
+ assert.Equal(t, "README.md", contentsResponse.FileContents.Name)
+ assert.Nil(t, contentsResponse.FileContents.Encoding)
+ assert.Nil(t, contentsResponse.FileContents.Content)
+ assert.Nil(t, contentsResponse.FileContents.LastCommitSHA)
+ assert.Nil(t, contentsResponse.FileContents.LastCommitMessage)
+
+ // file content is only returned when `includes=file_content`
+ req = NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/contents-ext/docs/README.md?ref=sub-home-md-img-check&includes=file_content,commit_metadata,commit_message")
+ resp = MakeRequest(t, req, http.StatusOK)
+ contentsResponse = api.ContentsExtResponse{}
+ DecodeJSON(t, resp, &contentsResponse)
+ assert.Nil(t, contentsResponse.DirContents)
+ assert.Equal(t, "README.md", contentsResponse.FileContents.Name)
+ assert.NotNil(t, contentsResponse.FileContents.Encoding)
+ assert.NotNil(t, contentsResponse.FileContents.Content)
+ assert.Equal(t, "4649299398e4d39a5c09eb4f534df6f1e1eb87cc", *contentsResponse.FileContents.LastCommitSHA)
+ assert.Equal(t, "Test how READMEs render images when found in a subfolder\n", *contentsResponse.FileContents.LastCommitMessage)
+
+ req = NewRequestf(t, "GET", "/api/v1/repos/user2/lfs/contents-ext/jpeg.jpg?includes=file_content").AddTokenAuth(token2)
+ resp = session.MakeRequest(t, req, http.StatusOK)
+ contentsResponse = api.ContentsExtResponse{}
+ DecodeJSON(t, resp, &contentsResponse)
+ assert.Nil(t, contentsResponse.DirContents)
+ assert.NotNil(t, contentsResponse.FileContents)
+ respFile := contentsResponse.FileContents
+ assert.Equal(t, "jpeg.jpg", respFile.Name)
+ assert.NotNil(t, respFile.Encoding)
+ assert.NotNil(t, respFile.Content)
+ assert.Nil(t, contentsResponse.FileContents.LastCommitSHA)
+ assert.Nil(t, contentsResponse.FileContents.LastCommitMessage)
+ assert.Equal(t, util.ToPointer(int64(107)), respFile.LfsSize)
+ assert.Equal(t, util.ToPointer("0b8d8b5f15046343fd32f451df93acc2bdd9e6373be478b968e4cad6b6647351"), respFile.LfsOid)
+ })
+}
diff --git a/tests/integration/api_repo_git_blobs_test.go b/tests/integration/api_repo_git_blobs_test.go
index 184362e7e3..d4274bdb40 100644
--- a/tests/integration/api_repo_git_blobs_test.go
+++ b/tests/integration/api_repo_git_blobs_test.go
@@ -41,7 +41,7 @@ func TestAPIReposGitBlobs(t *testing.T) {
DecodeJSON(t, resp, &gitBlobResponse)
assert.NotNil(t, gitBlobResponse)
expectedContent := "dHJlZSAyYTJmMWQ0NjcwNzI4YTJlMTAwNDllMzQ1YmQ3YTI3NjQ2OGJlYWI2CmF1dGhvciB1c2VyMSA8YWRkcmVzczFAZXhhbXBsZS5jb20+IDE0ODk5NTY0NzkgLTA0MDAKY29tbWl0dGVyIEV0aGFuIEtvZW5pZyA8ZXRoYW50a29lbmlnQGdtYWlsLmNvbT4gMTQ4OTk1NjQ3OSAtMDQwMAoKSW5pdGlhbCBjb21taXQK"
- assert.Equal(t, expectedContent, gitBlobResponse.Content)
+ assert.Equal(t, expectedContent, *gitBlobResponse.Content)
// Tests a private repo with no token so will fail
req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/git/blobs/%s", user2.Name, repo16.Name, repo16ReadmeSHA)
@@ -72,7 +72,7 @@ func TestAPIReposGitBlobs(t *testing.T) {
// Login as User4.
session = loginUser(t, user4.Name)
- token4 := getTokenForLoggedInUser(t, session)
+ token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAll)
// Test using org repo "org3/repo3" where user4 is a NOT collaborator
req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/git/blobs/d56a3073c1dbb7b15963110a049d50cdb5db99fc?access=%s", org3.Name, repo3.Name, token4)
diff --git a/tests/integration/api_repo_git_commits_test.go b/tests/integration/api_repo_git_commits_test.go
index c4c626eb49..a1584d4629 100644
--- a/tests/integration/api_repo_git_commits_test.go
+++ b/tests/integration/api_repo_git_commits_test.go
@@ -72,12 +72,12 @@ func TestAPIReposGitCommitList(t *testing.T) {
DecodeJSON(t, resp, &apiData)
assert.Len(t, apiData, 2)
- assert.EqualValues(t, "cfe3b3c1fd36fba04f9183287b106497e1afe986", apiData[0].CommitMeta.SHA)
+ assert.Equal(t, "cfe3b3c1fd36fba04f9183287b106497e1afe986", apiData[0].CommitMeta.SHA)
compareCommitFiles(t, []string{"link_hi", "test.csv"}, apiData[0].Files)
- assert.EqualValues(t, "c8e31bc7688741a5287fcde4fbb8fc129ca07027", apiData[1].CommitMeta.SHA)
+ assert.Equal(t, "c8e31bc7688741a5287fcde4fbb8fc129ca07027", apiData[1].CommitMeta.SHA)
compareCommitFiles(t, []string{"test.csv"}, apiData[1].Files)
- assert.EqualValues(t, "2", resp.Header().Get("X-Total"))
+ assert.Equal(t, "2", resp.Header().Get("X-Total"))
}
func TestAPIReposGitCommitListNotMaster(t *testing.T) {
@@ -96,14 +96,14 @@ func TestAPIReposGitCommitListNotMaster(t *testing.T) {
DecodeJSON(t, resp, &apiData)
assert.Len(t, apiData, 3)
- assert.EqualValues(t, "69554a64c1e6030f051e5c3f94bfbd773cd6a324", apiData[0].CommitMeta.SHA)
+ assert.Equal(t, "69554a64c1e6030f051e5c3f94bfbd773cd6a324", apiData[0].CommitMeta.SHA)
compareCommitFiles(t, []string{"readme.md"}, apiData[0].Files)
- assert.EqualValues(t, "27566bd5738fc8b4e3fef3c5e72cce608537bd95", apiData[1].CommitMeta.SHA)
+ assert.Equal(t, "27566bd5738fc8b4e3fef3c5e72cce608537bd95", apiData[1].CommitMeta.SHA)
compareCommitFiles(t, []string{"readme.md"}, apiData[1].Files)
- assert.EqualValues(t, "5099b81332712fe655e34e8dd63574f503f61811", apiData[2].CommitMeta.SHA)
+ assert.Equal(t, "5099b81332712fe655e34e8dd63574f503f61811", apiData[2].CommitMeta.SHA)
compareCommitFiles(t, []string{"readme.md"}, apiData[2].Files)
- assert.EqualValues(t, "3", resp.Header().Get("X-Total"))
+ assert.Equal(t, "3", resp.Header().Get("X-Total"))
}
func TestAPIReposGitCommitListPage2Empty(t *testing.T) {
@@ -177,7 +177,7 @@ func TestDownloadCommitDiffOrPatch(t *testing.T) {
reqDiff := NewRequestf(t, "GET", "/api/v1/repos/%s/repo16/git/commits/f27c2b2b03dcab38beaf89b0ab4ff61f6de63441.diff", user.Name).
AddTokenAuth(token)
resp := MakeRequest(t, reqDiff, http.StatusOK)
- assert.EqualValues(t,
+ assert.Equal(t,
"commit f27c2b2b03dcab38beaf89b0ab4ff61f6de63441\nAuthor: User2 <user2@example.com>\nDate: Sun Aug 6 19:55:01 2017 +0200\n\n good signed commit\n\ndiff --git a/readme.md b/readme.md\nnew file mode 100644\nindex 0000000..458121c\n--- /dev/null\n+++ b/readme.md\n@@ -0,0 +1 @@\n+good sign\n",
resp.Body.String())
@@ -185,7 +185,7 @@ func TestDownloadCommitDiffOrPatch(t *testing.T) {
reqPatch := NewRequestf(t, "GET", "/api/v1/repos/%s/repo16/git/commits/f27c2b2b03dcab38beaf89b0ab4ff61f6de63441.patch", user.Name).
AddTokenAuth(token)
resp = MakeRequest(t, reqPatch, http.StatusOK)
- assert.EqualValues(t,
+ assert.Equal(t,
"From f27c2b2b03dcab38beaf89b0ab4ff61f6de63441 Mon Sep 17 00:00:00 2001\nFrom: User2 <user2@example.com>\nDate: Sun, 6 Aug 2017 19:55:01 +0200\nSubject: [PATCH] good signed commit\n\n---\n readme.md | 1 +\n 1 file changed, 1 insertion(+)\n create mode 100644 readme.md\n\ndiff --git a/readme.md b/readme.md\nnew file mode 100644\nindex 0000000..458121c\n--- /dev/null\n+++ b/readme.md\n@@ -0,0 +1 @@\n+good sign\n",
resp.Body.String())
}
@@ -208,7 +208,7 @@ func TestGetFileHistory(t *testing.T) {
assert.Equal(t, "f27c2b2b03dcab38beaf89b0ab4ff61f6de63441", apiData[0].CommitMeta.SHA)
compareCommitFiles(t, []string{"readme.md"}, apiData[0].Files)
- assert.EqualValues(t, "1", resp.Header().Get("X-Total"))
+ assert.Equal(t, "1", resp.Header().Get("X-Total"))
}
func TestGetFileHistoryNotOnMaster(t *testing.T) {
@@ -229,5 +229,5 @@ func TestGetFileHistoryNotOnMaster(t *testing.T) {
assert.Equal(t, "c8e31bc7688741a5287fcde4fbb8fc129ca07027", apiData[0].CommitMeta.SHA)
compareCommitFiles(t, []string{"test.csv"}, apiData[0].Files)
- assert.EqualValues(t, "1", resp.Header().Get("X-Total"))
+ assert.Equal(t, "1", resp.Header().Get("X-Total"))
}
diff --git a/tests/integration/api_repo_git_tags_test.go b/tests/integration/api_repo_git_tags_test.go
index c5883a8058..5a66337589 100644
--- a/tests/integration/api_repo_git_tags_test.go
+++ b/tests/integration/api_repo_git_tags_test.go
@@ -30,8 +30,8 @@ func TestAPIGitTags(t *testing.T) {
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
// Set up git config for the tagger
- _ = git.NewCommand(git.DefaultContext, "config", "user.name").AddDynamicArguments(user.Name).Run(&git.RunOpts{Dir: repo.RepoPath()})
- _ = git.NewCommand(git.DefaultContext, "config", "user.email").AddDynamicArguments(user.Email).Run(&git.RunOpts{Dir: repo.RepoPath()})
+ _ = git.NewCommand("config", "user.name").AddDynamicArguments(user.Name).Run(git.DefaultContext, &git.RunOpts{Dir: repo.RepoPath()})
+ _ = git.NewCommand("config", "user.email").AddDynamicArguments(user.Email).Run(git.DefaultContext, &git.RunOpts{Dir: repo.RepoPath()})
gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo)
defer gitRepo.Close()
diff --git a/tests/integration/api_repo_git_trees_test.go b/tests/integration/api_repo_git_trees_test.go
index 8eec6d8d22..47063d9091 100644
--- a/tests/integration/api_repo_git_trees_test.go
+++ b/tests/integration/api_repo_git_trees_test.go
@@ -69,7 +69,7 @@ func TestAPIReposGitTrees(t *testing.T) {
// Login as User4.
session = loginUser(t, user4.Name)
- token4 := getTokenForLoggedInUser(t, session)
+ token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAll)
// Test using org repo "org3/repo3" where user4 is a NOT collaborator
req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/git/trees/d56a3073c1dbb7b15963110a049d50cdb5db99fc?access=%s", org3.Name, repo3.Name, token4)
diff --git a/tests/integration/api_repo_languages_test.go b/tests/integration/api_repo_languages_test.go
index 1045aef57d..6347a43b4e 100644
--- a/tests/integration/api_repo_languages_test.go
+++ b/tests/integration/api_repo_languages_test.go
@@ -9,6 +9,8 @@ import (
"testing"
"time"
+ "code.gitea.io/gitea/modules/test"
+
"github.com/stretchr/testify/assert"
)
@@ -32,7 +34,8 @@ func TestRepoLanguages(t *testing.T) {
"content": "package main",
"commit_choice": "direct",
})
- session.MakeRequest(t, req, http.StatusSeeOther)
+ resp = session.MakeRequest(t, req, http.StatusOK)
+ assert.NotEmpty(t, test.RedirectURL(resp))
// let gitea calculate language stats
time.Sleep(time.Second)
diff --git a/tests/integration/api_repo_lfs_locks_test.go b/tests/integration/api_repo_lfs_locks_test.go
index 4ba01e6d9b..161fa45dc6 100644
--- a/tests/integration/api_repo_lfs_locks_test.go
+++ b/tests/integration/api_repo_lfs_locks_test.go
@@ -112,7 +112,7 @@ func TestAPILFSLocksLogged(t *testing.T) {
var lfsLock api.LFSLockResponse
DecodeJSON(t, resp, &lfsLock)
assert.Equal(t, test.user.Name, lfsLock.Lock.Owner.Name)
- assert.EqualValues(t, lfsLock.Lock.LockedAt.Format(time.RFC3339), lfsLock.Lock.LockedAt.Format(time.RFC3339Nano)) // locked at should be rounded to second
+ assert.Equal(t, lfsLock.Lock.LockedAt.Format(time.RFC3339), lfsLock.Lock.LockedAt.Format(time.RFC3339Nano)) // locked at should be rounded to second
for _, id := range test.addTime {
resultsTests[id].locksTimes = append(resultsTests[id].locksTimes, time.Now())
}
@@ -129,9 +129,9 @@ func TestAPILFSLocksLogged(t *testing.T) {
DecodeJSON(t, resp, &lfsLocks)
assert.Len(t, lfsLocks.Locks, test.totalCount)
for i, lock := range lfsLocks.Locks {
- assert.EqualValues(t, test.locksOwners[i].Name, lock.Owner.Name)
+ assert.Equal(t, test.locksOwners[i].Name, lock.Owner.Name)
assert.WithinDuration(t, test.locksTimes[i], lock.LockedAt, 10*time.Second)
- assert.EqualValues(t, lock.LockedAt.Format(time.RFC3339), lock.LockedAt.Format(time.RFC3339Nano)) // locked at should be rounded to second
+ assert.Equal(t, lock.LockedAt.Format(time.RFC3339), lock.LockedAt.Format(time.RFC3339Nano)) // locked at should be rounded to second
}
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/%s.git/info/lfs/locks/verify", test.repo.FullName()), map[string]string{})
@@ -143,7 +143,7 @@ func TestAPILFSLocksLogged(t *testing.T) {
assert.Len(t, lfsLocksVerify.Ours, test.oursCount)
assert.Len(t, lfsLocksVerify.Theirs, test.theirsCount)
for _, lock := range lfsLocksVerify.Ours {
- assert.EqualValues(t, test.user.Name, lock.Owner.Name)
+ assert.Equal(t, test.user.Name, lock.Owner.Name)
deleteTests = append(deleteTests, struct {
user *user_model.User
repo *repo_model.Repository
diff --git a/tests/integration/api_repo_lfs_migrate_test.go b/tests/integration/api_repo_lfs_migrate_test.go
index 8b4d79db02..6ca6f9afab 100644
--- a/tests/integration/api_repo_lfs_migrate_test.go
+++ b/tests/integration/api_repo_lfs_migrate_test.go
@@ -40,7 +40,7 @@ func TestAPIRepoLFSMigrateLocal(t *testing.T) {
LFS: true,
}).AddTokenAuth(token)
resp := MakeRequest(t, req, NoExpectedStatus)
- assert.EqualValues(t, http.StatusCreated, resp.Code)
+ assert.Equal(t, http.StatusCreated, resp.Code)
store := lfs.NewContentStore()
ok, _ := store.Verify(lfs.Pointer{Oid: "fb8f7d8435968c4f82a726a92395be4d16f2f63116caf36c8ad35c60831ab041", Size: 6})
diff --git a/tests/integration/api_repo_lfs_test.go b/tests/integration/api_repo_lfs_test.go
index 6b42b83bc5..ec6a3a3b57 100644
--- a/tests/integration/api_repo_lfs_test.go
+++ b/tests/integration/api_repo_lfs_test.go
@@ -20,6 +20,7 @@ import (
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/lfs"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
@@ -226,9 +227,7 @@ func TestAPILFSBatch(t *testing.T) {
t.Run("FileTooBig", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
-
- oldMaxFileSize := setting.LFS.MaxFileSize
- setting.LFS.MaxFileSize = 2
+ defer test.MockVariableValue(&setting.LFS.MaxFileSize, 2)()
req := newRequest(t, &lfs.BatchRequest{
Operation: "upload",
@@ -243,8 +242,6 @@ func TestAPILFSBatch(t *testing.T) {
assert.NotNil(t, br.Objects[0].Error)
assert.Equal(t, http.StatusUnprocessableEntity, br.Objects[0].Error.Code)
assert.Equal(t, "Size must be less than or equal to 2", br.Objects[0].Error.Message)
-
- setting.LFS.MaxFileSize = oldMaxFileSize
})
t.Run("AddMeta", func(t *testing.T) {
diff --git a/tests/integration/api_repo_license_test.go b/tests/integration/api_repo_license_test.go
index 52d3085694..fb4450a2bd 100644
--- a/tests/integration/api_repo_license_test.go
+++ b/tests/integration/api_repo_license_test.go
@@ -12,12 +12,13 @@ import (
auth_model "code.gitea.io/gitea/models/auth"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/test"
"github.com/stretchr/testify/assert"
)
var testLicenseContent = `
-Copyright (c) 2024 Gitea
+Copyright (c) 2024 Gitea
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
@@ -48,7 +49,8 @@ func TestAPIRepoLicense(t *testing.T) {
"content": testLicenseContent,
"commit_choice": "direct",
})
- session.MakeRequest(t, req, http.StatusSeeOther)
+ resp = session.MakeRequest(t, req, http.StatusOK)
+ assert.NotEmpty(t, test.RedirectURL(resp))
// let gitea update repo license
time.Sleep(time.Second)
diff --git a/tests/integration/api_repo_raw_test.go b/tests/integration/api_repo_raw_test.go
index e5f83d1c80..e9d741925f 100644
--- a/tests/integration/api_repo_raw_test.go
+++ b/tests/integration/api_repo_raw_test.go
@@ -30,11 +30,11 @@ func TestAPIReposRaw(t *testing.T) {
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo1/raw/%s/README.md", user.Name, ref).
AddTokenAuth(token)
resp := MakeRequest(t, req, http.StatusOK)
- assert.EqualValues(t, "file", resp.Header().Get("x-gitea-object-type"))
+ assert.Equal(t, "file", resp.Header().Get("x-gitea-object-type"))
}
// Test default branch
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo1/raw/README.md", user.Name).
AddTokenAuth(token)
resp := MakeRequest(t, req, http.StatusOK)
- assert.EqualValues(t, "file", resp.Header().Get("x-gitea-object-type"))
+ assert.Equal(t, "file", resp.Header().Get("x-gitea-object-type"))
}
diff --git a/tests/integration/api_repo_secrets_test.go b/tests/integration/api_repo_secrets_test.go
index c3074d9ece..2059aff484 100644
--- a/tests/integration/api_repo_secrets_test.go
+++ b/tests/integration/api_repo_secrets_test.go
@@ -73,6 +73,33 @@ func TestAPIRepoSecrets(t *testing.T) {
}
})
+ t.Run("CreateWithDescription", func(t *testing.T) {
+ cases := []struct {
+ Name string
+ Description string
+ ExpectedStatus int
+ }{
+ {
+ Name: "no_description",
+ Description: "",
+ ExpectedStatus: http.StatusCreated,
+ },
+ {
+ Name: "description",
+ Description: "some description",
+ ExpectedStatus: http.StatusCreated,
+ },
+ }
+
+ for _, c := range cases {
+ req := NewRequestWithJSON(t, "PUT", fmt.Sprintf("/api/v1/repos/%s/actions/secrets/%s", repo.FullName(), c.Name), api.CreateOrUpdateSecretOption{
+ Data: "data",
+ Description: c.Description,
+ }).AddTokenAuth(token)
+ MakeRequest(t, req, c.ExpectedStatus)
+ }
+ })
+
t.Run("Update", func(t *testing.T) {
name := "update_secret"
url := fmt.Sprintf("/api/v1/repos/%s/actions/secrets/%s", repo.FullName(), name)
diff --git a/tests/integration/api_repo_tags_test.go b/tests/integration/api_repo_tags_test.go
index a7f021ca4f..3932a8ba2b 100644
--- a/tests/integration/api_repo_tags_test.go
+++ b/tests/integration/api_repo_tags_test.go
@@ -48,10 +48,10 @@ func TestAPIRepoTags(t *testing.T) {
assert.Len(t, tags, 2)
for _, tag := range tags {
if tag.Name != "v1.1" {
- assert.EqualValues(t, newTag.Name, tag.Name)
- assert.EqualValues(t, newTag.Message, tag.Message)
- assert.EqualValues(t, "nice!\nand some text", tag.Message)
- assert.EqualValues(t, newTag.Commit.SHA, tag.Commit.SHA)
+ assert.Equal(t, newTag.Name, tag.Name)
+ assert.Equal(t, newTag.Message, tag.Message)
+ assert.Equal(t, "nice!\nand some text", tag.Message)
+ assert.Equal(t, newTag.Commit.SHA, tag.Commit.SHA)
}
}
@@ -61,7 +61,7 @@ func TestAPIRepoTags(t *testing.T) {
resp = MakeRequest(t, req, http.StatusOK)
var tag *api.Tag
DecodeJSON(t, resp, &tag)
- assert.EqualValues(t, newTag, tag)
+ assert.Equal(t, newTag, tag)
// delete tag
delReq := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/tags/%s", user.Name, repoName, newTag.Name).
diff --git a/tests/integration/api_repo_teams_test.go b/tests/integration/api_repo_teams_test.go
index 07d065b02b..143e3dd29f 100644
--- a/tests/integration/api_repo_teams_test.go
+++ b/tests/integration/api_repo_teams_test.go
@@ -37,15 +37,15 @@ func TestAPIRepoTeams(t *testing.T) {
var teams []*api.Team
DecodeJSON(t, res, &teams)
if assert.Len(t, teams, 2) {
- assert.EqualValues(t, "Owners", teams[0].Name)
+ assert.Equal(t, "Owners", teams[0].Name)
assert.True(t, teams[0].CanCreateOrgRepo)
assert.True(t, util.SliceSortedEqual(unit.AllUnitKeyNames(), teams[0].Units), "%v == %v", unit.AllUnitKeyNames(), teams[0].Units)
- assert.EqualValues(t, "owner", teams[0].Permission)
+ assert.Equal(t, "owner", teams[0].Permission)
- assert.EqualValues(t, "test_team", teams[1].Name)
+ assert.Equal(t, "test_team", teams[1].Name)
assert.False(t, teams[1].CanCreateOrgRepo)
- assert.EqualValues(t, []string{"repo.issues"}, teams[1].Units)
- assert.EqualValues(t, "write", teams[1].Permission)
+ assert.Equal(t, []string{"repo.issues"}, teams[1].Units)
+ assert.Equal(t, "write", teams[1].Permission)
}
// IsTeam
@@ -54,7 +54,7 @@ func TestAPIRepoTeams(t *testing.T) {
res = MakeRequest(t, req, http.StatusOK)
var team *api.Team
DecodeJSON(t, res, &team)
- assert.EqualValues(t, teams[1], team)
+ assert.Equal(t, teams[1], team)
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/teams/%s", publicOrgRepo.FullName(), "NonExistingTeam")).
AddTokenAuth(token)
diff --git a/tests/integration/api_repo_test.go b/tests/integration/api_repo_test.go
index 13dc90f8a7..a2c3a467c6 100644
--- a/tests/integration/api_repo_test.go
+++ b/tests/integration/api_repo_test.go
@@ -37,7 +37,7 @@ func TestAPIUserReposNotLogin(t *testing.T) {
unittest.Cond("is_private = ?", false))
assert.Len(t, apiRepos, expectedLen)
for _, repo := range apiRepos {
- assert.EqualValues(t, user.ID, repo.Owner.ID)
+ assert.Equal(t, user.ID, repo.Owner.ID)
assert.False(t, repo.Private)
}
}
@@ -45,7 +45,7 @@ func TestAPIUserReposNotLogin(t *testing.T) {
func TestAPIUserReposWithWrongToken(t *testing.T) {
defer tests.PrepareTestEnv(t)()
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
- wrongToken := fmt.Sprintf("Bearer %s", "wrong_token")
+ wrongToken := "Bearer " + "wrong_token"
req := NewRequestf(t, "GET", "/api/v1/users/%s/repos", user.Name).
AddTokenAuth(wrongToken)
resp := MakeRequest(t, req, http.StatusUnauthorized)
@@ -266,25 +266,25 @@ func TestAPIViewRepo(t *testing.T) {
resp := MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &repo)
assert.EqualValues(t, 1, repo.ID)
- assert.EqualValues(t, "repo1", repo.Name)
- assert.EqualValues(t, 2, repo.Releases)
- assert.EqualValues(t, 1, repo.OpenIssues)
- assert.EqualValues(t, 3, repo.OpenPulls)
+ assert.Equal(t, "repo1", repo.Name)
+ assert.Equal(t, 2, repo.Releases)
+ assert.Equal(t, 1, repo.OpenIssues)
+ assert.Equal(t, 3, repo.OpenPulls)
req = NewRequest(t, "GET", "/api/v1/repos/user12/repo10")
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &repo)
assert.EqualValues(t, 10, repo.ID)
- assert.EqualValues(t, "repo10", repo.Name)
- assert.EqualValues(t, 1, repo.OpenPulls)
- assert.EqualValues(t, 1, repo.Forks)
+ assert.Equal(t, "repo10", repo.Name)
+ assert.Equal(t, 1, repo.OpenPulls)
+ assert.Equal(t, 1, repo.Forks)
req = NewRequest(t, "GET", "/api/v1/repos/user5/repo4")
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &repo)
assert.EqualValues(t, 4, repo.ID)
- assert.EqualValues(t, "repo4", repo.Name)
- assert.EqualValues(t, 1, repo.Stars)
+ assert.Equal(t, "repo4", repo.Name)
+ assert.Equal(t, 1, repo.Stars)
}
func TestAPIOrgRepos(t *testing.T) {
@@ -337,9 +337,9 @@ func TestAPIOrgReposWithCodeUnitDisabled(t *testing.T) {
var units []unit_model.Type
units = append(units, unit_model.TypeCode)
- if err := repo_service.UpdateRepositoryUnits(db.DefaultContext, repo21, nil, units); err != nil {
- assert.Fail(t, "should have been able to delete code repository unit; failed to %v", err)
- }
+ err := repo_service.UpdateRepositoryUnits(db.DefaultContext, repo21, nil, units)
+ assert.NoError(t, err, "should have been able to delete code repository unit")
+
assert.False(t, repo21.UnitEnabled(db.DefaultContext, unit_model.TypeCode))
session := loginUser(t, "user2")
@@ -403,12 +403,12 @@ func TestAPIRepoMigrate(t *testing.T) {
case "Remote visit addressed rate limitation.":
t.Log("test hit github rate limitation")
case "You can not import from disallowed hosts.":
- assert.EqualValues(t, "private-ip", testCase.repoName)
+ assert.Equal(t, "private-ip", testCase.repoName)
default:
- assert.FailNow(t, "unexpected error '%v' on url '%s'", respJSON["message"], testCase.cloneURL)
+ assert.FailNow(t, "unexpected error", "unexpected error '%v' on url '%s'", respJSON["message"], testCase.cloneURL)
}
} else {
- assert.EqualValues(t, testCase.expectedStatus, resp.Code)
+ assert.Equal(t, testCase.expectedStatus, resp.Code)
}
}
}
@@ -471,6 +471,15 @@ func TestAPIMirrorSyncNonMirrorRepo(t *testing.T) {
assert.Equal(t, "Repository is not a mirror", errRespJSON["message"])
}
+func testAPIOrgCreateRepo(t *testing.T, session *TestSession, orgName, repoName string, status int) {
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization, auth_model.AccessTokenScopeWriteRepository)
+
+ req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/org/%s/repos", orgName), &api.CreateRepoOption{
+ Name: repoName,
+ }).AddTokenAuth(token)
+ MakeRequest(t, req, status)
+}
+
func TestAPIOrgRepoCreate(t *testing.T) {
testCases := []struct {
ctxUserID int64
@@ -488,11 +497,7 @@ func TestAPIOrgRepoCreate(t *testing.T) {
for _, testCase := range testCases {
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: testCase.ctxUserID})
session := loginUser(t, user.Name)
- token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization, auth_model.AccessTokenScopeWriteRepository)
- req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/org/%s/repos", testCase.orgName), &api.CreateRepoOption{
- Name: testCase.repoName,
- }).AddTokenAuth(token)
- MakeRequest(t, req, testCase.expectedStatus)
+ testAPIOrgCreateRepo(t, session, testCase.orgName, testCase.repoName, testCase.expectedStatus)
}
}
@@ -581,7 +586,7 @@ func TestAPIRepoTransfer(t *testing.T) {
// cleanup
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID})
- _ = repo_service.DeleteRepositoryDirectly(db.DefaultContext, user, repo.ID)
+ _ = repo_service.DeleteRepositoryDirectly(db.DefaultContext, repo.ID)
}
func transfer(t *testing.T) *repo_model.Repository {
diff --git a/tests/integration/api_repo_topic_test.go b/tests/integration/api_repo_topic_test.go
index a10e159b78..82d0c54ca8 100644
--- a/tests/integration/api_repo_topic_test.go
+++ b/tests/integration/api_repo_topic_test.go
@@ -30,7 +30,7 @@ func TestAPITopicSearch(t *testing.T) {
res := MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
DecodeJSON(t, res, &topics)
assert.Len(t, topics.TopicNames, 6)
- assert.EqualValues(t, "6", res.Header().Get("x-total-count"))
+ assert.Equal(t, "6", res.Header().Get("x-total-count"))
// pagination search topics first page
topics.TopicNames = nil
@@ -40,7 +40,7 @@ func TestAPITopicSearch(t *testing.T) {
res = MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
DecodeJSON(t, res, &topics)
assert.Len(t, topics.TopicNames, 4)
- assert.EqualValues(t, "6", res.Header().Get("x-total-count"))
+ assert.Equal(t, "6", res.Header().Get("x-total-count"))
// pagination search topics second page
topics.TopicNames = nil
@@ -50,7 +50,7 @@ func TestAPITopicSearch(t *testing.T) {
res = MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
DecodeJSON(t, res, &topics)
assert.Len(t, topics.TopicNames, 2)
- assert.EqualValues(t, "6", res.Header().Get("x-total-count"))
+ assert.Equal(t, "6", res.Header().Get("x-total-count"))
// add keyword search
query = url.Values{"page": []string{"1"}, "limit": []string{"4"}}
@@ -66,8 +66,8 @@ func TestAPITopicSearch(t *testing.T) {
DecodeJSON(t, res, &topics)
if assert.Len(t, topics.TopicNames, 1) {
assert.EqualValues(t, 2, topics.TopicNames[0].ID)
- assert.EqualValues(t, "database", topics.TopicNames[0].Name)
- assert.EqualValues(t, 1, topics.TopicNames[0].RepoCount)
+ assert.Equal(t, "database", topics.TopicNames[0].Name)
+ assert.Equal(t, 1, topics.TopicNames[0].RepoCount)
}
}
diff --git a/tests/integration/api_repo_variables_test.go b/tests/integration/api_repo_variables_test.go
index 7847962b07..b5c88af279 100644
--- a/tests/integration/api_repo_variables_test.go
+++ b/tests/integration/api_repo_variables_test.go
@@ -35,11 +35,11 @@ func TestAPIRepoVariables(t *testing.T) {
},
{
Name: "_",
- ExpectedStatus: http.StatusNoContent,
+ ExpectedStatus: http.StatusCreated,
},
{
Name: "TEST_VAR",
- ExpectedStatus: http.StatusNoContent,
+ ExpectedStatus: http.StatusCreated,
},
{
Name: "test_var",
@@ -81,7 +81,7 @@ func TestAPIRepoVariables(t *testing.T) {
req := NewRequestWithJSON(t, "POST", url, api.CreateVariableOption{
Value: "initial_val",
}).AddTokenAuth(token)
- MakeRequest(t, req, http.StatusNoContent)
+ MakeRequest(t, req, http.StatusCreated)
cases := []struct {
Name string
@@ -138,7 +138,7 @@ func TestAPIRepoVariables(t *testing.T) {
req := NewRequestWithJSON(t, "POST", url, api.CreateVariableOption{
Value: "initial_val",
}).AddTokenAuth(token)
- MakeRequest(t, req, http.StatusNoContent)
+ MakeRequest(t, req, http.StatusCreated)
req = NewRequest(t, "DELETE", url).AddTokenAuth(token)
MakeRequest(t, req, http.StatusNoContent)
diff --git a/tests/integration/api_settings_test.go b/tests/integration/api_settings_test.go
index 9881578fba..743dbb0481 100644
--- a/tests/integration/api_settings_test.go
+++ b/tests/integration/api_settings_test.go
@@ -30,11 +30,12 @@ func TestAPIExposedSettings(t *testing.T) {
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiSettings)
- assert.EqualValues(t, &api.GeneralAPISettings{
+ assert.Equal(t, &api.GeneralAPISettings{
MaxResponseItems: setting.API.MaxResponseItems,
DefaultPagingNum: setting.API.DefaultPagingNum,
DefaultGitTreesPerPage: setting.API.DefaultGitTreesPerPage,
DefaultMaxBlobSize: setting.API.DefaultMaxBlobSize,
+ DefaultMaxResponseSize: setting.API.DefaultMaxResponseSize,
}, apiSettings)
repo := new(api.GeneralRepoSettings)
@@ -42,7 +43,7 @@ func TestAPIExposedSettings(t *testing.T) {
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &repo)
- assert.EqualValues(t, &api.GeneralRepoSettings{
+ assert.Equal(t, &api.GeneralRepoSettings{
MirrorsDisabled: !setting.Mirror.Enabled,
HTTPGitDisabled: setting.Repository.DisableHTTPGit,
MigrationsDisabled: setting.Repository.DisableMigrations,
@@ -55,7 +56,7 @@ func TestAPIExposedSettings(t *testing.T) {
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &attachment)
- assert.EqualValues(t, &api.GeneralAttachmentSettings{
+ assert.Equal(t, &api.GeneralAttachmentSettings{
Enabled: setting.Attachment.Enabled,
AllowedTypes: setting.Attachment.AllowedTypes,
MaxFiles: setting.Attachment.MaxFiles,
diff --git a/tests/integration/api_team_test.go b/tests/integration/api_team_test.go
index d14c66ff2c..e54203ed50 100644
--- a/tests/integration/api_team_test.go
+++ b/tests/integration/api_team_test.go
@@ -40,9 +40,9 @@ func TestAPITeam(t *testing.T) {
var apiTeam api.Team
DecodeJSON(t, resp, &apiTeam)
- assert.EqualValues(t, team.ID, apiTeam.ID)
+ assert.Equal(t, team.ID, apiTeam.ID)
assert.Equal(t, team.Name, apiTeam.Name)
- assert.EqualValues(t, convert.ToOrganization(db.DefaultContext, org), apiTeam.Organization)
+ assert.Equal(t, convert.ToOrganization(db.DefaultContext, org), apiTeam.Organization)
// non team member user will not access the teams details
teamUser2 := unittest.AssertExistsAndLoadBean(t, &organization.TeamUser{ID: 3})
@@ -78,9 +78,9 @@ func TestAPITeam(t *testing.T) {
apiTeam = api.Team{}
DecodeJSON(t, resp, &apiTeam)
checkTeamResponse(t, "CreateTeam1", &apiTeam, teamToCreate.Name, teamToCreate.Description, teamToCreate.IncludesAllRepositories,
- teamToCreate.Permission, teamToCreate.Units, nil)
+ "none", teamToCreate.Units, nil)
checkTeamBean(t, apiTeam.ID, teamToCreate.Name, teamToCreate.Description, teamToCreate.IncludesAllRepositories,
- teamToCreate.Permission, teamToCreate.Units, nil)
+ "none", teamToCreate.Units, nil)
teamID := apiTeam.ID
// Edit team.
@@ -149,9 +149,9 @@ func TestAPITeam(t *testing.T) {
apiTeam = api.Team{}
DecodeJSON(t, resp, &apiTeam)
checkTeamResponse(t, "CreateTeam2", &apiTeam, teamToCreate.Name, teamToCreate.Description, teamToCreate.IncludesAllRepositories,
- "read", nil, teamToCreate.UnitsMap)
+ "none", nil, teamToCreate.UnitsMap)
checkTeamBean(t, apiTeam.ID, teamToCreate.Name, teamToCreate.Description, teamToCreate.IncludesAllRepositories,
- "read", nil, teamToCreate.UnitsMap)
+ "none", nil, teamToCreate.UnitsMap)
teamID = apiTeam.ID
// Edit team.
@@ -171,9 +171,9 @@ func TestAPITeam(t *testing.T) {
apiTeam = api.Team{}
DecodeJSON(t, resp, &apiTeam)
checkTeamResponse(t, "EditTeam2", &apiTeam, teamToEdit.Name, *teamToEdit.Description, *teamToEdit.IncludesAllRepositories,
- "read", nil, teamToEdit.UnitsMap)
+ "none", nil, teamToEdit.UnitsMap)
checkTeamBean(t, apiTeam.ID, teamToEdit.Name, *teamToEdit.Description, *teamToEdit.IncludesAllRepositories,
- "read", nil, teamToEdit.UnitsMap)
+ "none", nil, teamToEdit.UnitsMap)
// Edit team Description only
editDescription = "second team"
@@ -184,9 +184,9 @@ func TestAPITeam(t *testing.T) {
apiTeam = api.Team{}
DecodeJSON(t, resp, &apiTeam)
checkTeamResponse(t, "EditTeam2_DescOnly", &apiTeam, teamToEdit.Name, *teamToEditDesc.Description, *teamToEdit.IncludesAllRepositories,
- "read", nil, teamToEdit.UnitsMap)
+ "none", nil, teamToEdit.UnitsMap)
checkTeamBean(t, apiTeam.ID, teamToEdit.Name, *teamToEditDesc.Description, *teamToEdit.IncludesAllRepositories,
- "read", nil, teamToEdit.UnitsMap)
+ "none", nil, teamToEdit.UnitsMap)
// Read team.
teamRead = unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID})
@@ -247,10 +247,10 @@ func checkTeamResponse(t *testing.T, testName string, apiTeam *api.Team, name, d
if units != nil {
sort.StringSlice(units).Sort()
sort.StringSlice(apiTeam.Units).Sort()
- assert.EqualValues(t, units, apiTeam.Units, "units")
+ assert.Equal(t, units, apiTeam.Units, "units")
}
if unitsMap != nil {
- assert.EqualValues(t, unitsMap, apiTeam.UnitsMap, "unitsMap")
+ assert.Equal(t, unitsMap, apiTeam.UnitsMap, "unitsMap")
}
})
}
diff --git a/tests/integration/api_team_user_test.go b/tests/integration/api_team_user_test.go
index 6c80bc9f80..cbbbe00a9e 100644
--- a/tests/integration/api_team_user_test.go
+++ b/tests/integration/api_team_user_test.go
@@ -21,29 +21,31 @@ import (
func TestAPITeamUser(t *testing.T) {
defer tests.PrepareTestEnv(t)()
-
- normalUsername := "user2"
- session := loginUser(t, normalUsername)
- token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrganization)
- req := NewRequest(t, "GET", "/api/v1/teams/1/members/user1").
- AddTokenAuth(token)
- MakeRequest(t, req, http.StatusNotFound)
-
- req = NewRequest(t, "GET", "/api/v1/teams/1/members/user2").
- AddTokenAuth(token)
- resp := MakeRequest(t, req, http.StatusOK)
- var user2 *api.User
- DecodeJSON(t, resp, &user2)
- user2.Created = user2.Created.In(time.Local)
- user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user2"})
-
- expectedUser := convert.ToUser(db.DefaultContext, user, user)
-
- // test time via unix timestamp
- assert.EqualValues(t, expectedUser.LastLogin.Unix(), user2.LastLogin.Unix())
- assert.EqualValues(t, expectedUser.Created.Unix(), user2.Created.Unix())
- expectedUser.LastLogin = user2.LastLogin
- expectedUser.Created = user2.Created
-
- assert.Equal(t, expectedUser, user2)
+ user2Session := loginUser(t, "user2")
+ user2Token := getTokenForLoggedInUser(t, user2Session, auth_model.AccessTokenScopeWriteOrganization)
+
+ t.Run("User2ReadUser1", func(t *testing.T) {
+ req := NewRequest(t, "GET", "/api/v1/teams/1/members/user1").AddTokenAuth(user2Token)
+ MakeRequest(t, req, http.StatusNotFound)
+ })
+
+ t.Run("User2ReadSelf", func(t *testing.T) {
+ // read self user
+ req := NewRequest(t, "GET", "/api/v1/teams/1/members/user2").AddTokenAuth(user2Token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ var user2 *api.User
+ DecodeJSON(t, resp, &user2)
+ user2.Created = user2.Created.In(time.Local)
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user2"})
+
+ expectedUser := convert.ToUser(db.DefaultContext, user, user)
+
+ // test time via unix timestamp
+ assert.Equal(t, expectedUser.LastLogin.Unix(), user2.LastLogin.Unix())
+ assert.Equal(t, expectedUser.Created.Unix(), user2.Created.Unix())
+ expectedUser.LastLogin = user2.LastLogin
+ expectedUser.Created = user2.Created
+
+ assert.Equal(t, expectedUser, user2)
+ })
}
diff --git a/tests/integration/api_token_test.go b/tests/integration/api_token_test.go
index 01d18ef6f1..1770358d21 100644
--- a/tests/integration/api_token_test.go
+++ b/tests/integration/api_token_test.go
@@ -507,7 +507,7 @@ func runTestCase(t *testing.T, testCase *requiredScopeTestCase, user *user_model
} else if minRequiredLevel == auth_model.Write {
unauthorizedLevel = auth_model.Read
} else {
- assert.FailNow(t, "Invalid test case: Unknown access token scope level: %v", minRequiredLevel)
+ assert.FailNow(t, "Invalid test case", "Unknown access token scope level: %v", minRequiredLevel)
}
}
diff --git a/tests/integration/api_twofa_test.go b/tests/integration/api_twofa_test.go
index 18e6fa91b7..938feba61a 100644
--- a/tests/integration/api_twofa_test.go
+++ b/tests/integration/api_twofa_test.go
@@ -94,7 +94,7 @@ func TestBasicAuthWithWebAuthn(t *testing.T) {
}
var userParsed userResponse
DecodeJSON(t, resp, &userParsed)
- assert.EqualValues(t, "Basic authorization is not allowed while webAuthn enrolled", userParsed.Message)
+ assert.Equal(t, "basic authorization is not allowed while WebAuthn enrolled", userParsed.Message)
// user32 has webauthn enrolled, he can't request git protocol with basic auth
req = NewRequest(t, "GET", "/user2/repo1/info/refs")
diff --git a/tests/integration/api_user_block_test.go b/tests/integration/api_user_block_test.go
index ae6b9eb849..6f73b089df 100644
--- a/tests/integration/api_user_block_test.go
+++ b/tests/integration/api_user_block_test.go
@@ -76,7 +76,7 @@ func TestBlockUser(t *testing.T) {
blockeeName := "user10"
t.Run("Block", func(t *testing.T) {
- req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/blocks/%s", blockeeName))
+ req := NewRequest(t, "PUT", "/api/v1/user/blocks/"+blockeeName)
MakeRequest(t, req, http.StatusUnauthorized)
assert.EqualValues(t, 1, countStars(t, blockerID, blockeeID))
@@ -84,7 +84,7 @@ func TestBlockUser(t *testing.T) {
assert.EqualValues(t, 1, countRepositoryTransfers(t, blockerID, blockeeID))
assert.EqualValues(t, 1, countCollaborations(t, blockerID, blockeeID))
- req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/blocks/%s", blockeeName)).
+ req = NewRequest(t, "GET", "/api/v1/user/blocks/"+blockeeName).
AddTokenAuth(blockerToken)
MakeRequest(t, req, http.StatusNotFound)
@@ -97,15 +97,15 @@ func TestBlockUser(t *testing.T) {
assert.EqualValues(t, 0, countRepositoryTransfers(t, blockerID, blockeeID))
assert.EqualValues(t, 0, countCollaborations(t, blockerID, blockeeID))
- req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/blocks/%s", blockeeName)).
+ req = NewRequest(t, "GET", "/api/v1/user/blocks/"+blockeeName).
AddTokenAuth(blockerToken)
MakeRequest(t, req, http.StatusNoContent)
- req = NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/blocks/%s", blockeeName)).
+ req = NewRequest(t, "PUT", "/api/v1/user/blocks/"+blockeeName).
AddTokenAuth(blockerToken)
MakeRequest(t, req, http.StatusBadRequest) // can't block blocked user
- req = NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/blocks/%s", "org3")).
+ req = NewRequest(t, "PUT", "/api/v1/user/blocks/"+"org3").
AddTokenAuth(blockerToken)
MakeRequest(t, req, http.StatusBadRequest) // can't block organization
@@ -124,18 +124,18 @@ func TestBlockUser(t *testing.T) {
})
t.Run("Unblock", func(t *testing.T) {
- req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/user/blocks/%s", blockeeName))
+ req := NewRequest(t, "DELETE", "/api/v1/user/blocks/"+blockeeName)
MakeRequest(t, req, http.StatusUnauthorized)
- req = NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/user/blocks/%s", blockeeName)).
+ req = NewRequest(t, "DELETE", "/api/v1/user/blocks/"+blockeeName).
AddTokenAuth(blockerToken)
MakeRequest(t, req, http.StatusNoContent)
- req = NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/user/blocks/%s", blockeeName)).
+ req = NewRequest(t, "DELETE", "/api/v1/user/blocks/"+blockeeName).
AddTokenAuth(blockerToken)
MakeRequest(t, req, http.StatusBadRequest)
- req = NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/user/blocks/%s", "org3")).
+ req = NewRequest(t, "DELETE", "/api/v1/user/blocks/"+"org3").
AddTokenAuth(blockerToken)
MakeRequest(t, req, http.StatusBadRequest)
diff --git a/tests/integration/api_user_email_test.go b/tests/integration/api_user_email_test.go
index 6441e2ed8e..5b6f0708ea 100644
--- a/tests/integration/api_user_email_test.go
+++ b/tests/integration/api_user_email_test.go
@@ -28,7 +28,7 @@ func TestAPIListEmails(t *testing.T) {
var emails []*api.Email
DecodeJSON(t, resp, &emails)
- assert.EqualValues(t, []*api.Email{
+ assert.Equal(t, []*api.Email{
{
Email: "user2@example.com",
Verified: true,
@@ -66,7 +66,7 @@ func TestAPIAddEmail(t *testing.T) {
var emails []*api.Email
DecodeJSON(t, resp, &emails)
- assert.EqualValues(t, []*api.Email{
+ assert.Equal(t, []*api.Email{
{
Email: "user2@example.com",
Verified: true,
@@ -119,7 +119,7 @@ func TestAPIDeleteEmail(t *testing.T) {
var emails []*api.Email
DecodeJSON(t, resp, &emails)
- assert.EqualValues(t, []*api.Email{
+ assert.Equal(t, []*api.Email{
{
Email: "user2@example.com",
Verified: true,
diff --git a/tests/integration/api_user_follow_test.go b/tests/integration/api_user_follow_test.go
index fe20af6769..6cb31a6802 100644
--- a/tests/integration/api_user_follow_test.go
+++ b/tests/integration/api_user_follow_test.go
@@ -32,7 +32,7 @@ func TestAPIFollow(t *testing.T) {
t.Run("Follow", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/following/%s", user1)).
+ req := NewRequest(t, "PUT", "/api/v1/user/following/"+user1).
AddTokenAuth(token2)
MakeRequest(t, req, http.StatusNoContent)
@@ -110,11 +110,11 @@ func TestAPIFollow(t *testing.T) {
t.Run("CheckMyFollowing", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/following/%s", user1)).
+ req := NewRequest(t, "GET", "/api/v1/user/following/"+user1).
AddTokenAuth(token2)
MakeRequest(t, req, http.StatusNoContent)
- req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/following/%s", user2)).
+ req = NewRequest(t, "GET", "/api/v1/user/following/"+user2).
AddTokenAuth(token1)
MakeRequest(t, req, http.StatusNotFound)
})
@@ -122,7 +122,7 @@ func TestAPIFollow(t *testing.T) {
t.Run("Unfollow", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/user/following/%s", user1)).
+ req := NewRequest(t, "DELETE", "/api/v1/user/following/"+user1).
AddTokenAuth(token2)
MakeRequest(t, req, http.StatusNoContent)
})
diff --git a/tests/integration/api_user_info_test.go b/tests/integration/api_user_info_test.go
index 89f7266859..06353eabe0 100644
--- a/tests/integration/api_user_info_test.go
+++ b/tests/integration/api_user_info_test.go
@@ -4,7 +4,6 @@
package integration
import (
- "fmt"
"net/http"
"testing"
@@ -31,7 +30,7 @@ func TestAPIUserInfo(t *testing.T) {
t.Run("GetInfo", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/users/%s", user2)).
+ req := NewRequest(t, "GET", "/api/v1/users/"+user2).
AddTokenAuth(token)
resp := MakeRequest(t, req, http.StatusOK)
@@ -39,17 +38,17 @@ func TestAPIUserInfo(t *testing.T) {
DecodeJSON(t, resp, &u)
assert.Equal(t, user2, u.UserName)
- req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/users/%s", user2))
+ req = NewRequest(t, "GET", "/api/v1/users/"+user2)
MakeRequest(t, req, http.StatusNotFound)
// test if the placaholder Mail is returned if a User is not logged in
- req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/users/%s", org3.Name))
+ req = NewRequest(t, "GET", "/api/v1/users/"+org3.Name)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &u)
assert.Equal(t, org3.GetPlaceholderEmail(), u.Email)
// Test if the correct Mail is returned if a User is logged in
- req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/users/%s", org3.Name)).
+ req = NewRequest(t, "GET", "/api/v1/users/"+org3.Name).
AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &u)
diff --git a/tests/integration/api_user_search_test.go b/tests/integration/api_user_search_test.go
index 5604a14259..97264969eb 100644
--- a/tests/integration/api_user_search_test.go
+++ b/tests/integration/api_user_search_test.go
@@ -66,7 +66,7 @@ func TestAPIUserSearchNotLoggedIn(t *testing.T) {
for _, user := range results.Data {
assert.Contains(t, user.UserName, query)
modelUser = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: user.ID})
- assert.EqualValues(t, modelUser.GetPlaceholderEmail(), user.Email)
+ assert.Equal(t, modelUser.GetPlaceholderEmail(), user.Email)
}
}
@@ -85,8 +85,8 @@ func TestAPIUserSearchSystemUsers(t *testing.T) {
assert.NotEmpty(t, results.Data)
if assert.Len(t, results.Data, 1) {
user := results.Data[0]
- assert.EqualValues(t, user.UserName, systemUser.Name)
- assert.EqualValues(t, user.ID, systemUser.ID)
+ assert.Equal(t, user.UserName, systemUser.Name)
+ assert.Equal(t, user.ID, systemUser.ID)
}
})
}
@@ -108,7 +108,7 @@ func TestAPIUserSearchAdminLoggedInUserHidden(t *testing.T) {
for _, user := range results.Data {
assert.Contains(t, user.UserName, query)
assert.NotEmpty(t, user.Email)
- assert.EqualValues(t, "private", user.Visibility)
+ assert.Equal(t, "private", user.Visibility)
}
}
diff --git a/tests/integration/api_user_secrets_test.go b/tests/integration/api_user_secrets_test.go
index 56bf30e804..10024ac090 100644
--- a/tests/integration/api_user_secrets_test.go
+++ b/tests/integration/api_user_secrets_test.go
@@ -4,7 +4,6 @@
package integration
import (
- "fmt"
"net/http"
"testing"
@@ -55,7 +54,7 @@ func TestAPIUserSecrets(t *testing.T) {
}
for _, c := range cases {
- req := NewRequestWithJSON(t, "PUT", fmt.Sprintf("/api/v1/user/actions/secrets/%s", c.Name), api.CreateOrUpdateSecretOption{
+ req := NewRequestWithJSON(t, "PUT", "/api/v1/user/actions/secrets/"+c.Name, api.CreateOrUpdateSecretOption{
Data: "data",
}).AddTokenAuth(token)
MakeRequest(t, req, c.ExpectedStatus)
@@ -64,7 +63,7 @@ func TestAPIUserSecrets(t *testing.T) {
t.Run("Update", func(t *testing.T) {
name := "update_secret"
- url := fmt.Sprintf("/api/v1/user/actions/secrets/%s", name)
+ url := "/api/v1/user/actions/secrets/" + name
req := NewRequestWithJSON(t, "PUT", url, api.CreateOrUpdateSecretOption{
Data: "initial",
@@ -79,7 +78,7 @@ func TestAPIUserSecrets(t *testing.T) {
t.Run("Delete", func(t *testing.T) {
name := "delete_secret"
- url := fmt.Sprintf("/api/v1/user/actions/secrets/%s", name)
+ url := "/api/v1/user/actions/secrets/" + name
req := NewRequestWithJSON(t, "PUT", url, api.CreateOrUpdateSecretOption{
Data: "initial",
diff --git a/tests/integration/api_user_star_test.go b/tests/integration/api_user_star_test.go
index 0062889a92..989e7ab1d1 100644
--- a/tests/integration/api_user_star_test.go
+++ b/tests/integration/api_user_star_test.go
@@ -11,7 +11,9 @@ import (
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
@@ -30,13 +32,13 @@ func TestAPIStar(t *testing.T) {
t.Run("Star", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/starred/%s", repo)).
+ req := NewRequest(t, "PUT", "/api/v1/user/starred/"+repo).
AddTokenAuth(tokenWithUserScope)
MakeRequest(t, req, http.StatusNoContent)
// blocked user can't star a repo
user34 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 34})
- req = NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/starred/%s", repo)).
+ req = NewRequest(t, "PUT", "/api/v1/user/starred/"+repo).
AddTokenAuth(getUserToken(t, user34.Name, auth_model.AccessTokenScopeWriteRepository))
MakeRequest(t, req, http.StatusForbidden)
})
@@ -74,11 +76,11 @@ func TestAPIStar(t *testing.T) {
t.Run("IsStarring", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred/%s", repo)).
+ req := NewRequest(t, "GET", "/api/v1/user/starred/"+repo).
AddTokenAuth(tokenWithUserScope)
MakeRequest(t, req, http.StatusNoContent)
- req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred/%s", repo+"notexisting")).
+ req = NewRequest(t, "GET", "/api/v1/user/starred/"+repo+"notexisting").
AddTokenAuth(tokenWithUserScope)
MakeRequest(t, req, http.StatusNotFound)
})
@@ -86,8 +88,70 @@ func TestAPIStar(t *testing.T) {
t.Run("Unstar", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
- req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/user/starred/%s", repo)).
+ req := NewRequest(t, "DELETE", "/api/v1/user/starred/"+repo).
AddTokenAuth(tokenWithUserScope)
MakeRequest(t, req, http.StatusNoContent)
})
}
+
+func TestAPIStarDisabled(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ user := "user1"
+ repo := "user2/repo1"
+
+ session := loginUser(t, user)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser)
+ tokenWithUserScope := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser, auth_model.AccessTokenScopeWriteRepository)
+
+ defer test.MockVariableValue(&setting.Repository.DisableStars, true)()
+
+ t.Run("Star", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ req := NewRequest(t, "PUT", "/api/v1/user/starred/"+repo).
+ AddTokenAuth(tokenWithUserScope)
+ MakeRequest(t, req, http.StatusForbidden)
+
+ user34 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 34})
+ req = NewRequest(t, "PUT", "/api/v1/user/starred/"+repo).
+ AddTokenAuth(getUserToken(t, user34.Name, auth_model.AccessTokenScopeWriteRepository))
+ MakeRequest(t, req, http.StatusForbidden)
+ })
+
+ t.Run("GetStarredRepos", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/users/%s/starred", user)).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusForbidden)
+ })
+
+ t.Run("GetMyStarredRepos", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ req := NewRequest(t, "GET", "/api/v1/user/starred").
+ AddTokenAuth(tokenWithUserScope)
+ MakeRequest(t, req, http.StatusForbidden)
+ })
+
+ t.Run("IsStarring", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ req := NewRequest(t, "GET", "/api/v1/user/starred/"+repo).
+ AddTokenAuth(tokenWithUserScope)
+ MakeRequest(t, req, http.StatusForbidden)
+
+ req = NewRequest(t, "GET", "/api/v1/user/starred/"+repo+"notexisting").
+ AddTokenAuth(tokenWithUserScope)
+ MakeRequest(t, req, http.StatusForbidden)
+ })
+
+ t.Run("Unstar", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ req := NewRequest(t, "DELETE", "/api/v1/user/starred/"+repo).
+ AddTokenAuth(tokenWithUserScope)
+ MakeRequest(t, req, http.StatusForbidden)
+ })
+}
diff --git a/tests/integration/api_user_variables_test.go b/tests/integration/api_user_variables_test.go
index 9fd84ddf81..d430c9e21d 100644
--- a/tests/integration/api_user_variables_test.go
+++ b/tests/integration/api_user_variables_test.go
@@ -4,7 +4,6 @@
package integration
import (
- "fmt"
"net/http"
"testing"
@@ -30,11 +29,11 @@ func TestAPIUserVariables(t *testing.T) {
},
{
Name: "_",
- ExpectedStatus: http.StatusNoContent,
+ ExpectedStatus: http.StatusCreated,
},
{
Name: "TEST_VAR",
- ExpectedStatus: http.StatusNoContent,
+ ExpectedStatus: http.StatusCreated,
},
{
Name: "test_var",
@@ -63,7 +62,7 @@ func TestAPIUserVariables(t *testing.T) {
}
for _, c := range cases {
- req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/user/actions/variables/%s", c.Name), api.CreateVariableOption{
+ req := NewRequestWithJSON(t, "POST", "/api/v1/user/actions/variables/"+c.Name, api.CreateVariableOption{
Value: "value",
}).AddTokenAuth(token)
MakeRequest(t, req, c.ExpectedStatus)
@@ -72,11 +71,11 @@ func TestAPIUserVariables(t *testing.T) {
t.Run("UpdateUserVariable", func(t *testing.T) {
variableName := "test_update_var"
- url := fmt.Sprintf("/api/v1/user/actions/variables/%s", variableName)
+ url := "/api/v1/user/actions/variables/" + variableName
req := NewRequestWithJSON(t, "POST", url, api.CreateVariableOption{
Value: "initial_val",
}).AddTokenAuth(token)
- MakeRequest(t, req, http.StatusNoContent)
+ MakeRequest(t, req, http.StatusCreated)
cases := []struct {
Name string
@@ -118,7 +117,7 @@ func TestAPIUserVariables(t *testing.T) {
}
for _, c := range cases {
- req := NewRequestWithJSON(t, "PUT", fmt.Sprintf("/api/v1/user/actions/variables/%s", c.Name), api.UpdateVariableOption{
+ req := NewRequestWithJSON(t, "PUT", "/api/v1/user/actions/variables/"+c.Name, api.UpdateVariableOption{
Name: c.UpdateName,
Value: "updated_val",
}).AddTokenAuth(token)
@@ -128,12 +127,12 @@ func TestAPIUserVariables(t *testing.T) {
t.Run("DeleteRepoVariable", func(t *testing.T) {
variableName := "test_delete_var"
- url := fmt.Sprintf("/api/v1/user/actions/variables/%s", variableName)
+ url := "/api/v1/user/actions/variables/" + variableName
req := NewRequestWithJSON(t, "POST", url, api.CreateVariableOption{
Value: "initial_val",
}).AddTokenAuth(token)
- MakeRequest(t, req, http.StatusNoContent)
+ MakeRequest(t, req, http.StatusCreated)
req = NewRequest(t, "DELETE", url).AddTokenAuth(token)
MakeRequest(t, req, http.StatusNoContent)
diff --git a/tests/integration/api_wiki_test.go b/tests/integration/api_wiki_test.go
index 05d90fc4e3..8e5f67e282 100644
--- a/tests/integration/api_wiki_test.go
+++ b/tests/integration/api_wiki_test.go
@@ -172,6 +172,19 @@ func TestAPIListWikiPages(t *testing.T) {
assert.Equal(t, dummymeta, meta)
}
+func testAPICreateWikiPage(t *testing.T, session *TestSession, userName, repoName, title string, status int) {
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/new", userName, repoName)
+
+ req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateWikiPageOptions{
+ Title: title,
+ ContentBase64: base64.StdEncoding.EncodeToString([]byte("Wiki page content for API unit tests")),
+ Message: "",
+ }).AddTokenAuth(token)
+ MakeRequest(t, req, status)
+}
+
func TestAPINewWikiPage(t *testing.T) {
for _, title := range []string{
"New page",
@@ -180,16 +193,7 @@ func TestAPINewWikiPage(t *testing.T) {
defer tests.PrepareTestEnv(t)()
username := "user2"
session := loginUser(t, username)
- token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
-
- urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/new", username, "repo1")
-
- req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateWikiPageOptions{
- Title: title,
- ContentBase64: base64.StdEncoding.EncodeToString([]byte("Wiki page content for API unit tests")),
- Message: "",
- }).AddTokenAuth(token)
- MakeRequest(t, req, http.StatusCreated)
+ testAPICreateWikiPage(t, session, username, "repo1", title, http.StatusCreated)
}
}
diff --git a/tests/integration/auth_ldap_test.go b/tests/integration/auth_ldap_test.go
index 5c50fd0288..24f0c03bed 100644
--- a/tests/integration/auth_ldap_test.go
+++ b/tests/integration/auth_ldap_test.go
@@ -4,7 +4,6 @@
package integration
import (
- "context"
"net/http"
"os"
"strings"
@@ -16,6 +15,7 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/optional"
+ "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/util"
@@ -238,7 +238,7 @@ func TestLDAPUserSync(t *testing.T) {
defer tests.PrepareTestEnv(t)()
te.addAuthSource(t)
- err := auth.SyncExternalUsers(context.Background(), true)
+ err := auth.SyncExternalUsers(t.Context(), true)
assert.NoError(t, err)
// Check if users exists
@@ -279,7 +279,7 @@ func TestLDAPUserSyncWithEmptyUsernameAttribute(t *testing.T) {
htmlDoc := NewHTMLParser(t, resp.Body)
- tr := htmlDoc.doc.Find("table.table tbody tr")
+ tr := htmlDoc.doc.Find("table.table tbody tr:not(.no-results-row)")
assert.Equal(t, 0, tr.Length())
}
@@ -292,7 +292,7 @@ func TestLDAPUserSyncWithEmptyUsernameAttribute(t *testing.T) {
MakeRequest(t, req, http.StatusSeeOther)
}
- require.NoError(t, auth.SyncExternalUsers(context.Background(), true))
+ require.NoError(t, auth.SyncExternalUsers(t.Context(), true))
authSource := unittest.AssertExistsAndLoadBean(t, &auth_model.Source{
Name: payload["name"],
@@ -328,7 +328,7 @@ func TestLDAPUserSyncWithGroupFilter(t *testing.T) {
u := te.otherLDAPUsers[0]
testLoginFailed(t, u.UserName, u.Password, translation.NewLocale("en-US").TrString("form.username_password_incorrect"))
- require.NoError(t, auth.SyncExternalUsers(context.Background(), true))
+ require.NoError(t, auth.SyncExternalUsers(t.Context(), true))
// Assert members of LDAP group "cn=git" are added
for _, gitLDAPUser := range te.gitLDAPUsers {
@@ -351,7 +351,7 @@ func TestLDAPUserSyncWithGroupFilter(t *testing.T) {
ldapConfig.GroupFilter = "(cn=ship_crew)"
require.NoError(t, auth_model.UpdateSource(db.DefaultContext, ldapSource))
- require.NoError(t, auth.SyncExternalUsers(context.Background(), true))
+ require.NoError(t, auth.SyncExternalUsers(t.Context(), true))
for _, gitLDAPUser := range te.gitLDAPUsers {
if gitLDAPUser.UserName == "fry" || gitLDAPUser.UserName == "leela" || gitLDAPUser.UserName == "bender" {
@@ -392,7 +392,7 @@ func TestLDAPUserSSHKeySync(t *testing.T) {
defer tests.PrepareTestEnv(t)()
te.addAuthSource(t, ldapAuthOptions{attributeSSHPublicKey: "sshPublicKey"})
- require.NoError(t, auth.SyncExternalUsers(context.Background(), true))
+ require.NoError(t, auth.SyncExternalUsers(t.Context(), true))
// Check if users has SSH keys synced
for _, u := range te.gitLDAPUsers {
@@ -432,14 +432,14 @@ func TestLDAPGroupTeamSyncAddMember(t *testing.T) {
assert.NoError(t, err)
team, err := organization.GetTeam(db.DefaultContext, org.ID, "team11")
assert.NoError(t, err)
- require.NoError(t, auth.SyncExternalUsers(context.Background(), true))
+ require.NoError(t, auth.SyncExternalUsers(t.Context(), true))
for _, gitLDAPUser := range te.gitLDAPUsers {
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{
Name: gitLDAPUser.UserName,
})
usersOrgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
- UserID: user.ID,
- IncludePrivate: true,
+ UserID: user.ID,
+ IncludeVisibility: structs.VisibleTypePrivate,
})
assert.NoError(t, err)
allOrgTeams, err := organization.GetUserOrgTeams(db.DefaultContext, org.ID, user.ID)
diff --git a/tests/integration/benchmarks_test.go b/tests/integration/benchmarks_test.go
deleted file mode 100644
index 62da761d2d..0000000000
--- a/tests/integration/benchmarks_test.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2017 The Gitea Authors. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-package integration
-
-import (
- "math/rand/v2"
- "net/http"
- "net/url"
- "testing"
-
- repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/models/unittest"
- api "code.gitea.io/gitea/modules/structs"
-)
-
-// StringWithCharset random string (from https://www.calhoun.io/creating-random-strings-in-go/)
-func StringWithCharset(length int, charset string) string {
- b := make([]byte, length)
- for i := range b {
- b[i] = charset[rand.IntN(len(charset))]
- }
- return string(b)
-}
-
-func BenchmarkRepoBranchCommit(b *testing.B) {
- onGiteaRun(b, func(b *testing.B, u *url.URL) {
- samples := []int64{1, 2, 3}
- b.ResetTimer()
-
- for _, repoID := range samples {
- b.StopTimer()
- repo := unittest.AssertExistsAndLoadBean(b, &repo_model.Repository{ID: repoID})
- b.StartTimer()
- b.Run(repo.Name, func(b *testing.B) {
- session := loginUser(b, "user2")
- b.ResetTimer()
- b.Run("CreateBranch", func(b *testing.B) {
- b.StopTimer()
- branchName := StringWithCharset(5+rand.IntN(10), "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- b.Run("new_"+branchName, func(b *testing.B) {
- b.Skip("benchmark broken") // TODO fix
- testAPICreateBranch(b, session, repo.OwnerName, repo.Name, repo.DefaultBranch, "new_"+branchName, http.StatusCreated)
- })
- }
- })
- b.Run("GetBranches", func(b *testing.B) {
- req := NewRequestf(b, "GET", "/api/v1/repos/%s/branches", repo.FullName())
- session.MakeRequest(b, req, http.StatusOK)
- })
- b.Run("AccessCommits", func(b *testing.B) {
- var branches []*api.Branch
- req := NewRequestf(b, "GET", "/api/v1/repos/%s/branches", repo.FullName())
- resp := session.MakeRequest(b, req, http.StatusOK)
- DecodeJSON(b, resp, &branches)
- b.ResetTimer() // We measure from here
- if len(branches) != 0 {
- for i := 0; i < b.N; i++ {
- req := NewRequestf(b, "GET", "/api/v1/repos/%s/commits?sha=%s", repo.FullName(), branches[i%len(branches)].Name)
- session.MakeRequest(b, req, http.StatusOK)
- }
- }
- })
- })
- }
- })
-}
diff --git a/tests/integration/change_default_branch_test.go b/tests/integration/change_default_branch_test.go
index 729eb1e4ce..9b61cff9fd 100644
--- a/tests/integration/change_default_branch_test.go
+++ b/tests/integration/change_default_branch_test.go
@@ -6,12 +6,16 @@ package integration
import (
"fmt"
"net/http"
+ "strconv"
"testing"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/tests"
+
+ "github.com/stretchr/testify/assert"
)
func TestChangeDefaultBranch(t *testing.T) {
@@ -38,3 +42,96 @@ func TestChangeDefaultBranch(t *testing.T) {
})
session.MakeRequest(t, req, http.StatusNotFound)
}
+
+func checkDivergence(t *testing.T, session *TestSession, branchesURL, expectedDefaultBranch string, expectedBranchToDivergence map[string]git.DivergeObject) {
+ req := NewRequest(t, "GET", branchesURL)
+ resp := session.MakeRequest(t, req, http.StatusOK)
+
+ htmlDoc := NewHTMLParser(t, resp.Body)
+
+ branchNodes := htmlDoc.doc.Find(".branch-name").Nodes
+ branchNames := []string{}
+ for _, node := range branchNodes {
+ branchNames = append(branchNames, node.FirstChild.Data)
+ }
+
+ expectBranchCount := len(expectedBranchToDivergence)
+
+ assert.Len(t, branchNames, expectBranchCount+1)
+ assert.Equal(t, expectedDefaultBranch, branchNames[0])
+
+ allCountBehindNodes := htmlDoc.doc.Find(".count-behind").Nodes
+ allCountAheadNodes := htmlDoc.doc.Find(".count-ahead").Nodes
+
+ assert.Len(t, allCountAheadNodes, expectBranchCount)
+ assert.Len(t, allCountBehindNodes, expectBranchCount)
+
+ for i := range expectBranchCount {
+ branchName := branchNames[i+1]
+ assert.Contains(t, expectedBranchToDivergence, branchName)
+
+ expectedCountAhead := expectedBranchToDivergence[branchName].Ahead
+ expectedCountBehind := expectedBranchToDivergence[branchName].Behind
+ countAhead, err := strconv.Atoi(allCountAheadNodes[i].FirstChild.Data)
+ assert.NoError(t, err)
+ countBehind, err := strconv.Atoi(allCountBehindNodes[i].FirstChild.Data)
+ assert.NoError(t, err)
+
+ assert.Equal(t, expectedCountAhead, countAhead)
+ assert.Equal(t, expectedCountBehind, countBehind)
+ }
+}
+
+func TestChangeDefaultBranchDivergence(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16})
+ owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+
+ session := loginUser(t, owner.Name)
+ branchesURL := fmt.Sprintf("/%s/%s/branches", owner.Name, repo.Name)
+ settingsBranchesURL := fmt.Sprintf("/%s/%s/settings/branches", owner.Name, repo.Name)
+
+ // check branch divergence before switching default branch
+ expectedBranchToDivergenceBefore := map[string]git.DivergeObject{
+ "not-signed": {
+ Ahead: 0,
+ Behind: 0,
+ },
+ "good-sign-not-yet-validated": {
+ Ahead: 0,
+ Behind: 1,
+ },
+ "good-sign": {
+ Ahead: 1,
+ Behind: 3,
+ },
+ }
+ checkDivergence(t, session, branchesURL, "master", expectedBranchToDivergenceBefore)
+
+ // switch default branch
+ newDefaultBranch := "good-sign-not-yet-validated"
+ csrf := GetUserCSRFToken(t, session)
+ req := NewRequestWithValues(t, "POST", settingsBranchesURL, map[string]string{
+ "_csrf": csrf,
+ "action": "default_branch",
+ "branch": newDefaultBranch,
+ })
+ session.MakeRequest(t, req, http.StatusSeeOther)
+
+ // check branch divergence after switching default branch
+ expectedBranchToDivergenceAfter := map[string]git.DivergeObject{
+ "master": {
+ Ahead: 1,
+ Behind: 0,
+ },
+ "not-signed": {
+ Ahead: 1,
+ Behind: 0,
+ },
+ "good-sign": {
+ Ahead: 1,
+ Behind: 2,
+ },
+ }
+ checkDivergence(t, session, branchesURL, newDefaultBranch, expectedBranchToDivergenceAfter)
+}
diff --git a/tests/integration/cmd_keys_test.go b/tests/integration/cmd_keys_test.go
index 61f11c58b0..3878302ef0 100644
--- a/tests/integration/cmd_keys_test.go
+++ b/tests/integration/cmd_keys_test.go
@@ -13,7 +13,7 @@ import (
"code.gitea.io/gitea/modules/util"
"github.com/stretchr/testify/assert"
- "github.com/urfave/cli/v2"
+ "github.com/urfave/cli/v3"
)
func Test_CmdKeys(t *testing.T) {
@@ -36,18 +36,21 @@ func Test_CmdKeys(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- out := new(bytes.Buffer)
- app := cli.NewApp()
- app.Writer = out
- app.Commands = []*cli.Command{cmd.CmdKeys}
+ var stdout, stderr bytes.Buffer
+ app := &cli.Command{
+ Writer: &stdout,
+ ErrWriter: &stderr,
+ Commands: []*cli.Command{cmd.CmdKeys},
+ }
cmd.CmdKeys.HideHelp = true
- err := app.Run(append([]string{"prog"}, tt.args...))
+ err := app.Run(t.Context(), append([]string{"prog"}, tt.args...))
if tt.wantErr {
assert.Error(t, err)
+ assert.Equal(t, tt.expectedOutput, stderr.String())
} else {
assert.NoError(t, err)
+ assert.Equal(t, tt.expectedOutput, stdout.String())
}
- assert.Equal(t, tt.expectedOutput, out.String())
})
}
})
diff --git a/tests/integration/compare_test.go b/tests/integration/compare_test.go
index cbf927813e..0648777fed 100644
--- a/tests/integration/compare_test.go
+++ b/tests/integration/compare_test.go
@@ -133,7 +133,7 @@ func TestCompareCodeExpand(t *testing.T) {
Readme: "Default",
AutoInit: true,
DefaultBranch: "main",
- })
+ }, true)
assert.NoError(t, err)
session := loginUser(t, user1.Name)
diff --git a/tests/integration/db_collation_test.go b/tests/integration/db_collation_test.go
index acec4aa5d1..339bfce71c 100644
--- a/tests/integration/db_collation_test.go
+++ b/tests/integration/db_collation_test.go
@@ -75,7 +75,7 @@ func TestDatabaseCollation(t *testing.T) {
defer test.MockVariableValue(&setting.Database.CharsetCollation, "utf8mb4_bin")()
r, err := db.CheckCollations(x)
assert.NoError(t, err)
- assert.EqualValues(t, "utf8mb4_bin", r.ExpectedCollation)
+ assert.Equal(t, "utf8mb4_bin", r.ExpectedCollation)
assert.NoError(t, db.ConvertDatabaseTable())
r, err = db.CheckCollations(x)
assert.NoError(t, err)
diff --git a/tests/integration/delete_user_test.go b/tests/integration/delete_user_test.go
index ad3c882882..4b02c4725a 100644
--- a/tests/integration/delete_user_test.go
+++ b/tests/integration/delete_user_test.go
@@ -4,7 +4,6 @@
package integration
import (
- "fmt"
"net/http"
"testing"
@@ -34,7 +33,7 @@ func TestUserDeleteAccount(t *testing.T) {
session := loginUser(t, "user8")
csrf := GetUserCSRFToken(t, session)
- urlStr := fmt.Sprintf("/user/settings/account/delete?password=%s", userPassword)
+ urlStr := "/user/settings/account/delete?password=" + userPassword
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
"_csrf": csrf,
})
@@ -49,7 +48,7 @@ func TestUserDeleteAccountStillOwnRepos(t *testing.T) {
session := loginUser(t, "user2")
csrf := GetUserCSRFToken(t, session)
- urlStr := fmt.Sprintf("/user/settings/account/delete?password=%s", userPassword)
+ urlStr := "/user/settings/account/delete?password=" + userPassword
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
"_csrf": csrf,
})
diff --git a/tests/integration/dump_restore_test.go b/tests/integration/dump_restore_test.go
index abec8f300c..d2d43075c3 100644
--- a/tests/integration/dump_restore_test.go
+++ b/tests/integration/dump_restore_test.go
@@ -4,7 +4,6 @@
package integration
import (
- "context"
"errors"
"fmt"
"net/url"
@@ -21,7 +20,6 @@ import (
base "code.gitea.io/gitea/modules/migration"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/migrations"
"github.com/stretchr/testify/assert"
@@ -44,10 +42,7 @@ func TestDumpRestore(t *testing.T) {
reponame := "repo1"
- basePath, err := os.MkdirTemp("", reponame)
- assert.NoError(t, err)
- defer util.RemoveAll(basePath)
-
+ basePath := t.TempDir()
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: reponame})
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
session := loginUser(t, repoOwner.Name)
@@ -57,7 +52,7 @@ func TestDumpRestore(t *testing.T) {
// Phase 1: dump repo1 from the Gitea instance to the filesystem
//
- ctx := context.Background()
+ ctx := t.Context()
opts := migrations.MigrateOptions{
GitServiceType: structs.GiteaService,
Issues: true,
@@ -66,10 +61,10 @@ func TestDumpRestore(t *testing.T) {
Milestones: true,
Comments: true,
AuthToken: token,
- CloneAddr: repo.CloneLinkGeneral(context.Background()).HTTPS,
+ CloneAddr: repo.CloneLinkGeneral(t.Context()).HTTPS,
RepoName: reponame,
}
- err = migrations.DumpRepository(ctx, basePath, repoOwner.Name, opts)
+ err := migrations.DumpRepository(ctx, basePath, repoOwner.Name, opts)
assert.NoError(t, err)
//
@@ -96,7 +91,7 @@ func TestDumpRestore(t *testing.T) {
// Phase 3: dump restored from the Gitea instance to the filesystem
//
opts.RepoName = newreponame
- opts.CloneAddr = newrepo.CloneLinkGeneral(context.Background()).HTTPS
+ opts.CloneAddr = newrepo.CloneLinkGeneral(t.Context()).HTTPS
err = migrations.DumpRepository(ctx, basePath, repoOwner.Name, opts)
assert.NoError(t, err)
@@ -183,7 +178,7 @@ func (c *compareDump) assertEquals(repoBefore, repoAfter *repo_model.Repository)
}).([]*base.Comment)
assert.True(c.t, ok)
for _, comment := range comments {
- assert.EqualValues(c.t, issue.Number, comment.IssueIndex)
+ assert.Equal(c.t, issue.Number, comment.IssueIndex)
}
}
@@ -210,7 +205,7 @@ func (c *compareDump) assertEquals(repoBefore, repoAfter *repo_model.Repository)
comments, ok := c.assertEqual(filename, []base.Comment{}, compareFields{}).([]*base.Comment)
assert.True(c.t, ok)
for _, comment := range comments {
- assert.EqualValues(c.t, pr.Number, comment.IssueIndex)
+ assert.Equal(c.t, pr.Number, comment.IssueIndex)
}
}
}
@@ -218,7 +213,7 @@ func (c *compareDump) assertEquals(repoBefore, repoAfter *repo_model.Repository)
func (c *compareDump) assertLoadYAMLFiles(beforeFilename, afterFilename string, before, after any) {
_, beforeErr := os.Stat(beforeFilename)
_, afterErr := os.Stat(afterFilename)
- assert.EqualValues(c.t, errors.Is(beforeErr, os.ErrNotExist), errors.Is(afterErr, os.ErrNotExist))
+ assert.Equal(c.t, errors.Is(beforeErr, os.ErrNotExist), errors.Is(afterErr, os.ErrNotExist))
if errors.Is(beforeErr, os.ErrNotExist) {
return
}
@@ -270,7 +265,7 @@ func (c *compareDump) assertEqual(filename string, kind any, fields compareField
}
func (c *compareDump) assertEqualSlices(before, after reflect.Value, fields compareFields) any {
- assert.EqualValues(c.t, before.Len(), after.Len())
+ assert.Equal(c.t, before.Len(), after.Len())
if before.Len() == after.Len() {
for i := 0; i < before.Len(); i++ {
_ = c.assertEqualValues(
@@ -303,15 +298,15 @@ func (c *compareDump) assertEqualValues(before, after reflect.Value, fields comp
assert.True(c.t, ok)
as, ok := ai.(string)
assert.True(c.t, ok)
- assert.EqualValues(c.t, compare.transform(bs), compare.transform(as))
+ assert.Equal(c.t, compare.transform(bs), compare.transform(as))
continue
}
if compare.before != nil && compare.after != nil {
//
// The fields are expected to have different values
//
- assert.EqualValues(c.t, compare.before, bi)
- assert.EqualValues(c.t, compare.after, ai)
+ assert.Equal(c.t, compare.before, bi)
+ assert.Equal(c.t, compare.after, ai)
continue
}
if compare.nested != nil {
@@ -322,7 +317,7 @@ func (c *compareDump) assertEqualValues(before, after reflect.Value, fields comp
continue
}
}
- assert.EqualValues(c.t, bi, ai)
+ assert.Equal(c.t, bi, ai)
}
return after.Interface()
}
diff --git a/tests/integration/editor_test.go b/tests/integration/editor_test.go
index f0f71b80d1..ac47ed0094 100644
--- a/tests/integration/editor_test.go
+++ b/tests/integration/editor_test.go
@@ -4,175 +4,452 @@
package integration
import (
+ "bytes"
"fmt"
+ "io"
+ "maps"
+ "mime/multipart"
"net/http"
"net/http/httptest"
"net/url"
"path"
+ "strings"
"testing"
- "code.gitea.io/gitea/modules/json"
- gitea_context "code.gitea.io/gitea/services/context"
+ repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unittest"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/test"
+ "code.gitea.io/gitea/modules/translation"
+ "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
-func TestCreateFile(t *testing.T) {
+func TestEditor(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
- session := loginUser(t, "user2")
- testCreateFile(t, session, "user2", "repo1", "master", "test.txt", "Content")
+ sessionUser2 := loginUser(t, "user2")
+ t.Run("EditFileNotAllowed", testEditFileNotAllowed)
+ t.Run("DiffPreview", testEditorDiffPreview)
+ t.Run("CreateFile", testEditorCreateFile)
+ t.Run("EditFile", func(t *testing.T) {
+ testEditFile(t, sessionUser2, "user2", "repo1", "master", "README.md", "Hello, World (direct)\n")
+ testEditFileToNewBranch(t, sessionUser2, "user2", "repo1", "master", "feature/test", "README.md", "Hello, World (commit-to-new-branch)\n")
+ })
+ t.Run("PatchFile", testEditorPatchFile)
+ t.Run("DeleteFile", func(t *testing.T) {
+ viewLink := "/user2/repo1/src/branch/branch2/README.md"
+ sessionUser2.MakeRequest(t, NewRequest(t, "GET", viewLink), http.StatusOK)
+ testEditorActionPostRequest(t, sessionUser2, "/user2/repo1/_delete/branch2/README.md", map[string]string{"commit_choice": "direct"})
+ sessionUser2.MakeRequest(t, NewRequest(t, "GET", viewLink), http.StatusNotFound)
+ })
+ t.Run("ForkToEditFile", func(t *testing.T) {
+ testForkToEditFile(t, loginUser(t, "user4"), "user4", "user2", "repo1", "master", "README.md")
+ })
+ t.Run("WebGitCommitEmail", testEditorWebGitCommitEmail)
+ t.Run("ProtectedBranch", testEditorProtectedBranch)
})
}
-func testCreateFile(t *testing.T, session *TestSession, user, repo, branch, filePath, content string) *httptest.ResponseRecorder {
- // Request editor page
- newURL := fmt.Sprintf("/%s/%s/_new/%s/", user, repo, branch)
- req := NewRequest(t, "GET", newURL)
- resp := session.MakeRequest(t, req, http.StatusOK)
-
- doc := NewHTMLParser(t, resp.Body)
- lastCommit := doc.GetInputValueByName("last_commit")
- assert.NotEmpty(t, lastCommit)
+func testEditorCreateFile(t *testing.T) {
+ session := loginUser(t, "user2")
+ testCreateFile(t, session, "user2", "repo1", "master", "test.txt", "Content")
+ testEditorActionPostRequestError(t, session, "/user2/repo1/_new/master/", map[string]string{
+ "tree_path": "test.txt",
+ "commit_choice": "direct",
+ "new_branch_name": "master",
+ }, `A file named "test.txt" already exists in this repository.`)
+ testEditorActionPostRequestError(t, session, "/user2/repo1/_new/master/", map[string]string{
+ "tree_path": "test.txt",
+ "commit_choice": "commit-to-new-branch",
+ "new_branch_name": "master",
+ }, `Branch "master" already exists in this repository.`)
+}
- // Save new file to master branch
- req = NewRequestWithValues(t, "POST", newURL, map[string]string{
- "_csrf": doc.GetCSRF(),
- "last_commit": lastCommit,
+func testCreateFile(t *testing.T, session *TestSession, user, repo, branch, filePath, content string) {
+ testEditorActionEdit(t, session, user, repo, "_new", branch, "", map[string]string{
"tree_path": filePath,
"content": content,
"commit_choice": "direct",
})
- return session.MakeRequest(t, req, http.StatusSeeOther)
}
-func TestCreateFileOnProtectedBranch(t *testing.T) {
- onGiteaRun(t, func(t *testing.T, u *url.URL) {
- session := loginUser(t, "user2")
-
- csrf := GetUserCSRFToken(t, session)
- // Change master branch to protected
- req := NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/edit", map[string]string{
- "_csrf": csrf,
- "rule_name": "master",
- "enable_push": "true",
- })
- session.MakeRequest(t, req, http.StatusSeeOther)
- // Check if master branch has been locked successfully
- flashCookie := session.GetCookie(gitea_context.CookieNameFlash)
- assert.NotNil(t, flashCookie)
- assert.EqualValues(t, "success%3DBranch%2Bprotection%2Bfor%2Brule%2B%2522master%2522%2Bhas%2Bbeen%2Bupdated.", flashCookie.Value)
+func testEditorProtectedBranch(t *testing.T) {
+ session := loginUser(t, "user2")
+ // Change the "master" branch to "protected"
+ req := NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/edit", map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ "rule_name": "master",
+ "enable_push": "true",
+ })
+ session.MakeRequest(t, req, http.StatusSeeOther)
+ flashMsg := session.GetCookieFlashMessage()
+ assert.Equal(t, `Branch protection for rule "master" has been updated.`, flashMsg.SuccessMsg)
- // Request editor page
- req = NewRequest(t, "GET", "/user2/repo1/_new/master/")
- resp := session.MakeRequest(t, req, http.StatusOK)
+ // Try to commit a file to the "master" branch and it should fail
+ resp := testEditorActionPostRequest(t, session, "/user2/repo1/_new/master/", map[string]string{"tree_path": "test-protected-branch.txt", "commit_choice": "direct"})
+ assert.Equal(t, http.StatusBadRequest, resp.Code)
+ assert.Equal(t, `Cannot commit to protected branch "master".`, test.ParseJSONError(resp.Body.Bytes()).ErrorMessage)
+}
- doc := NewHTMLParser(t, resp.Body)
- lastCommit := doc.GetInputValueByName("last_commit")
- assert.NotEmpty(t, lastCommit)
+func testEditorActionPostRequest(t *testing.T, session *TestSession, requestPath string, params map[string]string) *httptest.ResponseRecorder {
+ req := NewRequest(t, "GET", requestPath)
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ htmlDoc := NewHTMLParser(t, resp.Body)
+ form := map[string]string{
+ "_csrf": htmlDoc.GetCSRF(),
+ "last_commit": htmlDoc.GetInputValueByName("last_commit"),
+ }
+ maps.Copy(form, params)
+ req = NewRequestWithValues(t, "POST", requestPath, form)
+ return session.MakeRequest(t, req, NoExpectedStatus)
+}
- // Save new file to master branch
- req = NewRequestWithValues(t, "POST", "/user2/repo1/_new/master/", map[string]string{
- "_csrf": doc.GetCSRF(),
- "last_commit": lastCommit,
- "tree_path": "test.txt",
- "content": "Content",
- "commit_choice": "direct",
- })
+func testEditorActionPostRequestError(t *testing.T, session *TestSession, requestPath string, params map[string]string, errorMessage string) {
+ resp := testEditorActionPostRequest(t, session, requestPath, params)
+ assert.Equal(t, http.StatusBadRequest, resp.Code)
+ assert.Equal(t, errorMessage, test.ParseJSONError(resp.Body.Bytes()).ErrorMessage)
+}
- resp = session.MakeRequest(t, req, http.StatusOK)
- // Check body for error message
- assert.Contains(t, resp.Body.String(), "Cannot commit to protected branch &#34;master&#34;.")
+func testEditorActionEdit(t *testing.T, session *TestSession, user, repo, editorAction, branch, filePath string, params map[string]string) *httptest.ResponseRecorder {
+ params["tree_path"] = util.IfZero(params["tree_path"], filePath)
+ newBranchName := util.Iif(params["commit_choice"] == "direct", branch, params["new_branch_name"])
+ resp := testEditorActionPostRequest(t, session, fmt.Sprintf("/%s/%s/%s/%s/%s", user, repo, editorAction, branch, filePath), params)
+ assert.Equal(t, http.StatusOK, resp.Code)
+ assert.NotEmpty(t, test.RedirectURL(resp))
+ req := NewRequest(t, "GET", path.Join(user, repo, "raw/branch", newBranchName, params["tree_path"]))
+ resp = session.MakeRequest(t, req, http.StatusOK)
+ assert.Equal(t, params["content"], resp.Body.String())
+ return resp
+}
- // remove the protected branch
- csrf = GetUserCSRFToken(t, session)
+func testEditFile(t *testing.T, session *TestSession, user, repo, branch, filePath, newContent string) {
+ testEditorActionEdit(t, session, user, repo, "_edit", branch, filePath, map[string]string{
+ "content": newContent,
+ "commit_choice": "direct",
+ })
+}
- // Change master branch to protected
- req = NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/1/delete", map[string]string{
- "_csrf": csrf,
- })
+func testEditFileToNewBranch(t *testing.T, session *TestSession, user, repo, branch, targetBranch, filePath, newContent string) {
+ testEditorActionEdit(t, session, user, repo, "_edit", branch, filePath, map[string]string{
+ "content": newContent,
+ "commit_choice": "commit-to-new-branch",
+ "new_branch_name": targetBranch,
+ })
+}
- resp = session.MakeRequest(t, req, http.StatusOK)
+func testEditorDiffPreview(t *testing.T) {
+ session := loginUser(t, "user2")
+ req := NewRequestWithValues(t, "POST", "/user2/repo1/_preview/master/README.md", map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ "content": "Hello, World (Edited)\n",
+ })
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ assert.Contains(t, resp.Body.String(), `<span class="added-code">Hello, World (Edited)</span>`)
+}
- res := make(map[string]string)
- assert.NoError(t, json.NewDecoder(resp.Body).Decode(&res))
- assert.EqualValues(t, "/user2/repo1/settings/branches", res["redirect"])
+func testEditorPatchFile(t *testing.T) {
+ session := loginUser(t, "user2")
+ pathContentCommon := `diff --git a/patch-file-1.txt b/patch-file-1.txt
+new file mode 100644
+index 0000000000..aaaaaaaaaa
+--- /dev/null
++++ b/patch-file-1.txt
+@@ -0,0 +1 @@
++`
+ testEditorActionPostRequest(t, session, "/user2/repo1/_diffpatch/master/", map[string]string{
+ "content": pathContentCommon + "patched content\n",
+ "commit_choice": "commit-to-new-branch",
+ "new_branch_name": "patched-branch",
+ })
+ resp := MakeRequest(t, NewRequest(t, "GET", "/user2/repo1/raw/branch/patched-branch/patch-file-1.txt"), http.StatusOK)
+ assert.Equal(t, "patched content\n", resp.Body.String())
- // Check if master branch has been locked successfully
- flashCookie = session.GetCookie(gitea_context.CookieNameFlash)
- assert.NotNil(t, flashCookie)
- assert.EqualValues(t, "error%3DRemoving%2Bbranch%2Bprotection%2Brule%2B%25221%2522%2Bfailed.", flashCookie.Value)
+ // patch again, it should fail
+ resp = testEditorActionPostRequest(t, session, "/user2/repo1/_diffpatch/patched-branch/", map[string]string{
+ "content": pathContentCommon + "another patched content\n",
+ "commit_choice": "commit-to-new-branch",
+ "new_branch_name": "patched-branch-1",
})
+ assert.Equal(t, "Unable to apply patch", test.ParseJSONError(resp.Body.Bytes()).ErrorMessage)
}
-func testEditFile(t *testing.T, session *TestSession, user, repo, branch, filePath, newContent string) *httptest.ResponseRecorder {
- // Get to the 'edit this file' page
- req := NewRequest(t, "GET", path.Join(user, repo, "_edit", branch, filePath))
- resp := session.MakeRequest(t, req, http.StatusOK)
+func testEditorWebGitCommitEmail(t *testing.T) {
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ require.True(t, user.KeepEmailPrivate)
- htmlDoc := NewHTMLParser(t, resp.Body)
- lastCommit := htmlDoc.GetInputValueByName("last_commit")
- assert.NotEmpty(t, lastCommit)
-
- // Submit the edits
- req = NewRequestWithValues(t, "POST", path.Join(user, repo, "_edit", branch, filePath),
- map[string]string{
- "_csrf": htmlDoc.GetCSRF(),
- "last_commit": lastCommit,
- "tree_path": filePath,
- "content": newContent,
- "commit_choice": "direct",
- },
- )
- session.MakeRequest(t, req, http.StatusSeeOther)
+ repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
+ gitRepo, _ := git.OpenRepository(git.DefaultContext, repo1.RepoPath())
+ defer gitRepo.Close()
+ getLastCommit := func(t *testing.T) *git.Commit {
+ c, err := gitRepo.GetBranchCommit("master")
+ require.NoError(t, err)
+ return c
+ }
- // Verify the change
- req = NewRequest(t, "GET", path.Join(user, repo, "raw/branch", branch, filePath))
- resp = session.MakeRequest(t, req, http.StatusOK)
- assert.EqualValues(t, newContent, resp.Body.String())
+ session := loginUser(t, user.Name)
- return resp
-}
+ makeReq := func(t *testing.T, link string, params map[string]string, expectedUserName, expectedEmail string) *httptest.ResponseRecorder {
+ lastCommit := getLastCommit(t)
+ params["_csrf"] = GetUserCSRFToken(t, session)
+ params["last_commit"] = lastCommit.ID.String()
+ params["commit_choice"] = "direct"
+ req := NewRequestWithValues(t, "POST", link, params)
+ resp := session.MakeRequest(t, req, NoExpectedStatus)
+ newCommit := getLastCommit(t)
+ if expectedUserName == "" {
+ require.Equal(t, lastCommit.ID.String(), newCommit.ID.String())
+ respErr := test.ParseJSONError(resp.Body.Bytes())
+ assert.Equal(t, translation.NewLocale("en-US").TrString("repo.editor.invalid_commit_email"), respErr.ErrorMessage)
+ } else {
+ require.NotEqual(t, lastCommit.ID.String(), newCommit.ID.String())
+ assert.Equal(t, expectedUserName, newCommit.Author.Name)
+ assert.Equal(t, expectedEmail, newCommit.Author.Email)
+ assert.Equal(t, expectedUserName, newCommit.Committer.Name)
+ assert.Equal(t, expectedEmail, newCommit.Committer.Email)
+ }
+ return resp
+ }
-func testEditFileToNewBranch(t *testing.T, session *TestSession, user, repo, branch, targetBranch, filePath, newContent string) *httptest.ResponseRecorder {
- // Get to the 'edit this file' page
- req := NewRequest(t, "GET", path.Join(user, repo, "_edit", branch, filePath))
- resp := session.MakeRequest(t, req, http.StatusOK)
+ uploadFile := func(t *testing.T, name, content string) string {
+ body := &bytes.Buffer{}
+ uploadForm := multipart.NewWriter(body)
+ file, _ := uploadForm.CreateFormFile("file", name)
+ _, _ = io.Copy(file, strings.NewReader(content))
+ _ = uploadForm.WriteField("_csrf", GetUserCSRFToken(t, session))
+ _ = uploadForm.Close()
- htmlDoc := NewHTMLParser(t, resp.Body)
- lastCommit := htmlDoc.GetInputValueByName("last_commit")
- assert.NotEmpty(t, lastCommit)
-
- // Submit the edits
- req = NewRequestWithValues(t, "POST", path.Join(user, repo, "_edit", branch, filePath),
- map[string]string{
- "_csrf": htmlDoc.GetCSRF(),
- "last_commit": lastCommit,
- "tree_path": filePath,
- "content": newContent,
- "commit_choice": "commit-to-new-branch",
- "new_branch_name": targetBranch,
- },
- )
- session.MakeRequest(t, req, http.StatusSeeOther)
+ req := NewRequestWithBody(t, "POST", "/user2/repo1/upload-file", body)
+ req.Header.Add("Content-Type", uploadForm.FormDataContentType())
+ resp := session.MakeRequest(t, req, http.StatusOK)
- // Verify the change
- req = NewRequest(t, "GET", path.Join(user, repo, "raw/branch", targetBranch, filePath))
- resp = session.MakeRequest(t, req, http.StatusOK)
- assert.EqualValues(t, newContent, resp.Body.String())
+ respMap := map[string]string{}
+ DecodeJSON(t, resp, &respMap)
+ return respMap["uuid"]
+ }
- return resp
-}
+ t.Run("EmailInactive", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+ email := unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{ID: 35, UID: user.ID})
+ require.False(t, email.IsActivated)
+ makeReq(t, "/user2/repo1/_edit/master/README.md", map[string]string{
+ "tree_path": "README.md",
+ "content": "test content",
+ "commit_email": email.Email,
+ }, "", "")
+ })
-func TestEditFile(t *testing.T) {
- onGiteaRun(t, func(t *testing.T, u *url.URL) {
- session := loginUser(t, "user2")
- testEditFile(t, session, "user2", "repo1", "master", "README.md", "Hello, World (Edited)\n")
+ t.Run("EmailInvalid", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+ email := unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{ID: 1, IsActivated: true})
+ require.NotEqual(t, email.UID, user.ID)
+ makeReq(t, "/user2/repo1/_edit/master/README.md", map[string]string{
+ "tree_path": "README.md",
+ "content": "test content",
+ "commit_email": email.Email,
+ }, "", "")
+ })
+
+ testWebGit := func(t *testing.T, linkForKeepPrivate string, paramsForKeepPrivate map[string]string, linkForChosenEmail string, paramsForChosenEmail map[string]string) (resp1, resp2 *httptest.ResponseRecorder) {
+ t.Run("DefaultEmailKeepPrivate", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+ paramsForKeepPrivate["commit_email"] = ""
+ resp1 = makeReq(t, linkForKeepPrivate, paramsForKeepPrivate, "User Two", "user2@noreply.example.org")
+ })
+ t.Run("ChooseEmail", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+ paramsForChosenEmail["commit_email"] = "user2@example.com"
+ resp2 = makeReq(t, linkForChosenEmail, paramsForChosenEmail, "User Two", "user2@example.com")
+ })
+ return resp1, resp2
+ }
+
+ t.Run("Edit", func(t *testing.T) {
+ testWebGit(t,
+ "/user2/repo1/_edit/master/README.md", map[string]string{"tree_path": "README.md", "content": "for keep private"},
+ "/user2/repo1/_edit/master/README.md", map[string]string{"tree_path": "README.md", "content": "for chosen email"},
+ )
+ })
+
+ t.Run("UploadDelete", func(t *testing.T) {
+ file1UUID := uploadFile(t, "file1", "File 1")
+ file2UUID := uploadFile(t, "file2", "File 2")
+ testWebGit(t,
+ "/user2/repo1/_upload/master", map[string]string{"files": file1UUID},
+ "/user2/repo1/_upload/master", map[string]string{"files": file2UUID},
+ )
+ testWebGit(t,
+ "/user2/repo1/_delete/master/file1", map[string]string{},
+ "/user2/repo1/_delete/master/file2", map[string]string{},
+ )
+ })
+
+ t.Run("ApplyPatchCherryPick", func(t *testing.T) {
+ testWebGit(t,
+ "/user2/repo1/_diffpatch/master", map[string]string{
+ "tree_path": "__dummy__",
+ "content": `diff --git a/patch-file-1.txt b/patch-file-1.txt
+new file mode 100644
+index 0000000000..aaaaaaaaaa
+--- /dev/null
++++ b/patch-file-1.txt
+@@ -0,0 +1 @@
++File 1
+`,
+ },
+ "/user2/repo1/_diffpatch/master", map[string]string{
+ "tree_path": "__dummy__",
+ "content": `diff --git a/patch-file-2.txt b/patch-file-2.txt
+new file mode 100644
+index 0000000000..bbbbbbbbbb
+--- /dev/null
++++ b/patch-file-2.txt
+@@ -0,0 +1 @@
++File 2
+`,
+ },
+ )
+
+ commit1, err := gitRepo.GetCommitByPath("patch-file-1.txt")
+ require.NoError(t, err)
+ commit2, err := gitRepo.GetCommitByPath("patch-file-2.txt")
+ require.NoError(t, err)
+ resp1, _ := testWebGit(t,
+ "/user2/repo1/_cherrypick/"+commit1.ID.String()+"/master", map[string]string{"revert": "true"},
+ "/user2/repo1/_cherrypick/"+commit2.ID.String()+"/master", map[string]string{"revert": "true"},
+ )
+
+ // By the way, test the "cherrypick" page: a successful revert redirects to the main branch
+ assert.Equal(t, "/user2/repo1/src/branch/master", test.RedirectURL(resp1))
})
}
-func TestEditFileToNewBranch(t *testing.T) {
- onGiteaRun(t, func(t *testing.T, u *url.URL) {
- session := loginUser(t, "user2")
- testEditFileToNewBranch(t, session, "user2", "repo1", "master", "feature/test", "README.md", "Hello, World (Edited)\n")
+func testForkToEditFile(t *testing.T, session *TestSession, user, owner, repo, branch, filePath string) {
+ forkToEdit := func(t *testing.T, session *TestSession, owner, repo, operation, branch, filePath string) {
+ // visit the base repo, see the "Add File" button
+ req := NewRequest(t, "GET", path.Join(owner, repo))
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ htmlDoc := NewHTMLParser(t, resp.Body)
+ AssertHTMLElement(t, htmlDoc, ".repo-add-file", 1)
+
+ // attempt to edit a file, see the guideline page
+ req = NewRequest(t, "GET", path.Join(owner, repo, operation, branch, filePath))
+ resp = session.MakeRequest(t, req, http.StatusOK)
+ assert.Contains(t, resp.Body.String(), "Fork Repository to Propose Changes")
+
+ // fork the repository
+ req = NewRequestWithValues(t, "POST", path.Join(owner, repo, "_fork", branch), map[string]string{"_csrf": GetUserCSRFToken(t, session)})
+ resp = session.MakeRequest(t, req, http.StatusOK)
+ assert.JSONEq(t, `{"redirect":""}`, resp.Body.String())
+ }
+
+ t.Run("ForkButArchived", func(t *testing.T) {
+ // Fork repository because we can't edit it
+ forkToEdit(t, session, owner, repo, "_edit", branch, filePath)
+
+ // Archive the repository
+ req := NewRequestWithValues(t, "POST", path.Join(user, repo, "settings"),
+ map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ "repo_name": repo,
+ "action": "archive",
+ },
+ )
+ session.MakeRequest(t, req, http.StatusSeeOther)
+
+ // Check editing archived repository is disabled
+ req = NewRequest(t, "GET", path.Join(owner, repo, "_edit", branch, filePath)).SetHeader("Accept", "text/html")
+ resp := session.MakeRequest(t, req, http.StatusNotFound)
+ assert.Contains(t, resp.Body.String(), "You have forked this repository but your fork is not editable.")
+
+ // Unfork the repository
+ req = NewRequestWithValues(t, "POST", path.Join(user, repo, "settings"),
+ map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ "repo_name": repo,
+ "action": "convert_fork",
+ },
+ )
+ session.MakeRequest(t, req, http.StatusSeeOther)
+ })
+
+ // Fork repository again, and check the existence of the forked repo with unique name
+ forkToEdit(t, session, owner, repo, "_edit", branch, filePath)
+ session.MakeRequest(t, NewRequestf(t, "GET", "/%s/%s-1", user, repo), http.StatusOK)
+
+ t.Run("CheckBaseRepoForm", func(t *testing.T) {
+ // the base repo's edit form should have the correct action and upload links (pointing to the forked repo)
+ req := NewRequest(t, "GET", path.Join(owner, repo, "_upload", branch, filePath)+"?foo=bar")
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ htmlDoc := NewHTMLParser(t, resp.Body)
+
+ uploadForm := htmlDoc.doc.Find(".form-fetch-action")
+ formAction := uploadForm.AttrOr("action", "")
+ assert.Equal(t, fmt.Sprintf("/%s/%s-1/_upload/%s/%s?from_base_branch=%s&foo=bar", user, repo, branch, filePath, branch), formAction)
+ uploadLink := uploadForm.Find(".dropzone").AttrOr("data-link-url", "")
+ assert.Equal(t, fmt.Sprintf("/%s/%s-1/upload-file", user, repo), uploadLink)
+ newBranchName := uploadForm.Find("input[name=new_branch_name]").AttrOr("value", "")
+ assert.Equal(t, user+"-patch-1", newBranchName)
+ commitChoice := uploadForm.Find("input[name=commit_choice][checked]").AttrOr("value", "")
+ assert.Equal(t, "commit-to-new-branch", commitChoice)
+ lastCommit := uploadForm.Find("input[name=last_commit]").AttrOr("value", "")
+ assert.NotEmpty(t, lastCommit)
})
+
+ t.Run("ViewBaseEditFormAndCommitToFork", func(t *testing.T) {
+ req := NewRequest(t, "GET", path.Join(owner, repo, "_edit", branch, filePath))
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ htmlDoc := NewHTMLParser(t, resp.Body)
+ editRequestForm := map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ "last_commit": htmlDoc.GetInputValueByName("last_commit"),
+ "tree_path": filePath,
+ "content": "new content in fork",
+ "commit_choice": "commit-to-new-branch",
+ }
+ // change a file in the forked repo with existing branch name (should fail)
+ editRequestForm["new_branch_name"] = "master"
+ req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s-1/_edit/%s/%s?from_base_branch=%s", user, repo, branch, filePath, branch), editRequestForm)
+ resp = session.MakeRequest(t, req, http.StatusBadRequest)
+ respJSON := test.ParseJSONError(resp.Body.Bytes())
+ assert.Equal(t, `Branch "master" already exists in your fork, please choose a new branch name.`, respJSON.ErrorMessage)
+
+ // change a file in the forked repo (should succeed)
+ newBranchName := htmlDoc.GetInputValueByName("new_branch_name")
+ editRequestForm["new_branch_name"] = newBranchName
+ req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s-1/_edit/%s/%s?from_base_branch=%s", user, repo, branch, filePath, branch), editRequestForm)
+ resp = session.MakeRequest(t, req, http.StatusOK)
+ assert.Equal(t, fmt.Sprintf("/%s/%s/compare/%s...%s/%s-1:%s", owner, repo, branch, user, repo, newBranchName), test.RedirectURL(resp))
+
+ // check the file in the fork's branch is changed
+ req = NewRequest(t, "GET", fmt.Sprintf("/%s/%s-1/src/branch/%s/%s", user, repo, newBranchName, filePath))
+ resp = session.MakeRequest(t, req, http.StatusOK)
+ assert.Contains(t, resp.Body.String(), "new content in fork")
+ })
+}
+
+func testEditFileNotAllowed(t *testing.T) {
+ sessionUser1 := loginUser(t, "user1") // admin, all access
+ sessionUser4 := loginUser(t, "user4")
+ // "_cherrypick" has a different route pattern, so skip its test
+ operations := []string{"_new", "_edit", "_delete", "_upload", "_diffpatch"}
+ for _, operation := range operations {
+ t.Run(operation, func(t *testing.T) {
+ // Branch does not exist
+ targetLink := path.Join("user2", "repo1", operation, "missing", "README.md")
+ sessionUser1.MakeRequest(t, NewRequest(t, "GET", targetLink), http.StatusNotFound)
+
+ // Private repository
+ targetLink = path.Join("user2", "repo2", operation, "master", "Home.md")
+ sessionUser1.MakeRequest(t, NewRequest(t, "GET", targetLink), http.StatusOK)
+ sessionUser4.MakeRequest(t, NewRequest(t, "GET", targetLink), http.StatusNotFound)
+
+ // Empty repository
+ targetLink = path.Join("org41", "repo61", operation, "master", "README.md")
+ sessionUser1.MakeRequest(t, NewRequest(t, "GET", targetLink), http.StatusNotFound)
+ })
+ }
}
diff --git a/tests/integration/empty_repo_test.go b/tests/integration/empty_repo_test.go
index b19774a826..6a8c70f12f 100644
--- a/tests/integration/empty_repo_test.go
+++ b/tests/integration/empty_repo_test.go
@@ -10,7 +10,7 @@ import (
"io"
"mime/multipart"
"net/http"
- "net/http/httptest"
+ "strings"
"testing"
auth_model "code.gitea.io/gitea/models/auth"
@@ -22,13 +22,14 @@ import (
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/test"
+ "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
-func testAPINewFile(t *testing.T, session *TestSession, user, repo, branch, treePath, content string) *httptest.ResponseRecorder {
+func testAPINewFile(t *testing.T, session *TestSession, user, repo, branch, treePath, content string) {
url := fmt.Sprintf("/%s/%s/_new/%s", user, repo, branch)
req := NewRequestWithValues(t, "POST", url, map[string]string{
"_csrf": GetUserCSRFToken(t, session),
@@ -36,7 +37,8 @@ func testAPINewFile(t *testing.T, session *TestSession, user, repo, branch, tree
"tree_path": treePath,
"content": content,
})
- return session.MakeRequest(t, req, http.StatusSeeOther)
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ assert.NotEmpty(t, test.RedirectURL(resp))
}
func TestEmptyRepo(t *testing.T) {
@@ -60,12 +62,20 @@ func TestEmptyRepoAddFile(t *testing.T) {
defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user30")
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
+
+ // test web page
req := NewRequest(t, "GET", "/user30/empty")
resp := session.MakeRequest(t, req, http.StatusOK)
bodyString := resp.Body.String()
assert.Contains(t, bodyString, "empty-repo-guide")
assert.True(t, test.IsNormalPageCompleted(bodyString))
+ // test api
+ req = NewRequest(t, "GET", "/api/v1/repos/user30/empty/raw/main/README.md").AddTokenAuth(token)
+ session.MakeRequest(t, req, http.StatusNotFound)
+
+ // create a new file
req = NewRequest(t, "GET", "/user30/empty/_new/"+setting.Repository.DefaultBranch)
resp = session.MakeRequest(t, req, http.StatusOK)
doc := NewHTMLParser(t, resp.Body).Find(`input[name="commit_choice"]`)
@@ -77,7 +87,7 @@ func TestEmptyRepoAddFile(t *testing.T) {
"content": "newly-added-test-file",
})
- resp = session.MakeRequest(t, req, http.StatusSeeOther)
+ resp = session.MakeRequest(t, req, http.StatusOK)
redirect := test.RedirectURL(resp)
assert.Equal(t, "/user30/empty/src/branch/"+setting.Repository.DefaultBranch+"/test-file.md", redirect)
@@ -91,22 +101,29 @@ func TestEmptyRepoAddFile(t *testing.T) {
assert.Contains(t, resp.Body.String(), "test-file.md")
// if the repo is in incorrect state, it should be able to self-heal (recover to correct state)
- user30EmptyRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: 30, Name: "empty"})
- user30EmptyRepo.IsEmpty = true
- user30EmptyRepo.DefaultBranch = "no-such"
- _, err := db.GetEngine(db.DefaultContext).ID(user30EmptyRepo.ID).Cols("is_empty", "default_branch").Update(user30EmptyRepo)
- require.NoError(t, err)
- user30EmptyRepo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: 30, Name: "empty"})
- assert.True(t, user30EmptyRepo.IsEmpty)
-
- req = NewRequest(t, "GET", "/user30/empty")
- resp = session.MakeRequest(t, req, http.StatusSeeOther)
- redirect = test.RedirectURL(resp)
- assert.Equal(t, "/user30/empty", redirect)
-
- req = NewRequest(t, "GET", "/user30/empty")
- resp = session.MakeRequest(t, req, http.StatusOK)
- assert.Contains(t, resp.Body.String(), "test-file.md")
+ testEmptyOrBrokenRecover := func(t *testing.T, isEmpty, isBroken bool) {
+ user30EmptyRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: 30, Name: "empty"})
+ user30EmptyRepo.IsEmpty = isEmpty
+ user30EmptyRepo.Status = util.Iif(isBroken, repo_model.RepositoryBroken, repo_model.RepositoryReady)
+ user30EmptyRepo.DefaultBranch = "no-such"
+ _, err := db.GetEngine(db.DefaultContext).ID(user30EmptyRepo.ID).Cols("is_empty", "status", "default_branch").Update(user30EmptyRepo)
+ require.NoError(t, err)
+ user30EmptyRepo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: 30, Name: "empty"})
+ assert.Equal(t, isEmpty, user30EmptyRepo.IsEmpty)
+ assert.Equal(t, isBroken, user30EmptyRepo.Status == repo_model.RepositoryBroken)
+
+ req = NewRequest(t, "GET", "/user30/empty")
+ resp = session.MakeRequest(t, req, http.StatusSeeOther)
+ redirect = test.RedirectURL(resp)
+ assert.Equal(t, "/user30/empty", redirect)
+
+ req = NewRequest(t, "GET", "/user30/empty")
+ resp = session.MakeRequest(t, req, http.StatusOK)
+ assert.Contains(t, resp.Body.String(), "test-file.md")
+ }
+ testEmptyOrBrokenRecover(t, true, false)
+ testEmptyOrBrokenRecover(t, false, true)
+ testEmptyOrBrokenRecover(t, true, true)
}
func TestEmptyRepoUploadFile(t *testing.T) {
@@ -122,7 +139,7 @@ func TestEmptyRepoUploadFile(t *testing.T) {
mpForm := multipart.NewWriter(body)
_ = mpForm.WriteField("_csrf", GetUserCSRFToken(t, session))
file, _ := mpForm.CreateFormFile("file", "uploaded-file.txt")
- _, _ = io.Copy(file, bytes.NewBufferString("newly-uploaded-test-file"))
+ _, _ = io.Copy(file, strings.NewReader("newly-uploaded-test-file"))
_ = mpForm.Close()
req = NewRequestWithBody(t, "POST", "/user30/empty/upload-file", body)
@@ -137,9 +154,9 @@ func TestEmptyRepoUploadFile(t *testing.T) {
"files": respMap["uuid"],
"tree_path": "",
})
- resp = session.MakeRequest(t, req, http.StatusSeeOther)
+ resp = session.MakeRequest(t, req, http.StatusOK)
redirect := test.RedirectURL(resp)
- assert.Equal(t, "/user30/empty/src/branch/"+setting.Repository.DefaultBranch+"/", redirect)
+ assert.Equal(t, "/user30/empty/src/branch/"+setting.Repository.DefaultBranch, redirect)
req = NewRequest(t, "GET", redirect)
resp = session.MakeRequest(t, req, http.StatusOK)
@@ -164,7 +181,7 @@ func TestEmptyRepoAddFileByAPI(t *testing.T) {
var fileResponse api.FileResponse
DecodeJSON(t, resp, &fileResponse)
expectedHTMLURL := setting.AppURL + "user30/empty/src/branch/new_branch/new-file.txt"
- assert.EqualValues(t, expectedHTMLURL, *fileResponse.Content.HTMLURL)
+ assert.Equal(t, expectedHTMLURL, *fileResponse.Content.HTMLURL)
req = NewRequest(t, "GET", "/user30/empty/src/branch/new_branch/new-file.txt")
resp = session.MakeRequest(t, req, http.StatusOK)
diff --git a/tests/integration/ephemeral_actions_runner_deletion_test.go b/tests/integration/ephemeral_actions_runner_deletion_test.go
new file mode 100644
index 0000000000..40f8c643a8
--- /dev/null
+++ b/tests/integration/ephemeral_actions_runner_deletion_test.go
@@ -0,0 +1,77 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package integration
+
+import (
+ "testing"
+
+ actions_model "code.gitea.io/gitea/models/actions"
+ "code.gitea.io/gitea/models/unittest"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/util"
+ repo_service "code.gitea.io/gitea/services/repository"
+ user_service "code.gitea.io/gitea/services/user"
+ "code.gitea.io/gitea/tests"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestEphemeralActionsRunnerDeletion(t *testing.T) {
+ t.Run("ByTaskCompletion", testEphemeralActionsRunnerDeletionByTaskCompletion)
+ t.Run("ByRepository", testEphemeralActionsRunnerDeletionByRepository)
+ t.Run("ByUser", testEphemeralActionsRunnerDeletionByUser)
+}
+
+// Test that the ephemeral runner is deleted when the task is finished
+func testEphemeralActionsRunnerDeletionByTaskCompletion(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ _, err := actions_model.GetRunnerByID(t.Context(), 34350)
+ assert.NoError(t, err)
+
+ task := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionTask{ID: 52})
+ assert.Equal(t, actions_model.StatusRunning, task.Status)
+
+ task.Status = actions_model.StatusSuccess
+ err = actions_model.UpdateTask(t.Context(), task, "status")
+ assert.NoError(t, err)
+
+ _, err = actions_model.GetRunnerByID(t.Context(), 34350)
+ assert.ErrorIs(t, err, util.ErrNotExist)
+}
+
+func testEphemeralActionsRunnerDeletionByRepository(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ _, err := actions_model.GetRunnerByID(t.Context(), 34350)
+ assert.NoError(t, err)
+
+ task := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionTask{ID: 52})
+ assert.Equal(t, actions_model.StatusRunning, task.Status)
+
+ err = repo_service.DeleteRepositoryDirectly(t.Context(), task.RepoID, true)
+ assert.NoError(t, err)
+
+ _, err = actions_model.GetRunnerByID(t.Context(), 34350)
+ assert.ErrorIs(t, err, util.ErrNotExist)
+}
+
+// Test that the ephemeral runner is deleted when a user is deleted
+func testEphemeralActionsRunnerDeletionByUser(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ _, err := actions_model.GetRunnerByID(t.Context(), 34350)
+ assert.NoError(t, err)
+
+ task := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionTask{ID: 52})
+ assert.Equal(t, actions_model.StatusRunning, task.Status)
+
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+
+ err = user_service.DeleteUser(t.Context(), user, true)
+ assert.NoError(t, err)
+
+ _, err = actions_model.GetRunnerByID(t.Context(), 34350)
+ assert.ErrorIs(t, err, util.ErrNotExist)
+}
diff --git a/tests/integration/feed_repo_test.go b/tests/integration/feed_repo_test.go
new file mode 100644
index 0000000000..2915b9b3f4
--- /dev/null
+++ b/tests/integration/feed_repo_test.go
@@ -0,0 +1,35 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package integration
+
+import (
+ "encoding/xml"
+ "net/http"
+ "testing"
+
+ "code.gitea.io/gitea/tests"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestFeedRepo(t *testing.T) {
+ t.Run("RSS", func(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ req := NewRequest(t, "GET", "/user2/repo1.rss")
+ resp := MakeRequest(t, req, http.StatusOK)
+
+ data := resp.Body.String()
+ assert.Contains(t, data, `<rss version="2.0"`)
+
+ var rss RSS
+ err := xml.Unmarshal(resp.Body.Bytes(), &rss)
+ assert.NoError(t, err)
+ assert.Contains(t, rss.Channel.Link, "/user2/repo1")
+ assert.NotEmpty(t, rss.Channel.PubDate)
+ assert.Len(t, rss.Channel.Items, 1)
+ assert.Equal(t, "issue5", rss.Channel.Items[0].Description)
+ assert.NotEmpty(t, rss.Channel.Items[0].PubDate)
+ })
+}
diff --git a/tests/integration/api_feed_user_test.go b/tests/integration/feed_user_test.go
index c44f9a1951..4315c67f48 100644
--- a/tests/integration/api_feed_user_test.go
+++ b/tests/integration/feed_user_test.go
@@ -4,6 +4,7 @@
package integration
import (
+ "encoding/xml"
"net/http"
"testing"
@@ -12,7 +13,23 @@ import (
"github.com/stretchr/testify/assert"
)
-func TestFeed(t *testing.T) {
+// RSS is a struct to unmarshal RSS feeds test only
+type RSS struct {
+ Channel struct {
+ Title string `xml:"title"`
+ Link string `xml:"link"`
+ Description string `xml:"description"`
+ PubDate string `xml:"pubDate"`
+ Items []struct {
+ Title string `xml:"title"`
+ Link string `xml:"link"`
+ Description string `xml:"description"`
+ PubDate string `xml:"pubDate"`
+ } `xml:"item"`
+ } `xml:"channel"`
+}
+
+func TestFeedUser(t *testing.T) {
t.Run("User", func(t *testing.T) {
t.Run("Atom", func(t *testing.T) {
defer tests.PrepareTestEnv(t)()
@@ -32,6 +49,12 @@ func TestFeed(t *testing.T) {
data := resp.Body.String()
assert.Contains(t, data, `<rss version="2.0"`)
+
+ var rss RSS
+ err := xml.Unmarshal(resp.Body.Bytes(), &rss)
+ assert.NoError(t, err)
+ assert.Contains(t, rss.Channel.Link, "/user2")
+ assert.NotEmpty(t, rss.Channel.PubDate)
})
})
}
diff --git a/tests/integration/git_general_test.go b/tests/integration/git_general_test.go
index 5d915d8a51..3b0f9589d2 100644
--- a/tests/integration/git_general_test.go
+++ b/tests/integration/git_general_test.go
@@ -11,8 +11,10 @@ import (
"net/http"
"net/url"
"os"
+ "os/exec"
"path"
"path/filepath"
+ "slices"
"strconv"
"testing"
"time"
@@ -24,13 +26,14 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/commitstatus"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/lfs"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
- gitea_context "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/tests"
+ "github.com/kballard/go-shellquote"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -81,6 +84,7 @@ func testGitGeneral(t *testing.T, u *url.URL) {
mediaTest(t, &httpContext, pushedFilesStandard[0], pushedFilesStandard[1], pushedFilesLFS[0], pushedFilesLFS[1])
t.Run("CreateAgitFlowPull", doCreateAgitFlowPull(dstPath, &httpContext, "test/head"))
+ t.Run("CreateProtectedBranch", doCreateProtectedBranch(&httpContext, dstPath))
t.Run("BranchProtectMerge", doBranchProtectPRMerge(&httpContext, dstPath))
t.Run("AutoMerge", doAutoPRMerge(&httpContext, dstPath))
t.Run("CreatePRAndSetManuallyMerged", doCreatePRAndSetManuallyMerged(httpContext, httpContext, dstPath, "master", "test-manually-merge"))
@@ -105,7 +109,12 @@ func testGitGeneral(t *testing.T, u *url.URL) {
// Setup key the user ssh key
withKeyFile(t, keyname, func(keyFile string) {
- t.Run("CreateUserKey", doAPICreateUserKey(sshContext, "test-key", keyFile))
+ var keyID int64
+ t.Run("CreateUserKey", doAPICreateUserKey(sshContext, "test-key", keyFile, func(t *testing.T, key api.PublicKey) {
+ keyID = key.ID
+ }))
+ assert.NotZero(t, keyID)
+ t.Run("LFSAccessTest", doSSHLFSAccessTest(sshContext, keyID))
// Setup remote link
// TODO: get url from api
@@ -122,6 +131,7 @@ func testGitGeneral(t *testing.T, u *url.URL) {
mediaTest(t, &sshContext, pushedFilesStandard[0], pushedFilesStandard[1], pushedFilesLFS[0], pushedFilesLFS[1])
t.Run("CreateAgitFlowPull", doCreateAgitFlowPull(dstPath, &sshContext, "test/head2"))
+ t.Run("CreateProtectedBranch", doCreateProtectedBranch(&sshContext, dstPath))
t.Run("BranchProtectMerge", doBranchProtectPRMerge(&sshContext, dstPath))
t.Run("MergeFork", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
@@ -135,6 +145,36 @@ func testGitGeneral(t *testing.T, u *url.URL) {
})
}
+func doSSHLFSAccessTest(_ APITestContext, keyID int64) func(*testing.T) {
+ return func(t *testing.T) {
+ sshCommand := os.Getenv("GIT_SSH_COMMAND") // it is set in withKeyFile
+ sshCmdParts, err := shellquote.Split(sshCommand) // and parse the ssh command to construct some mocked arguments
+ require.NoError(t, err)
+
+ t.Run("User2AccessOwned", func(t *testing.T) {
+ sshCmdUser2Self := append(slices.Clone(sshCmdParts),
+ "-p", strconv.Itoa(setting.SSH.ListenPort), "git@"+setting.SSH.ListenHost,
+ "git-lfs-authenticate", "user2/repo1.git", "upload", // accessible to own repo
+ )
+ cmd := exec.CommandContext(t.Context(), sshCmdUser2Self[0], sshCmdUser2Self[1:]...)
+ _, err := cmd.Output()
+ assert.NoError(t, err) // accessible, no error
+ })
+
+ t.Run("User2AccessOther", func(t *testing.T) {
+ sshCmdUser2Other := append(slices.Clone(sshCmdParts),
+ "-p", strconv.Itoa(setting.SSH.ListenPort), "git@"+setting.SSH.ListenHost,
+ "git-lfs-authenticate", "user5/repo4.git", "upload", // inaccessible to other's (user5/repo4)
+ )
+ cmd := exec.CommandContext(t.Context(), sshCmdUser2Other[0], sshCmdUser2Other[1:]...)
+ _, err := cmd.Output()
+ var errExit *exec.ExitError
+ require.ErrorAs(t, err, &errExit) // inaccessible, error
+ assert.Contains(t, string(errExit.Stderr), fmt.Sprintf("User: 2:user2 with Key: %d:test-key is not authorized to write to user5/repo4.", keyID))
+ })
+ }
+}
+
func ensureAnonymousClone(t *testing.T, u *url.URL) {
dstLocalPath := t.TempDir()
t.Run("CloneAnonymous", doGitClone(dstLocalPath, u))
@@ -152,9 +192,9 @@ func lfsCommitAndPushTest(t *testing.T, dstPath string, sizes ...int) (pushedFil
t.Run("CommitAndPushLFS", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
prefix := "lfs-data-file-"
- err := git.NewCommand(git.DefaultContext, "lfs").AddArguments("install").Run(&git.RunOpts{Dir: dstPath})
+ err := git.NewCommand("lfs").AddArguments("install").Run(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
- _, _, err = git.NewCommand(git.DefaultContext, "lfs").AddArguments("track").AddDynamicArguments(prefix + "*").RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err = git.NewCommand("lfs").AddArguments("track").AddDynamicArguments(prefix+"*").RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
err = git.AddChanges(dstPath, false, ".gitattributes")
assert.NoError(t, err)
@@ -270,20 +310,20 @@ func lockTest(t *testing.T, repoPath string) {
}
func lockFileTest(t *testing.T, filename, repoPath string) {
- _, _, err := git.NewCommand(git.DefaultContext, "lfs").AddArguments("locks").RunStdString(&git.RunOpts{Dir: repoPath})
+ _, _, err := git.NewCommand("lfs").AddArguments("locks").RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath})
assert.NoError(t, err)
- _, _, err = git.NewCommand(git.DefaultContext, "lfs").AddArguments("lock").AddDynamicArguments(filename).RunStdString(&git.RunOpts{Dir: repoPath})
+ _, _, err = git.NewCommand("lfs").AddArguments("lock").AddDynamicArguments(filename).RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath})
assert.NoError(t, err)
- _, _, err = git.NewCommand(git.DefaultContext, "lfs").AddArguments("locks").RunStdString(&git.RunOpts{Dir: repoPath})
+ _, _, err = git.NewCommand("lfs").AddArguments("locks").RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath})
assert.NoError(t, err)
- _, _, err = git.NewCommand(git.DefaultContext, "lfs").AddArguments("unlock").AddDynamicArguments(filename).RunStdString(&git.RunOpts{Dir: repoPath})
+ _, _, err = git.NewCommand("lfs").AddArguments("unlock").AddDynamicArguments(filename).RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath})
assert.NoError(t, err)
}
func doCommitAndPush(t *testing.T, size int, repoPath, prefix string) string {
name, err := generateCommitWithNewData(size, repoPath, "user2@example.com", "User Two", prefix)
assert.NoError(t, err)
- _, _, err = git.NewCommand(git.DefaultContext, "push", "origin", "master").RunStdString(&git.RunOpts{Dir: repoPath}) // Push
+ _, _, err = git.NewCommand("push", "origin", "master").RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath}) // Push
assert.NoError(t, err)
return name
}
@@ -326,6 +366,34 @@ func generateCommitWithNewData(size int, repoPath, email, fullName, prefix strin
return filepath.Base(tmpFile.Name()), err
}
+func doCreateProtectedBranch(baseCtx *APITestContext, dstPath string) func(t *testing.T) {
+ return func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+ ctx := NewAPITestContext(t, baseCtx.Username, baseCtx.Reponame, auth_model.AccessTokenScopeWriteRepository)
+
+ t.Run("ProtectBranchWithFilePatterns", doProtectBranch(ctx, "release-*", baseCtx.Username, "", "", "config*"))
+
+ // push a new branch without any new commits
+ t.Run("CreateProtectedBranch-NoChanges", doGitCreateBranch(dstPath, "release-v1.0"))
+ t.Run("PushProtectedBranch-NoChanges", doGitPushTestRepository(dstPath, "origin", "release-v1.0"))
+ t.Run("CheckoutMaster-NoChanges", doGitCheckoutBranch(dstPath, "master"))
+
+ // push a new branch with a new unprotected file
+ t.Run("CreateProtectedBranch-UnprotectedFile", doGitCreateBranch(dstPath, "release-v2.0"))
+ _, err := generateCommitWithNewData(testFileSizeSmall, dstPath, "user2@example.com", "User Two", "abc.txt")
+ assert.NoError(t, err)
+ t.Run("PushProtectedBranch-UnprotectedFile", doGitPushTestRepository(dstPath, "origin", "release-v2.0"))
+ t.Run("CheckoutMaster-UnprotectedFile", doGitCheckoutBranch(dstPath, "master"))
+
+ // push a new branch with a new protected file
+ t.Run("CreateProtectedBranch-ProtectedFile", doGitCreateBranch(dstPath, "release-v3.0"))
+ _, err = generateCommitWithNewData(testFileSizeSmall, dstPath, "user2@example.com", "User Two", "config")
+ assert.NoError(t, err)
+ t.Run("PushProtectedBranch-ProtectedFile", doGitPushTestRepositoryFail(dstPath, "origin", "release-v3.0"))
+ t.Run("CheckoutMaster-ProtectedFile", doGitCheckoutBranch(dstPath, "master"))
+ }
+}
+
func doBranchProtectPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) {
return func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
@@ -335,60 +403,48 @@ func doBranchProtectPRMerge(baseCtx *APITestContext, dstPath string) func(t *tes
ctx := NewAPITestContext(t, baseCtx.Username, baseCtx.Reponame, auth_model.AccessTokenScopeWriteRepository)
// Protect branch without any whitelisting
- t.Run("ProtectBranchNoWhitelist", func(t *testing.T) {
- doProtectBranch(ctx, "protected", "", "", "")
- })
+ t.Run("ProtectBranchNoWhitelist", doProtectBranch(ctx, "protected", "", "", "", ""))
// Try to push without permissions, which should fail
t.Run("TryPushWithoutPermissions", func(t *testing.T) {
_, err := generateCommitWithNewData(testFileSizeSmall, dstPath, "user2@example.com", "User Two", "branch-data-file-")
assert.NoError(t, err)
- doGitPushTestRepositoryFail(dstPath, "origin", "protected")
+ doGitPushTestRepositoryFail(dstPath, "origin", "protected")(t)
})
// Set up permissions for normal push but not force push
- t.Run("SetupNormalPushPermissions", func(t *testing.T) {
- doProtectBranch(ctx, "protected", baseCtx.Username, "", "")
- })
+ t.Run("SetupNormalPushPermissions", doProtectBranch(ctx, "protected", baseCtx.Username, "", "", ""))
// Normal push should work
t.Run("NormalPushWithPermissions", func(t *testing.T) {
_, err := generateCommitWithNewData(testFileSizeSmall, dstPath, "user2@example.com", "User Two", "branch-data-file-")
assert.NoError(t, err)
- doGitPushTestRepository(dstPath, "origin", "protected")
+ doGitPushTestRepository(dstPath, "origin", "protected")(t)
})
// Try to force push without force push permissions, which should fail
t.Run("ForcePushWithoutForcePermissions", func(t *testing.T) {
t.Run("CreateDivergentHistory", func(t *testing.T) {
- git.NewCommand(git.DefaultContext, "reset", "--hard", "HEAD~1").Run(&git.RunOpts{Dir: dstPath})
+ git.NewCommand("reset", "--hard", "HEAD~1").Run(git.DefaultContext, &git.RunOpts{Dir: dstPath})
_, err := generateCommitWithNewData(testFileSizeSmall, dstPath, "user2@example.com", "User Two", "branch-data-file-new")
assert.NoError(t, err)
})
- doGitPushTestRepositoryFail(dstPath, "-f", "origin", "protected")
+ doGitPushTestRepositoryFail(dstPath, "-f", "origin", "protected")(t)
})
// Set up permissions for force push but not normal push
- t.Run("SetupForcePushPermissions", func(t *testing.T) {
- doProtectBranch(ctx, "protected", "", baseCtx.Username, "")
- })
+ t.Run("SetupForcePushPermissions", doProtectBranch(ctx, "protected", "", baseCtx.Username, "", ""))
// Try to force push without normal push permissions, which should fail
- t.Run("ForcePushWithoutNormalPermissions", func(t *testing.T) {
- doGitPushTestRepositoryFail(dstPath, "-f", "origin", "protected")
- })
+ t.Run("ForcePushWithoutNormalPermissions", doGitPushTestRepositoryFail(dstPath, "-f", "origin", "protected"))
// Set up permissions for normal and force push (both are required to force push)
- t.Run("SetupNormalAndForcePushPermissions", func(t *testing.T) {
- doProtectBranch(ctx, "protected", baseCtx.Username, baseCtx.Username, "")
- })
+ t.Run("SetupNormalAndForcePushPermissions", doProtectBranch(ctx, "protected", baseCtx.Username, baseCtx.Username, "", ""))
// Force push should now work
- t.Run("ForcePushWithPermissions", func(t *testing.T) {
- doGitPushTestRepository(dstPath, "-f", "origin", "protected")
- })
+ t.Run("ForcePushWithPermissions", doGitPushTestRepository(dstPath, "-f", "origin", "protected"))
- t.Run("ProtectProtectedBranchNoWhitelist", doProtectBranch(ctx, "protected", "", "", ""))
+ t.Run("ProtectProtectedBranchNoWhitelist", doProtectBranch(ctx, "protected", "", "", "", ""))
t.Run("PushToUnprotectedBranch", doGitPushTestRepository(dstPath, "origin", "protected:unprotected"))
var pr api.PullRequest
var err error
@@ -410,14 +466,14 @@ func doBranchProtectPRMerge(baseCtx *APITestContext, dstPath string) func(t *tes
t.Run("MergePR", doAPIMergePullRequest(ctx, baseCtx.Username, baseCtx.Reponame, pr.Index))
t.Run("PullProtected", doGitPull(dstPath, "origin", "protected"))
- t.Run("ProtectProtectedBranchUnprotectedFilePaths", doProtectBranch(ctx, "protected", "", "", "unprotected-file-*"))
+ t.Run("ProtectProtectedBranchUnprotectedFilePaths", doProtectBranch(ctx, "protected", "", "", "unprotected-file-*", ""))
t.Run("GenerateCommit", func(t *testing.T) {
_, err := generateCommitWithNewData(testFileSizeSmall, dstPath, "user2@example.com", "User Two", "unprotected-file-")
assert.NoError(t, err)
})
t.Run("PushUnprotectedFilesToProtectedBranch", doGitPushTestRepository(dstPath, "origin", "protected"))
- t.Run("ProtectProtectedBranchWhitelist", doProtectBranch(ctx, "protected", baseCtx.Username, "", ""))
+ t.Run("ProtectProtectedBranchWhitelist", doProtectBranch(ctx, "protected", baseCtx.Username, "", "", ""))
t.Run("CheckoutMaster", doGitCheckoutBranch(dstPath, "master"))
t.Run("CreateBranchForced", doGitCreateBranch(dstPath, "toforce"))
@@ -432,7 +488,7 @@ func doBranchProtectPRMerge(baseCtx *APITestContext, dstPath string) func(t *tes
}
}
-func doProtectBranch(ctx APITestContext, branch, userToWhitelistPush, userToWhitelistForcePush, unprotectedFilePatterns string) func(t *testing.T) {
+func doProtectBranch(ctx APITestContext, branch, userToWhitelistPush, userToWhitelistForcePush, unprotectedFilePatterns, protectedFilePatterns string) func(t *testing.T) {
// We are going to just use the owner to set the protection.
return func(t *testing.T) {
csrf := GetUserCSRFToken(t, ctx.Session)
@@ -441,6 +497,7 @@ func doProtectBranch(ctx APITestContext, branch, userToWhitelistPush, userToWhit
"_csrf": csrf,
"rule_name": branch,
"unprotected_file_patterns": unprotectedFilePatterns,
+ "protected_file_patterns": protectedFilePatterns,
}
if userToWhitelistPush != "" {
@@ -464,9 +521,8 @@ func doProtectBranch(ctx APITestContext, branch, userToWhitelistPush, userToWhit
ctx.Session.MakeRequest(t, req, http.StatusSeeOther)
// Check if master branch has been locked successfully
- flashCookie := ctx.Session.GetCookie(gitea_context.CookieNameFlash)
- assert.NotNil(t, flashCookie)
- assert.EqualValues(t, "success%3DBranch%2Bprotection%2Bfor%2Brule%2B%2522"+url.QueryEscape(branch)+"%2522%2Bhas%2Bbeen%2Bupdated.", flashCookie.Value)
+ flashMsg := ctx.Session.GetCookieFlashMessage()
+ assert.Equal(t, `Branch protection for rule "`+branch+`" has been updated.`, flashMsg.SuccessMsg)
}
}
@@ -575,7 +631,7 @@ func doPushCreate(ctx APITestContext, u *url.URL) func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
// create a context for a currently non-existent repository
- ctx.Reponame = fmt.Sprintf("repo-tmp-push-create-%s", u.Scheme)
+ ctx.Reponame = "repo-tmp-push-create-" + u.Scheme
u.Path = ctx.GitPath()
// Create a temporary directory
@@ -606,7 +662,7 @@ func doPushCreate(ctx APITestContext, u *url.URL) func(t *testing.T) {
// Now add a remote that is invalid to "Push To Create"
invalidCtx := ctx
- invalidCtx.Reponame = fmt.Sprintf("invalid/repo-tmp-push-create-%s", u.Scheme)
+ invalidCtx.Reponame = "invalid/repo-tmp-push-create-" + u.Scheme
u.Path = invalidCtx.GitPath()
t.Run("AddInvalidRemote", doGitAddRemote(tmpDir, "invalid", u))
@@ -658,7 +714,7 @@ func doAutoPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) {
commitID := path.Base(commitURL)
- addCommitStatus := func(status api.CommitStatusState) func(*testing.T) {
+ addCommitStatus := func(status commitstatus.CommitStatusState) func(*testing.T) {
return doAPICreateCommitStatus(ctx, commitID, api.CreateStatusOption{
State: status,
TargetURL: "http://test.ci/",
@@ -668,7 +724,7 @@ func doAutoPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) {
}
// Call API to add Pending status for commit
- t.Run("CreateStatus", addCommitStatus(api.CommitStatusPending))
+ t.Run("CreateStatus", addCommitStatus(commitstatus.CommitStatusPending))
// Cancel not existing auto merge
ctx.ExpectedCode = http.StatusNotFound
@@ -697,7 +753,7 @@ func doAutoPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) {
assert.False(t, pr.HasMerged)
// Call API to add Failure status for commit
- t.Run("CreateStatus", addCommitStatus(api.CommitStatusFailure))
+ t.Run("CreateStatus", addCommitStatus(commitstatus.CommitStatusFailure))
// Check pr status
pr, err = doAPIGetPullRequest(ctx, baseCtx.Username, baseCtx.Reponame, pr.Index)(t)
@@ -705,7 +761,7 @@ func doAutoPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) {
assert.False(t, pr.HasMerged)
// Call API to add Success status for commit
- t.Run("CreateStatus", addCommitStatus(api.CommitStatusSuccess))
+ t.Run("CreateStatus", addCommitStatus(commitstatus.CommitStatusSuccess))
// wait to let gitea merge stuff
time.Sleep(time.Second)
@@ -768,7 +824,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string
})
t.Run("Push", func(t *testing.T) {
- err := git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/master", "-o").AddDynamicArguments("topic=" + headBranch).Run(&git.RunOpts{Dir: dstPath})
+ err := git.NewCommand("push", "origin", "HEAD:refs/for/master", "-o").AddDynamicArguments("topic="+headBranch).Run(git.DefaultContext, &git.RunOpts{Dir: dstPath})
require.NoError(t, err)
unittest.AssertCount(t, &issues_model.PullRequest{}, pullNum+1)
@@ -786,7 +842,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string
assert.Contains(t, "Testing commit 1", prMsg.Body)
assert.Equal(t, commit, prMsg.Head.Sha)
- _, _, err = git.NewCommand(git.DefaultContext, "push", "origin").AddDynamicArguments("HEAD:refs/for/master/test/" + headBranch).RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err = git.NewCommand("push", "origin").AddDynamicArguments("HEAD:refs/for/master/test/"+headBranch).RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
require.NoError(t, err)
unittest.AssertCount(t, &issues_model.PullRequest{}, pullNum+2)
@@ -834,7 +890,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string
})
t.Run("Push2", func(t *testing.T) {
- err := git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/master", "-o").AddDynamicArguments("topic=" + headBranch).Run(&git.RunOpts{Dir: dstPath})
+ err := git.NewCommand("push", "origin", "HEAD:refs/for/master", "-o").AddDynamicArguments("topic="+headBranch).Run(git.DefaultContext, &git.RunOpts{Dir: dstPath})
require.NoError(t, err)
unittest.AssertCount(t, &issues_model.PullRequest{}, pullNum+2)
@@ -844,7 +900,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string
assert.False(t, prMsg.HasMerged)
assert.Equal(t, commit, prMsg.Head.Sha)
- _, _, err = git.NewCommand(git.DefaultContext, "push", "origin").AddDynamicArguments("HEAD:refs/for/master/test/" + headBranch).RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err = git.NewCommand("push", "origin").AddDynamicArguments("HEAD:refs/for/master/test/"+headBranch).RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
require.NoError(t, err)
unittest.AssertCount(t, &issues_model.PullRequest{}, pullNum+2)
diff --git a/tests/integration/git_helper_for_declarative_test.go b/tests/integration/git_helper_for_declarative_test.go
index 43b151e0b6..7d42508bfe 100644
--- a/tests/integration/git_helper_for_declarative_test.go
+++ b/tests/integration/git_helper_for_declarative_test.go
@@ -10,7 +10,6 @@ import (
"net/http"
"net/url"
"os"
- "path"
"path/filepath"
"strconv"
"testing"
@@ -35,12 +34,12 @@ func withKeyFile(t *testing.T, keyname string, callback func(string)) {
err = ssh.GenKeyPair(keyFile)
assert.NoError(t, err)
- err = os.WriteFile(path.Join(tmpDir, "ssh"), []byte("#!/bin/bash\n"+
+ err = os.WriteFile(filepath.Join(tmpDir, "ssh"), []byte("#!/bin/bash\n"+
"ssh -o \"UserKnownHostsFile=/dev/null\" -o \"StrictHostKeyChecking=no\" -o \"IdentitiesOnly=yes\" -i \""+keyFile+"\" \"$@\""), 0o700)
assert.NoError(t, err)
// Setup ssh wrapper
- t.Setenv("GIT_SSH", path.Join(tmpDir, "ssh"))
+ t.Setenv("GIT_SSH", filepath.Join(tmpDir, "ssh"))
t.Setenv("GIT_SSH_COMMAND",
"ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o IdentitiesOnly=yes -i \""+keyFile+"\"")
t.Setenv("GIT_SSH_VARIANT", "ssh")
@@ -76,7 +75,7 @@ func onGiteaRun[T testing.TB](t T, callback func(T, *url.URL)) {
u.Host = listener.Addr().String()
defer func() {
- ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
+ ctx, cancel := context.WithTimeout(t.Context(), 2*time.Minute)
s.Shutdown(ctx)
cancel()
}()
@@ -89,7 +88,7 @@ func onGiteaRun[T testing.TB](t T, callback func(T, *url.URL)) {
func doGitClone(dstLocalPath string, u *url.URL) func(*testing.T) {
return func(t *testing.T) {
- assert.NoError(t, git.CloneWithArgs(context.Background(), git.AllowLFSFiltersArgs(), u.String(), dstLocalPath, git.CloneRepoOptions{}))
+ assert.NoError(t, git.CloneWithArgs(t.Context(), git.AllowLFSFiltersArgs(), u.String(), dstLocalPath, git.CloneRepoOptions{}))
exist, err := util.IsExist(filepath.Join(dstLocalPath, "README.md"))
assert.NoError(t, err)
assert.True(t, exist)
@@ -98,7 +97,7 @@ func doGitClone(dstLocalPath string, u *url.URL) func(*testing.T) {
func doPartialGitClone(dstLocalPath string, u *url.URL) func(*testing.T) {
return func(t *testing.T) {
- assert.NoError(t, git.CloneWithArgs(context.Background(), git.AllowLFSFiltersArgs(), u.String(), dstLocalPath, git.CloneRepoOptions{
+ assert.NoError(t, git.CloneWithArgs(t.Context(), git.AllowLFSFiltersArgs(), u.String(), dstLocalPath, git.CloneRepoOptions{
Filter: "blob:none",
}))
exist, err := util.IsExist(filepath.Join(dstLocalPath, "README.md"))
@@ -122,9 +121,9 @@ func doGitInitTestRepository(dstPath string) func(*testing.T) {
// Init repository in dstPath
assert.NoError(t, git.InitRepository(git.DefaultContext, dstPath, false, git.Sha1ObjectFormat.Name()))
// forcibly set default branch to master
- _, _, err := git.NewCommand(git.DefaultContext, "symbolic-ref", "HEAD", git.BranchPrefix+"master").RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err := git.NewCommand("symbolic-ref", "HEAD", git.BranchPrefix+"master").RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
- assert.NoError(t, os.WriteFile(filepath.Join(dstPath, "README.md"), []byte(fmt.Sprintf("# Testing Repository\n\nOriginally created in: %s", dstPath)), 0o644))
+ assert.NoError(t, os.WriteFile(filepath.Join(dstPath, "README.md"), []byte("# Testing Repository\n\nOriginally created in: "+dstPath), 0o644))
assert.NoError(t, git.AddChanges(dstPath, true))
signature := git.Signature{
Email: "test@example.com",
@@ -141,21 +140,21 @@ func doGitInitTestRepository(dstPath string) func(*testing.T) {
func doGitAddRemote(dstPath, remoteName string, u *url.URL) func(*testing.T) {
return func(t *testing.T) {
- _, _, err := git.NewCommand(git.DefaultContext, "remote", "add").AddDynamicArguments(remoteName, u.String()).RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err := git.NewCommand("remote", "add").AddDynamicArguments(remoteName, u.String()).RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
}
}
func doGitPushTestRepository(dstPath string, args ...string) func(*testing.T) {
return func(t *testing.T) {
- _, _, err := git.NewCommand(git.DefaultContext, "push", "-u").AddArguments(git.ToTrustedCmdArgs(args)...).RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err := git.NewCommand("push", "-u").AddArguments(git.ToTrustedCmdArgs(args)...).RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
}
}
func doGitPushTestRepositoryFail(dstPath string, args ...string) func(*testing.T) {
return func(t *testing.T) {
- _, _, err := git.NewCommand(git.DefaultContext, "push").AddArguments(git.ToTrustedCmdArgs(args)...).RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err := git.NewCommand("push").AddArguments(git.ToTrustedCmdArgs(args)...).RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.Error(t, err)
}
}
@@ -164,7 +163,7 @@ func doGitAddSomeCommits(dstPath, branch string) func(*testing.T) {
return func(t *testing.T) {
doGitCheckoutBranch(dstPath, branch)(t)
- assert.NoError(t, os.WriteFile(filepath.Join(dstPath, fmt.Sprintf("file-%s.txt", branch)), []byte(fmt.Sprintf("file %s", branch)), 0o644))
+ assert.NoError(t, os.WriteFile(filepath.Join(dstPath, fmt.Sprintf("file-%s.txt", branch)), []byte("file "+branch), 0o644))
assert.NoError(t, git.AddChanges(dstPath, true))
signature := git.Signature{
Email: "test@test.test",
@@ -173,35 +172,35 @@ func doGitAddSomeCommits(dstPath, branch string) func(*testing.T) {
assert.NoError(t, git.CommitChanges(dstPath, git.CommitChangesOptions{
Committer: &signature,
Author: &signature,
- Message: fmt.Sprintf("update %s", branch),
+ Message: "update " + branch,
}))
}
}
func doGitCreateBranch(dstPath, branch string) func(*testing.T) {
return func(t *testing.T) {
- _, _, err := git.NewCommand(git.DefaultContext, "checkout", "-b").AddDynamicArguments(branch).RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err := git.NewCommand("checkout", "-b").AddDynamicArguments(branch).RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
}
}
func doGitCheckoutBranch(dstPath string, args ...string) func(*testing.T) {
return func(t *testing.T) {
- _, _, err := git.NewCommandContextNoGlobals(git.DefaultContext, git.AllowLFSFiltersArgs()...).AddArguments("checkout").AddArguments(git.ToTrustedCmdArgs(args)...).RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err := git.NewCommandNoGlobals(git.AllowLFSFiltersArgs()...).AddArguments("checkout").AddArguments(git.ToTrustedCmdArgs(args)...).RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
}
}
func doGitMerge(dstPath string, args ...string) func(*testing.T) {
return func(t *testing.T) {
- _, _, err := git.NewCommand(git.DefaultContext, "merge").AddArguments(git.ToTrustedCmdArgs(args)...).RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err := git.NewCommand("merge").AddArguments(git.ToTrustedCmdArgs(args)...).RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
}
}
func doGitPull(dstPath string, args ...string) func(*testing.T) {
return func(t *testing.T) {
- _, _, err := git.NewCommandContextNoGlobals(git.DefaultContext, git.AllowLFSFiltersArgs()...).AddArguments("pull").AddArguments(git.ToTrustedCmdArgs(args)...).RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err := git.NewCommandNoGlobals(git.AllowLFSFiltersArgs()...).AddArguments("pull").AddArguments(git.ToTrustedCmdArgs(args)...).RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
}
}
diff --git a/tests/integration/git_lfs_ssh_test.go b/tests/integration/git_lfs_ssh_test.go
index 9cb7fd089b..64a403f513 100644
--- a/tests/integration/git_lfs_ssh_test.go
+++ b/tests/integration/git_lfs_ssh_test.go
@@ -4,7 +4,6 @@
package integration
import (
- gocontext "context"
"net/url"
"slices"
"strings"
@@ -46,7 +45,7 @@ func TestGitLFSSSH(t *testing.T) {
setting.LFS.AllowPureSSH = true
require.NoError(t, cfg.Save())
- _, _, cmdErr := git.NewCommand(gocontext.Background(), "config", "lfs.sshtransfer", "always").RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, cmdErr := git.NewCommand("config", "lfs.sshtransfer", "always").RunStdString(t.Context(), &git.RunOpts{Dir: dstPath})
assert.NoError(t, cmdErr)
lfsCommitAndPushTest(t, dstPath, 10)
})
@@ -55,9 +54,14 @@ func TestGitLFSSSH(t *testing.T) {
return strings.Contains(s, "POST /api/internal/repo/user2/repo1.git/info/lfs/objects/batch")
})
countUpload := slices.ContainsFunc(routerCalls, func(s string) bool {
- return strings.Contains(s, "PUT /user2/repo1.git/info/lfs/objects/")
+ return strings.Contains(s, "PUT /api/internal/repo/user2/repo1.git/info/lfs/objects/")
+ })
+ nonAPIRequests := slices.ContainsFunc(routerCalls, func(s string) bool {
+ fields := strings.Fields(s)
+ return !strings.HasPrefix(fields[1], "/api/")
})
assert.NotZero(t, countBatch)
assert.NotZero(t, countUpload)
+ assert.Zero(t, nonAPIRequests)
})
}
diff --git a/tests/integration/git_misc_test.go b/tests/integration/git_misc_test.go
index 00ed2a766f..bf9e2c02ab 100644
--- a/tests/integration/git_misc_test.go
+++ b/tests/integration/git_misc_test.go
@@ -5,7 +5,6 @@ package integration
import (
"bytes"
- "context"
"io"
"net/url"
"sync"
@@ -91,7 +90,7 @@ func TestAgitPullPush(t *testing.T) {
dstPath := t.TempDir()
doGitClone(dstPath, u)(t)
- gitRepo, err := git.OpenRepository(context.Background(), dstPath)
+ gitRepo, err := git.OpenRepository(t.Context(), dstPath)
assert.NoError(t, err)
defer gitRepo.Close()
@@ -102,10 +101,10 @@ func TestAgitPullPush(t *testing.T) {
assert.NoError(t, err)
// push to create an agit pull request
- err = git.NewCommand(git.DefaultContext, "push", "origin",
+ err = git.NewCommand("push", "origin",
"-o", "title=test-title", "-o", "description=test-description",
"HEAD:refs/for/master/test-agit-push",
- ).Run(&git.RunOpts{Dir: dstPath})
+ ).Run(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
// check pull request exist
@@ -119,20 +118,20 @@ func TestAgitPullPush(t *testing.T) {
assert.NoError(t, err)
// push 2
- err = git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/master/test-agit-push").Run(&git.RunOpts{Dir: dstPath})
+ err = git.NewCommand("push", "origin", "HEAD:refs/for/master/test-agit-push").Run(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
// reset to first commit
- err = git.NewCommand(git.DefaultContext, "reset", "--hard", "HEAD~1").Run(&git.RunOpts{Dir: dstPath})
+ err = git.NewCommand("reset", "--hard", "HEAD~1").Run(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
// test force push without confirm
- _, stderr, err := git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/master/test-agit-push").RunStdString(&git.RunOpts{Dir: dstPath})
+ _, stderr, err := git.NewCommand("push", "origin", "HEAD:refs/for/master/test-agit-push").RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.Error(t, err)
assert.Contains(t, stderr, "[remote rejected] HEAD -> refs/for/master/test-agit-push (request `force-push` push option)")
// test force push with confirm
- err = git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/master/test-agit-push", "-o", "force-push").Run(&git.RunOpts{Dir: dstPath})
+ err = git.NewCommand("push", "origin", "HEAD:refs/for/master/test-agit-push", "-o", "force-push").Run(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
})
}
diff --git a/tests/integration/git_push_test.go b/tests/integration/git_push_test.go
index e68f8bfce2..d716847b54 100644
--- a/tests/integration/git_push_test.go
+++ b/tests/integration/git_push_test.go
@@ -27,7 +27,7 @@ func TestGitPush(t *testing.T) {
func testGitPush(t *testing.T, u *url.URL) {
t.Run("Push branches at once", func(t *testing.T) {
runTestGitPush(t, u, func(t *testing.T, gitPath string) (pushed, deleted []string) {
- for i := 0; i < 100; i++ {
+ for i := range 100 {
branchName := fmt.Sprintf("branch-%d", i)
pushed = append(pushed, branchName)
doGitCreateBranch(gitPath, branchName)(t)
@@ -40,7 +40,7 @@ func testGitPush(t *testing.T, u *url.URL) {
t.Run("Push branches exists", func(t *testing.T) {
runTestGitPush(t, u, func(t *testing.T, gitPath string) (pushed, deleted []string) {
- for i := 0; i < 10; i++ {
+ for i := range 10 {
branchName := fmt.Sprintf("branch-%d", i)
if i < 5 {
pushed = append(pushed, branchName)
@@ -54,7 +54,7 @@ func testGitPush(t *testing.T, u *url.URL) {
pushed = pushed[:0]
// do some changes for the first 5 branches created above
- for i := 0; i < 5; i++ {
+ for i := range 5 {
branchName := fmt.Sprintf("branch-%d", i)
pushed = append(pushed, branchName)
@@ -75,7 +75,7 @@ func testGitPush(t *testing.T, u *url.URL) {
t.Run("Push branches one by one", func(t *testing.T) {
runTestGitPush(t, u, func(t *testing.T, gitPath string) (pushed, deleted []string) {
- for i := 0; i < 100; i++ {
+ for i := range 100 {
branchName := fmt.Sprintf("branch-%d", i)
doGitCreateBranch(gitPath, branchName)(t)
doGitPushTestRepository(gitPath, "origin", branchName)(t)
@@ -101,14 +101,14 @@ func testGitPush(t *testing.T, u *url.URL) {
doGitPushTestRepository(gitPath, "origin", "master")(t) // make sure master is the default branch instead of a branch we are going to delete
pushed = append(pushed, "master")
- for i := 0; i < 100; i++ {
+ for i := range 100 {
branchName := fmt.Sprintf("branch-%d", i)
pushed = append(pushed, branchName)
doGitCreateBranch(gitPath, branchName)(t)
}
doGitPushTestRepository(gitPath, "origin", "--all")(t)
- for i := 0; i < 10; i++ {
+ for i := range 10 {
branchName := fmt.Sprintf("branch-%d", i)
doGitPushTestRepository(gitPath, "origin", "--delete", branchName)(t)
deleted = append(deleted, branchName)
@@ -170,7 +170,7 @@ func runTestGitPush(t *testing.T, u *url.URL, gitOperation func(t *testing.T, gi
dbBranches := make([]*git_model.Branch, 0)
require.NoError(t, db.GetEngine(db.DefaultContext).Where("repo_id=?", repo.ID).Find(&dbBranches))
- assert.Equalf(t, len(pushedBranches), len(dbBranches), "mismatched number of branches in db")
+ assert.Lenf(t, dbBranches, len(pushedBranches), "mismatched number of branches in db")
dbBranchesMap := make(map[string]*git_model.Branch, len(dbBranches))
for _, branch := range dbBranches {
dbBranchesMap[branch.Name] = branch
@@ -191,7 +191,7 @@ func runTestGitPush(t *testing.T, u *url.URL, gitOperation func(t *testing.T, gi
assert.Equal(t, commitID, branch.CommitID)
}
- require.NoError(t, repo_service.DeleteRepositoryDirectly(db.DefaultContext, user, repo.ID))
+ require.NoError(t, repo_service.DeleteRepositoryDirectly(db.DefaultContext, repo.ID))
}
func TestPushPullRefs(t *testing.T) {
@@ -204,8 +204,8 @@ func TestPushPullRefs(t *testing.T) {
dstPath := t.TempDir()
doGitClone(dstPath, u)(t)
- cmd := git.NewCommand(git.DefaultContext, "push", "--delete", "origin", "refs/pull/2/head")
- stdout, stderr, err := cmd.RunStdString(&git.RunOpts{
+ cmd := git.NewCommand("push", "--delete", "origin", "refs/pull/2/head")
+ stdout, stderr, err := cmd.RunStdString(git.DefaultContext, &git.RunOpts{
Dir: dstPath,
})
assert.Error(t, err)
diff --git a/tests/integration/git_smart_http_test.go b/tests/integration/git_smart_http_test.go
index 15336b9b81..e984fd3aad 100644
--- a/tests/integration/git_smart_http_test.go
+++ b/tests/integration/git_smart_http_test.go
@@ -9,60 +9,90 @@ import (
"net/url"
"testing"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/test"
+ "code.gitea.io/gitea/modules/util"
+
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
func TestGitSmartHTTP(t *testing.T) {
- onGiteaRun(t, testGitSmartHTTP)
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ testGitSmartHTTP(t, u)
+ testRenamedRepoRedirect(t)
+ })
}
func testGitSmartHTTP(t *testing.T, u *url.URL) {
kases := []struct {
- p string
- code int
+ method, path string
+ code int
}{
{
- p: "user2/repo1/info/refs",
+ path: "user2/repo1/info/refs",
code: http.StatusOK,
},
{
- p: "user2/repo1/HEAD",
+ method: "HEAD",
+ path: "user2/repo1/info/refs",
+ code: http.StatusOK,
+ },
+ {
+ path: "user2/repo1/HEAD",
code: http.StatusOK,
},
{
- p: "user2/repo1/objects/info/alternates",
+ path: "user2/repo1/objects/info/alternates",
code: http.StatusNotFound,
},
{
- p: "user2/repo1/objects/info/http-alternates",
+ path: "user2/repo1/objects/info/http-alternates",
code: http.StatusNotFound,
},
{
- p: "user2/repo1/../../custom/conf/app.ini",
+ path: "user2/repo1/../../custom/conf/app.ini",
code: http.StatusNotFound,
},
{
- p: "user2/repo1/objects/info/../../../../custom/conf/app.ini",
+ path: "user2/repo1/objects/info/../../../../custom/conf/app.ini",
code: http.StatusNotFound,
},
{
- p: `user2/repo1/objects/info/..\..\..\..\custom\conf\app.ini`,
+ path: `user2/repo1/objects/info/..\..\..\..\custom\conf\app.ini`,
code: http.StatusBadRequest,
},
}
for _, kase := range kases {
- t.Run(kase.p, func(t *testing.T) {
- p := u.String() + kase.p
- req, err := http.NewRequest("GET", p, nil)
- assert.NoError(t, err)
+ t.Run(kase.path, func(t *testing.T) {
+ req, err := http.NewRequest(util.IfZero(kase.method, "GET"), u.String()+kase.path, nil)
+ require.NoError(t, err)
req.SetBasicAuth("user2", userPassword)
resp, err := http.DefaultClient.Do(req)
- assert.NoError(t, err)
+ require.NoError(t, err)
defer resp.Body.Close()
- assert.EqualValues(t, kase.code, resp.StatusCode)
+ assert.Equal(t, kase.code, resp.StatusCode)
_, err = io.ReadAll(resp.Body)
- assert.NoError(t, err)
+ require.NoError(t, err)
})
}
}
+
+func testRenamedRepoRedirect(t *testing.T) {
+ defer test.MockVariableValue(&setting.Service.RequireSignInViewStrict, true)()
+
+ // git client requires to get a 301 redirect response before 401 unauthorized response
+ req := NewRequest(t, "GET", "/user2/oldrepo1/info/refs")
+ resp := MakeRequest(t, req, http.StatusMovedPermanently)
+ redirect := resp.Header().Get("Location")
+ assert.Equal(t, "/user2/repo1/info/refs", redirect)
+
+ req = NewRequest(t, "GET", redirect)
+ resp = MakeRequest(t, req, http.StatusUnauthorized)
+ assert.Equal(t, "Unauthorized\n", resp.Body.String())
+
+ req = NewRequest(t, "GET", redirect).AddBasicAuth("user2")
+ resp = MakeRequest(t, req, http.StatusOK)
+ assert.Contains(t, resp.Body.String(), "65f1bf27bc3bf70f64657658635e66094edbcb4d\trefs/tags/v1.1")
+}
diff --git a/tests/integration/gpg_git_test.go b/tests/integration/gpg_ssh_git_test.go
index 31695fb2e1..56f9f87783 100644
--- a/tests/integration/gpg_git_test.go
+++ b/tests/integration/gpg_ssh_git_test.go
@@ -4,7 +4,10 @@
package integration
import (
+ "crypto/ed25519"
+ "crypto/rand"
"encoding/base64"
+ "encoding/pem"
"fmt"
"net/url"
"os"
@@ -23,6 +26,7 @@ import (
"github.com/ProtonMail/go-crypto/openpgp/armor"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "golang.org/x/crypto/ssh"
)
func TestGPGGit(t *testing.T) {
@@ -42,6 +46,37 @@ func TestGPGGit(t *testing.T) {
defer test.MockVariableValue(&setting.Repository.Signing.InitialCommit, []string{"never"})()
defer test.MockVariableValue(&setting.Repository.Signing.CRUDActions, []string{"never"})()
+ testGitSigning(t)
+}
+
+func TestSSHGit(t *testing.T) {
+ tmpDir := t.TempDir() // use a temp dir to store the SSH keys
+ err := os.Chmod(tmpDir, 0o700)
+ assert.NoError(t, err)
+
+ pub, priv, err := ed25519.GenerateKey(rand.Reader)
+ require.NoError(t, err, "ed25519.GenerateKey")
+ sshPubKey, err := ssh.NewPublicKey(pub)
+ require.NoError(t, err, "ssh.NewPublicKey")
+
+ err = os.WriteFile(tmpDir+"/id_ed25519.pub", ssh.MarshalAuthorizedKey(sshPubKey), 0o600)
+ require.NoError(t, err, "os.WriteFile id_ed25519.pub")
+ block, err := ssh.MarshalPrivateKey(priv, "")
+ require.NoError(t, err, "ssh.MarshalPrivateKey")
+ err = os.WriteFile(tmpDir+"/id_ed25519", pem.EncodeToMemory(block), 0o600)
+ require.NoError(t, err, "os.WriteFile id_ed25519")
+
+ defer test.MockVariableValue(&setting.Repository.Signing.SigningKey, tmpDir+"/id_ed25519.pub")()
+ defer test.MockVariableValue(&setting.Repository.Signing.SigningName, "gitea")()
+ defer test.MockVariableValue(&setting.Repository.Signing.SigningEmail, "gitea@fake.local")()
+ defer test.MockVariableValue(&setting.Repository.Signing.SigningFormat, "ssh")()
+ defer test.MockVariableValue(&setting.Repository.Signing.InitialCommit, []string{"never"})()
+ defer test.MockVariableValue(&setting.Repository.Signing.CRUDActions, []string{"never"})()
+
+ testGitSigning(t)
+}
+
+func testGitSigning(t *testing.T) {
username := "user2"
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: username})
baseAPITestContext := NewAPITestContext(t, username, "repo1")
@@ -99,26 +134,14 @@ func TestGPGGit(t *testing.T) {
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
t.Run("CreateCRUDFile-Always", crudActionCreateFile(
t, testCtx, user, "master", "always", "signed-always.txt", func(t *testing.T, response api.FileResponse) {
- assert.NotNil(t, response.Verification)
- if response.Verification == nil {
- assert.FailNow(t, "no verification provided with response! %v", response)
- }
- assert.True(t, response.Verification.Verified)
- if !response.Verification.Verified {
- t.FailNow()
- }
+ require.NotNil(t, response.Verification, "no verification provided with response! %v", response)
+ require.True(t, response.Verification.Verified)
assert.Equal(t, "gitea@fake.local", response.Verification.Signer.Email)
}))
t.Run("CreateCRUDFile-ParentSigned-always", crudActionCreateFile(
t, testCtx, user, "parentsigned", "parentsigned-always", "signed-parent2.txt", func(t *testing.T, response api.FileResponse) {
- assert.NotNil(t, response.Verification)
- if response.Verification == nil {
- assert.FailNow(t, "no verification provided with response! %v", response)
- }
- assert.True(t, response.Verification.Verified)
- if !response.Verification.Verified {
- t.FailNow()
- }
+ require.NotNil(t, response.Verification, "no verification provided with response! %v", response)
+ require.True(t, response.Verification.Verified)
assert.Equal(t, "gitea@fake.local", response.Verification.Signer.Email)
}))
})
@@ -129,14 +152,8 @@ func TestGPGGit(t *testing.T) {
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
t.Run("CreateCRUDFile-Always-ParentSigned", crudActionCreateFile(
t, testCtx, user, "always", "always-parentsigned", "signed-always-parentsigned.txt", func(t *testing.T, response api.FileResponse) {
- assert.NotNil(t, response.Verification)
- if response.Verification == nil {
- assert.FailNow(t, "no verification provided with response! %v", response)
- }
- assert.True(t, response.Verification.Verified)
- if !response.Verification.Verified {
- t.FailNow()
- }
+ require.NotNil(t, response.Verification, "no verification provided with response! %v", response)
+ require.True(t, response.Verification.Verified)
assert.Equal(t, "gitea@fake.local", response.Verification.Signer.Email)
}))
})
@@ -147,18 +164,9 @@ func TestGPGGit(t *testing.T) {
testCtx := NewAPITestContext(t, username, "initial-always", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
t.Run("CheckMasterBranchSigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
- assert.NotNil(t, branch.Commit)
- if branch.Commit == nil {
- assert.FailNow(t, "no commit provided with branch! %v", branch)
- }
- assert.NotNil(t, branch.Commit.Verification)
- if branch.Commit.Verification == nil {
- assert.FailNow(t, "no verification provided with branch commit! %v", branch.Commit)
- }
- assert.True(t, branch.Commit.Verification.Verified)
- if !branch.Commit.Verification.Verified {
- t.FailNow()
- }
+ require.NotNil(t, branch.Commit, "no commit provided with branch! %v", branch)
+ require.NotNil(t, branch.Commit.Verification, "no verification provided with branch commit! %v", branch.Commit)
+ require.True(t, branch.Commit.Verification.Verified)
assert.Equal(t, "gitea@fake.local", branch.Commit.Verification.Signer.Email)
}))
})
@@ -181,11 +189,7 @@ func TestGPGGit(t *testing.T) {
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
t.Run("CreateCRUDFile-ParentSigned", crudActionCreateFile(
t, testCtx, user, "master", "parentsigned", "signed-parent.txt", func(t *testing.T, response api.FileResponse) {
- assert.True(t, response.Verification.Verified)
- if !response.Verification.Verified {
- t.FailNow()
- return
- }
+ require.True(t, response.Verification.Verified)
assert.Equal(t, "gitea@fake.local", response.Verification.Signer.Email)
}))
})
@@ -197,11 +201,7 @@ func TestGPGGit(t *testing.T) {
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
t.Run("CreateCRUDFile-Always", crudActionCreateFile(
t, testCtx, user, "master", "always", "signed-always.txt", func(t *testing.T, response api.FileResponse) {
- assert.True(t, response.Verification.Verified)
- if !response.Verification.Verified {
- t.FailNow()
- return
- }
+ require.True(t, response.Verification.Verified)
assert.Equal(t, "gitea@fake.local", response.Verification.Signer.Email)
}))
})
@@ -273,7 +273,7 @@ func crudActionCreateFile(_ *testing.T, ctx APITestContext, user *user_model.Use
Email: user.Email,
},
},
- ContentBase64: base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("This is new text for %s", path))),
+ ContentBase64: base64.StdEncoding.EncodeToString([]byte("This is new text for " + path)),
}, callback...)
}
diff --git a/tests/integration/html_helper.go b/tests/integration/html_helper.go
index 2217ddec2e..4d589b32e7 100644
--- a/tests/integration/html_helper.go
+++ b/tests/integration/html_helper.go
@@ -42,12 +42,13 @@ func (doc *HTMLDoc) GetCSRF() string {
return doc.GetInputValueByName("_csrf")
}
-// AssertElement check if element by selector exists or does not exist depending on checkExists
-func (doc *HTMLDoc) AssertElement(t testing.TB, selector string, checkExists bool) {
+// AssertHTMLElement check if the element by selector exists or does not exist depending on checkExists
+func AssertHTMLElement[T int | bool](t testing.TB, doc *HTMLDoc, selector string, checkExists T) {
sel := doc.doc.Find(selector)
- if checkExists {
- assert.Equal(t, 1, sel.Length())
- } else {
- assert.Equal(t, 0, sel.Length())
+ switch v := any(checkExists).(type) {
+ case bool:
+ assert.Equal(t, v, sel.Length() > 0)
+ case int:
+ assert.Equal(t, v, sel.Length())
}
}
diff --git a/tests/integration/incoming_email_test.go b/tests/integration/incoming_email_test.go
index e968a2956e..6ccf82a9eb 100644
--- a/tests/integration/incoming_email_test.go
+++ b/tests/integration/incoming_email_test.go
@@ -50,12 +50,12 @@ func TestIncomingEmail(t *testing.T) {
ref, err := incoming_payload.GetReferenceFromPayload(db.DefaultContext, issuePayload)
assert.NoError(t, err)
assert.IsType(t, ref, new(issues_model.Issue))
- assert.EqualValues(t, issue.ID, ref.(*issues_model.Issue).ID)
+ assert.Equal(t, issue.ID, ref.(*issues_model.Issue).ID)
ref, err = incoming_payload.GetReferenceFromPayload(db.DefaultContext, commentPayload)
assert.NoError(t, err)
assert.IsType(t, ref, new(issues_model.Comment))
- assert.EqualValues(t, comment.ID, ref.(*issues_model.Comment).ID)
+ assert.Equal(t, comment.ID, ref.(*issues_model.Comment).ID)
})
t.Run("Token", func(t *testing.T) {
diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go
index 46b93b0a10..21126b63c5 100644
--- a/tests/integration/integration_test.go
+++ b/tests/integration/integration_test.go
@@ -1,7 +1,7 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
-//nolint:forbidigo
+//nolint:forbidigo // use of print functions is allowed in tests
package integration
import (
@@ -29,6 +29,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/routers"
gitea_context "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/tests"
@@ -118,12 +119,11 @@ type TestSession struct {
jar http.CookieJar
}
-func (s *TestSession) GetCookie(name string) *http.Cookie {
+func (s *TestSession) GetRawCookie(name string) *http.Cookie {
baseURL, err := url.Parse(setting.AppURL)
if err != nil {
return nil
}
-
for _, c := range s.jar.Cookies(baseURL) {
if c.Name == name {
return c
@@ -132,6 +132,20 @@ func (s *TestSession) GetCookie(name string) *http.Cookie {
return nil
}
+func (s *TestSession) GetSiteCookie(name string) string {
+ c := s.GetRawCookie(name)
+ if c != nil {
+ v, _ := url.QueryUnescape(c.Value)
+ return v
+ }
+ return ""
+}
+
+func (s *TestSession) GetCookieFlashMessage() *middleware.Flash {
+ cookie := s.GetSiteCookie(gitea_context.CookieNameFlash)
+ return middleware.ParseCookieFlashMessage(cookie)
+}
+
func (s *TestSession) MakeRequest(t testing.TB, rw *RequestWrapper, expectedStatus int) *httptest.ResponseRecorder {
t.Helper()
req := rw.Request
@@ -235,55 +249,19 @@ func loginUserWithPassword(t testing.TB, userName, password string) *TestSession
// token has to be unique this counter take care of
var tokenCounter int64
-// getTokenForLoggedInUser returns a token for a logged in user.
-// The scope is an optional list of snake_case strings like the frontend form fields,
-// but without the "scope_" prefix.
+// getTokenForLoggedInUser returns a token for a logged-in user.
func getTokenForLoggedInUser(t testing.TB, session *TestSession, scopes ...auth.AccessTokenScope) string {
t.Helper()
- var token string
- req := NewRequest(t, "GET", "/user/settings/applications")
- resp := session.MakeRequest(t, req, http.StatusOK)
- var csrf string
- for _, cookie := range resp.Result().Cookies() {
- if cookie.Name != "_csrf" {
- continue
- }
- csrf = cookie.Value
- break
- }
- if csrf == "" {
- doc := NewHTMLParser(t, resp.Body)
- csrf = doc.GetCSRF()
- }
- assert.NotEmpty(t, csrf)
urlValues := url.Values{}
- urlValues.Add("_csrf", csrf)
+ urlValues.Add("_csrf", GetUserCSRFToken(t, session))
urlValues.Add("name", fmt.Sprintf("api-testing-token-%d", atomic.AddInt64(&tokenCounter, 1)))
for _, scope := range scopes {
- urlValues.Add("scope", string(scope))
+ urlValues.Add("scope-dummy", string(scope)) // it only needs to start with "scope-" to be accepted
}
- req = NewRequestWithURLValues(t, "POST", "/user/settings/applications", urlValues)
- resp = session.MakeRequest(t, req, http.StatusSeeOther)
-
- // Log the flash values on failure
- if !assert.Equal(t, []string{"/user/settings/applications"}, resp.Result().Header["Location"]) {
- for _, cookie := range resp.Result().Cookies() {
- if cookie.Name != gitea_context.CookieNameFlash {
- continue
- }
- flash, _ := url.ParseQuery(cookie.Value)
- for key, value := range flash {
- t.Logf("Flash %q: %q", key, value)
- }
- }
- }
-
- req = NewRequest(t, "GET", "/user/settings/applications")
- resp = session.MakeRequest(t, req, http.StatusOK)
- htmlDoc := NewHTMLParser(t, resp.Body)
- token = htmlDoc.doc.Find(".ui.info p").Text()
- assert.NotEmpty(t, token)
- return token
+ req := NewRequestWithURLValues(t, "POST", "/user/settings/applications", urlValues)
+ session.MakeRequest(t, req, http.StatusSeeOther)
+ flashes := session.GetCookieFlashMessage()
+ return flashes.InfoMsg
}
type RequestWrapper struct {
@@ -332,7 +310,7 @@ func NewRequestWithValues(t testing.TB, method, urlStr string, values map[string
func NewRequestWithURLValues(t testing.TB, method, urlStr string, urlValues url.Values) *RequestWrapper {
t.Helper()
- return NewRequestWithBody(t, method, urlStr, bytes.NewBufferString(urlValues.Encode())).
+ return NewRequestWithBody(t, method, urlStr, strings.NewReader(urlValues.Encode())).
SetHeader("Content-Type", "application/x-www-form-urlencoded")
}
@@ -382,7 +360,7 @@ func MakeRequestNilResponseRecorder(t testing.TB, rw *RequestWrapper, expectedSt
recorder := NewNilResponseRecorder()
testWebRoutes.ServeHTTP(recorder, req)
if expectedStatus != NoExpectedStatus {
- if !assert.EqualValues(t, expectedStatus, recorder.Code,
+ if !assert.Equal(t, expectedStatus, recorder.Code,
"Request: %s %s", req.Method, req.URL.String()) {
logUnexpectedResponse(t, &recorder.ResponseRecorder)
}
@@ -396,7 +374,7 @@ func MakeRequestNilResponseHashSumRecorder(t testing.TB, rw *RequestWrapper, exp
recorder := NewNilResponseHashSumRecorder()
testWebRoutes.ServeHTTP(recorder, req)
if expectedStatus != NoExpectedStatus {
- if !assert.EqualValues(t, expectedStatus, recorder.Code,
+ if !assert.Equal(t, expectedStatus, recorder.Code,
"Request: %s %s", req.Method, req.URL.String()) {
logUnexpectedResponse(t, &recorder.ResponseRecorder)
}
@@ -458,9 +436,9 @@ func VerifyJSONSchema(t testing.TB, resp *httptest.ResponseRecorder, schemaFile
// GetUserCSRFToken returns CSRF token for current user
func GetUserCSRFToken(t testing.TB, session *TestSession) string {
t.Helper()
- cookie := session.GetCookie("_csrf")
+ cookie := session.GetSiteCookie("_csrf")
require.NotEmpty(t, cookie)
- return cookie.Value
+ return cookie
}
// GetUserCSRFToken returns CSRF token for anonymous user (not logged in)
diff --git a/tests/integration/issue_test.go b/tests/integration/issue_test.go
index 4617c5f89a..b5dca58357 100644
--- a/tests/integration/issue_test.go
+++ b/tests/integration/issue_test.go
@@ -4,7 +4,6 @@
package integration
import (
- "context"
"fmt"
"html/template"
"net/http"
@@ -33,7 +32,7 @@ import (
func getIssuesSelection(t testing.TB, htmlDoc *HTMLDoc) *goquery.Selection {
issueList := htmlDoc.doc.Find("#issue-list")
- assert.EqualValues(t, 1, issueList.Length())
+ assert.Equal(t, 1, issueList.Length())
return issueList.Find(".flex-item").Find(".issue-title")
}
@@ -77,19 +76,16 @@ func TestViewIssuesSortByType(t *testing.T) {
htmlDoc := NewHTMLParser(t, resp.Body)
issuesSelection := getIssuesSelection(t, htmlDoc)
- expectedNumIssues := unittest.GetCount(t,
+ expectedNumIssues := min(unittest.GetCount(t,
&issues_model.Issue{RepoID: repo.ID, PosterID: user.ID},
unittest.Cond("is_closed=?", false),
unittest.Cond("is_pull=?", false),
- )
- if expectedNumIssues > setting.UI.IssuePagingNum {
- expectedNumIssues = setting.UI.IssuePagingNum
- }
- assert.EqualValues(t, expectedNumIssues, issuesSelection.Length())
+ ), setting.UI.IssuePagingNum)
+ assert.Equal(t, expectedNumIssues, issuesSelection.Length())
issuesSelection.Each(func(_ int, selection *goquery.Selection) {
issue := getIssue(t, repo.ID, selection)
- assert.EqualValues(t, user.ID, issue.PosterID)
+ assert.Equal(t, user.ID, issue.PosterID)
})
}
@@ -101,7 +97,7 @@ func TestViewIssuesKeyword(t *testing.T) {
RepoID: repo.ID,
Index: 1,
})
- issues.UpdateIssueIndexer(context.Background(), issue.ID)
+ issues.UpdateIssueIndexer(t.Context(), issue.ID)
time.Sleep(time.Second * 1)
const keyword = "first"
req := NewRequestf(t, "GET", "%s/issues?q=%s", repo.Link(), keyword)
@@ -109,7 +105,7 @@ func TestViewIssuesKeyword(t *testing.T) {
htmlDoc := NewHTMLParser(t, resp.Body)
issuesSelection := getIssuesSelection(t, htmlDoc)
- assert.EqualValues(t, 1, issuesSelection.Length())
+ assert.Equal(t, 1, issuesSelection.Length())
issuesSelection.Each(func(_ int, selection *goquery.Selection) {
issue := getIssue(t, repo.ID, selection)
assert.False(t, issue.IsClosed)
@@ -152,6 +148,22 @@ func testNewIssue(t *testing.T, session *TestSession, user, repo, title, content
return issueURL
}
+func testIssueDelete(t *testing.T, session *TestSession, issueURL string) {
+ req := NewRequestWithValues(t, "POST", path.Join(issueURL, "delete"), map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ })
+ session.MakeRequest(t, req, http.StatusSeeOther)
+}
+
+func testIssueAssign(t *testing.T, session *TestSession, repoLink string, issueID, assigneeID int64) {
+ req := NewRequestWithValues(t, "POST", fmt.Sprintf(repoLink+"/issues/assignee?issue_ids=%d", issueID), map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ "id": strconv.FormatInt(assigneeID, 10),
+ "action": "", // empty action means assign
+ })
+ session.MakeRequest(t, req, http.StatusOK)
+}
+
func testIssueAddComment(t *testing.T, session *TestSession, issueURL, content, status string) int64 {
req := NewRequest(t, "GET", issueURL)
resp := session.MakeRequest(t, req, http.StatusOK)
@@ -174,7 +186,7 @@ func testIssueAddComment(t *testing.T, session *TestSession, issueURL, content,
htmlDoc = NewHTMLParser(t, resp.Body)
- val := htmlDoc.doc.Find(".comment-list .comment .render-content p").Eq(commentCount).Text()
+ val := strings.TrimSpace(htmlDoc.doc.Find(".comment-list .comment .render-content").Eq(commentCount).Text())
assert.Equal(t, content, val)
idAttr, has := htmlDoc.doc.Find(".comment-list .comment").Eq(commentCount).Attr("id")
@@ -185,6 +197,15 @@ func testIssueAddComment(t *testing.T, session *TestSession, issueURL, content,
return int64(id)
}
+func testIssueChangeMilestone(t *testing.T, session *TestSession, repoLink string, issueID, milestoneID int64) {
+ req := NewRequestWithValues(t, "POST", fmt.Sprintf(repoLink+"/issues/milestone?issue_ids=%d", issueID), map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ "id": strconv.FormatInt(milestoneID, 10),
+ })
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ assert.Equal(t, `{"ok":true}`, strings.TrimSpace(resp.Body.String()))
+}
+
func TestNewIssue(t *testing.T) {
defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user2")
@@ -196,21 +217,21 @@ func TestEditIssue(t *testing.T) {
session := loginUser(t, "user2")
issueURL := testNewIssue(t, session, "user2", "repo1", "Title", "Description")
- req := NewRequestWithValues(t, "POST", fmt.Sprintf("%s/content", issueURL), map[string]string{
+ req := NewRequestWithValues(t, "POST", issueURL+"/content", map[string]string{
"_csrf": GetUserCSRFToken(t, session),
"content": "modified content",
"context": fmt.Sprintf("/%s/%s", "user2", "repo1"),
})
session.MakeRequest(t, req, http.StatusOK)
- req = NewRequestWithValues(t, "POST", fmt.Sprintf("%s/content", issueURL), map[string]string{
+ req = NewRequestWithValues(t, "POST", issueURL+"/content", map[string]string{
"_csrf": GetUserCSRFToken(t, session),
"content": "modified content",
"context": fmt.Sprintf("/%s/%s", "user2", "repo1"),
})
session.MakeRequest(t, req, http.StatusBadRequest)
- req = NewRequestWithValues(t, "POST", fmt.Sprintf("%s/content", issueURL), map[string]string{
+ req = NewRequestWithValues(t, "POST", issueURL+"/content", map[string]string{
"_csrf": GetUserCSRFToken(t, session),
"content": "modified content",
"content_version": "1",
@@ -474,10 +495,7 @@ func TestSearchIssues(t *testing.T) {
session := loginUser(t, "user2")
- expectedIssueCount := 20 // from the fixtures
- if expectedIssueCount > setting.UI.IssuePagingNum {
- expectedIssueCount = setting.UI.IssuePagingNum
- }
+ expectedIssueCount := min(20, setting.UI.IssuePagingNum) // 20 is from the fixtures
link, _ := url.Parse("/issues/search")
req := NewRequest(t, "GET", link.String())
@@ -511,7 +529,7 @@ func TestSearchIssues(t *testing.T) {
req = NewRequest(t, "GET", link.String())
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
- assert.EqualValues(t, "22", resp.Header().Get("X-Total-Count"))
+ assert.Equal(t, "22", resp.Header().Get("X-Total-Count"))
assert.Len(t, apiIssues, 20)
query.Add("limit", "5")
@@ -519,7 +537,7 @@ func TestSearchIssues(t *testing.T) {
req = NewRequest(t, "GET", link.String())
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
- assert.EqualValues(t, "22", resp.Header().Get("X-Total-Count"))
+ assert.Equal(t, "22", resp.Header().Get("X-Total-Count"))
assert.Len(t, apiIssues, 5)
query = url.Values{"assigned": {"true"}, "state": {"all"}}
@@ -568,10 +586,7 @@ func TestSearchIssues(t *testing.T) {
func TestSearchIssuesWithLabels(t *testing.T) {
defer tests.PrepareTestEnv(t)()
- expectedIssueCount := 20 // from the fixtures
- if expectedIssueCount > setting.UI.IssuePagingNum {
- expectedIssueCount = setting.UI.IssuePagingNum
- }
+ expectedIssueCount := min(20, setting.UI.IssuePagingNum) // 20 is from the fixtures
session := loginUser(t, "user1")
link, _ := url.Parse("/issues/search")
@@ -646,7 +661,7 @@ func TestGetIssueInfo(t *testing.T) {
}
DecodeJSON(t, resp, &respStruct)
- assert.EqualValues(t, issue.ID, respStruct.ConvertedIssue.ID)
+ assert.Equal(t, issue.ID, respStruct.ConvertedIssue.ID)
assert.Contains(t, string(respStruct.RenderedLabels), `"labels-list"`)
}
@@ -666,7 +681,7 @@ func TestUpdateIssueDeadline(t *testing.T) {
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{"deadline": "2022-04-06"})
session.MakeRequest(t, req, http.StatusOK)
issueAfter := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 10})
- assert.EqualValues(t, "2022-04-06", issueAfter.DeadlineUnix.FormatDate())
+ assert.Equal(t, "2022-04-06", issueAfter.DeadlineUnix.FormatDate())
req = NewRequestWithValues(t, "POST", urlStr, map[string]string{"deadline": ""})
session.MakeRequest(t, req, http.StatusOK)
@@ -687,8 +702,8 @@ func TestIssueReferenceURL(t *testing.T) {
// the "reference" uses relative URLs, then JS code will convert them to absolute URLs for current origin, in case users are using multiple domains
ref, _ := htmlDoc.Find(`.timeline-item.comment.first .reference-issue`).Attr("data-reference")
- assert.EqualValues(t, "/user2/repo1/issues/1#issue-1", ref)
+ assert.Equal(t, "/user2/repo1/issues/1#issue-1", ref)
ref, _ = htmlDoc.Find(`.timeline-item.comment:not(.first) .reference-issue`).Attr("data-reference")
- assert.EqualValues(t, "/user2/repo1/issues/1#issuecomment-2", ref)
+ assert.Equal(t, "/user2/repo1/issues/1#issuecomment-2", ref)
}
diff --git a/tests/integration/lfs_local_endpoint_test.go b/tests/integration/lfs_local_endpoint_test.go
index d42888bbe1..e67f0712a3 100644
--- a/tests/integration/lfs_local_endpoint_test.go
+++ b/tests/integration/lfs_local_endpoint_test.go
@@ -4,7 +4,6 @@
package integration
import (
- "fmt"
"net/url"
"os"
"path/filepath"
@@ -41,55 +40,55 @@ func TestDetermineLocalEndpoint(t *testing.T) {
{
cloneurl: root,
lfsurl: "",
- expected: str2url(fmt.Sprintf("file://%s", root)),
+ expected: str2url("file://" + root),
},
// case 1
{
cloneurl: root,
lfsurl: lfsroot,
- expected: str2url(fmt.Sprintf("file://%s", lfsroot)),
+ expected: str2url("file://" + lfsroot),
},
// case 2
{
cloneurl: "https://git.com/repo.git",
lfsurl: lfsroot,
- expected: str2url(fmt.Sprintf("file://%s", lfsroot)),
+ expected: str2url("file://" + lfsroot),
},
// case 3
{
cloneurl: rootdotgit,
lfsurl: "",
- expected: str2url(fmt.Sprintf("file://%s", filepath.Join(rootdotgit, ".git"))),
+ expected: str2url("file://" + filepath.Join(rootdotgit, ".git")),
},
// case 4
{
cloneurl: "",
lfsurl: rootdotgit,
- expected: str2url(fmt.Sprintf("file://%s", filepath.Join(rootdotgit, ".git"))),
+ expected: str2url("file://" + filepath.Join(rootdotgit, ".git")),
},
// case 5
{
cloneurl: rootdotgit,
lfsurl: rootdotgit,
- expected: str2url(fmt.Sprintf("file://%s", filepath.Join(rootdotgit, ".git"))),
+ expected: str2url("file://" + filepath.Join(rootdotgit, ".git")),
},
// case 6
{
- cloneurl: fmt.Sprintf("file://%s", root),
+ cloneurl: "file://" + root,
lfsurl: "",
- expected: str2url(fmt.Sprintf("file://%s", root)),
+ expected: str2url("file://" + root),
},
// case 7
{
- cloneurl: fmt.Sprintf("file://%s", root),
- lfsurl: fmt.Sprintf("file://%s", lfsroot),
- expected: str2url(fmt.Sprintf("file://%s", lfsroot)),
+ cloneurl: "file://" + root,
+ lfsurl: "file://" + lfsroot,
+ expected: str2url("file://" + lfsroot),
},
// case 8
{
cloneurl: root,
- lfsurl: fmt.Sprintf("file://%s", lfsroot),
- expected: str2url(fmt.Sprintf("file://%s", lfsroot)),
+ lfsurl: "file://" + lfsroot,
+ expected: str2url("file://" + lfsroot),
},
// case 9
{
diff --git a/tests/integration/lfs_view_test.go b/tests/integration/lfs_view_test.go
index a0e004ed58..c26ece22be 100644
--- a/tests/integration/lfs_view_test.go
+++ b/tests/integration/lfs_view_test.go
@@ -4,7 +4,6 @@
package integration
import (
- "context"
"fmt"
"net/http"
"strings"
@@ -39,7 +38,7 @@ func TestLFSRender(t *testing.T) {
doc := NewHTMLParser(t, resp.Body).doc
fileInfo := doc.Find("div.file-info-entry").First().Text()
- assert.Contains(t, fileInfo, "Stored with Git LFS")
+ assert.Contains(t, fileInfo, "LFS")
content := doc.Find("div.file-view").Text()
assert.Contains(t, content, "Testing documents in LFS")
@@ -55,7 +54,7 @@ func TestLFSRender(t *testing.T) {
doc := NewHTMLParser(t, resp.Body).doc
fileInfo := doc.Find("div.file-info-entry").First().Text()
- assert.Contains(t, fileInfo, "Stored with Git LFS")
+ assert.Contains(t, fileInfo, "LFS")
src, exists := doc.Find(".file-view img").Attr("src")
assert.True(t, exists, "The image should be in an <img> tag")
@@ -69,14 +68,15 @@ func TestLFSRender(t *testing.T) {
req := NewRequest(t, "GET", "/user2/lfs/src/branch/master/crypt.bin")
resp := session.MakeRequest(t, req, http.StatusOK)
- doc := NewHTMLParser(t, resp.Body).doc
+ doc := NewHTMLParser(t, resp.Body)
fileInfo := doc.Find("div.file-info-entry").First().Text()
- assert.Contains(t, fileInfo, "Stored with Git LFS")
+ assert.Contains(t, fileInfo, "LFS")
- rawLink, exists := doc.Find("div.file-view > div.view-raw > a").Attr("href")
- assert.True(t, exists, "Download link should render instead of content because this is a binary file")
- assert.Equal(t, "/user2/lfs/media/branch/master/crypt.bin", rawLink, "The download link should use the proper /media link because it's in LFS")
+ // find new file view container
+ fileViewContainer := doc.Find("[data-global-init=initRepoFileView]")
+ assert.Equal(t, "/user2/lfs/media/branch/master/crypt.bin", fileViewContainer.AttrOr("data-raw-file-link", ""))
+ AssertHTMLElement(t, doc, ".view-raw > .file-view-render-container > .file-view-raw-prompt", 1)
})
// check that a directory with a README file shows its text
@@ -143,7 +143,7 @@ func TestLFSLockView(t *testing.T) {
defer tests.PrintCurrentTest(t)()
// make sure the display names are different, or the test is meaningless
- require.NoError(t, repo3.LoadOwner(context.Background()))
+ require.NoError(t, repo3.LoadOwner(t.Context()))
require.NotEqual(t, user2.DisplayName(), repo3.Owner.DisplayName())
req := NewRequest(t, "GET", fmt.Sprintf("/%s/settings/lfs/locks", repo3.FullName()))
diff --git a/tests/integration/linguist_test.go b/tests/integration/linguist_test.go
index 2d50dc599a..d156dd6f3d 100644
--- a/tests/integration/linguist_test.go
+++ b/tests/integration/linguist_test.go
@@ -4,7 +4,6 @@
package integration
import (
- "context"
"net/url"
"strconv"
"strings"
@@ -246,7 +245,7 @@ func TestLinguist(t *testing.T) {
assert.NoError(t, err)
assert.NoError(t, stats.UpdateRepoIndexer(repo))
- assert.NoError(t, queue.GetManager().FlushAll(context.Background(), 10*time.Second))
+ assert.NoError(t, queue.GetManager().FlushAll(t.Context(), 10*time.Second))
stats, err := repo_model.GetTopLanguageStats(db.DefaultContext, repo, len(c.FilesToAdd))
assert.NoError(t, err)
diff --git a/tests/integration/links_test.go b/tests/integration/links_test.go
index b54f670c23..ec59e147d2 100644
--- a/tests/integration/links_test.go
+++ b/tests/integration/links_test.go
@@ -52,15 +52,19 @@ func TestRedirectsNoLogin(t *testing.T) {
redirects := []struct{ from, to string }{
{"/user2/repo1/commits/master", "/user2/repo1/commits/branch/master"},
{"/user2/repo1/src/master", "/user2/repo1/src/branch/master"},
- {"/user2/repo1/src/master/file.txt", "/user2/repo1/src/branch/master/file.txt"},
- {"/user2/repo1/src/master/directory/file.txt", "/user2/repo1/src/branch/master/directory/file.txt"},
- {"/user/avatar/Ghost/-1", "/assets/img/avatar_default.png"},
+ {"/user2/repo1/src/master/a%2fb.txt", "/user2/repo1/src/branch/master/a%2fb.txt"},
+ {"/user2/repo1/src/master/directory/file.txt?a=1", "/user2/repo1/src/branch/master/directory/file.txt?a=1"},
+ {"/user2/repo1/src/branch/master/directory/file.txt?raw=1&other=2", "/user2/repo1/raw/branch/master/directory/file.txt"},
+ {"/user2/repo1/tree/a%2fb?a=1", "/user2/repo1/src/a%2fb?a=1"},
+ {"/user2/repo1/blob/123456/%20?a=1", "/user2/repo1/src/commit/123456/%20?a=1"},
+ {"/user/avatar/GhosT/-1", "/assets/img/avatar_default.png"},
+ {"/user/avatar/Gitea-ActionS/0", "/assets/img/avatar_default.png"},
{"/api/v1/swagger", "/api/swagger"},
}
for _, c := range redirects {
req := NewRequest(t, "GET", c.from)
resp := MakeRequest(t, req, http.StatusSeeOther)
- assert.EqualValues(t, path.Join(setting.AppSubURL, c.to), test.RedirectURL(resp))
+ assert.Equal(t, path.Join(setting.AppSubURL, c.to), test.RedirectURL(resp))
}
}
diff --git a/tests/integration/markup_external_test.go b/tests/integration/markup_external_test.go
index 2d713b0eb9..47d143a29e 100644
--- a/tests/integration/markup_external_test.go
+++ b/tests/integration/markup_external_test.go
@@ -27,7 +27,7 @@ func TestExternalMarkupRenderer(t *testing.T) {
req := NewRequest(t, "GET", "/user30/renderer/src/branch/master/README.html")
resp := MakeRequest(t, req, http.StatusOK)
- assert.EqualValues(t, "text/html; charset=utf-8", resp.Header().Get("Content-Type"))
+ assert.Equal(t, "text/html; charset=utf-8", resp.Header().Get("Content-Type"))
bs, err := io.ReadAll(resp.Body)
assert.NoError(t, err)
@@ -36,25 +36,25 @@ func TestExternalMarkupRenderer(t *testing.T) {
div := doc.Find("div.file-view")
data, err := div.Html()
assert.NoError(t, err)
- assert.EqualValues(t, "<div>\n\ttest external renderer\n</div>", strings.TrimSpace(data))
+ assert.Equal(t, "<div>\n\ttest external renderer\n</div>", strings.TrimSpace(data))
r := markup.GetRendererByFileName("a.html").(*external.Renderer)
r.RenderContentMode = setting.RenderContentModeIframe
req = NewRequest(t, "GET", "/user30/renderer/src/branch/master/README.html")
resp = MakeRequest(t, req, http.StatusOK)
- assert.EqualValues(t, "text/html; charset=utf-8", resp.Header().Get("Content-Type"))
+ assert.Equal(t, "text/html; charset=utf-8", resp.Header().Get("Content-Type"))
bs, err = io.ReadAll(resp.Body)
assert.NoError(t, err)
doc = NewHTMLParser(t, bytes.NewBuffer(bs))
iframe := doc.Find("iframe")
- assert.EqualValues(t, "/user30/renderer/render/branch/master/README.html", iframe.AttrOr("src", ""))
+ assert.Equal(t, "/user30/renderer/render/branch/master/README.html", iframe.AttrOr("src", ""))
req = NewRequest(t, "GET", "/user30/renderer/render/branch/master/README.html")
resp = MakeRequest(t, req, http.StatusOK)
- assert.EqualValues(t, "text/html; charset=utf-8", resp.Header().Get("Content-Type"))
+ assert.Equal(t, "text/html; charset=utf-8", resp.Header().Get("Content-Type"))
bs, err = io.ReadAll(resp.Body)
assert.NoError(t, err)
- assert.EqualValues(t, "frame-src 'self'; sandbox allow-scripts", resp.Header().Get("Content-Security-Policy"))
- assert.EqualValues(t, "<div>\n\ttest external renderer\n</div>\n", string(bs))
+ assert.Equal(t, "frame-src 'self'; sandbox allow-scripts", resp.Header().Get("Content-Security-Policy"))
+ assert.Equal(t, "<div>\n\ttest external renderer\n</div>\n", string(bs))
}
diff --git a/tests/integration/migrate_test.go b/tests/integration/migrate_test.go
index 59dd6907db..a89dc8b85c 100644
--- a/tests/integration/migrate_test.go
+++ b/tests/integration/migrate_test.go
@@ -9,6 +9,7 @@ import (
"net/url"
"os"
"path/filepath"
+ "strconv"
"testing"
auth_model "code.gitea.io/gitea/models/auth"
@@ -84,7 +85,7 @@ func TestMigrateGiteaForm(t *testing.T) {
assert.True(t, exists, "The template has changed")
serviceInput, exists := form.Find(`input[name="service"]`).Attr("value")
assert.True(t, exists)
- assert.EqualValues(t, fmt.Sprintf("%d", structs.GiteaService), serviceInput)
+ assert.Equal(t, fmt.Sprintf("%d", structs.GiteaService), serviceInput)
// Step 4: submit the migration to only migrate issues
migratedRepoName := "otherrepo"
req = NewRequestWithValues(t, "POST", link, map[string]string{
@@ -95,12 +96,12 @@ func TestMigrateGiteaForm(t *testing.T) {
"issues": "on",
"repo_name": migratedRepoName,
"description": "",
- "uid": fmt.Sprintf("%d", repoOwner.ID),
+ "uid": strconv.FormatInt(repoOwner.ID, 10),
})
resp = session.MakeRequest(t, req, http.StatusSeeOther)
// Step 5: a redirection displays the migrated repository
loc := resp.Header().Get("Location")
- assert.EqualValues(t, fmt.Sprintf("/%s/%s", ownerName, migratedRepoName), loc)
+ assert.Equal(t, fmt.Sprintf("/%s/%s", ownerName, migratedRepoName), loc)
// Step 6: check the repo was created
unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: migratedRepoName})
})
diff --git a/tests/integration/migration-test/migration_test.go b/tests/integration/migration-test/migration_test.go
index 616ccf291a..0fc8a6e24d 100644
--- a/tests/integration/migration-test/migration_test.go
+++ b/tests/integration/migration-test/migration_test.go
@@ -38,7 +38,7 @@ var currentEngine *xorm.Engine
func initMigrationTest(t *testing.T) func() {
testlogger.Init()
giteaRoot := test.SetupGiteaRoot()
- setting.AppPath = path.Join(giteaRoot, "gitea")
+ setting.AppPath = filepath.Join(giteaRoot, "gitea")
if _, err := os.Stat(setting.AppPath); err != nil {
testlogger.Fatalf(fmt.Sprintf("Could not find gitea binary at %s\n", setting.AppPath))
}
@@ -47,16 +47,16 @@ func initMigrationTest(t *testing.T) func() {
if giteaConf == "" {
testlogger.Fatalf("Environment variable $GITEA_CONF not set\n")
} else if !path.IsAbs(giteaConf) {
- setting.CustomConf = path.Join(giteaRoot, giteaConf)
+ setting.CustomConf = filepath.Join(giteaRoot, giteaConf)
} else {
setting.CustomConf = giteaConf
}
- unittest.InitSettings()
+ unittest.InitSettingsForTesting()
assert.NotEmpty(t, setting.RepoRootPath)
- assert.NoError(t, unittest.SyncDirs(path.Join(filepath.Dir(setting.AppPath), "tests/gitea-repositories-meta"), setting.RepoRootPath))
- assert.NoError(t, git.InitFull(context.Background()))
+ assert.NoError(t, unittest.SyncDirs(filepath.Join(filepath.Dir(setting.AppPath), "tests/gitea-repositories-meta"), setting.RepoRootPath))
+ assert.NoError(t, git.InitFull(t.Context()))
setting.LoadDBSetting()
setting.InitLoggersForTest()
@@ -140,10 +140,10 @@ func restoreOldDB(t *testing.T, version string) {
assert.NoError(t, err)
defer db.Close()
- _, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", setting.Database.Name))
+ _, err = db.Exec("DROP DATABASE IF EXISTS " + setting.Database.Name)
assert.NoError(t, err)
- _, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", setting.Database.Name))
+ _, err = db.Exec("CREATE DATABASE IF NOT EXISTS " + setting.Database.Name)
assert.NoError(t, err)
db.Close()
@@ -170,10 +170,10 @@ func restoreOldDB(t *testing.T, version string) {
}
defer db.Close()
- _, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", setting.Database.Name))
+ _, err = db.Exec("DROP DATABASE IF EXISTS " + setting.Database.Name)
assert.NoError(t, err)
- _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", setting.Database.Name))
+ _, err = db.Exec("CREATE DATABASE " + setting.Database.Name)
assert.NoError(t, err)
db.Close()
@@ -195,7 +195,7 @@ func restoreOldDB(t *testing.T, version string) {
if !schrows.Next() {
// Create and setup a DB schema
- _, err = db.Exec(fmt.Sprintf("CREATE SCHEMA %s", setting.Database.Schema))
+ _, err = db.Exec("CREATE SCHEMA " + setting.Database.Schema)
assert.NoError(t, err)
}
schrows.Close()
@@ -248,7 +248,7 @@ func restoreOldDB(t *testing.T, version string) {
}
}
-func wrappedMigrate(x *xorm.Engine) error {
+func wrappedMigrate(ctx context.Context, x *xorm.Engine) error {
currentEngine = x
return migrations.Migrate(x)
}
@@ -259,13 +259,13 @@ func doMigrationTest(t *testing.T, version string) {
setting.InitSQLLoggersForCli(log.INFO)
- err := db.InitEngineWithMigration(context.Background(), wrappedMigrate)
+ err := db.InitEngineWithMigration(t.Context(), wrappedMigrate)
assert.NoError(t, err)
currentEngine.Close()
beans, _ := db.NamesToBean()
- err = db.InitEngineWithMigration(context.Background(), func(x *xorm.Engine) error {
+ err = db.InitEngineWithMigration(t.Context(), func(ctx context.Context, x *xorm.Engine) error {
currentEngine = x
return migrate_base.RecreateTables(beans...)(x)
})
@@ -273,7 +273,7 @@ func doMigrationTest(t *testing.T, version string) {
currentEngine.Close()
// We do this a second time to ensure that there is not a problem with retained indices
- err = db.InitEngineWithMigration(context.Background(), func(x *xorm.Engine) error {
+ err = db.InitEngineWithMigration(t.Context(), func(ctx context.Context, x *xorm.Engine) error {
currentEngine = x
return migrate_base.RecreateTables(beans...)(x)
})
diff --git a/tests/integration/mirror_pull_test.go b/tests/integration/mirror_pull_test.go
index 77050c4bbc..c33b2eb04d 100644
--- a/tests/integration/mirror_pull_test.go
+++ b/tests/integration/mirror_pull_test.go
@@ -4,11 +4,12 @@
package integration
import (
- "context"
+ "slices"
"testing"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
@@ -20,11 +21,13 @@ import (
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
func TestMirrorPull(t *testing.T) {
defer tests.PrepareTestEnv(t)()
+ ctx := t.Context()
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
repoPath := repo_model.RepoPath(user.Name, repo.Name)
@@ -36,24 +39,28 @@ func TestMirrorPull(t *testing.T) {
Mirror: true,
CloneAddr: repoPath,
Wiki: true,
- Releases: false,
+ Releases: true,
}
- mirrorRepo, err := repo_service.CreateRepositoryDirectly(db.DefaultContext, user, user, repo_service.CreateRepoOptions{
+ mirrorRepo, err := repo_service.CreateRepositoryDirectly(ctx, user, user, repo_service.CreateRepoOptions{
Name: opts.RepoName,
Description: opts.Description,
IsPrivate: opts.Private,
IsMirror: opts.Mirror,
Status: repo_model.RepositoryBeingMigrated,
- })
+ }, false)
assert.NoError(t, err)
assert.True(t, mirrorRepo.IsMirror, "expected pull-mirror repo to be marked as a mirror immediately after its creation")
- ctx := context.Background()
-
- mirror, err := repo_service.MigrateRepositoryGitData(ctx, user, mirrorRepo, opts, nil)
+ mirrorRepo, err = repo_service.MigrateRepositoryGitData(ctx, user, mirrorRepo, opts, nil)
assert.NoError(t, err)
+ // these units should have been enabled
+ mirrorRepo.Units = nil
+ require.NoError(t, mirrorRepo.LoadUnits(ctx))
+ assert.True(t, slices.ContainsFunc(mirrorRepo.Units, func(u *repo_model.RepoUnit) bool { return u.Type == unit.TypeReleases }))
+ assert.True(t, slices.ContainsFunc(mirrorRepo.Units, func(u *repo_model.RepoUnit) bool { return u.Type == unit.TypeWiki }))
+
gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo)
assert.NoError(t, err)
defer gitRepo.Close()
@@ -61,10 +68,11 @@ func TestMirrorPull(t *testing.T) {
findOptions := repo_model.FindReleasesOptions{
IncludeDrafts: true,
IncludeTags: true,
- RepoID: mirror.ID,
+ RepoID: mirrorRepo.ID,
}
initCount, err := db.Count[repo_model.Release](db.DefaultContext, findOptions)
assert.NoError(t, err)
+ assert.Zero(t, initCount) // no sync yet, so even though there is a tag in source repo, the mirror's release table is still empty
assert.NoError(t, release_service.CreateRelease(gitRepo, &repo_model.Release{
RepoID: repo.ID,
@@ -80,24 +88,27 @@ func TestMirrorPull(t *testing.T) {
IsTag: true,
}, nil, ""))
- _, err = repo_model.GetMirrorByRepoID(ctx, mirror.ID)
+ _, err = repo_model.GetMirrorByRepoID(ctx, mirrorRepo.ID)
assert.NoError(t, err)
- ok := mirror_service.SyncPullMirror(ctx, mirror.ID)
+ ok := mirror_service.SyncPullMirror(ctx, mirrorRepo.ID)
assert.True(t, ok)
+ // actually there is a tag in the source repo, so after "sync", that tag will also come into the mirror
+ initCount++
+
count, err := db.Count[repo_model.Release](db.DefaultContext, findOptions)
assert.NoError(t, err)
- assert.EqualValues(t, initCount+1, count)
+ assert.Equal(t, initCount+1, count)
release, err := repo_model.GetRelease(db.DefaultContext, repo.ID, "v0.2")
assert.NoError(t, err)
assert.NoError(t, release_service.DeleteReleaseByID(ctx, repo, release, user, true))
- ok = mirror_service.SyncPullMirror(ctx, mirror.ID)
+ ok = mirror_service.SyncPullMirror(ctx, mirrorRepo.ID)
assert.True(t, ok)
count, err = db.Count[repo_model.Release](db.DefaultContext, findOptions)
assert.NoError(t, err)
- assert.EqualValues(t, initCount, count)
+ assert.Equal(t, initCount, count)
}
diff --git a/tests/integration/mirror_push_test.go b/tests/integration/mirror_push_test.go
index 0dd8919bff..9b6d4c4017 100644
--- a/tests/integration/mirror_push_test.go
+++ b/tests/integration/mirror_push_test.go
@@ -4,12 +4,10 @@
package integration
import (
- "context"
"fmt"
"net/http"
"net/url"
"strconv"
- "strings"
"testing"
"time"
@@ -20,7 +18,6 @@ import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/setting"
- gitea_context "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/migrations"
mirror_service "code.gitea.io/gitea/services/mirror"
repo_service "code.gitea.io/gitea/services/repository"
@@ -43,7 +40,7 @@ func testMirrorPush(t *testing.T, u *url.URL) {
mirrorRepo, err := repo_service.CreateRepositoryDirectly(db.DefaultContext, user, user, repo_service.CreateRepoOptions{
Name: "test-push-mirror",
- })
+ }, true)
assert.NoError(t, err)
session := loginUser(t, user.Name)
@@ -55,7 +52,7 @@ func testMirrorPush(t *testing.T, u *url.URL) {
assert.NoError(t, err)
assert.Len(t, mirrors, 1)
- ok := mirror_service.SyncPushMirror(context.Background(), mirrors[0].ID)
+ ok := mirror_service.SyncPushMirror(t.Context(), mirrors[0].ID)
assert.True(t, ok)
srcGitRepo, err := gitrepo.OpenRepository(git.DefaultContext, srcRepo)
@@ -92,9 +89,8 @@ func testCreatePushMirror(t *testing.T, session *TestSession, owner, repo, addre
})
session.MakeRequest(t, req, http.StatusSeeOther)
- flashCookie := session.GetCookie(gitea_context.CookieNameFlash)
- assert.NotNil(t, flashCookie)
- assert.Contains(t, flashCookie.Value, "success")
+ flashMsg := session.GetCookieFlashMessage()
+ assert.NotEmpty(t, flashMsg.SuccessMsg)
}
func doRemovePushMirror(t *testing.T, session *TestSession, owner, repo string, pushMirrorID int64) bool {
@@ -104,8 +100,8 @@ func doRemovePushMirror(t *testing.T, session *TestSession, owner, repo string,
"push_mirror_id": strconv.FormatInt(pushMirrorID, 10),
})
resp := session.MakeRequest(t, req, NoExpectedStatus)
- flashCookie := session.GetCookie(gitea_context.CookieNameFlash)
- return resp.Code == http.StatusSeeOther && flashCookie != nil && strings.Contains(flashCookie.Value, "success")
+ flashMsg := session.GetCookieFlashMessage()
+ return resp.Code == http.StatusSeeOther && assert.NotEmpty(t, flashMsg.SuccessMsg)
}
func doUpdatePushMirror(t *testing.T, session *TestSession, owner, repo string, pushMirrorID int64, interval string) bool {
@@ -132,18 +128,18 @@ func TestRepoSettingPushMirrorUpdate(t *testing.T) {
pushMirrors, cnt, err := repo_model.GetPushMirrorsByRepoID(db.DefaultContext, repo2.ID, db.ListOptions{})
assert.NoError(t, err)
assert.EqualValues(t, 1, cnt)
- assert.EqualValues(t, 24*time.Hour, pushMirrors[0].Interval)
+ assert.Equal(t, 24*time.Hour, pushMirrors[0].Interval)
repo2PushMirrorID := pushMirrors[0].ID
// update repo2 push mirror
assert.True(t, doUpdatePushMirror(t, session, "user2", "repo2", repo2PushMirrorID, "10m0s"))
pushMirror := unittest.AssertExistsAndLoadBean(t, &repo_model.PushMirror{ID: repo2PushMirrorID})
- assert.EqualValues(t, 10*time.Minute, pushMirror.Interval)
+ assert.Equal(t, 10*time.Minute, pushMirror.Interval)
// avoid updating repo2 push mirror from repo1
assert.False(t, doUpdatePushMirror(t, session, "user2", "repo1", repo2PushMirrorID, "20m0s"))
pushMirror = unittest.AssertExistsAndLoadBean(t, &repo_model.PushMirror{ID: repo2PushMirrorID})
- assert.EqualValues(t, 10*time.Minute, pushMirror.Interval) // not changed
+ assert.Equal(t, 10*time.Minute, pushMirror.Interval) // not changed
// avoid deleting repo2 push mirror from repo1
assert.False(t, doRemovePushMirror(t, session, "user2", "repo1", repo2PushMirrorID))
diff --git a/tests/integration/nonascii_branches_test.go b/tests/integration/nonascii_branches_test.go
index ae348d8173..cc71acf002 100644
--- a/tests/integration/nonascii_branches_test.go
+++ b/tests/integration/nonascii_branches_test.go
@@ -46,21 +46,21 @@ func TestNonAsciiBranches(t *testing.T) {
{
from: "master/badfile",
to: "branch/master/badfile",
- status: http.StatusNotFound, // it does not exists
+ status: http.StatusNotFound, // it does not exist
},
{
from: "ГлавнаяВетка",
- to: "branch/%D0%93%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F%D0%92%D0%B5%D1%82%D0%BA%D0%B0",
+ to: "branch/%d0%93%d0%bb%d0%b0%d0%b2%d0%bd%d0%b0%d1%8f%d0%92%d0%b5%d1%82%d0%ba%d0%b0",
status: http.StatusOK,
},
{
from: "а/б/в",
- to: "branch/%D0%B0/%D0%B1/%D0%B2",
+ to: "branch/%d0%b0/%d0%b1/%d0%b2",
status: http.StatusOK,
},
{
from: "Grüßen/README.md",
- to: "branch/Gr%C3%BC%C3%9Fen/README.md",
+ to: "branch/Gr%c3%bc%c3%9fen/README.md",
status: http.StatusOK,
},
{
@@ -70,7 +70,7 @@ func TestNonAsciiBranches(t *testing.T) {
},
{
from: "Plus+Is+Not+Space/Файл.md",
- to: "branch/Plus+Is+Not+Space/%D0%A4%D0%B0%D0%B9%D0%BB.md",
+ to: "branch/Plus+Is+Not+Space/%d0%a4%d0%b0%d0%b9%d0%bb.md",
status: http.StatusOK,
},
{
@@ -80,29 +80,29 @@ func TestNonAsciiBranches(t *testing.T) {
},
{
from: "ブランチ",
- to: "branch/%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81",
+ to: "branch/%e3%83%96%e3%83%a9%e3%83%b3%e3%83%81",
status: http.StatusOK,
},
// Tags
{
from: "Тэг",
- to: "tag/%D0%A2%D1%8D%D0%B3",
+ to: "tag/%d0%a2%d1%8d%d0%b3",
status: http.StatusOK,
},
{
from: "Ё/人",
- to: "tag/%D0%81/%E4%BA%BA",
+ to: "tag/%d0%81/%e4%ba%ba",
status: http.StatusOK,
},
{
from: "タグ",
- to: "tag/%E3%82%BF%E3%82%B0",
+ to: "tag/%e3%82%bf%e3%82%b0",
status: http.StatusOK,
},
{
from: "タグ/ファイル.md",
- to: "tag/%E3%82%BF%E3%82%B0/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB.md",
+ to: "tag/%e3%82%bf%e3%82%b0/%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab.md",
status: http.StatusOK,
},
@@ -114,12 +114,12 @@ func TestNonAsciiBranches(t *testing.T) {
},
{
from: "Файл.md",
- to: "branch/Plus+Is+Not+Space/%D0%A4%D0%B0%D0%B9%D0%BB.md",
+ to: "branch/Plus+Is+Not+Space/%d0%a4%d0%b0%d0%b9%d0%bb.md",
status: http.StatusOK,
},
{
from: "ファイル.md",
- to: "branch/Plus+Is+Not+Space/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB.md",
+ to: "branch/Plus+Is+Not+Space/%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab.md",
status: http.StatusNotFound, // it's not on default branch
},
@@ -131,7 +131,7 @@ func TestNonAsciiBranches(t *testing.T) {
},
{
from: "%E3%82%BF%E3%82%b0",
- to: "tag/%E3%82%BF%E3%82%B0",
+ to: "tag/%E3%82%BF%E3%82%b0",
status: http.StatusOK,
},
{
@@ -141,12 +141,12 @@ func TestNonAsciiBranches(t *testing.T) {
},
{
from: "%D0%81%2F%E4%BA%BA",
- to: "tag/%D0%81/%E4%BA%BA",
+ to: "tag/%D0%81%2F%E4%BA%BA",
status: http.StatusOK,
},
{
from: "Ё%2F%E4%BA%BA",
- to: "tag/%D0%81/%E4%BA%BA",
+ to: "tag/%d0%81%2F%E4%BA%BA",
status: http.StatusOK,
},
{
diff --git a/tests/integration/oauth_test.go b/tests/integration/oauth_test.go
index d6f1ba33ec..d2228bae79 100644
--- a/tests/integration/oauth_test.go
+++ b/tests/integration/oauth_test.go
@@ -19,7 +19,7 @@ import (
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
- oauth2_provider "code.gitea.io/gitea/services/oauth2_provider"
+ "code.gitea.io/gitea/services/oauth2_provider"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
@@ -77,7 +77,7 @@ func TestAuthorizeShow(t *testing.T) {
resp := ctx.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
- htmlDoc.AssertElement(t, "#authorize-app", true)
+ AssertHTMLElement(t, htmlDoc, "#authorize-app", true)
htmlDoc.GetCSRF()
}
@@ -691,10 +691,6 @@ func TestOAuth_GrantScopesReadRepositoryFailOrganization(t *testing.T) {
FullRepoName: "user2/commitsonpr",
Private: false,
},
- {
- FullRepoName: "user2/test_commit_revert",
- Private: true,
- },
}
assert.Equal(t, reposExpected, reposCaptured)
diff --git a/tests/integration/org_count_test.go b/tests/integration/org_count_test.go
index 8a33c218be..c48008e627 100644
--- a/tests/integration/org_count_test.go
+++ b/tests/integration/org_count_test.go
@@ -4,7 +4,6 @@
package integration
import (
- "net/url"
"strings"
"testing"
@@ -14,15 +13,17 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
)
func TestOrgCounts(t *testing.T) {
- onGiteaRun(t, testOrgCounts)
+ defer tests.PrepareTestEnv(t)()
+ testOrgCounts(t)
}
-func testOrgCounts(t *testing.T, u *url.URL) {
+func testOrgCounts(t *testing.T) {
orgOwner := "user2"
orgName := "testOrg"
orgCollaborator := "user4"
@@ -119,8 +120,8 @@ func doCheckOrgCounts(username string, orgCounts map[string]int, strict bool, ca
})
orgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
- UserID: user.ID,
- IncludePrivate: true,
+ UserID: user.ID,
+ IncludeVisibility: api.VisibleTypePrivate,
})
assert.NoError(t, err)
diff --git a/tests/integration/org_team_invite_test.go b/tests/integration/org_team_invite_test.go
index 4c1053702e..7444980ea8 100644
--- a/tests/integration/org_team_invite_test.go
+++ b/tests/integration/org_team_invite_test.go
@@ -58,7 +58,7 @@ func TestOrgTeamEmailInvite(t *testing.T) {
session = loginUser(t, user.Name)
// join the team
- inviteURL := fmt.Sprintf("/org/invite/%s", invites[0].Token)
+ inviteURL := "/org/invite/" + invites[0].Token
csrf = GetUserCSRFToken(t, session)
req = NewRequestWithValues(t, "POST", inviteURL, map[string]string{
"_csrf": csrf,
@@ -108,8 +108,8 @@ func TestOrgTeamEmailInviteRedirectsExistingUser(t *testing.T) {
assert.Len(t, invites, 1)
// accept the invite
- inviteURL := fmt.Sprintf("/org/invite/%s", invites[0].Token)
- req = NewRequest(t, "GET", fmt.Sprintf("/user/login?redirect_to=%s", url.QueryEscape(inviteURL)))
+ inviteURL := "/org/invite/" + invites[0].Token
+ req = NewRequest(t, "GET", "/user/login?redirect_to="+url.QueryEscape(inviteURL))
resp = MakeRequest(t, req, http.StatusOK)
doc := NewHTMLParser(t, resp.Body)
@@ -179,8 +179,8 @@ func TestOrgTeamEmailInviteRedirectsNewUser(t *testing.T) {
assert.Len(t, invites, 1)
// accept the invite
- inviteURL := fmt.Sprintf("/org/invite/%s", invites[0].Token)
- req = NewRequest(t, "GET", fmt.Sprintf("/user/sign_up?redirect_to=%s", url.QueryEscape(inviteURL)))
+ inviteURL := "/org/invite/" + invites[0].Token
+ req = NewRequest(t, "GET", "/user/sign_up?redirect_to="+url.QueryEscape(inviteURL))
resp = MakeRequest(t, req, http.StatusOK)
doc := NewHTMLParser(t, resp.Body)
@@ -260,8 +260,8 @@ func TestOrgTeamEmailInviteRedirectsNewUserWithActivation(t *testing.T) {
// new user: accept the invite
session = emptyTestSession(t)
- inviteURL := fmt.Sprintf("/org/invite/%s", invites[0].Token)
- req = NewRequest(t, "GET", fmt.Sprintf("/user/sign_up?redirect_to=%s", url.QueryEscape(inviteURL)))
+ inviteURL := "/org/invite/" + invites[0].Token
+ req = NewRequest(t, "GET", "/user/sign_up?redirect_to="+url.QueryEscape(inviteURL))
session.MakeRequest(t, req, http.StatusOK)
req = NewRequestWithValues(t, "POST", "/user/sign_up", map[string]string{
"user_name": "doesnotexist",
@@ -275,7 +275,7 @@ func TestOrgTeamEmailInviteRedirectsNewUserWithActivation(t *testing.T) {
assert.NoError(t, err)
activationCode := user_model.GenerateUserTimeLimitCode(&user_model.TimeLimitCodeOptions{Purpose: user_model.TimeLimitCodeActivateAccount}, user)
- activateURL := fmt.Sprintf("/user/activate?code=%s", activationCode)
+ activateURL := "/user/activate?code=" + activationCode
req = NewRequestWithValues(t, "POST", activateURL, map[string]string{
"password": "examplePassword!1",
})
@@ -337,8 +337,8 @@ func TestOrgTeamEmailInviteRedirectsExistingUserWithLogin(t *testing.T) {
session = loginUser(t, "user5")
// accept the invite (note: this uses the sign_up url)
- inviteURL := fmt.Sprintf("/org/invite/%s", invites[0].Token)
- req = NewRequest(t, "GET", fmt.Sprintf("/user/sign_up?redirect_to=%s", url.QueryEscape(inviteURL)))
+ inviteURL := "/org/invite/" + invites[0].Token
+ req = NewRequest(t, "GET", "/user/sign_up?redirect_to="+url.QueryEscape(inviteURL))
resp = session.MakeRequest(t, req, http.StatusSeeOther)
assert.Equal(t, inviteURL, test.RedirectURL(resp))
diff --git a/tests/integration/org_test.go b/tests/integration/org_test.go
index ef4ef2bb9b..3ed7baa5ba 100644
--- a/tests/integration/org_test.go
+++ b/tests/integration/org_test.go
@@ -10,12 +10,17 @@ import (
"testing"
auth_model "code.gitea.io/gitea/models/auth"
+ "code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/models/organization"
+ "code.gitea.io/gitea/models/perm"
+ "code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
func TestOrgRepos(t *testing.T) {
@@ -40,8 +45,8 @@ func TestOrgRepos(t *testing.T) {
sel := htmlDoc.doc.Find("a.name")
assert.Len(t, repos, len(sel.Nodes))
- for i := 0; i < len(repos); i++ {
- assert.EqualValues(t, repos[i], strings.TrimSpace(sel.Eq(i).Text()))
+ for i := range repos {
+ assert.Equal(t, repos[i], strings.TrimSpace(sel.Eq(i).Text()))
}
}
})
@@ -151,7 +156,7 @@ func TestOrgRestrictedUser(t *testing.T) {
// assert restrictedUser cannot see the org or the public repo
restrictedSession := loginUser(t, restrictedUser)
- req := NewRequest(t, "GET", fmt.Sprintf("/%s", orgName))
+ req := NewRequest(t, "GET", "/"+orgName)
restrictedSession.MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "GET", fmt.Sprintf("/%s/%s", orgName, repoName))
@@ -177,9 +182,9 @@ func TestOrgRestrictedUser(t *testing.T) {
resp := adminSession.MakeRequest(t, req, http.StatusCreated)
DecodeJSON(t, resp, &apiTeam)
checkTeamResponse(t, "CreateTeam_codereader", &apiTeam, teamToCreate.Name, teamToCreate.Description, teamToCreate.IncludesAllRepositories,
- teamToCreate.Permission, teamToCreate.Units, nil)
+ "none", teamToCreate.Units, nil)
checkTeamBean(t, apiTeam.ID, teamToCreate.Name, teamToCreate.Description, teamToCreate.IncludesAllRepositories,
- teamToCreate.Permission, teamToCreate.Units, nil)
+ "none", teamToCreate.Units, nil)
// teamID := apiTeam.ID
// Now we need to add the restricted user to the team
@@ -188,7 +193,7 @@ func TestOrgRestrictedUser(t *testing.T) {
_ = adminSession.MakeRequest(t, req, http.StatusNoContent)
// Now we need to check if the restrictedUser can access the repo
- req = NewRequest(t, "GET", fmt.Sprintf("/%s", orgName))
+ req = NewRequest(t, "GET", "/"+orgName)
restrictedSession.MakeRequest(t, req, http.StatusOK)
req = NewRequest(t, "GET", fmt.Sprintf("/%s/%s", orgName, repoName))
@@ -217,4 +222,32 @@ func TestTeamSearch(t *testing.T) {
session = loginUser(t, user5.Name)
req = NewRequestf(t, "GET", "/org/%s/teams/-/search?q=%s", org.Name, "team")
session.MakeRequest(t, req, http.StatusNotFound)
+
+ t.Run("SearchWithPermission", func(t *testing.T) {
+ ctx := t.Context()
+ const testOrgID int64 = 500
+ const testRepoID int64 = 2000
+ testTeam := &organization.Team{OrgID: testOrgID, LowerName: "test_team", AccessMode: perm.AccessModeNone}
+ require.NoError(t, db.Insert(ctx, testTeam))
+ require.NoError(t, db.Insert(ctx, &organization.TeamRepo{OrgID: testOrgID, TeamID: testTeam.ID, RepoID: testRepoID}))
+ require.NoError(t, db.Insert(ctx, &organization.TeamUnit{OrgID: testOrgID, TeamID: testTeam.ID, Type: unit.TypeCode, AccessMode: perm.AccessModeRead}))
+ require.NoError(t, db.Insert(ctx, &organization.TeamUnit{OrgID: testOrgID, TeamID: testTeam.ID, Type: unit.TypeIssues, AccessMode: perm.AccessModeWrite}))
+
+ teams, err := organization.GetTeamsWithAccessToAnyRepoUnit(ctx, testOrgID, testRepoID, perm.AccessModeRead, unit.TypeCode, unit.TypeIssues)
+ require.NoError(t, err)
+ assert.Len(t, teams, 1) // can read "code" or "issues"
+
+ teams, err = organization.GetTeamsWithAccessToAnyRepoUnit(ctx, testOrgID, testRepoID, perm.AccessModeWrite, unit.TypeCode)
+ require.NoError(t, err)
+ assert.Empty(t, teams) // cannot write "code"
+
+ teams, err = organization.GetTeamsWithAccessToAnyRepoUnit(ctx, testOrgID, testRepoID, perm.AccessModeWrite, unit.TypeIssues)
+ require.NoError(t, err)
+ assert.Len(t, teams, 1) // can write "issues"
+
+ _, _ = db.GetEngine(ctx).ID(testTeam.ID).Update(&organization.Team{AccessMode: perm.AccessModeWrite})
+ teams, err = organization.GetTeamsWithAccessToAnyRepoUnit(ctx, testOrgID, testRepoID, perm.AccessModeWrite, unit.TypeCode)
+ require.NoError(t, err)
+ assert.Len(t, teams, 1) // team permission is "write", so can write "code"
+ })
}
diff --git a/tests/integration/org_worktime_test.go b/tests/integration/org_worktime_test.go
new file mode 100644
index 0000000000..fb5216be8d
--- /dev/null
+++ b/tests/integration/org_worktime_test.go
@@ -0,0 +1,293 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package integration_test
+
+import (
+ "testing"
+
+ "code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/models/organization"
+ "code.gitea.io/gitea/models/unittest"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+// TestTimesByRepos tests TimesByRepos functionality
+func testTimesByRepos(t *testing.T) {
+ kases := []struct {
+ name string
+ unixfrom int64
+ unixto int64
+ orgname int64
+ expected []organization.WorktimeSumByRepos
+ }{
+ {
+ name: "Full sum for org 1",
+ unixfrom: 0,
+ unixto: 9223372036854775807,
+ orgname: 1,
+ expected: []organization.WorktimeSumByRepos(nil),
+ },
+ {
+ name: "Full sum for org 2",
+ unixfrom: 0,
+ unixto: 9223372036854775807,
+ orgname: 2,
+ expected: []organization.WorktimeSumByRepos{
+ {
+ RepoName: "repo1",
+ SumTime: 4083,
+ },
+ {
+ RepoName: "repo2",
+ SumTime: 75,
+ },
+ },
+ },
+ {
+ name: "Simple time bound",
+ unixfrom: 946684801,
+ unixto: 946684802,
+ orgname: 2,
+ expected: []organization.WorktimeSumByRepos{
+ {
+ RepoName: "repo1",
+ SumTime: 3662,
+ },
+ },
+ },
+ {
+ name: "Both times inclusive",
+ unixfrom: 946684801,
+ unixto: 946684801,
+ orgname: 2,
+ expected: []organization.WorktimeSumByRepos{
+ {
+ RepoName: "repo1",
+ SumTime: 3661,
+ },
+ },
+ },
+ {
+ name: "Should ignore deleted",
+ unixfrom: 947688814,
+ unixto: 947688815,
+ orgname: 2,
+ expected: []organization.WorktimeSumByRepos{
+ {
+ RepoName: "repo2",
+ SumTime: 71,
+ },
+ },
+ },
+ }
+
+ // Run test kases
+ for _, kase := range kases {
+ t.Run(kase.name, func(t *testing.T) {
+ org, err := organization.GetOrgByID(db.DefaultContext, kase.orgname)
+ assert.NoError(t, err)
+ results, err := organization.GetWorktimeByRepos(org, kase.unixfrom, kase.unixto)
+ assert.NoError(t, err)
+ assert.Equal(t, kase.expected, results)
+ })
+ }
+}
+
+// TestTimesByMilestones tests TimesByMilestones functionality
+func testTimesByMilestones(t *testing.T) {
+ kases := []struct {
+ name string
+ unixfrom int64
+ unixto int64
+ orgname int64
+ expected []organization.WorktimeSumByMilestones
+ }{
+ {
+ name: "Full sum for org 1",
+ unixfrom: 0,
+ unixto: 9223372036854775807,
+ orgname: 1,
+ expected: []organization.WorktimeSumByMilestones(nil),
+ },
+ {
+ name: "Full sum for org 2",
+ unixfrom: 0,
+ unixto: 9223372036854775807,
+ orgname: 2,
+ expected: []organization.WorktimeSumByMilestones{
+ {
+ RepoName: "repo1",
+ MilestoneName: "",
+ MilestoneID: 0,
+ SumTime: 401,
+ HideRepoName: false,
+ },
+ {
+ RepoName: "repo1",
+ MilestoneName: "milestone1",
+ MilestoneID: 1,
+ SumTime: 3682,
+ HideRepoName: true,
+ },
+ {
+ RepoName: "repo2",
+ MilestoneName: "",
+ MilestoneID: 0,
+ SumTime: 75,
+ HideRepoName: false,
+ },
+ },
+ },
+ {
+ name: "Simple time bound",
+ unixfrom: 946684801,
+ unixto: 946684802,
+ orgname: 2,
+ expected: []organization.WorktimeSumByMilestones{
+ {
+ RepoName: "repo1",
+ MilestoneName: "milestone1",
+ MilestoneID: 1,
+ SumTime: 3662,
+ HideRepoName: false,
+ },
+ },
+ },
+ {
+ name: "Both times inclusive",
+ unixfrom: 946684801,
+ unixto: 946684801,
+ orgname: 2,
+ expected: []organization.WorktimeSumByMilestones{
+ {
+ RepoName: "repo1",
+ MilestoneName: "milestone1",
+ MilestoneID: 1,
+ SumTime: 3661,
+ HideRepoName: false,
+ },
+ },
+ },
+ {
+ name: "Should ignore deleted",
+ unixfrom: 947688814,
+ unixto: 947688815,
+ orgname: 2,
+ expected: []organization.WorktimeSumByMilestones{
+ {
+ RepoName: "repo2",
+ MilestoneName: "",
+ MilestoneID: 0,
+ SumTime: 71,
+ HideRepoName: false,
+ },
+ },
+ },
+ }
+
+ // Run test kases
+ for _, kase := range kases {
+ t.Run(kase.name, func(t *testing.T) {
+ org, err := organization.GetOrgByID(db.DefaultContext, kase.orgname)
+ require.NoError(t, err)
+ results, err := organization.GetWorktimeByMilestones(org, kase.unixfrom, kase.unixto)
+ if assert.NoError(t, err) {
+ assert.Equal(t, kase.expected, results)
+ }
+ })
+ }
+}
+
+// TestTimesByMembers tests TimesByMembers functionality
+func testTimesByMembers(t *testing.T) {
+ kases := []struct {
+ name string
+ unixfrom int64
+ unixto int64
+ orgname int64
+ expected []organization.WorktimeSumByMembers
+ }{
+ {
+ name: "Full sum for org 1",
+ unixfrom: 0,
+ unixto: 9223372036854775807,
+ orgname: 1,
+ expected: []organization.WorktimeSumByMembers(nil),
+ },
+ {
+ // Test case: Sum of times forever in org no. 2
+ name: "Full sum for org 2",
+ unixfrom: 0,
+ unixto: 9223372036854775807,
+ orgname: 2,
+ expected: []organization.WorktimeSumByMembers{
+ {
+ UserName: "user2",
+ SumTime: 3666,
+ },
+ {
+ UserName: "user1",
+ SumTime: 491,
+ },
+ },
+ },
+ {
+ name: "Simple time bound",
+ unixfrom: 946684801,
+ unixto: 946684802,
+ orgname: 2,
+ expected: []organization.WorktimeSumByMembers{
+ {
+ UserName: "user2",
+ SumTime: 3662,
+ },
+ },
+ },
+ {
+ name: "Both times inclusive",
+ unixfrom: 946684801,
+ unixto: 946684801,
+ orgname: 2,
+ expected: []organization.WorktimeSumByMembers{
+ {
+ UserName: "user2",
+ SumTime: 3661,
+ },
+ },
+ },
+ {
+ name: "Should ignore deleted",
+ unixfrom: 947688814,
+ unixto: 947688815,
+ orgname: 2,
+ expected: []organization.WorktimeSumByMembers{
+ {
+ UserName: "user1",
+ SumTime: 71,
+ },
+ },
+ },
+ }
+
+ // Run test kases
+ for _, kase := range kases {
+ t.Run(kase.name, func(t *testing.T) {
+ org, err := organization.GetOrgByID(db.DefaultContext, kase.orgname)
+ assert.NoError(t, err)
+ results, err := organization.GetWorktimeByMembers(org, kase.unixfrom, kase.unixto)
+ assert.NoError(t, err)
+ assert.Equal(t, kase.expected, results)
+ })
+ }
+}
+
+func TestOrgWorktime(t *testing.T) {
+ // we need to run these tests in integration test because there are complex SQL queries
+ assert.NoError(t, unittest.PrepareTestDatabase())
+ t.Run("ByRepos", testTimesByRepos)
+ t.Run("ByMilestones", testTimesByMilestones)
+ t.Run("ByMembers", testTimesByMembers)
+}
diff --git a/tests/integration/project_test.go b/tests/integration/project_test.go
index cdff9aa2fd..43a489d4c4 100644
--- a/tests/integration/project_test.go
+++ b/tests/integration/project_test.go
@@ -47,7 +47,7 @@ func TestMoveRepoProjectColumns(t *testing.T) {
err := project_model.NewProject(db.DefaultContext, &project1)
assert.NoError(t, err)
- for i := 0; i < 3; i++ {
+ for i := range 3 {
err = project_model.NewColumn(db.DefaultContext, &project_model.Column{
Title: fmt.Sprintf("column %d", i+1),
ProjectID: project1.ID,
@@ -78,10 +78,10 @@ func TestMoveRepoProjectColumns(t *testing.T) {
columnsAfter, err := project1.GetColumns(db.DefaultContext)
assert.NoError(t, err)
- assert.Len(t, columns, 3)
- assert.EqualValues(t, columns[1].ID, columnsAfter[0].ID)
- assert.EqualValues(t, columns[2].ID, columnsAfter[1].ID)
- assert.EqualValues(t, columns[0].ID, columnsAfter[2].ID)
+ assert.Len(t, columnsAfter, 3)
+ assert.Equal(t, columns[1].ID, columnsAfter[0].ID)
+ assert.Equal(t, columns[2].ID, columnsAfter[1].ID)
+ assert.Equal(t, columns[0].ID, columnsAfter[2].ID)
assert.NoError(t, project_model.DeleteProjectByID(db.DefaultContext, project1.ID))
}
diff --git a/tests/integration/pull_commit_test.go b/tests/integration/pull_commit_test.go
index 8d98349fd3..9f3b1a9ef5 100644
--- a/tests/integration/pull_commit_test.go
+++ b/tests/integration/pull_commit_test.go
@@ -5,30 +5,37 @@ package integration
import (
"net/http"
- "net/url"
"testing"
pull_service "code.gitea.io/gitea/services/pull"
+ "code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
func TestListPullCommits(t *testing.T) {
- onGiteaRun(t, func(t *testing.T, u *url.URL) {
- session := loginUser(t, "user5")
- req := NewRequest(t, "GET", "/user2/repo1/pulls/3/commits/list")
- resp := session.MakeRequest(t, req, http.StatusOK)
-
- var pullCommitList struct {
- Commits []pull_service.CommitInfo `json:"commits"`
- LastReviewCommitSha string `json:"last_review_commit_sha"`
- }
- DecodeJSON(t, resp, &pullCommitList)
-
- if assert.Len(t, pullCommitList.Commits, 2) {
- assert.Equal(t, "985f0301dba5e7b34be866819cd15ad3d8f508ee", pullCommitList.Commits[0].ID)
- assert.Equal(t, "5c050d3b6d2db231ab1f64e324f1b6b9a0b181c2", pullCommitList.Commits[1].ID)
- }
- assert.Equal(t, "4a357436d925b5c974181ff12a994538ddc5a269", pullCommitList.LastReviewCommitSha)
+ defer tests.PrepareTestEnv(t)()
+
+ session := loginUser(t, "user5")
+ req := NewRequest(t, "GET", "/user2/repo1/pulls/3/commits/list")
+ resp := session.MakeRequest(t, req, http.StatusOK)
+
+ var pullCommitList struct {
+ Commits []pull_service.CommitInfo `json:"commits"`
+ LastReviewCommitSha string `json:"last_review_commit_sha"`
+ }
+ DecodeJSON(t, resp, &pullCommitList)
+
+ require.Len(t, pullCommitList.Commits, 2)
+ assert.Equal(t, "985f0301dba5e7b34be866819cd15ad3d8f508ee", pullCommitList.Commits[0].ID)
+ assert.Equal(t, "5c050d3b6d2db231ab1f64e324f1b6b9a0b181c2", pullCommitList.Commits[1].ID)
+ assert.Equal(t, "4a357436d925b5c974181ff12a994538ddc5a269", pullCommitList.LastReviewCommitSha)
+
+ t.Run("CommitBlobExcerpt", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+ req = NewRequest(t, "GET", "/user2/repo1/blob_excerpt/985f0301dba5e7b34be866819cd15ad3d8f508ee?last_left=0&last_right=0&left=2&right=2&left_hunk_size=2&right_hunk_size=2&path=README.md&style=split&direction=up")
+ resp = session.MakeRequest(t, req, http.StatusOK)
+ assert.Contains(t, resp.Body.String(), `<td class="lines-code lines-code-new"><code class="code-inner"># repo1</code>`)
})
}
diff --git a/tests/integration/pull_compare_test.go b/tests/integration/pull_compare_test.go
index 106774aa54..f95a2f1690 100644
--- a/tests/integration/pull_compare_test.go
+++ b/tests/integration/pull_compare_test.go
@@ -13,7 +13,6 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
- user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/test"
repo_service "code.gitea.io/gitea/services/repository"
"code.gitea.io/gitea/tests"
@@ -24,23 +23,38 @@ import (
func TestPullCompare(t *testing.T) {
defer tests.PrepareTestEnv(t)()
- session := loginUser(t, "user2")
- req := NewRequest(t, "GET", "/user2/repo1/pulls")
- resp := session.MakeRequest(t, req, http.StatusOK)
- htmlDoc := NewHTMLParser(t, resp.Body)
- link, exists := htmlDoc.doc.Find(".new-pr-button").Attr("href")
- assert.True(t, exists, "The template has changed")
+ t.Run("PullsNewRedirect", func(t *testing.T) {
+ req := NewRequest(t, "GET", "/user2/repo1/pulls/new/foo")
+ resp := MakeRequest(t, req, http.StatusSeeOther)
+ redirect := test.RedirectURL(resp)
+ assert.Equal(t, "/user2/repo1/compare/master...foo?expand=1", redirect)
- req = NewRequest(t, "GET", link)
- resp = session.MakeRequest(t, req, http.StatusOK)
- assert.EqualValues(t, http.StatusOK, resp.Code)
+ req = NewRequest(t, "GET", "/user13/repo11/pulls/new/foo")
+ resp = MakeRequest(t, req, http.StatusSeeOther)
+ redirect = test.RedirectURL(resp)
+ assert.Equal(t, "/user12/repo10/compare/master...user13:foo?expand=1", redirect)
+ })
+
+ t.Run("ButtonsExist", func(t *testing.T) {
+ session := loginUser(t, "user2")
+
+ // test the "New PR" button
+ req := NewRequest(t, "GET", "/user2/repo1/pulls")
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ htmlDoc := NewHTMLParser(t, resp.Body)
+ link, exists := htmlDoc.doc.Find(".new-pr-button").Attr("href")
+ assert.True(t, exists, "The template has changed")
+ req = NewRequest(t, "GET", link)
+ resp = session.MakeRequest(t, req, http.StatusOK)
+ assert.Equal(t, http.StatusOK, resp.Code)
- // test the edit button in the PR diff view
- req = NewRequest(t, "GET", "/user2/repo1/pulls/3/files")
- resp = session.MakeRequest(t, req, http.StatusOK)
- doc := NewHTMLParser(t, resp.Body)
- editButtonCount := doc.doc.Find(".diff-file-header-actions a[href*='/_edit/']").Length()
- assert.Positive(t, editButtonCount, "Expected to find a button to edit a file in the PR diff view but there were none")
+ // test the edit button in the PR diff view
+ req = NewRequest(t, "GET", "/user2/repo1/pulls/3/files")
+ resp = session.MakeRequest(t, req, http.StatusOK)
+ doc := NewHTMLParser(t, resp.Body)
+ editButtonCount := doc.doc.Find(".diff-file-header-actions a[href*='/_edit/']").Length()
+ assert.Positive(t, editButtonCount, "Expected to find a button to edit a file in the PR diff view but there were none")
+ })
onGiteaRun(t, func(t *testing.T, u *url.URL) {
defer tests.PrepareTestEnv(t)()
@@ -54,24 +68,23 @@ func TestPullCompare(t *testing.T) {
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user2", Name: "repo1"})
issueIndex := unittest.AssertExistsAndLoadBean(t, &issues_model.IssueIndex{GroupID: repo1.ID}, unittest.OrderBy("group_id ASC"))
prFilesURL := fmt.Sprintf("/user2/repo1/pulls/%d/files", issueIndex.MaxIndex)
- req = NewRequest(t, "GET", prFilesURL)
- resp = session.MakeRequest(t, req, http.StatusOK)
+ req := NewRequest(t, "GET", prFilesURL)
+ resp := session.MakeRequest(t, req, http.StatusOK)
doc := NewHTMLParser(t, resp.Body)
editButtonCount := doc.doc.Find(".diff-file-header-actions a[href*='/_edit/']").Length()
assert.Positive(t, editButtonCount, "Expected to find a button to edit a file in the PR diff view but there were none")
repoForked := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user1", Name: "repo1"})
- user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
// delete the head repository and revisit the PR diff view
- err := repo_service.DeleteRepositoryDirectly(db.DefaultContext, user2, repoForked.ID)
+ err := repo_service.DeleteRepositoryDirectly(db.DefaultContext, repoForked.ID)
assert.NoError(t, err)
req = NewRequest(t, "GET", prFilesURL)
resp = session.MakeRequest(t, req, http.StatusOK)
doc = NewHTMLParser(t, resp.Body)
editButtonCount = doc.doc.Find(".diff-file-header-actions a[href*='/_edit/']").Length()
- assert.EqualValues(t, 0, editButtonCount, "Expected not to find a button to edit a file in the PR diff view because head repository has been deleted")
+ assert.Equal(t, 0, editButtonCount, "Expected not to find a button to edit a file in the PR diff view because head repository has been deleted")
})
}
@@ -95,7 +108,7 @@ func TestPullCompare_EnableAllowEditsFromMaintainer(t *testing.T) {
// user2 (admin of repo3) goes to the PR files page
user2Session := loginUser(t, "user2")
- resp = user2Session.MakeRequest(t, NewRequest(t, "GET", fmt.Sprintf("%s/files", prURL)), http.StatusOK)
+ resp = user2Session.MakeRequest(t, NewRequest(t, "GET", prURL+"/files"), http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
nodes := htmlDoc.doc.Find(".diff-file-box[data-new-filename=\"README.md\"] .diff-file-header-actions .tippy-target a")
if assert.Equal(t, 1, nodes.Length()) {
@@ -112,14 +125,14 @@ func TestPullCompare_EnableAllowEditsFromMaintainer(t *testing.T) {
htmlDoc = NewHTMLParser(t, resp.Body)
dataURL, exists := htmlDoc.doc.Find("#allow-edits-from-maintainers").Attr("data-url")
assert.True(t, exists)
- req := NewRequestWithValues(t, "POST", fmt.Sprintf("%s/set_allow_maintainer_edit", dataURL), map[string]string{
+ req := NewRequestWithValues(t, "POST", dataURL+"/set_allow_maintainer_edit", map[string]string{
"_csrf": htmlDoc.GetCSRF(),
"allow_maintainer_edit": "true",
})
user4Session.MakeRequest(t, req, http.StatusOK)
// user2 (admin of repo3) goes to the PR files page again
- resp = user2Session.MakeRequest(t, NewRequest(t, "GET", fmt.Sprintf("%s/files", prURL)), http.StatusOK)
+ resp = user2Session.MakeRequest(t, NewRequest(t, "GET", prURL+"/files"), http.StatusOK)
htmlDoc = NewHTMLParser(t, resp.Body)
nodes = htmlDoc.doc.Find(".diff-file-box[data-new-filename=\"README.md\"] .diff-file-header-actions .tippy-target a")
if assert.Equal(t, 2, nodes.Length()) {
@@ -146,7 +159,8 @@ func TestPullCompare_EnableAllowEditsFromMaintainer(t *testing.T) {
"commit_summary": "user2 updated the file",
"commit_choice": "direct",
})
- user2Session.MakeRequest(t, req, http.StatusSeeOther)
+ resp = user2Session.MakeRequest(t, req, http.StatusOK)
+ assert.NotEmpty(t, test.RedirectURL(resp))
}
}
})
diff --git a/tests/integration/pull_create_test.go b/tests/integration/pull_create_test.go
index 162ea532c8..179c84e673 100644
--- a/tests/integration/pull_create_test.go
+++ b/tests/integration/pull_create_test.go
@@ -265,7 +265,7 @@ func TestCreateAgitPullWithReadPermission(t *testing.T) {
t.Run("add commit", doGitAddSomeCommits(dstPath, "master"))
t.Run("do agit pull create", func(t *testing.T) {
- err := git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/master", "-o").AddDynamicArguments("topic=" + "test-topic").Run(&git.RunOpts{Dir: dstPath})
+ err := git.NewCommand("push", "origin", "HEAD:refs/for/master", "-o").AddDynamicArguments("topic="+"test-topic").Run(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
})
})
@@ -293,10 +293,10 @@ func TestCreatePullWhenBlocked(t *testing.T) {
// sessionBase := loginUser(t, "user2")
token := getUserToken(t, RepoOwner, auth_model.AccessTokenScopeWriteUser)
- req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/blocks/%s", ForkOwner)).
+ req := NewRequest(t, "GET", "/api/v1/user/blocks/"+ForkOwner).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNotFound)
- req = NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/blocks/%s", ForkOwner)).
+ req = NewRequest(t, "PUT", "/api/v1/user/blocks/"+ForkOwner).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNoContent)
@@ -308,7 +308,7 @@ func TestCreatePullWhenBlocked(t *testing.T) {
// Teardown
// Unblock user
- req = NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/user/blocks/%s", ForkOwner)).
+ req = NewRequest(t, "DELETE", "/api/v1/user/blocks/"+ForkOwner).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNoContent)
})
diff --git a/tests/integration/pull_merge_test.go b/tests/integration/pull_merge_test.go
index 169df8618e..73b4c22070 100644
--- a/tests/integration/pull_merge_test.go
+++ b/tests/integration/pull_merge_test.go
@@ -5,7 +5,6 @@ package integration
import (
"bytes"
- "context"
"fmt"
"net/http"
"net/http/httptest"
@@ -27,6 +26,7 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/models/webhook"
+ "code.gitea.io/gitea/modules/commitstatus"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/queue"
@@ -67,7 +67,7 @@ func testPullMerge(t *testing.T, session *TestSession, user, repo, pullnum strin
}{}
DecodeJSON(t, resp, &respJSON)
- assert.EqualValues(t, fmt.Sprintf("/%s/%s/pulls/%s", user, repo, pullnum), respJSON.Redirect)
+ assert.Equal(t, fmt.Sprintf("/%s/%s/pulls/%s", user, repo, pullnum), respJSON.Redirect)
return resp
}
@@ -101,7 +101,7 @@ func TestPullMerge(t *testing.T) {
resp := testPullCreate(t, session, "user1", "repo1", false, "master", "master", "This is a pull title")
elem := strings.Split(test.RedirectURL(resp), "/")
- assert.EqualValues(t, "pulls", elem[3])
+ assert.Equal(t, "pulls", elem[3])
testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleMerge, false)
hookTasks, err = webhook.HookTasks(db.DefaultContext, 1, 1)
@@ -123,7 +123,7 @@ func TestPullRebase(t *testing.T) {
resp := testPullCreate(t, session, "user1", "repo1", false, "master", "master", "This is a pull title")
elem := strings.Split(test.RedirectURL(resp), "/")
- assert.EqualValues(t, "pulls", elem[3])
+ assert.Equal(t, "pulls", elem[3])
testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleRebase, false)
hookTasks, err = webhook.HookTasks(db.DefaultContext, 1, 1)
@@ -145,7 +145,7 @@ func TestPullRebaseMerge(t *testing.T) {
resp := testPullCreate(t, session, "user1", "repo1", false, "master", "master", "This is a pull title")
elem := strings.Split(test.RedirectURL(resp), "/")
- assert.EqualValues(t, "pulls", elem[3])
+ assert.Equal(t, "pulls", elem[3])
testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleRebaseMerge, false)
hookTasks, err = webhook.HookTasks(db.DefaultContext, 1, 1)
@@ -168,7 +168,7 @@ func TestPullSquash(t *testing.T) {
resp := testPullCreate(t, session, "user1", "repo1", false, "master", "master", "This is a pull title")
elem := strings.Split(test.RedirectURL(resp), "/")
- assert.EqualValues(t, "pulls", elem[3])
+ assert.Equal(t, "pulls", elem[3])
testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleSquash, false)
hookTasks, err = webhook.HookTasks(db.DefaultContext, 1, 1)
@@ -186,7 +186,7 @@ func TestPullCleanUpAfterMerge(t *testing.T) {
resp := testPullCreate(t, session, "user1", "repo1", false, "master", "feature/test", "This is a pull title")
elem := strings.Split(test.RedirectURL(resp), "/")
- assert.EqualValues(t, "pulls", elem[3])
+ assert.Equal(t, "pulls", elem[3])
testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleMerge, false)
// Check PR branch deletion
@@ -199,7 +199,7 @@ func TestPullCleanUpAfterMerge(t *testing.T) {
assert.NotEmpty(t, respJSON.Redirect, "Redirected URL is not found")
elem = strings.Split(respJSON.Redirect, "/")
- assert.EqualValues(t, "pulls", elem[3])
+ assert.Equal(t, "pulls", elem[3])
// Check branch deletion result
req := NewRequest(t, "GET", respJSON.Redirect)
@@ -208,7 +208,7 @@ func TestPullCleanUpAfterMerge(t *testing.T) {
htmlDoc := NewHTMLParser(t, resp.Body)
resultMsg := htmlDoc.doc.Find(".ui.message>p").Text()
- assert.EqualValues(t, "Branch \"user1/repo1:feature/test\" has been deleted.", resultMsg)
+ assert.Equal(t, "Branch \"user1/repo1:feature/test\" has been deleted.", resultMsg)
})
}
@@ -266,11 +266,11 @@ func TestCantMergeConflict(t *testing.T) {
gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo1)
assert.NoError(t, err)
- err = pull_service.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleMerge, "", "CONFLICT", false)
+ err = pull_service.Merge(t.Context(), pr, user1, gitRepo, repo_model.MergeStyleMerge, "", "CONFLICT", false)
assert.Error(t, err, "Merge should return an error due to conflict")
assert.True(t, pull_service.IsErrMergeConflicts(err), "Merge error is not a conflict error")
- err = pull_service.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleRebase, "", "CONFLICT", false)
+ err = pull_service.Merge(t.Context(), pr, user1, gitRepo, repo_model.MergeStyleRebase, "", "CONFLICT", false)
assert.Error(t, err, "Merge should return an error due to conflict")
assert.True(t, pull_service.IsErrRebaseConflicts(err), "Merge error is not a conflict error")
gitRepo.Close()
@@ -294,12 +294,12 @@ func TestCantMergeUnrelated(t *testing.T) {
})
path := repo_model.RepoPath(user1.Name, repo1.Name)
- err := git.NewCommand(git.DefaultContext, "read-tree", "--empty").Run(&git.RunOpts{Dir: path})
+ err := git.NewCommand("read-tree", "--empty").Run(git.DefaultContext, &git.RunOpts{Dir: path})
assert.NoError(t, err)
- stdin := bytes.NewBufferString("Unrelated File")
+ stdin := strings.NewReader("Unrelated File")
var stdout strings.Builder
- err = git.NewCommand(git.DefaultContext, "hash-object", "-w", "--stdin").Run(&git.RunOpts{
+ err = git.NewCommand("hash-object", "-w", "--stdin").Run(git.DefaultContext, &git.RunOpts{
Dir: path,
Stdin: stdin,
Stdout: &stdout,
@@ -308,10 +308,10 @@ func TestCantMergeUnrelated(t *testing.T) {
assert.NoError(t, err)
sha := strings.TrimSpace(stdout.String())
- _, _, err = git.NewCommand(git.DefaultContext, "update-index", "--add", "--replace", "--cacheinfo").AddDynamicArguments("100644", sha, "somewher-over-the-rainbow").RunStdString(&git.RunOpts{Dir: path})
+ _, _, err = git.NewCommand("update-index", "--add", "--replace", "--cacheinfo").AddDynamicArguments("100644", sha, "somewher-over-the-rainbow").RunStdString(git.DefaultContext, &git.RunOpts{Dir: path})
assert.NoError(t, err)
- treeSha, _, err := git.NewCommand(git.DefaultContext, "write-tree").RunStdString(&git.RunOpts{Dir: path})
+ treeSha, _, err := git.NewCommand("write-tree").RunStdString(git.DefaultContext, &git.RunOpts{Dir: path})
assert.NoError(t, err)
treeSha = strings.TrimSpace(treeSha)
@@ -331,8 +331,8 @@ func TestCantMergeUnrelated(t *testing.T) {
_, _ = messageBytes.WriteString("\n")
stdout.Reset()
- err = git.NewCommand(git.DefaultContext, "commit-tree").AddDynamicArguments(treeSha).
- Run(&git.RunOpts{
+ err = git.NewCommand("commit-tree").AddDynamicArguments(treeSha).
+ Run(git.DefaultContext, &git.RunOpts{
Env: env,
Dir: path,
Stdin: messageBytes,
@@ -341,7 +341,7 @@ func TestCantMergeUnrelated(t *testing.T) {
assert.NoError(t, err)
commitSha := strings.TrimSpace(stdout.String())
- _, _, err = git.NewCommand(git.DefaultContext, "branch", "unrelated").AddDynamicArguments(commitSha).RunStdString(&git.RunOpts{Dir: path})
+ _, _, err = git.NewCommand("branch", "unrelated").AddDynamicArguments(commitSha).RunStdString(git.DefaultContext, &git.RunOpts{Dir: path})
assert.NoError(t, err)
testEditFileToNewBranch(t, session, "user1", "repo1", "master", "conflict", "README.md", "Hello, World (Edited Once)\n")
@@ -365,7 +365,7 @@ func TestCantMergeUnrelated(t *testing.T) {
BaseBranch: "base",
})
- err = pull_service.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleMerge, "", "UNRELATED", false)
+ err = pull_service.Merge(t.Context(), pr, user1, gitRepo, repo_model.MergeStyleMerge, "", "UNRELATED", false)
assert.Error(t, err, "Merge should return an error due to unrelated")
assert.True(t, pull_service.IsErrMergeUnrelatedHistories(err), "Merge error is not a unrelated histories error")
gitRepo.Close()
@@ -405,7 +405,7 @@ func TestFastForwardOnlyMerge(t *testing.T) {
gitRepo, err := git.OpenRepository(git.DefaultContext, repo_model.RepoPath(user1.Name, repo1.Name))
assert.NoError(t, err)
- err = pull_service.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleFastForwardOnly, "", "FAST-FORWARD-ONLY", false)
+ err = pull_service.Merge(t.Context(), pr, user1, gitRepo, repo_model.MergeStyleFastForwardOnly, "", "FAST-FORWARD-ONLY", false)
assert.NoError(t, err)
@@ -447,7 +447,7 @@ func TestCantFastForwardOnlyMergeDiverging(t *testing.T) {
gitRepo, err := git.OpenRepository(git.DefaultContext, repo_model.RepoPath(user1.Name, repo1.Name))
assert.NoError(t, err)
- err = pull_service.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleFastForwardOnly, "", "DIVERGING", false)
+ err = pull_service.Merge(t.Context(), pr, user1, gitRepo, repo_model.MergeStyleFastForwardOnly, "", "DIVERGING", false)
assert.Error(t, err, "Merge should return an error due to being for a diverging branch")
assert.True(t, pull_service.IsErrMergeDivergingFastForwardOnly(err), "Merge error is not a diverging fast-forward-only error")
@@ -545,11 +545,11 @@ func TestPullRetargetChildOnBranchDelete(t *testing.T) {
respBasePR := testPullCreate(t, session, "user2", "repo1", true, "master", "base-pr", "Base Pull Request")
elemBasePR := strings.Split(test.RedirectURL(respBasePR), "/")
- assert.EqualValues(t, "pulls", elemBasePR[3])
+ assert.Equal(t, "pulls", elemBasePR[3])
respChildPR := testPullCreate(t, session, "user1", "repo1", false, "base-pr", "child-pr", "Child Pull Request")
elemChildPR := strings.Split(test.RedirectURL(respChildPR), "/")
- assert.EqualValues(t, "pulls", elemChildPR[3])
+ assert.Equal(t, "pulls", elemChildPR[3])
testPullMerge(t, session, elemBasePR[1], elemBasePR[2], elemBasePR[4], repo_model.MergeStyleMerge, true)
@@ -565,8 +565,8 @@ func TestPullRetargetChildOnBranchDelete(t *testing.T) {
targetBranch := htmlDoc.doc.Find("#branch_target>a").Text()
prStatus := strings.TrimSpace(htmlDoc.doc.Find(".issue-title-meta>.issue-state-label").Text())
- assert.EqualValues(t, "master", targetBranch)
- assert.EqualValues(t, "Open", prStatus)
+ assert.Equal(t, "master", targetBranch)
+ assert.Equal(t, "Open", prStatus)
})
}
@@ -579,11 +579,11 @@ func TestPullDontRetargetChildOnWrongRepo(t *testing.T) {
respBasePR := testPullCreate(t, session, "user1", "repo1", false, "master", "base-pr", "Base Pull Request")
elemBasePR := strings.Split(test.RedirectURL(respBasePR), "/")
- assert.EqualValues(t, "pulls", elemBasePR[3])
+ assert.Equal(t, "pulls", elemBasePR[3])
respChildPR := testPullCreate(t, session, "user1", "repo1", true, "base-pr", "child-pr", "Child Pull Request")
elemChildPR := strings.Split(test.RedirectURL(respChildPR), "/")
- assert.EqualValues(t, "pulls", elemChildPR[3])
+ assert.Equal(t, "pulls", elemChildPR[3])
defer test.MockVariableValue(&setting.Repository.PullRequest.RetargetChildrenOnMerge, false)()
@@ -602,8 +602,8 @@ func TestPullDontRetargetChildOnWrongRepo(t *testing.T) {
targetBranch := htmlDoc.doc.Find("#branch_target>span").Text()
prStatus := strings.TrimSpace(htmlDoc.doc.Find(".issue-title-meta>.issue-state-label").Text())
- assert.EqualValues(t, "base-pr", targetBranch)
- assert.EqualValues(t, "Closed", prStatus)
+ assert.Equal(t, "base-pr", targetBranch)
+ assert.Equal(t, "Closed", prStatus)
})
}
@@ -615,7 +615,7 @@ func TestPullRequestMergedWithNoPermissionDeleteBranch(t *testing.T) {
respBasePR := testPullCreate(t, session, "user4", "repo1", false, "master", "base-pr", "Base Pull Request")
elemBasePR := strings.Split(test.RedirectURL(respBasePR), "/")
- assert.EqualValues(t, "pulls", elemBasePR[3])
+ assert.Equal(t, "pulls", elemBasePR[3])
// user2 has no permission to delete branch of repo user1/repo1
session2 := loginUser(t, "user2")
@@ -636,7 +636,7 @@ func TestPullMergeIndexerNotifier(t *testing.T) {
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
createPullResp := testPullCreate(t, session, "user1", "repo1", false, "master", "master", "Indexer notifier test pull")
- assert.NoError(t, queue.GetManager().FlushAll(context.Background(), 0))
+ assert.NoError(t, queue.GetManager().FlushAll(t.Context(), 0))
time.Sleep(time.Second)
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{
@@ -666,7 +666,7 @@ func TestPullMergeIndexerNotifier(t *testing.T) {
// merge the pull request
elem := strings.Split(test.RedirectURL(createPullResp), "/")
- assert.EqualValues(t, "pulls", elem[3])
+ assert.Equal(t, "pulls", elem[3])
testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleMerge, false)
// check if the issue is closed
@@ -675,7 +675,7 @@ func TestPullMergeIndexerNotifier(t *testing.T) {
})
assert.True(t, issue.IsClosed)
- assert.NoError(t, queue.GetManager().FlushAll(context.Background(), 0))
+ assert.NoError(t, queue.GetManager().FlushAll(t.Context(), 0))
time.Sleep(time.Second)
// search issues again
@@ -695,12 +695,12 @@ func testResetRepo(t *testing.T, repoPath, branch, commitID string) {
assert.NoError(t, err)
f.Close()
- repo, err := git.OpenRepository(context.Background(), repoPath)
+ repo, err := git.OpenRepository(t.Context(), repoPath)
assert.NoError(t, err)
defer repo.Close()
id, err := repo.GetBranchCommitID(branch)
assert.NoError(t, err)
- assert.EqualValues(t, commitID, id)
+ assert.Equal(t, commitID, id)
}
func TestPullAutoMergeAfterCommitStatusSucceed(t *testing.T) {
@@ -769,7 +769,7 @@ func TestPullAutoMergeAfterCommitStatusSucceed(t *testing.T) {
}()
err = commitstatus_service.CreateCommitStatus(db.DefaultContext, baseRepo, user1, sha, &git_model.CommitStatus{
- State: api.CommitStatusSuccess,
+ State: commitstatus.CommitStatusSuccess,
TargetURL: "https://gitea.com",
Context: "gitea/actions",
})
@@ -849,7 +849,7 @@ func TestPullAutoMergeAfterCommitStatusSucceedAndApproval(t *testing.T) {
}()
err = commitstatus_service.CreateCommitStatus(db.DefaultContext, baseRepo, user1, sha, &git_model.CommitStatus{
- State: api.CommitStatusSuccess,
+ State: commitstatus.CommitStatusSuccess,
TargetURL: "https://gitea.com",
Context: "gitea/actions",
})
@@ -915,13 +915,13 @@ func TestPullAutoMergeAfterCommitStatusSucceedAndApprovalForAgitFlow(t *testing.
stderrBuf := &bytes.Buffer{}
- err = git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/master", "-o").
+ err = git.NewCommand("push", "origin", "HEAD:refs/for/master", "-o").
AddDynamicArguments(`topic=test/head2`).
AddArguments("-o").
AddDynamicArguments(`title="create a test pull request with agit"`).
AddArguments("-o").
AddDynamicArguments(`description="This PR is a test pull request which created with agit"`).
- Run(&git.RunOpts{Dir: dstPath, Stderr: stderrBuf})
+ Run(git.DefaultContext, &git.RunOpts{Dir: dstPath, Stderr: stderrBuf})
assert.NoError(t, err)
assert.Contains(t, stderrBuf.String(), setting.AppURL+"user2/repo1/pulls/6")
@@ -978,14 +978,12 @@ func TestPullAutoMergeAfterCommitStatusSucceedAndApprovalForAgitFlow(t *testing.
}()
err = commitstatus_service.CreateCommitStatus(db.DefaultContext, baseRepo, user1, sha, &git_model.CommitStatus{
- State: api.CommitStatusSuccess,
+ State: commitstatus.CommitStatusSuccess,
TargetURL: "https://gitea.com",
Context: "gitea/actions",
})
assert.NoError(t, err)
- time.Sleep(2 * time.Second)
-
// reload pr again
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
assert.False(t, pr.HasMerged)
@@ -998,8 +996,6 @@ func TestPullAutoMergeAfterCommitStatusSucceedAndApprovalForAgitFlow(t *testing.
htmlDoc := NewHTMLParser(t, resp.Body)
testSubmitReview(t, approveSession, htmlDoc.GetCSRF(), "user2", "repo1", strconv.Itoa(int(pr.Index)), sha, "approve", http.StatusOK)
- time.Sleep(2 * time.Second)
-
// realod pr again
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
assert.True(t, pr.HasMerged)
diff --git a/tests/integration/pull_review_test.go b/tests/integration/pull_review_test.go
index 68de421413..1121751c88 100644
--- a/tests/integration/pull_review_test.go
+++ b/tests/integration/pull_review_test.go
@@ -57,7 +57,7 @@ func TestPullView_CodeOwner(t *testing.T) {
AutoInit: true,
ObjectFormatName: git.Sha1ObjectFormat.Name(),
DefaultBranch: "master",
- })
+ }, true)
assert.NoError(t, err)
// add CODEOWNERS to default branch
@@ -67,7 +67,7 @@ func TestPullView_CodeOwner(t *testing.T) {
{
Operation: "create",
TreePath: "CODEOWNERS",
- ContentReader: strings.NewReader("README.md @user5\n"),
+ ContentReader: strings.NewReader("README.md @user5\nuser8-file.md @user8\n"),
},
},
})
@@ -75,7 +75,7 @@ func TestPullView_CodeOwner(t *testing.T) {
t.Run("First Pull Request", func(t *testing.T) {
// create a new branch to prepare for pull request
- _, err = files_service.ChangeRepoFiles(db.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
+ _, err := files_service.ChangeRepoFiles(db.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
NewBranch: "codeowner-basebranch",
Files: []*files_service.ChangeRepoFile{
{
@@ -95,17 +95,35 @@ func TestPullView_CodeOwner(t *testing.T) {
unittest.AssertExistsAndLoadBean(t, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 5})
assert.NoError(t, pr.LoadIssue(db.DefaultContext))
- err := issue_service.ChangeTitle(db.DefaultContext, pr.Issue, user2, "[WIP] Test Pull Request")
+ // update the file on the pr branch
+ _, err = files_service.ChangeRepoFiles(db.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
+ OldBranch: "codeowner-basebranch",
+ Files: []*files_service.ChangeRepoFile{
+ {
+ Operation: "create",
+ TreePath: "user8-file.md",
+ ContentReader: strings.NewReader("# This is a new project2\n"),
+ },
+ },
+ })
+ assert.NoError(t, err)
+
+ reviewNotifiers, err := issue_service.PullRequestCodeOwnersReview(db.DefaultContext, pr)
+ assert.NoError(t, err)
+ assert.Len(t, reviewNotifiers, 1)
+ assert.EqualValues(t, 8, reviewNotifiers[0].Reviewer.ID)
+
+ err = issue_service.ChangeTitle(db.DefaultContext, pr.Issue, user2, "[WIP] Test Pull Request")
assert.NoError(t, err)
prUpdated1 := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
assert.NoError(t, prUpdated1.LoadIssue(db.DefaultContext))
- assert.EqualValues(t, "[WIP] Test Pull Request", prUpdated1.Issue.Title)
+ assert.Equal(t, "[WIP] Test Pull Request", prUpdated1.Issue.Title)
err = issue_service.ChangeTitle(db.DefaultContext, prUpdated1.Issue, user2, "Test Pull Request2")
assert.NoError(t, err)
prUpdated2 := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
assert.NoError(t, prUpdated2.LoadIssue(db.DefaultContext))
- assert.EqualValues(t, "Test Pull Request2", prUpdated2.Issue.Title)
+ assert.Equal(t, "Test Pull Request2", prUpdated2.Issue.Title)
})
// change the default branch CODEOWNERS file to change README.md's codeowner
@@ -193,7 +211,7 @@ func TestPullView_GivenApproveOrRejectReviewOnClosedPR(t *testing.T) {
testEditFile(t, user1Session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
resp := testPullCreate(t, user1Session, "user1", "repo1", false, "master", "master", "This is a pull title")
elem := strings.Split(test.RedirectURL(resp), "/")
- assert.EqualValues(t, "pulls", elem[3])
+ assert.Equal(t, "pulls", elem[3])
testPullMerge(t, user1Session, elem[1], elem[2], elem[4], repo_model.MergeStyleMerge, false)
// Grab the CSRF token.
@@ -213,7 +231,7 @@ func TestPullView_GivenApproveOrRejectReviewOnClosedPR(t *testing.T) {
testEditFileToNewBranch(t, user1Session, "user1", "repo1", "master", "a-test-branch", "README.md", "Hello, World (Editied...again)\n")
resp := testPullCreate(t, user1Session, "user1", "repo1", false, "master", "a-test-branch", "This is a pull title")
elem := strings.Split(test.RedirectURL(resp), "/")
- assert.EqualValues(t, "pulls", elem[3])
+ assert.Equal(t, "pulls", elem[3])
testIssueClose(t, user1Session, elem[1], elem[2], elem[4])
// Grab the CSRF token.
diff --git a/tests/integration/pull_status_test.go b/tests/integration/pull_status_test.go
index ac9036ca96..49326a594a 100644
--- a/tests/integration/pull_status_test.go
+++ b/tests/integration/pull_status_test.go
@@ -13,9 +13,14 @@ import (
auth_model "code.gitea.io/gitea/models/auth"
git_model "code.gitea.io/gitea/models/git"
+ "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
+ "code.gitea.io/gitea/modules/commitstatus"
+ "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/test"
+ "code.gitea.io/gitea/services/pull"
"github.com/stretchr/testify/assert"
)
@@ -51,20 +56,20 @@ func TestPullCreate_CommitStatus(t *testing.T) {
commitID := path.Base(commitURL)
- statusList := []api.CommitStatusState{
- api.CommitStatusPending,
- api.CommitStatusError,
- api.CommitStatusFailure,
- api.CommitStatusSuccess,
- api.CommitStatusWarning,
+ statusList := []commitstatus.CommitStatusState{
+ commitstatus.CommitStatusPending,
+ commitstatus.CommitStatusError,
+ commitstatus.CommitStatusFailure,
+ commitstatus.CommitStatusSuccess,
+ commitstatus.CommitStatusWarning,
}
- statesIcons := map[api.CommitStatusState]string{
- api.CommitStatusPending: "octicon-dot-fill",
- api.CommitStatusSuccess: "octicon-check",
- api.CommitStatusError: "gitea-exclamation",
- api.CommitStatusFailure: "octicon-x",
- api.CommitStatusWarning: "gitea-exclamation",
+ statesIcons := map[commitstatus.CommitStatusState]string{
+ commitstatus.CommitStatusPending: "octicon-dot-fill",
+ commitstatus.CommitStatusSuccess: "octicon-check",
+ commitstatus.CommitStatusError: "gitea-exclamation",
+ commitstatus.CommitStatusFailure: "octicon-x",
+ commitstatus.CommitStatusWarning: "gitea-exclamation",
}
testCtx := NewAPITestContext(t, "user1", "repo1", auth_model.AccessTokenScopeWriteRepository)
@@ -86,7 +91,7 @@ func TestPullCreate_CommitStatus(t *testing.T) {
commitURL, exists = doc.doc.Find("#commits-table tbody tr td.sha a").Last().Attr("href")
assert.True(t, exists)
assert.NotEmpty(t, commitURL)
- assert.EqualValues(t, commitID, path.Base(commitURL))
+ assert.Equal(t, commitID, path.Base(commitURL))
cls, ok := doc.doc.Find("#commits-table tbody tr td.message .commit-status").Last().Attr("class")
assert.True(t, ok)
@@ -95,7 +100,7 @@ func TestPullCreate_CommitStatus(t *testing.T) {
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user1", Name: "repo1"})
css := unittest.AssertExistsAndLoadBean(t, &git_model.CommitStatusSummary{RepoID: repo1.ID, SHA: commitID})
- assert.EqualValues(t, api.CommitStatusWarning, css.State)
+ assert.Equal(t, commitstatus.CommitStatusSuccess, css.State)
})
}
@@ -124,7 +129,7 @@ func TestPullCreate_EmptyChangesWithDifferentCommits(t *testing.T) {
session := loginUser(t, "user1")
testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "")
testEditFileToNewBranch(t, session, "user1", "repo1", "master", "status1", "README.md", "status1")
- testEditFileToNewBranch(t, session, "user1", "repo1", "status1", "status1", "README.md", "# repo1\n\nDescription for repo1")
+ testEditFile(t, session, "user1", "repo1", "status1", "README.md", "# repo1\n\nDescription for repo1")
url := path.Join("user1", "repo1", "compare", "master...status1")
req := NewRequestWithValues(t, "POST", url,
@@ -165,3 +170,74 @@ func TestPullCreate_EmptyChangesWithSameCommits(t *testing.T) {
assert.Contains(t, text, "This branch is already included in the target branch. There is nothing to merge.")
})
}
+
+func TestPullStatusDelayCheck(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ defer test.MockVariableValue(&setting.Repository.PullRequest.DelayCheckForInactiveDays, 1)()
+ defer test.MockVariableValue(&pull.AddPullRequestToCheckQueue)()
+
+ session := loginUser(t, "user2")
+
+ run := func(t *testing.T, fn func(*testing.T)) (issue3 *issues.Issue, checkedPrID int64) {
+ pull.AddPullRequestToCheckQueue = func(prID int64) {
+ checkedPrID = prID
+ }
+ fn(t)
+ issue3 = unittest.AssertExistsAndLoadBean(t, &issues.Issue{RepoID: 1, Index: 3})
+ _ = issue3.LoadPullRequest(t.Context())
+ return issue3, checkedPrID
+ }
+
+ assertReloadingInterval := func(t *testing.T, interval string) {
+ req := NewRequest(t, "GET", "/user2/repo1/pulls/3")
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ attr := "data-pull-merge-box-reloading-interval"
+ if interval == "" {
+ assert.NotContains(t, resp.Body.String(), attr)
+ } else {
+ assert.Contains(t, resp.Body.String(), fmt.Sprintf(`%s="%v"`, attr, interval))
+ }
+ }
+
+ // PR issue3 is merageable at the beginning
+ issue3, checkedPrID := run(t, func(t *testing.T) {})
+ assert.Equal(t, issues.PullRequestStatusMergeable, issue3.PullRequest.Status)
+ assert.Zero(t, checkedPrID)
+ assertReloadingInterval(t, "") // the PR is mergeable, so no need to reload the merge box
+
+ // setting.IsProd = false // it would cause data-race because the queue handlers might be running and reading its value
+ // assertReloadingInterval(t, "1") // make sure dev mode always do merge box reloading, to make sure the UI logic won't break
+ // setting.IsProd = true
+
+ // when base branch changes, PR status should be updated, but it is inactive for long time, so no real check
+ issue3, checkedPrID = run(t, func(t *testing.T) {
+ testEditFile(t, session, "user2", "repo1", "master", "README.md", "new content 1")
+ })
+ assert.Equal(t, issues.PullRequestStatusChecking, issue3.PullRequest.Status)
+ assert.Zero(t, checkedPrID)
+ assertReloadingInterval(t, "2000") // the PR status is "checking", so try to reload the merge box
+
+ // view a PR with status=checking, it starts the real check
+ issue3, checkedPrID = run(t, func(t *testing.T) {
+ req := NewRequest(t, "GET", "/user2/repo1/pulls/3")
+ session.MakeRequest(t, req, http.StatusOK)
+ })
+ assert.Equal(t, issues.PullRequestStatusChecking, issue3.PullRequest.Status)
+ assert.Equal(t, issue3.PullRequest.ID, checkedPrID)
+
+ // when base branch changes, still so no real check
+ issue3, checkedPrID = run(t, func(t *testing.T) {
+ testEditFile(t, session, "user2", "repo1", "master", "README.md", "new content 2")
+ })
+ assert.Equal(t, issues.PullRequestStatusChecking, issue3.PullRequest.Status)
+ assert.Zero(t, checkedPrID)
+
+ // then allow to check PRs without delay, when base branch changes, the PRs will be checked
+ setting.Repository.PullRequest.DelayCheckForInactiveDays = -1
+ issue3, checkedPrID = run(t, func(t *testing.T) {
+ testEditFile(t, session, "user2", "repo1", "master", "README.md", "new content 3")
+ })
+ assert.Equal(t, issues.PullRequestStatusChecking, issue3.PullRequest.Status)
+ assert.Equal(t, issue3.PullRequest.ID, checkedPrID)
+ })
+}
diff --git a/tests/integration/pull_update_test.go b/tests/integration/pull_update_test.go
index dfe47c1053..d28537112d 100644
--- a/tests/integration/pull_update_test.go
+++ b/tests/integration/pull_update_test.go
@@ -33,8 +33,8 @@ func TestAPIPullUpdate(t *testing.T) {
// Test GetDiverging
diffCount, err := pull_service.GetDiverging(git.DefaultContext, pr)
assert.NoError(t, err)
- assert.EqualValues(t, 1, diffCount.Behind)
- assert.EqualValues(t, 1, diffCount.Ahead)
+ assert.Equal(t, 1, diffCount.Behind)
+ assert.Equal(t, 1, diffCount.Ahead)
assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext))
assert.NoError(t, pr.LoadIssue(db.DefaultContext))
@@ -47,8 +47,8 @@ func TestAPIPullUpdate(t *testing.T) {
// Test GetDiverging after update
diffCount, err = pull_service.GetDiverging(git.DefaultContext, pr)
assert.NoError(t, err)
- assert.EqualValues(t, 0, diffCount.Behind)
- assert.EqualValues(t, 2, diffCount.Ahead)
+ assert.Equal(t, 0, diffCount.Behind)
+ assert.Equal(t, 2, diffCount.Ahead)
})
}
@@ -62,8 +62,8 @@ func TestAPIPullUpdateByRebase(t *testing.T) {
// Test GetDiverging
diffCount, err := pull_service.GetDiverging(git.DefaultContext, pr)
assert.NoError(t, err)
- assert.EqualValues(t, 1, diffCount.Behind)
- assert.EqualValues(t, 1, diffCount.Ahead)
+ assert.Equal(t, 1, diffCount.Behind)
+ assert.Equal(t, 1, diffCount.Ahead)
assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext))
assert.NoError(t, pr.LoadIssue(db.DefaultContext))
@@ -76,8 +76,8 @@ func TestAPIPullUpdateByRebase(t *testing.T) {
// Test GetDiverging after update
diffCount, err = pull_service.GetDiverging(git.DefaultContext, pr)
assert.NoError(t, err)
- assert.EqualValues(t, 0, diffCount.Behind)
- assert.EqualValues(t, 1, diffCount.Ahead)
+ assert.Equal(t, 0, diffCount.Behind)
+ assert.Equal(t, 1, diffCount.Ahead)
})
}
@@ -115,12 +115,12 @@ func createOutdatedPR(t *testing.T, actor, forkOrg *user_model.User) *issues_mod
OldBranch: "master",
NewBranch: "master",
Author: &files_service.IdentityOptions{
- Name: actor.Name,
- Email: actor.Email,
+ GitUserName: actor.Name,
+ GitUserEmail: actor.Email,
},
Committer: &files_service.IdentityOptions{
- Name: actor.Name,
- Email: actor.Email,
+ GitUserName: actor.Name,
+ GitUserEmail: actor.Email,
},
Dates: &files_service.CommitDateOptions{
Author: time.Now(),
@@ -142,12 +142,12 @@ func createOutdatedPR(t *testing.T, actor, forkOrg *user_model.User) *issues_mod
OldBranch: "master",
NewBranch: "newBranch",
Author: &files_service.IdentityOptions{
- Name: actor.Name,
- Email: actor.Email,
+ GitUserName: actor.Name,
+ GitUserEmail: actor.Email,
},
Committer: &files_service.IdentityOptions{
- Name: actor.Name,
- Email: actor.Email,
+ GitUserName: actor.Name,
+ GitUserEmail: actor.Email,
},
Dates: &files_service.CommitDateOptions{
Author: time.Now(),
diff --git a/tests/integration/release_test.go b/tests/integration/release_test.go
index 1a7f9e38b5..88a58787af 100644
--- a/tests/integration/release_test.go
+++ b/tests/integration/release_test.go
@@ -7,7 +7,6 @@ import (
"fmt"
"net/http"
"testing"
- "time"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
@@ -54,12 +53,12 @@ func checkLatestReleaseAndCount(t *testing.T, session *TestSession, repoURL, ver
htmlDoc := NewHTMLParser(t, resp.Body)
labelText := htmlDoc.doc.Find("#release-list > li .detail .label").First().Text()
- assert.EqualValues(t, label, labelText)
+ assert.Equal(t, label, labelText)
titleText := htmlDoc.doc.Find("#release-list > li .detail h4 a").First().Text()
- assert.EqualValues(t, version, titleText)
+ assert.Equal(t, version, titleText)
releaseList := htmlDoc.doc.Find("#release-list > li")
- assert.EqualValues(t, count, releaseList.Length())
+ assert.Equal(t, count, releaseList.Length())
}
func TestViewReleases(t *testing.T) {
@@ -68,9 +67,6 @@ func TestViewReleases(t *testing.T) {
session := loginUser(t, "user2")
req := NewRequest(t, "GET", "/user2/repo1/releases")
session.MakeRequest(t, req, http.StatusOK)
-
- // if CI is to slow this test fail, so lets wait a bit
- time.Sleep(time.Millisecond * 100)
}
func TestViewReleasesNoLogin(t *testing.T) {
@@ -118,7 +114,7 @@ func TestCreateReleasePaging(t *testing.T) {
session := loginUser(t, "user2")
// Create enough releases to have paging
- for i := 0; i < 12; i++ {
+ for i := range 12 {
version := fmt.Sprintf("v0.0.%d", i)
createNewRelease(t, session, "/user2/repo1", version, version, false, false)
}
@@ -157,14 +153,14 @@ func TestViewReleaseListNoLogin(t *testing.T) {
commitsToMain = append(commitsToMain, s.Find(".ahead > a").Text())
})
- assert.EqualValues(t, []string{
+ assert.Equal(t, []string{
"/user2/repo-release/releases/tag/empty-target-branch",
"/user2/repo-release/releases/tag/non-existing-target-branch",
"/user2/repo-release/releases/tag/v2.0",
"/user2/repo-release/releases/tag/v1.1",
"/user2/repo-release/releases/tag/v1.0",
}, links)
- assert.EqualValues(t, []string{
+ assert.Equal(t, []string{
"1 commits", // like v1.1
"1 commits", // like v1.1
"0 commits",
@@ -182,8 +178,8 @@ func TestViewSingleRelease(t *testing.T) {
htmlDoc := NewHTMLParser(t, resp.Body)
// check the "number of commits to main since this release"
releaseList := htmlDoc.doc.Find("#release-list .ahead > a")
- assert.EqualValues(t, 1, releaseList.Length())
- assert.EqualValues(t, "3 commits", releaseList.First().Text())
+ assert.Equal(t, 1, releaseList.Length())
+ assert.Equal(t, "3 commits", releaseList.First().Text())
})
t.Run("Login", func(t *testing.T) {
session := loginUser(t, "user1")
@@ -218,7 +214,7 @@ func TestViewReleaseListLogin(t *testing.T) {
links = append(links, link)
})
- assert.EqualValues(t, []string{
+ assert.Equal(t, []string{
"/user2/repo1/releases/tag/draft-release",
"/user2/repo1/releases/tag/v1.0",
"/user2/repo1/releases/tag/v1.1",
@@ -245,7 +241,7 @@ func TestViewTagsList(t *testing.T) {
tagNames = append(tagNames, s.Text())
})
- assert.EqualValues(t, []string{"v1.0", "delete-tag", "v1.1"}, tagNames)
+ assert.Equal(t, []string{"v1.0", "delete-tag", "v1.1"}, tagNames)
}
func TestDownloadReleaseAttachment(t *testing.T) {
diff --git a/tests/integration/rename_branch_test.go b/tests/integration/rename_branch_test.go
index 576264ba95..492fdf781b 100644
--- a/tests/integration/rename_branch_test.go
+++ b/tests/integration/rename_branch_test.go
@@ -11,7 +11,6 @@ import (
git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
- gitea_context "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
@@ -82,9 +81,8 @@ func testRenameBranch(t *testing.T, u *url.URL) {
"to": "branch1",
})
session.MakeRequest(t, req, http.StatusSeeOther)
- flashCookie := session.GetCookie(gitea_context.CookieNameFlash)
- assert.NotNil(t, flashCookie)
- assert.Contains(t, flashCookie.Value, "error")
+ flashMsg := session.GetCookieFlashMessage()
+ assert.NotEmpty(t, flashMsg.ErrorMsg)
branch2 = unittest.AssertExistsAndLoadBean(t, &git_model.Branch{RepoID: repo1.ID, Name: "branch2"})
assert.Equal(t, "branch2", branch2.Name)
@@ -110,9 +108,8 @@ func testRenameBranch(t *testing.T, u *url.URL) {
})
session.MakeRequest(t, req, http.StatusSeeOther)
- flashCookie = session.GetCookie(gitea_context.CookieNameFlash)
- assert.NotNil(t, flashCookie)
- assert.Contains(t, flashCookie.Value, "success")
+ flashMsg = session.GetCookieFlashMessage()
+ assert.NotEmpty(t, flashMsg.SuccessMsg)
unittest.AssertNotExistsBean(t, &git_model.Branch{RepoID: repo1.ID, Name: "branch2"})
branch1 = unittest.AssertExistsAndLoadBean(t, &git_model.Branch{RepoID: repo1.ID, Name: "branch1"})
diff --git a/tests/integration/repo_activity_test.go b/tests/integration/repo_activity_test.go
index b04560379d..d5025decba 100644
--- a/tests/integration/repo_activity_test.go
+++ b/tests/integration/repo_activity_test.go
@@ -9,7 +9,9 @@ import (
"strings"
"testing"
+ "code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/test"
"github.com/stretchr/testify/assert"
@@ -24,7 +26,7 @@ func TestRepoActivity(t *testing.T) {
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
resp := testPullCreate(t, session, "user1", "repo1", false, "master", "master", "This is a pull title")
elem := strings.Split(test.RedirectURL(resp), "/")
- assert.EqualValues(t, "pulls", elem[3])
+ assert.Equal(t, "pulls", elem[3])
testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleMerge, false)
testEditFileToNewBranch(t, session, "user1", "repo1", "master", "feat/better_readme", "README.md", "Hello, World (Edited Again)\n")
@@ -61,5 +63,14 @@ func TestRepoActivity(t *testing.T) {
// Should be 3 new issues
list = htmlDoc.doc.Find("#new-issues").Next().Find("p.desc")
assert.Len(t, list.Nodes, 3)
+
+ // Non-existing default branch
+ repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: "repo1"})
+ repo1.DefaultBranch = "no-such-branch"
+ _, _ = db.GetEngine(t.Context()).Cols("default_branch").Update(repo1)
+ req = NewRequest(t, "GET", "/user2/repo1/activity")
+ req.Header.Add("Accept", "text/html")
+ resp = session.MakeRequest(t, req, http.StatusNotFound)
+ assert.Contains(t, resp.Body.String(), `Default branch "no-such-branch" does not exist.`)
})
}
diff --git a/tests/integration/repo_branch_test.go b/tests/integration/repo_branch_test.go
index f9cf13112a..50ceb65330 100644
--- a/tests/integration/repo_branch_test.go
+++ b/tests/integration/repo_branch_test.go
@@ -138,7 +138,7 @@ func TestCreateBranchInvalidCSRF(t *testing.T) {
}
func prepareRecentlyPushedBranchTest(t *testing.T, headSession *TestSession, baseRepo, headRepo *repo_model.Repository) {
- refSubURL := fmt.Sprintf("branch/%s", headRepo.DefaultBranch)
+ refSubURL := "branch/" + headRepo.DefaultBranch
baseRepoPath := baseRepo.OwnerName + "/" + baseRepo.Name
headRepoPath := headRepo.OwnerName + "/" + headRepo.Name
// Case 1: Normal branch changeset to display pushed message
@@ -168,7 +168,7 @@ func prepareRecentlyPushedBranchTest(t *testing.T, headSession *TestSession, bas
}
func prepareRecentlyPushedBranchSpecialTest(t *testing.T, session *TestSession, baseRepo, headRepo *repo_model.Repository) {
- refSubURL := fmt.Sprintf("branch/%s", headRepo.DefaultBranch)
+ refSubURL := "branch/" + headRepo.DefaultBranch
baseRepoPath := baseRepo.OwnerName + "/" + baseRepo.Name
headRepoPath := headRepo.OwnerName + "/" + headRepo.Name
// create branch with no new commit
@@ -196,7 +196,7 @@ func testCreatePullToDefaultBranch(t *testing.T, session *TestSession, baseRepo,
}
func prepareRepoPR(t *testing.T, baseSession, headSession *TestSession, baseRepo, headRepo *repo_model.Repository) {
- refSubURL := fmt.Sprintf("branch/%s", headRepo.DefaultBranch)
+ refSubURL := "branch/" + headRepo.DefaultBranch
testCreateBranch(t, headSession, headRepo.OwnerName, headRepo.Name, refSubURL, "new-commit", http.StatusSeeOther)
// create opening PR
diff --git a/tests/integration/repo_commits_search_test.go b/tests/integration/repo_commits_search_test.go
index 74ac25c0f5..9b05e36399 100644
--- a/tests/integration/repo_commits_search_test.go
+++ b/tests/integration/repo_commits_search_test.go
@@ -23,7 +23,7 @@ func testRepoCommitsSearch(t *testing.T, query, commit string) {
doc := NewHTMLParser(t, resp.Body)
sel := doc.doc.Find("#commits-table tbody tr td.sha a")
- assert.EqualValues(t, commit, strings.TrimSpace(sel.Text()))
+ assert.Equal(t, commit, strings.TrimSpace(sel.Text()))
}
func TestRepoCommitsSearch(t *testing.T) {
diff --git a/tests/integration/repo_commits_test.go b/tests/integration/repo_commits_test.go
index fc066e06d3..0097a7f62e 100644
--- a/tests/integration/repo_commits_test.go
+++ b/tests/integration/repo_commits_test.go
@@ -12,11 +12,13 @@ import (
"testing"
auth_model "code.gitea.io/gitea/models/auth"
+ "code.gitea.io/gitea/modules/commitstatus"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/tests"
+ "github.com/PuerkitoBio/goquery"
"github.com/stretchr/testify/assert"
)
@@ -35,6 +37,28 @@ func TestRepoCommits(t *testing.T) {
assert.NotEmpty(t, commitURL)
}
+func Test_ReposGitCommitListNotMaster(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+ session := loginUser(t, "user2")
+ req := NewRequest(t, "GET", "/user2/repo16/commits/branch/master")
+ resp := session.MakeRequest(t, req, http.StatusOK)
+
+ doc := NewHTMLParser(t, resp.Body)
+ var commits []string
+ doc.doc.Find("#commits-table .commit-id-short").Each(func(i int, s *goquery.Selection) {
+ commitURL, _ := s.Attr("href")
+ commits = append(commits, path.Base(commitURL))
+ })
+ assert.Equal(t, []string{"69554a64c1e6030f051e5c3f94bfbd773cd6a324", "27566bd5738fc8b4e3fef3c5e72cce608537bd95", "5099b81332712fe655e34e8dd63574f503f61811"}, commits)
+
+ var userHrefs []string
+ doc.doc.Find("#commits-table .author-wrapper").Each(func(i int, s *goquery.Selection) {
+ userHref, _ := s.Attr("href")
+ userHrefs = append(userHrefs, userHref)
+ })
+ assert.Equal(t, []string{"/user2", "/user21", "/user2"}, userHrefs)
+}
+
func doTestRepoCommitWithStatus(t *testing.T, state string, classes ...string) {
defer tests.PrepareTestEnv(t)()
@@ -53,7 +77,7 @@ func doTestRepoCommitWithStatus(t *testing.T, state string, classes ...string) {
// Call API to add status for commit
ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository)
t.Run("CreateStatus", doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
- State: api.CommitStatusState(state),
+ State: commitstatus.CommitStatusState(state),
TargetURL: "http://test.ci/",
Description: "",
Context: "testci",
@@ -97,10 +121,10 @@ func testRepoCommitsWithStatus(t *testing.T, resp, respOne *httptest.ResponseRec
assert.NotNil(t, status)
if assert.Len(t, statuses, 1) {
- assert.Equal(t, api.CommitStatusState(state), statuses[0].State)
+ assert.Equal(t, commitstatus.CommitStatusState(state), statuses[0].State)
assert.Equal(t, setting.AppURL+"api/v1/repos/user2/repo1/statuses/65f1bf27bc3bf70f64657658635e66094edbcb4d", statuses[0].URL)
assert.Equal(t, "http://test.ci/", statuses[0].TargetURL)
- assert.Equal(t, "", statuses[0].Description)
+ assert.Empty(t, statuses[0].Description)
assert.Equal(t, "testci", statuses[0].Context)
assert.Len(t, status.Statuses, 1)
@@ -145,13 +169,13 @@ func TestRepoCommitsStatusParallel(t *testing.T) {
assert.NotEmpty(t, commitURL)
var wg sync.WaitGroup
- for i := 0; i < 10; i++ {
+ for i := range 10 {
wg.Add(1)
go func(parentT *testing.T, i int) {
parentT.Run(fmt.Sprintf("ParallelCreateStatus_%d", i), func(t *testing.T) {
ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository)
runBody := doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
- State: api.CommitStatusPending,
+ State: commitstatus.CommitStatusPending,
TargetURL: "http://test.ci/",
Description: "",
Context: "testci",
@@ -182,14 +206,14 @@ func TestRepoCommitsStatusMultiple(t *testing.T) {
// Call API to add status for commit
ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository)
t.Run("CreateStatus", doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
- State: api.CommitStatusSuccess,
+ State: commitstatus.CommitStatusSuccess,
TargetURL: "http://test.ci/",
Description: "",
Context: "testci",
}))
t.Run("CreateStatus", doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
- State: api.CommitStatusSuccess,
+ State: commitstatus.CommitStatusSuccess,
TargetURL: "http://test.ci/",
Description: "",
Context: "other_context",
@@ -199,7 +223,7 @@ func TestRepoCommitsStatusMultiple(t *testing.T) {
resp = session.MakeRequest(t, req, http.StatusOK)
doc = NewHTMLParser(t, resp.Body)
- // Check that the data-tippy="commit-statuses" (for trigger) and commit-status (svg) are present
- sel := doc.doc.Find("#commits-table .message [data-tippy=\"commit-statuses\"] .commit-status")
+ // Check that the data-global-init="initCommitStatuses" (for trigger) and commit-status (svg) are present
+ sel := doc.doc.Find(`#commits-table .message [data-global-init="initCommitStatuses"] .commit-status`)
assert.Equal(t, 1, sel.Length())
}
diff --git a/tests/integration/repo_fork_test.go b/tests/integration/repo_fork_test.go
index 267fd0d56e..95325eefeb 100644
--- a/tests/integration/repo_fork_test.go
+++ b/tests/integration/repo_fork_test.go
@@ -7,6 +7,7 @@ import (
"fmt"
"net/http"
"net/http/httptest"
+ "strconv"
"testing"
"code.gitea.io/gitea/models/db"
@@ -14,6 +15,7 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/test"
org_service "code.gitea.io/gitea/services/org"
"code.gitea.io/gitea/tests"
@@ -46,11 +48,12 @@ func testRepoFork(t *testing.T, session *TestSession, ownerName, repoName, forkO
assert.True(t, exists, "Fork owner '%s' is not present in select box", forkOwnerName)
req = NewRequestWithValues(t, "POST", link, map[string]string{
"_csrf": htmlDoc.GetCSRF(),
- "uid": fmt.Sprintf("%d", forkOwner.ID),
+ "uid": strconv.FormatInt(forkOwner.ID, 10),
"repo_name": forkRepoName,
"fork_single_branch": forkBranch,
})
- session.MakeRequest(t, req, http.StatusSeeOther)
+ resp = session.MakeRequest(t, req, http.StatusOK)
+ assert.Equal(t, fmt.Sprintf("/%s/%s", forkOwnerName, forkRepoName), test.RedirectURL(resp))
// Step4: check the existence of the forked repo
req = NewRequestf(t, "GET", "/%s/%s", forkOwnerName, forkRepoName)
@@ -81,14 +84,14 @@ func TestRepoForkToOrg(t *testing.T) {
func TestForkListLimitedAndPrivateRepos(t *testing.T) {
defer tests.PrepareTestEnv(t)()
- forkItemSelector := ".repo-fork-item"
+ forkItemSelector := ".fork-list .flex-item"
user1Sess := loginUser(t, "user1")
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user1"})
// fork to a limited org
limitedOrg := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 22})
- assert.EqualValues(t, structs.VisibleTypeLimited, limitedOrg.Visibility)
+ assert.Equal(t, structs.VisibleTypeLimited, limitedOrg.Visibility)
ownerTeam1, err := org_model.OrgFromUser(limitedOrg).GetOwnerTeam(db.DefaultContext)
assert.NoError(t, err)
assert.NoError(t, org_service.AddTeamMember(db.DefaultContext, ownerTeam1, user1))
@@ -98,7 +101,7 @@ func TestForkListLimitedAndPrivateRepos(t *testing.T) {
user4Sess := loginUser(t, "user4")
user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user4"})
privateOrg := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 23})
- assert.EqualValues(t, structs.VisibleTypePrivate, privateOrg.Visibility)
+ assert.Equal(t, structs.VisibleTypePrivate, privateOrg.Visibility)
ownerTeam2, err := org_model.OrgFromUser(privateOrg).GetOwnerTeam(db.DefaultContext)
assert.NoError(t, err)
assert.NoError(t, org_service.AddTeamMember(db.DefaultContext, ownerTeam2, user4))
@@ -109,7 +112,7 @@ func TestForkListLimitedAndPrivateRepos(t *testing.T) {
req := NewRequest(t, "GET", "/user2/repo1/forks")
resp := MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
- assert.EqualValues(t, 0, htmlDoc.Find(forkItemSelector).Length())
+ assert.Equal(t, 0, htmlDoc.Find(forkItemSelector).Length())
})
t.Run("Logged in", func(t *testing.T) {
@@ -118,11 +121,12 @@ func TestForkListLimitedAndPrivateRepos(t *testing.T) {
req := NewRequest(t, "GET", "/user2/repo1/forks")
resp := user1Sess.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
- assert.EqualValues(t, 1, htmlDoc.Find(forkItemSelector).Length())
+ // since user1 is an admin, he can get both of the forked repositories
+ assert.Equal(t, 2, htmlDoc.Find(forkItemSelector).Length())
assert.NoError(t, org_service.AddTeamMember(db.DefaultContext, ownerTeam2, user1))
resp = user1Sess.MakeRequest(t, req, http.StatusOK)
htmlDoc = NewHTMLParser(t, resp.Body)
- assert.EqualValues(t, 2, htmlDoc.Find(forkItemSelector).Length())
+ assert.Equal(t, 2, htmlDoc.Find(forkItemSelector).Length())
})
}
diff --git a/tests/integration/repo_generate_test.go b/tests/integration/repo_generate_test.go
index ff2aa220d3..fca4e92982 100644
--- a/tests/integration/repo_generate_test.go
+++ b/tests/integration/repo_generate_test.go
@@ -7,6 +7,7 @@ import (
"fmt"
"net/http"
"net/http/httptest"
+ "strconv"
"strings"
"testing"
@@ -31,20 +32,20 @@ func testRepoGenerate(t *testing.T, session *TestSession, templateID, templateOw
// Step2: click the "Use this template" button
htmlDoc := NewHTMLParser(t, resp.Body)
- link, exists := htmlDoc.doc.Find("a.ui.button[href^=\"/repo/create\"]").Attr("href")
+ link, exists := htmlDoc.doc.Find(`a.ui.button[href^="/repo/create"]`).Attr("href")
assert.True(t, exists, "The template has changed")
req = NewRequest(t, "GET", link)
resp = session.MakeRequest(t, req, http.StatusOK)
- // Step3: fill the form of the create
+ // Step3: fill the form on the "create" page
htmlDoc = NewHTMLParser(t, resp.Body)
- link, exists = htmlDoc.doc.Find("form.ui.form[action^=\"/repo/create\"]").Attr("action")
+ link, exists = htmlDoc.doc.Find(`form.ui.form[action^="/repo/create"]`).Attr("action")
assert.True(t, exists, "The template has changed")
- _, exists = htmlDoc.doc.Find(fmt.Sprintf(".owner.dropdown .item[data-value=\"%d\"]", generateOwner.ID)).Attr("data-value")
+ _, exists = htmlDoc.doc.Find(fmt.Sprintf(`#repo_owner_dropdown .item[data-value="%d"]`, generateOwner.ID)).Attr("data-value")
assert.True(t, exists, "Generate owner '%s' is not present in select box", generateOwnerName)
req = NewRequestWithValues(t, "POST", link, map[string]string{
"_csrf": htmlDoc.GetCSRF(),
- "uid": fmt.Sprintf("%d", generateOwner.ID),
+ "uid": strconv.FormatInt(generateOwner.ID, 10),
"repo_name": generateRepoName,
"repo_template": templateID,
"git_content": "true",
diff --git a/tests/integration/repo_merge_upstream_test.go b/tests/integration/repo_merge_upstream_test.go
index e3e423c51d..d33d31c646 100644
--- a/tests/integration/repo_merge_upstream_test.go
+++ b/tests/integration/repo_merge_upstream_test.go
@@ -60,25 +60,54 @@ func TestRepoMergeUpstream(t *testing.T) {
t.Run("HeadBeforeBase", func(t *testing.T) {
// add a file in base repo
+ sessionBaseUser := loginUser(t, baseUser.Name)
require.NoError(t, createOrReplaceFileInBranch(baseUser, baseRepo, "new-file.txt", "master", "test-content-1"))
- // the repo shows a prompt to "sync fork"
var mergeUpstreamLink string
- require.Eventually(t, func() bool {
- resp := session.MakeRequest(t, NewRequestf(t, "GET", "/%s/test-repo-fork/src/branch/fork-branch", forkUser.Name), http.StatusOK)
- htmlDoc := NewHTMLParser(t, resp.Body)
- mergeUpstreamLink = queryMergeUpstreamButtonLink(htmlDoc)
- if mergeUpstreamLink == "" {
- return false
- }
- respMsg, _ := htmlDoc.Find(".ui.message:not(.positive)").Html()
- return strings.Contains(respMsg, `This branch is 1 commit behind <a href="/user2/repo1/src/branch/master">user2/repo1:master</a>`)
- }, 5*time.Second, 100*time.Millisecond)
+ t.Run("DetectDefaultBranch", func(t *testing.T) {
+ // the repo shows a prompt to "sync fork" (defaults to the default branch)
+ require.Eventually(t, func() bool {
+ resp := session.MakeRequest(t, NewRequestf(t, "GET", "/%s/test-repo-fork/src/branch/fork-branch", forkUser.Name), http.StatusOK)
+ htmlDoc := NewHTMLParser(t, resp.Body)
+ mergeUpstreamLink = queryMergeUpstreamButtonLink(htmlDoc)
+ if mergeUpstreamLink == "" {
+ return false
+ }
+ respMsg, _ := htmlDoc.Find(".ui.message:not(.positive)").Html()
+ return strings.Contains(respMsg, `This branch is 1 commit behind <a href="/user2/repo1/src/branch/master">user2/repo1:master</a>`)
+ }, 5*time.Second, 100*time.Millisecond)
+ })
+
+ t.Run("DetectSameBranch", func(t *testing.T) {
+ // if the fork-branch name also exists in the base repo, then use that branch instead
+ req = NewRequestWithValues(t, "POST", "/user2/repo1/branches/_new/branch/master", map[string]string{
+ "_csrf": GetUserCSRFToken(t, sessionBaseUser),
+ "new_branch_name": "fork-branch",
+ })
+ sessionBaseUser.MakeRequest(t, req, http.StatusSeeOther)
+
+ require.Eventually(t, func() bool {
+ resp := session.MakeRequest(t, NewRequestf(t, "GET", "/%s/test-repo-fork/src/branch/fork-branch", forkUser.Name), http.StatusOK)
+ htmlDoc := NewHTMLParser(t, resp.Body)
+ mergeUpstreamLink = queryMergeUpstreamButtonLink(htmlDoc)
+ if mergeUpstreamLink == "" {
+ return false
+ }
+ respMsg, _ := htmlDoc.Find(".ui.message:not(.positive)").Html()
+ return strings.Contains(respMsg, `This branch is 1 commit behind <a href="/user2/repo1/src/branch/fork-branch">user2/repo1:fork-branch</a>`)
+ }, 5*time.Second, 100*time.Millisecond)
+ })
// click the "sync fork" button
req = NewRequestWithValues(t, "POST", mergeUpstreamLink, map[string]string{"_csrf": GetUserCSRFToken(t, session)})
session.MakeRequest(t, req, http.StatusOK)
checkFileContent("fork-branch", "test-content-1")
+
+ // delete the "fork-branch" from the base repo
+ req = NewRequestWithValues(t, "POST", "/user2/repo1/branches/delete?name=fork-branch", map[string]string{
+ "_csrf": GetUserCSRFToken(t, sessionBaseUser),
+ })
+ sessionBaseUser.MakeRequest(t, req, http.StatusOK)
})
t.Run("BaseChangeAfterHeadChange", func(t *testing.T) {
@@ -118,5 +147,37 @@ func TestRepoMergeUpstream(t *testing.T) {
return queryMergeUpstreamButtonLink(htmlDoc) == ""
}, 5*time.Second, 100*time.Millisecond)
})
+
+ t.Run("FastForwardOnly", func(t *testing.T) {
+ // Create a clean branch for fast-forward testing
+ req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/test-repo-fork/branches/_new/branch/master", forkUser.Name), map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ "new_branch_name": "ff-test-branch",
+ })
+ session.MakeRequest(t, req, http.StatusSeeOther)
+
+ // Add content to base repository that can be fast-forwarded
+ require.NoError(t, createOrReplaceFileInBranch(baseUser, baseRepo, "ff-test.txt", "master", "ff-content-1"))
+
+ // ff_only=true with fast-forward possible (should succeed)
+ req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/test-repo-fork/merge-upstream", forkUser.Name), &api.MergeUpstreamRequest{
+ Branch: "ff-test-branch",
+ FfOnly: true,
+ }).AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+
+ var mergeResp api.MergeUpstreamResponse
+ DecodeJSON(t, resp, &mergeResp)
+ assert.Equal(t, "fast-forward", mergeResp.MergeStyle)
+
+ // ff_only=true when fast-forward is not possible (should fail)
+ require.NoError(t, createOrReplaceFileInBranch(baseUser, baseRepo, "another-file.txt", "master", "more-content"))
+
+ req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/test-repo-fork/merge-upstream", forkUser.Name), &api.MergeUpstreamRequest{
+ Branch: "fork-branch",
+ FfOnly: true,
+ }).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusBadRequest)
+ })
})
}
diff --git a/tests/integration/repo_mergecommit_revert_test.go b/tests/integration/repo_mergecommit_revert_test.go
deleted file mode 100644
index 103fb47e2b..0000000000
--- a/tests/integration/repo_mergecommit_revert_test.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2024 The Gitea Authors. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-package integration
-
-import (
- "net/http"
- "testing"
-
- "code.gitea.io/gitea/tests"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestRepoMergeCommitRevert(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
- session := loginUser(t, "user2")
-
- req := NewRequest(t, "GET", "/user2/test_commit_revert/_cherrypick/deebcbc752e540bab4ce3ee713d3fc8fdc35b2f7/main?ref=main&refType=branch&cherry-pick-type=revert")
- resp := session.MakeRequest(t, req, http.StatusOK)
-
- htmlDoc := NewHTMLParser(t, resp.Body)
- req = NewRequestWithValues(t, "POST", "/user2/test_commit_revert/_cherrypick/deebcbc752e540bab4ce3ee713d3fc8fdc35b2f7/main", map[string]string{
- "_csrf": htmlDoc.GetCSRF(),
- "last_commit": "deebcbc752e540bab4ce3ee713d3fc8fdc35b2f7",
- "page_has_posted": "true",
- "revert": "true",
- "commit_summary": "reverting test commit",
- "commit_message": "test message",
- "commit_choice": "direct",
- "new_branch_name": "test-revert-branch-1",
- })
- resp = session.MakeRequest(t, req, http.StatusSeeOther)
-
- // A successful revert redirects to the main branch
- assert.EqualValues(t, "/user2/test_commit_revert/src/branch/main", resp.Header().Get("Location"))
-}
diff --git a/tests/integration/repo_search_test.go b/tests/integration/repo_search_test.go
index 29d1517f4e..36a2e81f3b 100644
--- a/tests/integration/repo_search_test.go
+++ b/tests/integration/repo_search_test.go
@@ -57,5 +57,5 @@ func testSearch(t *testing.T, url string, expected []string) {
resp := MakeRequest(t, req, http.StatusOK)
filenames := resultFilenames(NewHTMLParser(t, resp.Body))
- assert.EqualValues(t, expected, filenames)
+ assert.Equal(t, expected, filenames)
}
diff --git a/tests/integration/repo_tag_test.go b/tests/integration/repo_tag_test.go
index 5638826ea0..8ea7508559 100644
--- a/tests/integration/repo_tag_test.go
+++ b/tests/integration/repo_tag_test.go
@@ -55,10 +55,10 @@ func TestCreateNewTagProtected(t *testing.T) {
doGitClone(dstPath, u)(t)
- _, _, err := git.NewCommand(git.DefaultContext, "tag", "v-2").RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err := git.NewCommand("tag", "v-2").RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
- _, _, err = git.NewCommand(git.DefaultContext, "push", "--tags").RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err = git.NewCommand("push", "--tags").RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.Error(t, err)
assert.Contains(t, err.Error(), "Tag v-2 is protected")
})
@@ -75,20 +75,20 @@ func TestCreateNewTagProtected(t *testing.T) {
doGitClone(dstPath, u)(t)
- _, _, err := git.NewCommand(git.DefaultContext, "tag", "v-1.1", "-m", "force update", "--force").RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err := git.NewCommand("tag", "v-1.1", "-m", "force update", "--force").RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
require.NoError(t, err)
- _, _, err = git.NewCommand(git.DefaultContext, "push", "--tags").RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err = git.NewCommand("push", "--tags").RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
require.NoError(t, err)
- _, _, err = git.NewCommand(git.DefaultContext, "tag", "v-1.1", "-m", "force update v2", "--force").RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err = git.NewCommand("tag", "v-1.1", "-m", "force update v2", "--force").RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
require.NoError(t, err)
- _, _, err = git.NewCommand(git.DefaultContext, "push", "--tags").RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err = git.NewCommand("push", "--tags").RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
require.Error(t, err)
assert.Contains(t, err.Error(), "the tag already exists in the remote")
- _, _, err = git.NewCommand(git.DefaultContext, "push", "--tags", "--force").RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err = git.NewCommand("push", "--tags", "--force").RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
require.NoError(t, err)
req := NewRequestf(t, "GET", "/%s/releases/tag/v-1.1", repo.FullName())
resp := MakeRequest(t, req, http.StatusOK)
@@ -137,15 +137,15 @@ func TestRepushTag(t *testing.T) {
doGitClone(dstPath, u)(t)
// create and push a tag
- _, _, err := git.NewCommand(git.DefaultContext, "tag", "v2.0").RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err := git.NewCommand("tag", "v2.0").RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
- _, _, err = git.NewCommand(git.DefaultContext, "push", "origin", "--tags", "v2.0").RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err = git.NewCommand("push", "origin", "--tags", "v2.0").RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
// create a release for the tag
createdRelease := createNewReleaseUsingAPI(t, token, owner, repo, "v2.0", "", "Release of v2.0", "desc")
assert.False(t, createdRelease.IsDraft)
// delete the tag
- _, _, err = git.NewCommand(git.DefaultContext, "push", "origin", "--delete", "v2.0").RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err = git.NewCommand("push", "origin", "--delete", "v2.0").RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
// query the release by API and it should be a draft
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/%s", owner.Name, repo.Name, "v2.0"))
@@ -154,7 +154,7 @@ func TestRepushTag(t *testing.T) {
DecodeJSON(t, resp, &respRelease)
assert.True(t, respRelease.IsDraft)
// re-push the tag
- _, _, err = git.NewCommand(git.DefaultContext, "push", "origin", "--tags", "v2.0").RunStdString(&git.RunOpts{Dir: dstPath})
+ _, _, err = git.NewCommand("push", "origin", "--tags", "v2.0").RunStdString(git.DefaultContext, &git.RunOpts{Dir: dstPath})
assert.NoError(t, err)
// query the release by API and it should not be a draft
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/%s", owner.Name, repo.Name, "v2.0"))
diff --git a/tests/integration/repo_test.go b/tests/integration/repo_test.go
index 8c568a1272..adfe07519f 100644
--- a/tests/integration/repo_test.go
+++ b/tests/integration/repo_test.go
@@ -6,21 +6,51 @@ package integration
import (
"fmt"
"net/http"
+ "os"
"path"
+ "strconv"
"strings"
"testing"
"time"
+ "code.gitea.io/gitea/models/db"
+ repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unit"
+ "code.gitea.io/gitea/models/unittest"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
+ "code.gitea.io/gitea/modules/util"
+ repo_service "code.gitea.io/gitea/services/repository"
"code.gitea.io/gitea/tests"
"github.com/PuerkitoBio/goquery"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
-func TestViewRepo(t *testing.T) {
+func TestRepoView(t *testing.T) {
defer tests.PrepareTestEnv(t)()
+ t.Run("ViewRepoPublic", testViewRepoPublic)
+ t.Run("ViewRepoWithCache", testViewRepoWithCache)
+ t.Run("ViewRepoPrivate", testViewRepoPrivate)
+ t.Run("ViewRepo1CloneLinkAnonymous", testViewRepo1CloneLinkAnonymous)
+ t.Run("ViewRepo1CloneLinkAuthorized", testViewRepo1CloneLinkAuthorized)
+ t.Run("ViewRepoWithSymlinks", testViewRepoWithSymlinks)
+ t.Run("ViewFileInRepo", testViewFileInRepo)
+ t.Run("BlameFileInRepo", testBlameFileInRepo)
+ t.Run("ViewRepoDirectory", testViewRepoDirectory)
+ t.Run("ViewRepoDirectoryReadme", testViewRepoDirectoryReadme)
+ t.Run("ViewRepoSymlink", testViewRepoSymlink)
+ t.Run("MarkDownReadmeImage", testMarkDownReadmeImage)
+ t.Run("MarkDownReadmeImageSubfolder", testMarkDownReadmeImageSubfolder)
+ t.Run("GeneratedSourceLink", testGeneratedSourceLink)
+ t.Run("ViewCommit", testViewCommit)
+}
+
+func testViewRepoPublic(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
session := loginUser(t, "user2")
@@ -41,87 +71,118 @@ func TestViewRepo(t *testing.T) {
session.MakeRequest(t, req, http.StatusNotFound)
}
-func testViewRepo(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
-
- req := NewRequest(t, "GET", "/org3/repo3")
- session := loginUser(t, "user2")
- resp := session.MakeRequest(t, req, http.StatusOK)
-
- htmlDoc := NewHTMLParser(t, resp.Body)
- files := htmlDoc.doc.Find("#repo-files-table .repo-file-item")
-
- type file struct {
- fileName string
- commitID string
- commitMsg string
- commitTime string
- }
+func testViewRepoWithCache(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+ testView := func(t *testing.T) {
+ req := NewRequest(t, "GET", "/org3/repo3")
+ session := loginUser(t, "user2")
+ resp := session.MakeRequest(t, req, http.StatusOK)
- var items []file
-
- files.Each(func(i int, s *goquery.Selection) {
- tds := s.Find(".repo-file-cell")
- var f file
- tds.Each(func(i int, s *goquery.Selection) {
- if i == 0 {
- f.fileName = strings.TrimSpace(s.Text())
- } else if i == 1 {
- a := s.Find("a")
- f.commitMsg = strings.TrimSpace(a.Text())
- l, _ := a.Attr("href")
- f.commitID = path.Base(l)
- }
+ htmlDoc := NewHTMLParser(t, resp.Body)
+ files := htmlDoc.doc.Find("#repo-files-table .repo-file-item")
+
+ type file struct {
+ fileName string
+ commitID string
+ commitMsg string
+ commitTime string
+ }
+
+ var items []file
+
+ files.Each(func(i int, s *goquery.Selection) {
+ tds := s.Find(".repo-file-cell")
+ var f file
+ tds.Each(func(i int, s *goquery.Selection) {
+ if i == 0 {
+ f.fileName = strings.TrimSpace(s.Text())
+ } else if i == 1 {
+ a := s.Find("a")
+ f.commitMsg = strings.TrimSpace(a.Text())
+ l, _ := a.Attr("href")
+ f.commitID = path.Base(l)
+ }
+ })
+
+ // convert "2017-06-14 21:54:21 +0800" to "Wed, 14 Jun 2017 13:54:21 UTC"
+ htmlTimeString, _ := s.Find("relative-time").Attr("datetime")
+ htmlTime, _ := time.Parse(time.RFC3339, htmlTimeString)
+ f.commitTime = htmlTime.In(time.Local).Format(time.RFC1123)
+ items = append(items, f)
})
- // convert "2017-06-14 21:54:21 +0800" to "Wed, 14 Jun 2017 13:54:21 UTC"
- htmlTimeString, _ := s.Find("relative-time").Attr("datetime")
- htmlTime, _ := time.Parse(time.RFC3339, htmlTimeString)
- f.commitTime = htmlTime.In(time.Local).Format(time.RFC1123)
- items = append(items, f)
- })
-
- commitT := time.Date(2017, time.June, 14, 13, 54, 21, 0, time.UTC).In(time.Local).Format(time.RFC1123)
- assert.EqualValues(t, []file{
- {
- fileName: "doc",
- commitID: "2a47ca4b614a9f5a43abbd5ad851a54a616ffee6",
- commitMsg: "init project",
- commitTime: commitT,
- },
- {
- fileName: "README.md",
- commitID: "2a47ca4b614a9f5a43abbd5ad851a54a616ffee6",
- commitMsg: "init project",
- commitTime: commitT,
- },
- }, items)
-}
+ commitT := time.Date(2017, time.June, 14, 13, 54, 21, 0, time.UTC).In(time.Local).Format(time.RFC1123)
+ assert.Equal(t, []file{
+ {
+ fileName: "doc",
+ commitID: "2a47ca4b614a9f5a43abbd5ad851a54a616ffee6",
+ commitMsg: "init project",
+ commitTime: commitT,
+ },
+ {
+ fileName: "README.md",
+ commitID: "2a47ca4b614a9f5a43abbd5ad851a54a616ffee6",
+ commitMsg: "init project",
+ commitTime: commitT,
+ },
+ }, items)
+ }
-func TestViewRepo2(t *testing.T) {
+ // FIXME: these test don't seem quite right, no enough assert
// no last commit cache
- testViewRepo(t)
-
+ testView(t)
// enable last commit cache for all repositories
oldCommitsCount := setting.CacheService.LastCommit.CommitsCount
setting.CacheService.LastCommit.CommitsCount = 0
// first view will not hit the cache
- testViewRepo(t)
+ testView(t)
// second view will hit the cache
- testViewRepo(t)
+ testView(t)
setting.CacheService.LastCommit.CommitsCount = oldCommitsCount
}
-func TestViewRepo3(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
+func testViewRepoPrivate(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", "/org3/repo3")
- session := loginUser(t, "user4")
- session.MakeRequest(t, req, http.StatusOK)
+ MakeRequest(t, req, http.StatusNotFound)
+
+ t.Run("OrgMemberAccess", func(t *testing.T) {
+ req = NewRequest(t, "GET", "/org3/repo3")
+ session := loginUser(t, "user4")
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ assert.Contains(t, resp.Body.String(), `<div id="repo-files-table"`)
+ })
+
+ t.Run("PublicAccess-AnonymousAccess", func(t *testing.T) {
+ session := loginUser(t, "user1")
+
+ // set unit code to "anonymous read"
+ req = NewRequestWithValues(t, "POST", "/org3/repo3/settings/public_access", map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ "repo-unit-access-" + strconv.Itoa(int(unit.TypeCode)): "anonymous-read",
+ })
+ session.MakeRequest(t, req, http.StatusSeeOther)
+
+ // try to "anonymous read" (ok)
+ req = NewRequest(t, "GET", "/org3/repo3")
+ resp := MakeRequest(t, req, http.StatusOK)
+ assert.Contains(t, resp.Body.String(), `<span class="ui basic orange label">Public Access</span>`)
+
+ // remove "anonymous read"
+ req = NewRequestWithValues(t, "POST", "/org3/repo3/settings/public_access", map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ })
+ session.MakeRequest(t, req, http.StatusSeeOther)
+
+ // try to "anonymous read" (not found)
+ req = NewRequest(t, "GET", "/org3/repo3")
+ MakeRequest(t, req, http.StatusNotFound)
+ })
}
-func TestViewRepo1CloneLinkAnonymous(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
+func testViewRepo1CloneLinkAnonymous(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", "/user2/repo1")
resp := MakeRequest(t, req, http.StatusOK)
@@ -130,12 +191,17 @@ func TestViewRepo1CloneLinkAnonymous(t *testing.T) {
link, exists := htmlDoc.doc.Find(".repo-clone-https").Attr("data-link")
assert.True(t, exists, "The template has changed")
assert.Equal(t, setting.AppURL+"user2/repo1.git", link)
+
_, exists = htmlDoc.doc.Find(".repo-clone-ssh").Attr("data-link")
assert.False(t, exists)
+
+ link, exists = htmlDoc.doc.Find(".repo-clone-tea").Attr("data-link")
+ assert.True(t, exists, "The template has changed")
+ assert.Equal(t, "tea clone user2/repo1", link)
}
-func TestViewRepo1CloneLinkAuthorized(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
+func testViewRepo1CloneLinkAuthorized(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
session := loginUser(t, "user2")
@@ -146,15 +212,20 @@ func TestViewRepo1CloneLinkAuthorized(t *testing.T) {
link, exists := htmlDoc.doc.Find(".repo-clone-https").Attr("data-link")
assert.True(t, exists, "The template has changed")
assert.Equal(t, setting.AppURL+"user2/repo1.git", link)
+
link, exists = htmlDoc.doc.Find(".repo-clone-ssh").Attr("data-link")
assert.True(t, exists, "The template has changed")
sshURL := fmt.Sprintf("ssh://%s@%s:%d/user2/repo1.git", setting.SSH.User, setting.SSH.Domain, setting.SSH.Port)
assert.Equal(t, sshURL, link)
-}
-func TestViewRepoWithSymlinks(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
+ link, exists = htmlDoc.doc.Find(".repo-clone-tea").Attr("data-link")
+ assert.True(t, exists, "The template has changed")
+ assert.Equal(t, "tea clone user2/repo1", link)
+}
+func testViewRepoWithSymlinks(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+ defer test.MockVariableValue(&setting.UI.FileIconTheme, "basic")()
session := loginUser(t, "user2")
req := NewRequest(t, "GET", "/user2/repo20.git")
@@ -176,8 +247,8 @@ func TestViewRepoWithSymlinks(t *testing.T) {
}
// TestViewFileInRepo repo description, topics and summary should not be displayed when viewing a file
-func TestViewFileInRepo(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
+func testViewFileInRepo(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
session := loginUser(t, "user2")
@@ -189,14 +260,14 @@ func TestViewFileInRepo(t *testing.T) {
repoTopics := htmlDoc.doc.Find("#repo-topics")
repoSummary := htmlDoc.doc.Find(".repository-summary")
- assert.EqualValues(t, 0, description.Length())
- assert.EqualValues(t, 0, repoTopics.Length())
- assert.EqualValues(t, 0, repoSummary.Length())
+ assert.Equal(t, 0, description.Length())
+ assert.Equal(t, 0, repoTopics.Length())
+ assert.Equal(t, 0, repoSummary.Length())
}
// TestBlameFileInRepo repo description, topics and summary should not be displayed when running blame on a file
-func TestBlameFileInRepo(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
+func testBlameFileInRepo(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
session := loginUser(t, "user2")
@@ -208,14 +279,14 @@ func TestBlameFileInRepo(t *testing.T) {
repoTopics := htmlDoc.doc.Find("#repo-topics")
repoSummary := htmlDoc.doc.Find(".repository-summary")
- assert.EqualValues(t, 0, description.Length())
- assert.EqualValues(t, 0, repoTopics.Length())
- assert.EqualValues(t, 0, repoSummary.Length())
+ assert.Equal(t, 0, description.Length())
+ assert.Equal(t, 0, repoTopics.Length())
+ assert.Equal(t, 0, repoSummary.Length())
}
// TestViewRepoDirectory repo description, topics and summary should not be displayed when within a directory
-func TestViewRepoDirectory(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
+func testViewRepoDirectory(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
session := loginUser(t, "user2")
@@ -236,8 +307,8 @@ func TestViewRepoDirectory(t *testing.T) {
}
// ensure that the all the different ways to find and render a README work
-func TestViewRepoDirectoryReadme(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
+func testViewRepoDirectoryReadme(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
// there are many combinations:
// - READMEs can be .md, .txt, or have no extension
@@ -343,8 +414,23 @@ func TestViewRepoDirectoryReadme(t *testing.T) {
missing("symlink-loop", "/user2/readme-test/src/branch/symlink-loop/")
}
-func TestMarkDownReadmeImage(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
+func testViewRepoSymlink(t *testing.T) {
+ session := loginUser(t, "user2")
+ req := NewRequest(t, "GET", "/user2/readme-test/src/branch/symlink")
+ resp := session.MakeRequest(t, req, http.StatusOK)
+
+ htmlDoc := NewHTMLParser(t, resp.Body)
+ AssertHTMLElement(t, htmlDoc, ".entry-symbol-link", true)
+ followSymbolLinkHref := htmlDoc.Find(".entry-symbol-link").AttrOr("href", "")
+ require.Equal(t, "/user2/readme-test/src/branch/symlink/README.md?follow_symlink=1", followSymbolLinkHref)
+
+ req = NewRequest(t, "GET", followSymbolLinkHref)
+ resp = session.MakeRequest(t, req, http.StatusSeeOther)
+ assert.Equal(t, "/user2/readme-test/src/branch/symlink/some/other/path/awefulcake.txt?follow_symlink=1", resp.Header().Get("Location"))
+}
+
+func testMarkDownReadmeImage(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
session := loginUser(t, "user2")
@@ -365,8 +451,8 @@ func TestMarkDownReadmeImage(t *testing.T) {
assert.Equal(t, "/user2/repo1/media/branch/home-md-img-check/test-fake-img.jpg", src)
}
-func TestMarkDownReadmeImageSubfolder(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
+func testMarkDownReadmeImageSubfolder(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
session := loginUser(t, "user2")
@@ -388,8 +474,8 @@ func TestMarkDownReadmeImageSubfolder(t *testing.T) {
assert.Equal(t, "/user2/repo1/media/branch/sub-home-md-img-check/docs/test-fake-img.jpg", src)
}
-func TestGeneratedSourceLink(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
+func testGeneratedSourceLink(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
t.Run("Rendered file", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
@@ -424,11 +510,54 @@ func TestGeneratedSourceLink(t *testing.T) {
})
}
-func TestViewCommit(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
+func testViewCommit(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", "/user2/repo1/commit/0123456789012345678901234567890123456789")
req.Header.Add("Accept", "text/html")
resp := MakeRequest(t, req, http.StatusNotFound)
assert.True(t, test.IsNormalPageCompleted(resp.Body.String()), "non-existing commit should render 404 page")
}
+
+// TestGenerateRepository the test cannot succeed when moved as a unit test
+func TestGenerateRepository(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ // a successful generate from template
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ repo44 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 44})
+
+ generatedRepo, err := repo_service.GenerateRepository(git.DefaultContext, user2, user2, repo44, repo_service.GenerateRepoOptions{
+ Name: "generated-from-template-44",
+ GitContent: true,
+ })
+ assert.NoError(t, err)
+ assert.NotNil(t, generatedRepo)
+
+ exist, err := util.IsExist(repo_model.RepoPath(user2.Name, generatedRepo.Name))
+ assert.NoError(t, err)
+ assert.True(t, exist)
+
+ unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: user2.Name, Name: generatedRepo.Name})
+
+ err = repo_service.DeleteRepositoryDirectly(db.DefaultContext, generatedRepo.ID)
+ assert.NoError(t, err)
+
+ // a failed creating because some mock data
+ // create the repository directory so that the creation will fail after database record created.
+ assert.NoError(t, os.MkdirAll(repo_model.RepoPath(user2.Name, "generated-from-template-44"), os.ModePerm))
+
+ generatedRepo2, err := repo_service.GenerateRepository(db.DefaultContext, user2, user2, repo44, repo_service.GenerateRepoOptions{
+ Name: "generated-from-template-44",
+ GitContent: true,
+ })
+ assert.Nil(t, generatedRepo2)
+ assert.Error(t, err)
+
+ // assert the cleanup is successful
+ unittest.AssertNotExistsBean(t, &repo_model.Repository{OwnerName: user2.Name, Name: generatedRepo.Name})
+
+ exist, err = util.IsExist(repo_model.RepoPath(user2.Name, generatedRepo.Name))
+ assert.NoError(t, err)
+ assert.False(t, exist)
+}
diff --git a/tests/integration/repo_topic_test.go b/tests/integration/repo_topic_test.go
index f198397007..7f9594b9fd 100644
--- a/tests/integration/repo_topic_test.go
+++ b/tests/integration/repo_topic_test.go
@@ -25,7 +25,7 @@ func TestTopicSearch(t *testing.T) {
res := MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
DecodeJSON(t, res, &topics)
assert.Len(t, topics.TopicNames, 6)
- assert.EqualValues(t, "6", res.Header().Get("x-total-count"))
+ assert.Equal(t, "6", res.Header().Get("x-total-count"))
// pagination search topics
topics.TopicNames = nil
@@ -35,7 +35,7 @@ func TestTopicSearch(t *testing.T) {
res = MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
DecodeJSON(t, res, &topics)
assert.Len(t, topics.TopicNames, 4)
- assert.EqualValues(t, "6", res.Header().Get("x-total-count"))
+ assert.Equal(t, "6", res.Header().Get("x-total-count"))
// second page
topics.TopicNames = nil
@@ -45,7 +45,7 @@ func TestTopicSearch(t *testing.T) {
res = MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
DecodeJSON(t, res, &topics)
assert.Len(t, topics.TopicNames, 2)
- assert.EqualValues(t, "6", res.Header().Get("x-total-count"))
+ assert.Equal(t, "6", res.Header().Get("x-total-count"))
// add keyword search
topics.TopicNames = nil
@@ -63,7 +63,7 @@ func TestTopicSearch(t *testing.T) {
DecodeJSON(t, res, &topics)
if assert.Len(t, topics.TopicNames, 1) {
assert.EqualValues(t, 2, topics.TopicNames[0].ID)
- assert.EqualValues(t, "database", topics.TopicNames[0].Name)
- assert.EqualValues(t, 1, topics.TopicNames[0].RepoCount)
+ assert.Equal(t, "database", topics.TopicNames[0].Name)
+ assert.Equal(t, 1, topics.TopicNames[0].RepoCount)
}
}
diff --git a/tests/integration/repo_webhook_test.go b/tests/integration/repo_webhook_test.go
index ef44a9e2d0..1da7bc9d3c 100644
--- a/tests/integration/repo_webhook_test.go
+++ b/tests/integration/repo_webhook_test.go
@@ -4,14 +4,31 @@
package integration
import (
+ "fmt"
+ "io"
"net/http"
+ "net/http/httptest"
+ "net/url"
+ "path"
"strings"
"testing"
+ auth_model "code.gitea.io/gitea/models/auth"
+ "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unittest"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/models/webhook"
+ "code.gitea.io/gitea/modules/commitstatus"
+ "code.gitea.io/gitea/modules/gitrepo"
+ "code.gitea.io/gitea/modules/json"
+ api "code.gitea.io/gitea/modules/structs"
+ webhook_module "code.gitea.io/gitea/modules/webhook"
"code.gitea.io/gitea/tests"
+ runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
"github.com/PuerkitoBio/goquery"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
func TestNewWebHookLink(t *testing.T) {
@@ -39,3 +56,1169 @@ func TestNewWebHookLink(t *testing.T) {
})
}
}
+
+func testAPICreateWebhookForRepo(t *testing.T, session *TestSession, userName, repoName, url, event string, branchFilter ...string) {
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAll)
+ var branchFilterString string
+ if len(branchFilter) > 0 {
+ branchFilterString = branchFilter[0]
+ }
+ req := NewRequestWithJSON(t, "POST", "/api/v1/repos/"+userName+"/"+repoName+"/hooks", api.CreateHookOption{
+ Type: "gitea",
+ Config: api.CreateHookOptionConfig{
+ "content_type": "json",
+ "url": url,
+ },
+ Events: []string{event},
+ Active: true,
+ BranchFilter: branchFilterString,
+ }).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusCreated)
+}
+
+func testCreateWebhookForRepo(t *testing.T, session *TestSession, webhookType, userName, repoName, url, eventKind string) {
+ csrf := GetUserCSRFToken(t, session)
+ req := NewRequestWithValues(t, "POST", "/"+userName+"/"+repoName+"/settings/hooks/"+webhookType+"/new", map[string]string{
+ "_csrf": csrf,
+ "payload_url": url,
+ "events": eventKind,
+ "active": "true",
+ "content_type": fmt.Sprintf("%d", webhook.ContentTypeJSON),
+ "http_method": "POST",
+ })
+ session.MakeRequest(t, req, http.StatusSeeOther)
+}
+
+func testAPICreateWebhookForOrg(t *testing.T, session *TestSession, userName, url, event string) {
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAll)
+ req := NewRequestWithJSON(t, "POST", "/api/v1/orgs/"+userName+"/hooks", api.CreateHookOption{
+ Type: "gitea",
+ Config: api.CreateHookOptionConfig{
+ "content_type": "json",
+ "url": url,
+ },
+ Events: []string{event},
+ Active: true,
+ }).AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusCreated)
+}
+
+type mockWebhookProvider struct {
+ server *httptest.Server
+}
+
+func newMockWebhookProvider(callback func(r *http.Request), status int) *mockWebhookProvider {
+ m := &mockWebhookProvider{}
+ m.server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ callback(r)
+ w.WriteHeader(status)
+ }))
+ return m
+}
+
+func (m *mockWebhookProvider) URL() string {
+ if m.server == nil {
+ return ""
+ }
+ return m.server.URL
+}
+
+// Close closes the mock webhook http server
+func (m *mockWebhookProvider) Close() {
+ if m.server != nil {
+ m.server.Close()
+ m.server = nil
+ }
+}
+
+func Test_WebhookCreate(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var payloads []api.CreatePayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ content, _ := io.ReadAll(r.Body)
+ var payload api.CreatePayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = string(webhook_module.HookEventCreate)
+ }, http.StatusOK)
+ defer provider.Close()
+
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user2")
+
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "create")
+
+ // 2. trigger the webhook
+ testAPICreateBranch(t, session, "user2", "repo1", "master", "master2", http.StatusCreated)
+
+ // 3. validate the webhook is triggered
+ assert.Len(t, payloads, 1)
+ assert.Equal(t, string(webhook_module.HookEventCreate), triggeredEvent)
+ assert.Equal(t, "repo1", payloads[0].Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[0].Repo.FullName)
+ assert.Equal(t, "master2", payloads[0].Ref)
+ assert.Equal(t, "branch", payloads[0].RefType)
+ })
+}
+
+func Test_WebhookDelete(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var payloads []api.DeletePayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ content, _ := io.ReadAll(r.Body)
+ var payload api.DeletePayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "delete"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user2")
+
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "delete")
+
+ // 2. trigger the webhook
+ testAPICreateBranch(t, session, "user2", "repo1", "master", "master2", http.StatusCreated)
+ testAPIDeleteBranch(t, "master2", http.StatusNoContent)
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "delete", triggeredEvent)
+ assert.Len(t, payloads, 1)
+ assert.Equal(t, "repo1", payloads[0].Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[0].Repo.FullName)
+ assert.Equal(t, "master2", payloads[0].Ref)
+ assert.Equal(t, "branch", payloads[0].RefType)
+ })
+}
+
+func Test_WebhookFork(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var payloads []api.ForkPayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ content, _ := io.ReadAll(r.Body)
+ var payload api.ForkPayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "fork"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user1")
+
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "fork")
+
+ // 2. trigger the webhook
+ testRepoFork(t, session, "user2", "repo1", "user1", "repo1-fork", "master")
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "fork", triggeredEvent)
+ assert.Len(t, payloads, 1)
+ assert.Equal(t, "repo1-fork", payloads[0].Repo.Name)
+ assert.Equal(t, "user1/repo1-fork", payloads[0].Repo.FullName)
+ assert.Equal(t, "repo1", payloads[0].Forkee.Name)
+ assert.Equal(t, "user2/repo1", payloads[0].Forkee.FullName)
+ })
+}
+
+func Test_WebhookIssueComment(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var payloads []api.IssueCommentPayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ content, _ := io.ReadAll(r.Body)
+ var payload api.IssueCommentPayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "issue_comment"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user2")
+
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "issue_comment")
+
+ t.Run("create comment", func(t *testing.T) {
+ // 2. trigger the webhook
+ issueURL := testNewIssue(t, session, "user2", "repo1", "Title2", "Description2")
+ testIssueAddComment(t, session, issueURL, "issue title2 comment1", "")
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "issue_comment", triggeredEvent)
+ assert.Len(t, payloads, 1)
+ assert.EqualValues(t, "created", payloads[0].Action)
+ assert.Equal(t, "repo1", payloads[0].Issue.Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[0].Issue.Repo.FullName)
+ assert.Equal(t, "Title2", payloads[0].Issue.Title)
+ assert.Equal(t, "Description2", payloads[0].Issue.Body)
+ assert.Equal(t, "issue title2 comment1", payloads[0].Comment.Body)
+ })
+
+ t.Run("update comment", func(t *testing.T) {
+ payloads = make([]api.IssueCommentPayload, 0, 2)
+ triggeredEvent = ""
+
+ // 2. trigger the webhook
+ issueURL := testNewIssue(t, session, "user2", "repo1", "Title3", "Description3")
+ commentID := testIssueAddComment(t, session, issueURL, "issue title3 comment1", "")
+ modifiedContent := "issue title2 comment1 - modified"
+ req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/comments/%d", "user2", "repo1", commentID), map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ "content": modifiedContent,
+ })
+ session.MakeRequest(t, req, http.StatusOK)
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "issue_comment", triggeredEvent)
+ assert.Len(t, payloads, 2)
+ assert.EqualValues(t, "edited", payloads[1].Action)
+ assert.Equal(t, "repo1", payloads[1].Issue.Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[1].Issue.Repo.FullName)
+ assert.Equal(t, "Title3", payloads[1].Issue.Title)
+ assert.Equal(t, "Description3", payloads[1].Issue.Body)
+ assert.Equal(t, modifiedContent, payloads[1].Comment.Body)
+ })
+
+ t.Run("Update comment with no content change", func(t *testing.T) {
+ payloads = make([]api.IssueCommentPayload, 0, 2)
+ triggeredEvent = ""
+ commentContent := "issue title3 comment1"
+
+ // 2. trigger the webhook
+ issueURL := testNewIssue(t, session, "user2", "repo1", "Title3", "Description3")
+ commentID := testIssueAddComment(t, session, issueURL, commentContent, "")
+
+ payloads = make([]api.IssueCommentPayload, 0, 2)
+ triggeredEvent = ""
+ req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/comments/%d", "user2", "repo1", commentID), map[string]string{
+ "_csrf": GetUserCSRFToken(t, session),
+ "content": commentContent,
+ })
+ session.MakeRequest(t, req, http.StatusOK)
+
+ // 3. validate the webhook is not triggered because no content change
+ assert.Empty(t, triggeredEvent)
+ assert.Empty(t, payloads)
+ })
+ })
+}
+
+func Test_WebhookRelease(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var payloads []api.ReleasePayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ content, _ := io.ReadAll(r.Body)
+ var payload api.ReleasePayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "release"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user2")
+
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "release")
+
+ // 2. trigger the webhook
+ createNewRelease(t, session, "/user2/repo1", "v0.0.99", "v0.0.99", false, false)
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "release", triggeredEvent)
+ assert.Len(t, payloads, 1)
+ assert.Equal(t, "repo1", payloads[0].Repository.Name)
+ assert.Equal(t, "user2/repo1", payloads[0].Repository.FullName)
+ assert.Equal(t, "v0.0.99", payloads[0].Release.TagName)
+ assert.False(t, payloads[0].Release.IsDraft)
+ assert.False(t, payloads[0].Release.IsPrerelease)
+ })
+}
+
+func Test_WebhookPush(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var payloads []api.PushPayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ content, _ := io.ReadAll(r.Body)
+ var payload api.PushPayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "push"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user2")
+
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "push")
+
+ // 2. trigger the webhook
+ testCreateFile(t, session, "user2", "repo1", "master", "test_webhook_push.md", "# a test file for webhook push")
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "push", triggeredEvent)
+ assert.Len(t, payloads, 1)
+ assert.Equal(t, "repo1", payloads[0].Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[0].Repo.FullName)
+ assert.Len(t, payloads[0].Commits, 1)
+ assert.Equal(t, []string{"test_webhook_push.md"}, payloads[0].Commits[0].Added)
+ })
+}
+
+func Test_WebhookPushDevBranch(t *testing.T) {
+ var payloads []api.PushPayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ content, _ := io.ReadAll(r.Body)
+ var payload api.PushPayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "push"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user2")
+
+ // only for dev branch
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "push", "develop")
+
+ // 2. this should not trigger the webhook
+ testCreateFile(t, session, "user2", "repo1", "master", "test_webhook_push.md", "# a test file for webhook push")
+ assert.Empty(t, triggeredEvent)
+ assert.Empty(t, payloads)
+
+ // 3. trigger the webhook
+ testCreateFile(t, session, "user2", "repo1", "develop", "test_webhook_push.md", "# a test file for webhook push")
+
+ // 4. validate the webhook is triggered
+ assert.Equal(t, "push", triggeredEvent)
+ assert.Len(t, payloads, 1)
+ assert.Equal(t, "repo1", payloads[0].Repo.Name)
+ assert.Equal(t, "develop", payloads[0].Branch())
+ assert.Equal(t, "user2/repo1", payloads[0].Repo.FullName)
+ assert.Len(t, payloads[0].Commits, 1)
+ assert.Equal(t, []string{"test_webhook_push.md"}, payloads[0].Commits[0].Added)
+ })
+}
+
+func Test_WebhookIssue(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var payloads []api.IssuePayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ content, _ := io.ReadAll(r.Body)
+ var payload api.IssuePayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "issues"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user2")
+
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "issues")
+
+ // 2. trigger the webhook
+ testNewIssue(t, session, "user2", "repo1", "Title1", "Description1")
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "issues", triggeredEvent)
+ assert.Len(t, payloads, 1)
+ assert.EqualValues(t, "opened", payloads[0].Action)
+ assert.Equal(t, "repo1", payloads[0].Issue.Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[0].Issue.Repo.FullName)
+ assert.Equal(t, "Title1", payloads[0].Issue.Title)
+ assert.Equal(t, "Description1", payloads[0].Issue.Body)
+ assert.Positive(t, payloads[0].Issue.Created.Unix())
+ assert.Positive(t, payloads[0].Issue.Updated.Unix())
+ })
+}
+
+func Test_WebhookIssueDelete(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var payloads []api.IssuePayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ content, _ := io.ReadAll(r.Body)
+ var payload api.IssuePayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "issue"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user2")
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "issues")
+ issueURL := testNewIssue(t, session, "user2", "repo1", "Title1", "Description1")
+
+ // 2. trigger the webhook
+ testIssueDelete(t, session, issueURL)
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "issue", triggeredEvent)
+ require.Len(t, payloads, 2)
+ assert.EqualValues(t, "deleted", payloads[1].Action)
+ assert.Equal(t, "repo1", payloads[1].Issue.Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[1].Issue.Repo.FullName)
+ assert.Equal(t, "Title1", payloads[1].Issue.Title)
+ assert.Equal(t, "Description1", payloads[1].Issue.Body)
+ })
+}
+
+func Test_WebhookIssueAssign(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var payloads []api.PullRequestPayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ content, _ := io.ReadAll(r.Body)
+ var payload api.PullRequestPayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "pull_request_assign"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ repo1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1})
+
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user2")
+
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "pull_request_assign")
+
+ // 2. trigger the webhook, issue 2 is a pull request
+ testIssueAssign(t, session, repo1.Link(), 2, user2.ID)
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "pull_request_assign", triggeredEvent)
+ assert.Len(t, payloads, 1)
+ assert.EqualValues(t, "assigned", payloads[0].Action)
+ assert.Equal(t, "repo1", payloads[0].PullRequest.Base.Repository.Name)
+ assert.Equal(t, "user2/repo1", payloads[0].PullRequest.Base.Repository.FullName)
+ assert.Equal(t, "issue2", payloads[0].PullRequest.Title)
+ assert.Equal(t, "content for the second issue", payloads[0].PullRequest.Body)
+ assert.Equal(t, user2.ID, payloads[0].PullRequest.Assignee.ID)
+ })
+}
+
+func Test_WebhookIssueMilestone(t *testing.T) {
+ var payloads []api.IssuePayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ content, _ := io.ReadAll(r.Body)
+ var payload api.IssuePayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "issues"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ // create a new webhook with special webhook for repo1
+ session := loginUser(t, "user2")
+ repo1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1})
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "issue_milestone")
+
+ t.Run("assign a milestone", func(t *testing.T) {
+ // trigger the webhook
+ testIssueChangeMilestone(t, session, repo1.Link(), 1, 1)
+
+ // validate the webhook is triggered
+ assert.Equal(t, "issues", triggeredEvent)
+ assert.Len(t, payloads, 1)
+ assert.Equal(t, "milestoned", string(payloads[0].Action))
+ assert.Equal(t, "repo1", payloads[0].Issue.Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[0].Issue.Repo.FullName)
+ assert.Equal(t, "issue1", payloads[0].Issue.Title)
+ assert.Equal(t, "content for the first issue", payloads[0].Issue.Body)
+ assert.EqualValues(t, 1, payloads[0].Issue.Milestone.ID)
+ })
+
+ t.Run("change a milestong", func(t *testing.T) {
+ // trigger the webhook again
+ triggeredEvent = ""
+ payloads = make([]api.IssuePayload, 0, 1)
+ // change milestone to 2
+ testIssueChangeMilestone(t, session, repo1.Link(), 1, 2)
+
+ // validate the webhook is triggered
+ assert.Equal(t, "issues", triggeredEvent)
+ assert.Len(t, payloads, 1)
+ assert.Equal(t, "milestoned", string(payloads[0].Action))
+ assert.Equal(t, "repo1", payloads[0].Issue.Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[0].Issue.Repo.FullName)
+ assert.Equal(t, "issue1", payloads[0].Issue.Title)
+ assert.Equal(t, "content for the first issue", payloads[0].Issue.Body)
+ assert.EqualValues(t, 2, payloads[0].Issue.Milestone.ID)
+ })
+
+ t.Run("remove a milestone", func(t *testing.T) {
+ // trigger the webhook again
+ triggeredEvent = ""
+ payloads = make([]api.IssuePayload, 0, 1)
+ // change milestone to 0
+ testIssueChangeMilestone(t, session, repo1.Link(), 1, 0)
+
+ // validate the webhook is triggered
+ assert.Equal(t, "issues", triggeredEvent)
+ assert.Len(t, payloads, 1)
+ assert.Equal(t, "demilestoned", string(payloads[0].Action))
+ assert.Equal(t, "repo1", payloads[0].Issue.Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[0].Issue.Repo.FullName)
+ assert.Equal(t, "issue1", payloads[0].Issue.Title)
+ assert.Equal(t, "content for the first issue", payloads[0].Issue.Body)
+ assert.Nil(t, payloads[0].Issue.Milestone)
+ })
+ })
+}
+
+func Test_WebhookPullRequest(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var payloads []api.PullRequestPayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ content, _ := io.ReadAll(r.Body)
+ var payload api.PullRequestPayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "pull_request"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user2")
+
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "pull_request")
+
+ testAPICreateBranch(t, session, "user2", "repo1", "master", "master2", http.StatusCreated)
+ // 2. trigger the webhook
+ repo1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1})
+ testCreatePullToDefaultBranch(t, session, repo1, repo1, "master2", "first pull request")
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "pull_request", triggeredEvent)
+ require.Len(t, payloads, 1)
+ assert.Equal(t, "repo1", payloads[0].PullRequest.Base.Repository.Name)
+ assert.Equal(t, "user2/repo1", payloads[0].PullRequest.Base.Repository.FullName)
+ assert.Equal(t, "repo1", payloads[0].PullRequest.Head.Repository.Name)
+ assert.Equal(t, "user2/repo1", payloads[0].PullRequest.Head.Repository.FullName)
+ assert.Equal(t, 0, *payloads[0].PullRequest.Additions)
+ assert.Equal(t, 0, *payloads[0].PullRequest.ChangedFiles)
+ assert.Equal(t, 0, *payloads[0].PullRequest.Deletions)
+ })
+}
+
+func Test_WebhookPullRequestDelete(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var payloads []api.PullRequestPayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ content, _ := io.ReadAll(r.Body)
+ var payload api.PullRequestPayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "pull_request"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user2")
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "pull_request")
+
+ testAPICreateBranch(t, session, "user2", "repo1", "master", "master2", http.StatusCreated)
+
+ repo1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1})
+ issueURL := testCreatePullToDefaultBranch(t, session, repo1, repo1, "master2", "first pull request")
+
+ // 2. trigger the webhook
+ testIssueDelete(t, session, path.Join(repo1.Link(), "pulls", issueURL))
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "pull_request", triggeredEvent)
+ require.Len(t, payloads, 2)
+ assert.EqualValues(t, "deleted", payloads[1].Action)
+ assert.Equal(t, "repo1", payloads[1].PullRequest.Base.Repository.Name)
+ assert.Equal(t, "user2/repo1", payloads[1].PullRequest.Base.Repository.FullName)
+ assert.Equal(t, 0, *payloads[1].PullRequest.Additions)
+ assert.Equal(t, 0, *payloads[1].PullRequest.ChangedFiles)
+ assert.Equal(t, 0, *payloads[1].PullRequest.Deletions)
+ })
+}
+
+func Test_WebhookPullRequestComment(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var payloads []api.IssueCommentPayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ content, _ := io.ReadAll(r.Body)
+ var payload api.IssueCommentPayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "pull_request_comment"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user2")
+
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "pull_request_comment")
+
+ // 2. trigger the webhook
+ testAPICreateBranch(t, session, "user2", "repo1", "master", "master2", http.StatusCreated)
+ repo1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1})
+ prID := testCreatePullToDefaultBranch(t, session, repo1, repo1, "master2", "first pull request")
+
+ testIssueAddComment(t, session, "/user2/repo1/pulls/"+prID, "pull title2 comment1", "")
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "pull_request_comment", triggeredEvent)
+ assert.Len(t, payloads, 1)
+ assert.EqualValues(t, "created", payloads[0].Action)
+ assert.Equal(t, "repo1", payloads[0].Issue.Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[0].Issue.Repo.FullName)
+ assert.Equal(t, "first pull request", payloads[0].Issue.Title)
+ assert.Empty(t, payloads[0].Issue.Body)
+ assert.Equal(t, "pull title2 comment1", payloads[0].Comment.Body)
+ })
+}
+
+func Test_WebhookWiki(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var payloads []api.WikiPayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ content, _ := io.ReadAll(r.Body)
+ var payload api.WikiPayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "wiki"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user2")
+
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "wiki")
+
+ // 2. trigger the webhook
+ testAPICreateWikiPage(t, session, "user2", "repo1", "Test Wiki Page", http.StatusCreated)
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "wiki", triggeredEvent)
+ assert.Len(t, payloads, 1)
+ assert.EqualValues(t, "created", payloads[0].Action)
+ assert.Equal(t, "repo1", payloads[0].Repository.Name)
+ assert.Equal(t, "user2/repo1", payloads[0].Repository.FullName)
+ assert.Equal(t, "Test-Wiki-Page", payloads[0].Page)
+ })
+}
+
+func Test_WebhookRepository(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var payloads []api.RepositoryPayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ content, _ := io.ReadAll(r.Body)
+ var payload api.RepositoryPayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "repository"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user1")
+
+ testAPICreateWebhookForOrg(t, session, "org3", provider.URL(), "repository")
+
+ // 2. trigger the webhook
+ testAPIOrgCreateRepo(t, session, "org3", "repo_new", http.StatusCreated)
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "repository", triggeredEvent)
+ assert.Len(t, payloads, 1)
+ assert.EqualValues(t, "created", payloads[0].Action)
+ assert.Equal(t, "org3", payloads[0].Organization.UserName)
+ assert.Equal(t, "repo_new", payloads[0].Repository.Name)
+ assert.Equal(t, "org3/repo_new", payloads[0].Repository.FullName)
+ })
+}
+
+func Test_WebhookPackage(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var payloads []api.PackagePayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ content, _ := io.ReadAll(r.Body)
+ var payload api.PackagePayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "package"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user1")
+
+ testAPICreateWebhookForOrg(t, session, "org3", provider.URL(), "package")
+
+ // 2. trigger the webhook
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAll)
+ url := fmt.Sprintf("/api/packages/%s/generic/%s/%s", "org3", "gitea", "v1.24.0")
+ req := NewRequestWithBody(t, "PUT", url+"/gitea", strings.NewReader("This is a dummy file")).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusCreated)
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "package", triggeredEvent)
+ assert.Len(t, payloads, 1)
+ assert.EqualValues(t, "created", payloads[0].Action)
+ assert.Equal(t, "gitea", payloads[0].Package.Name)
+ assert.Equal(t, "generic", payloads[0].Package.Type)
+ assert.Equal(t, "org3", payloads[0].Organization.UserName)
+ assert.Equal(t, "v1.24.0", payloads[0].Package.Version)
+ })
+}
+
+func Test_WebhookStatus(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var payloads []api.CommitStatusPayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ assert.Contains(t, r.Header["X-Github-Event-Type"], "status", "X-GitHub-Event-Type should contain status")
+ assert.Contains(t, r.Header["X-Github-Hook-Installation-Target-Type"], "repository", "X-GitHub-Hook-Installation-Target-Type should contain repository")
+ assert.Contains(t, r.Header["X-Gitea-Event-Type"], "status", "X-Gitea-Event-Type should contain status")
+ assert.Contains(t, r.Header["X-Gitea-Hook-Installation-Target-Type"], "repository", "X-Gitea-Hook-Installation-Target-Type should contain repository")
+ assert.Contains(t, r.Header["X-Gogs-Event-Type"], "status", "X-Gogs-Event-Type should contain status")
+ content, _ := io.ReadAll(r.Body)
+ var payload api.CommitStatusPayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "status"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user2")
+
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "status")
+
+ repo1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1})
+
+ gitRepo1, err := gitrepo.OpenRepository(t.Context(), repo1)
+ assert.NoError(t, err)
+ commitID, err := gitRepo1.GetBranchCommitID(repo1.DefaultBranch)
+ assert.NoError(t, err)
+
+ // 2. trigger the webhook
+ testCtx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeAll)
+
+ // update a status for a commit via API
+ doAPICreateCommitStatus(testCtx, commitID, api.CreateStatusOption{
+ State: commitstatus.CommitStatusSuccess,
+ TargetURL: "http://test.ci/",
+ Description: "",
+ Context: "testci",
+ })(t)
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "status", triggeredEvent)
+ assert.Len(t, payloads, 1)
+ assert.Equal(t, commitID, payloads[0].Commit.ID)
+ assert.Equal(t, "repo1", payloads[0].Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[0].Repo.FullName)
+ assert.Equal(t, "testci", payloads[0].Context)
+ assert.Equal(t, commitID, payloads[0].SHA)
+ })
+}
+
+func Test_WebhookStatus_NoWrongTrigger(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var trigger string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ assert.NotContains(t, r.Header["X-Github-Event-Type"], "status", "X-GitHub-Event-Type should not contain status")
+ assert.NotContains(t, r.Header["X-Gitea-Event-Type"], "status", "X-Gitea-Event-Type should not contain status")
+ assert.NotContains(t, r.Header["X-Gogs-Event-Type"], "status", "X-Gogs-Event-Type should not contain status")
+ trigger = "push"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ // 1. create a new webhook with special webhook for repo1
+ session := loginUser(t, "user2")
+
+ // create a push_only webhook from web UI
+ testCreateWebhookForRepo(t, session, "gitea", "user2", "repo1", provider.URL(), "push_only")
+
+ // 2. trigger the webhook with a push action
+ testCreateFile(t, session, "user2", "repo1", "master", "test_webhook_push.md", "# a test file for webhook push")
+
+ // 3. validate the webhook is triggered with right event
+ assert.Equal(t, "push", trigger)
+ })
+}
+
+func Test_WebhookWorkflowJob(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ var payloads []api.WorkflowJobPayload
+ var triggeredEvent string
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ assert.Contains(t, r.Header["X-Github-Event-Type"], "workflow_job", "X-GitHub-Event-Type should contain workflow_job")
+ assert.Contains(t, r.Header["X-Gitea-Event-Type"], "workflow_job", "X-Gitea-Event-Type should contain workflow_job")
+ assert.Contains(t, r.Header["X-Gogs-Event-Type"], "workflow_job", "X-Gogs-Event-Type should contain workflow_job")
+ content, _ := io.ReadAll(r.Body)
+ var payload api.WorkflowJobPayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ payloads = append(payloads, payload)
+ triggeredEvent = "workflow_job"
+ }, http.StatusOK)
+ defer provider.Close()
+
+ // 1. create a new webhook with special webhook for repo1
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ session := loginUser(t, "user2")
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
+
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "workflow_job")
+
+ repo1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1})
+
+ gitRepo1, err := gitrepo.OpenRepository(t.Context(), repo1)
+ assert.NoError(t, err)
+
+ runner := newMockRunner()
+ runner.registerAsRepoRunner(t, "user2", "repo1", "mock-runner", []string{"ubuntu-latest"}, false)
+
+ // 2. trigger the webhooks
+
+ // add workflow file to the repo
+ // init the workflow
+ wfTreePath := ".gitea/workflows/push.yml"
+ wfFileContent := `name: Push
+on: push
+jobs:
+ wf1-job:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo 'test the webhook'
+ wf2-job:
+ runs-on: ubuntu-latest
+ needs: wf1-job
+ steps:
+ - run: echo 'cmd 1'
+ - run: echo 'cmd 2'
+`
+ opts := getWorkflowCreateFileOptions(user2, repo1.DefaultBranch, "create "+wfTreePath, wfFileContent)
+ createWorkflowFile(t, token, "user2", "repo1", wfTreePath, opts)
+
+ commitID, err := gitRepo1.GetBranchCommitID(repo1.DefaultBranch)
+ assert.NoError(t, err)
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "workflow_job", triggeredEvent)
+ assert.Len(t, payloads, 2)
+ assert.Equal(t, "queued", payloads[0].Action)
+ assert.Equal(t, "queued", payloads[0].WorkflowJob.Status)
+ assert.Equal(t, []string{"ubuntu-latest"}, payloads[0].WorkflowJob.Labels)
+ assert.Equal(t, commitID, payloads[0].WorkflowJob.HeadSha)
+ assert.Equal(t, "repo1", payloads[0].Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[0].Repo.FullName)
+
+ assert.Equal(t, "waiting", payloads[1].Action)
+ assert.Equal(t, "waiting", payloads[1].WorkflowJob.Status)
+ assert.Equal(t, commitID, payloads[1].WorkflowJob.HeadSha)
+ assert.Equal(t, "repo1", payloads[1].Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[1].Repo.FullName)
+
+ // 4. Execute a single Job
+ task := runner.fetchTask(t)
+ outcome := &mockTaskOutcome{
+ result: runnerv1.Result_RESULT_SUCCESS,
+ }
+ runner.execTask(t, task, outcome)
+
+ // 5. validate the webhook is triggered
+ assert.Equal(t, "workflow_job", triggeredEvent)
+ assert.Len(t, payloads, 5)
+ assert.Equal(t, "in_progress", payloads[2].Action)
+ assert.Equal(t, "in_progress", payloads[2].WorkflowJob.Status)
+ assert.Equal(t, "mock-runner", payloads[2].WorkflowJob.RunnerName)
+ assert.Equal(t, commitID, payloads[2].WorkflowJob.HeadSha)
+ assert.Equal(t, "repo1", payloads[2].Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[2].Repo.FullName)
+
+ assert.Equal(t, "completed", payloads[3].Action)
+ assert.Equal(t, "completed", payloads[3].WorkflowJob.Status)
+ assert.Equal(t, "mock-runner", payloads[3].WorkflowJob.RunnerName)
+ assert.Equal(t, "success", payloads[3].WorkflowJob.Conclusion)
+ assert.Equal(t, commitID, payloads[3].WorkflowJob.HeadSha)
+ assert.Equal(t, "repo1", payloads[3].Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[3].Repo.FullName)
+ assert.Contains(t, payloads[3].WorkflowJob.URL, fmt.Sprintf("/actions/jobs/%d", payloads[3].WorkflowJob.ID))
+ assert.Contains(t, payloads[3].WorkflowJob.HTMLURL, fmt.Sprintf("/jobs/%d", 0))
+ assert.Len(t, payloads[3].WorkflowJob.Steps, 1)
+
+ assert.Equal(t, "queued", payloads[4].Action)
+ assert.Equal(t, "queued", payloads[4].WorkflowJob.Status)
+ assert.Equal(t, []string{"ubuntu-latest"}, payloads[4].WorkflowJob.Labels)
+ assert.Equal(t, commitID, payloads[4].WorkflowJob.HeadSha)
+ assert.Equal(t, "repo1", payloads[4].Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[4].Repo.FullName)
+
+ // 6. Execute a single Job
+ task = runner.fetchTask(t)
+ outcome = &mockTaskOutcome{
+ result: runnerv1.Result_RESULT_FAILURE,
+ }
+ runner.execTask(t, task, outcome)
+
+ // 7. validate the webhook is triggered
+ assert.Equal(t, "workflow_job", triggeredEvent)
+ assert.Len(t, payloads, 7)
+ assert.Equal(t, "in_progress", payloads[5].Action)
+ assert.Equal(t, "in_progress", payloads[5].WorkflowJob.Status)
+ assert.Equal(t, "mock-runner", payloads[5].WorkflowJob.RunnerName)
+
+ assert.Equal(t, commitID, payloads[5].WorkflowJob.HeadSha)
+ assert.Equal(t, "repo1", payloads[5].Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[5].Repo.FullName)
+
+ assert.Equal(t, "completed", payloads[6].Action)
+ assert.Equal(t, "completed", payloads[6].WorkflowJob.Status)
+ assert.Equal(t, "failure", payloads[6].WorkflowJob.Conclusion)
+ assert.Equal(t, "mock-runner", payloads[6].WorkflowJob.RunnerName)
+ assert.Equal(t, commitID, payloads[6].WorkflowJob.HeadSha)
+ assert.Equal(t, "repo1", payloads[6].Repo.Name)
+ assert.Equal(t, "user2/repo1", payloads[6].Repo.FullName)
+ assert.Contains(t, payloads[6].WorkflowJob.URL, fmt.Sprintf("/actions/jobs/%d", payloads[6].WorkflowJob.ID))
+ assert.Contains(t, payloads[6].WorkflowJob.HTMLURL, fmt.Sprintf("/jobs/%d", 1))
+ assert.Len(t, payloads[6].WorkflowJob.Steps, 2)
+ })
+}
+
+type workflowRunWebhook struct {
+ URL string
+ payloads []api.WorkflowRunPayload
+ triggeredEvent string
+}
+
+func Test_WebhookWorkflowRun(t *testing.T) {
+ webhookData := &workflowRunWebhook{}
+ provider := newMockWebhookProvider(func(r *http.Request) {
+ assert.Contains(t, r.Header["X-Github-Event-Type"], "workflow_run", "X-GitHub-Event-Type should contain workflow_run")
+ assert.Contains(t, r.Header["X-Gitea-Event-Type"], "workflow_run", "X-Gitea-Event-Type should contain workflow_run")
+ assert.Contains(t, r.Header["X-Gogs-Event-Type"], "workflow_run", "X-Gogs-Event-Type should contain workflow_run")
+ content, _ := io.ReadAll(r.Body)
+ var payload api.WorkflowRunPayload
+ err := json.Unmarshal(content, &payload)
+ assert.NoError(t, err)
+ webhookData.payloads = append(webhookData.payloads, payload)
+ webhookData.triggeredEvent = "workflow_run"
+ }, http.StatusOK)
+ defer provider.Close()
+ webhookData.URL = provider.URL()
+
+ tests := []struct {
+ name string
+ callback func(t *testing.T, webhookData *workflowRunWebhook)
+ }{
+ {
+ name: "WorkflowRun",
+ callback: testWebhookWorkflowRun,
+ },
+ {
+ name: "WorkflowRunDepthLimit",
+ callback: testWebhookWorkflowRunDepthLimit,
+ },
+ }
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ webhookData.payloads = nil
+ webhookData.triggeredEvent = ""
+ onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+ test.callback(t, webhookData)
+ })
+ })
+ }
+}
+
+func testWebhookWorkflowRun(t *testing.T, webhookData *workflowRunWebhook) {
+ // 1. create a new webhook with special webhook for repo1
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ session := loginUser(t, "user2")
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
+
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", webhookData.URL, "workflow_run")
+
+ repo1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1})
+
+ gitRepo1, err := gitrepo.OpenRepository(t.Context(), repo1)
+ assert.NoError(t, err)
+
+ runner := newMockRunner()
+ runner.registerAsRepoRunner(t, "user2", "repo1", "mock-runner", []string{"ubuntu-latest"}, false)
+
+ // 2.1 add workflow_run workflow file to the repo
+
+ opts := getWorkflowCreateFileOptions(user2, repo1.DefaultBranch, "create "+"dispatch.yml", `
+on:
+ workflow_run:
+ workflows: ["Push"]
+ types:
+ - completed
+jobs:
+ dispatch:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo 'test the webhook'
+`)
+ createWorkflowFile(t, token, "user2", "repo1", ".gitea/workflows/dispatch.yml", opts)
+
+ // 2.2 trigger the webhooks
+
+ // add workflow file to the repo
+ // init the workflow
+ wfTreePath := ".gitea/workflows/push.yml"
+ wfFileContent := `name: Push
+on: push
+jobs:
+ wf1-job:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo 'test the webhook'
+ wf2-job:
+ runs-on: ubuntu-latest
+ needs: wf1-job
+ steps:
+ - run: echo 'cmd 1'
+ - run: echo 'cmd 2'
+`
+ opts = getWorkflowCreateFileOptions(user2, repo1.DefaultBranch, "create "+wfTreePath, wfFileContent)
+ createWorkflowFile(t, token, "user2", "repo1", wfTreePath, opts)
+
+ commitID, err := gitRepo1.GetBranchCommitID(repo1.DefaultBranch)
+ assert.NoError(t, err)
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "workflow_run", webhookData.triggeredEvent)
+ assert.Len(t, webhookData.payloads, 1)
+ assert.Equal(t, "requested", webhookData.payloads[0].Action)
+ assert.Equal(t, "queued", webhookData.payloads[0].WorkflowRun.Status)
+ assert.Equal(t, repo1.DefaultBranch, webhookData.payloads[0].WorkflowRun.HeadBranch)
+ assert.Equal(t, commitID, webhookData.payloads[0].WorkflowRun.HeadSha)
+ assert.Equal(t, "repo1", webhookData.payloads[0].Repo.Name)
+ assert.Equal(t, "user2/repo1", webhookData.payloads[0].Repo.FullName)
+
+ // 4. Execute two Jobs
+ task := runner.fetchTask(t)
+ outcome := &mockTaskOutcome{
+ result: runnerv1.Result_RESULT_SUCCESS,
+ }
+ runner.execTask(t, task, outcome)
+
+ task = runner.fetchTask(t)
+ outcome = &mockTaskOutcome{
+ result: runnerv1.Result_RESULT_FAILURE,
+ }
+ runner.execTask(t, task, outcome)
+
+ // 7. validate the webhook is triggered
+ assert.Equal(t, "workflow_run", webhookData.triggeredEvent)
+ assert.Len(t, webhookData.payloads, 3)
+ assert.Equal(t, "completed", webhookData.payloads[1].Action)
+ assert.Equal(t, "push", webhookData.payloads[1].WorkflowRun.Event)
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "workflow_run", webhookData.triggeredEvent)
+ assert.Len(t, webhookData.payloads, 3)
+ assert.Equal(t, "requested", webhookData.payloads[2].Action)
+ assert.Equal(t, "queued", webhookData.payloads[2].WorkflowRun.Status)
+ assert.Equal(t, "workflow_run", webhookData.payloads[2].WorkflowRun.Event)
+ assert.Equal(t, repo1.DefaultBranch, webhookData.payloads[2].WorkflowRun.HeadBranch)
+ assert.Equal(t, commitID, webhookData.payloads[2].WorkflowRun.HeadSha)
+ assert.Equal(t, "repo1", webhookData.payloads[2].Repo.Name)
+ assert.Equal(t, "user2/repo1", webhookData.payloads[2].Repo.FullName)
+}
+
+func testWebhookWorkflowRunDepthLimit(t *testing.T, webhookData *workflowRunWebhook) {
+ // 1. create a new webhook with special webhook for repo1
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+ session := loginUser(t, "user2")
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
+
+ testAPICreateWebhookForRepo(t, session, "user2", "repo1", webhookData.URL, "workflow_run")
+
+ repo1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1})
+
+ gitRepo1, err := gitrepo.OpenRepository(t.Context(), repo1)
+ assert.NoError(t, err)
+
+ // 2. trigger the webhooks
+
+ // add workflow file to the repo
+ // init the workflow
+ wfTreePath := ".gitea/workflows/push.yml"
+ wfFileContent := `name: Endless Loop
+on:
+ push:
+ workflow_run:
+ types:
+ - requested
+jobs:
+ dispatch:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo 'test the webhook'
+`
+ opts := getWorkflowCreateFileOptions(user2, repo1.DefaultBranch, "create "+wfTreePath, wfFileContent)
+ createWorkflowFile(t, token, "user2", "repo1", wfTreePath, opts)
+
+ commitID, err := gitRepo1.GetBranchCommitID(repo1.DefaultBranch)
+ assert.NoError(t, err)
+
+ // 3. validate the webhook is triggered
+ assert.Equal(t, "workflow_run", webhookData.triggeredEvent)
+ // 1x push + 5x workflow_run requested chain
+ assert.Len(t, webhookData.payloads, 6)
+ for i := range 6 {
+ assert.Equal(t, "requested", webhookData.payloads[i].Action)
+ assert.Equal(t, "queued", webhookData.payloads[i].WorkflowRun.Status)
+ assert.Equal(t, repo1.DefaultBranch, webhookData.payloads[i].WorkflowRun.HeadBranch)
+ assert.Equal(t, commitID, webhookData.payloads[i].WorkflowRun.HeadSha)
+ if i == 0 {
+ assert.Equal(t, "push", webhookData.payloads[i].WorkflowRun.Event)
+ } else {
+ assert.Equal(t, "workflow_run", webhookData.payloads[i].WorkflowRun.Event)
+ }
+ assert.Equal(t, "repo1", webhookData.payloads[i].Repo.Name)
+ assert.Equal(t, "user2/repo1", webhookData.payloads[i].Repo.FullName)
+ }
+}
diff --git a/tests/integration/repofiles_change_test.go b/tests/integration/repofiles_change_test.go
index d86dcc01fe..dc389f5680 100644
--- a/tests/integration/repofiles_change_test.go
+++ b/tests/integration/repofiles_change_test.go
@@ -4,8 +4,9 @@
package integration
import (
+ "fmt"
"net/url"
- "path/filepath"
+ "path"
"strings"
"testing"
"time"
@@ -16,6 +17,7 @@ import (
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/contexttest"
files_service "code.gitea.io/gitea/services/repository/files"
@@ -57,6 +59,40 @@ func getUpdateRepoFilesOptions(repo *repo_model.Repository) *files_service.Chang
}
}
+func getUpdateRepoFilesRenameOptions(repo *repo_model.Repository) *files_service.ChangeRepoFilesOptions {
+ return &files_service.ChangeRepoFilesOptions{
+ Files: []*files_service.ChangeRepoFile{
+ // move normally
+ {
+ Operation: "rename",
+ FromTreePath: "README.md",
+ TreePath: "README.txt",
+ },
+ // move from in lfs
+ {
+ Operation: "rename",
+ FromTreePath: "crypt.bin",
+ TreePath: "crypt1.bin",
+ },
+ // move from lfs to normal
+ {
+ Operation: "rename",
+ FromTreePath: "jpeg.jpg",
+ TreePath: "jpeg.jpeg",
+ },
+ // move from normal to lfs
+ {
+ Operation: "rename",
+ FromTreePath: "CONTRIBUTING.md",
+ TreePath: "CONTRIBUTING.md.bin",
+ },
+ },
+ OldBranch: repo.DefaultBranch,
+ NewBranch: repo.DefaultBranch,
+ Message: "Rename files",
+ }
+}
+
func getDeleteRepoFilesOptions(repo *repo_model.Repository) *files_service.ChangeRepoFilesOptions {
return &files_service.ChangeRepoFilesOptions{
Files: []*files_service.ChangeRepoFile{
@@ -71,14 +107,14 @@ func getDeleteRepoFilesOptions(repo *repo_model.Repository) *files_service.Chang
NewBranch: repo.DefaultBranch,
Message: "Deletes README.md",
Author: &files_service.IdentityOptions{
- Name: "Bob Smith",
- Email: "bob@smith.com",
+ GitUserName: "Bob Smith",
+ GitUserEmail: "bob@smith.com",
},
Committer: nil,
}
}
-func getExpectedFileResponseForRepofilesDelete() *api.FileResponse {
+func getExpectedFileResponseForRepoFilesDelete() *api.FileResponse {
// Just returns fields that don't change, i.e. fields with commit SHAs and dates can't be determined
return &api.FileResponse{
Content: nil,
@@ -106,7 +142,7 @@ func getExpectedFileResponseForRepofilesDelete() *api.FileResponse {
}
}
-func getExpectedFileResponseForRepofilesCreate(commitID, lastCommitSHA string) *api.FileResponse {
+func getExpectedFileResponseForRepoFilesCreate(commitID string, lastCommit *git.Commit) *api.FileResponse {
treePath := "new/file.txt"
encoding := "base64"
content := "VGhpcyBpcyBhIE5FVyBmaWxl"
@@ -116,18 +152,20 @@ func getExpectedFileResponseForRepofilesCreate(commitID, lastCommitSHA string) *
downloadURL := setting.AppURL + "user2/repo1/raw/branch/master/" + treePath
return &api.FileResponse{
Content: &api.ContentsResponse{
- Name: filepath.Base(treePath),
- Path: treePath,
- SHA: "103ff9234cefeee5ec5361d22b49fbb04d385885",
- LastCommitSHA: lastCommitSHA,
- Type: "file",
- Size: 18,
- Encoding: &encoding,
- Content: &content,
- URL: &selfURL,
- HTMLURL: &htmlURL,
- GitURL: &gitURL,
- DownloadURL: &downloadURL,
+ Name: path.Base(treePath),
+ Path: treePath,
+ SHA: "103ff9234cefeee5ec5361d22b49fbb04d385885",
+ LastCommitSHA: util.ToPointer(lastCommit.ID.String()),
+ LastCommitterDate: util.ToPointer(lastCommit.Committer.When),
+ LastAuthorDate: util.ToPointer(lastCommit.Author.When),
+ Type: "file",
+ Size: 18,
+ Encoding: &encoding,
+ Content: &content,
+ URL: &selfURL,
+ HTMLURL: &htmlURL,
+ GitURL: &gitURL,
+ DownloadURL: &downloadURL,
Links: &api.FileLinksResponse{
Self: &selfURL,
GitURL: &gitURL,
@@ -160,7 +198,7 @@ func getExpectedFileResponseForRepofilesCreate(commitID, lastCommitSHA string) *
SHA: "65f1bf27bc3bf70f64657658635e66094edbcb4d",
},
},
- Message: "Updates README.md\n",
+ Message: "Creates new/file.txt\n",
Tree: &api.CommitMeta{
URL: setting.AppURL + "api/v1/repos/user2/repo1/git/trees/f93e3a1a1525fb5b91020da86e44810c87a2d7bc",
SHA: "f93e3a1a1525fb5b91020git dda86e44810c87a2d7bc",
@@ -175,7 +213,7 @@ func getExpectedFileResponseForRepofilesCreate(commitID, lastCommitSHA string) *
}
}
-func getExpectedFileResponseForRepofilesUpdate(commitID, filename, lastCommitSHA string) *api.FileResponse {
+func getExpectedFileResponseForRepoFilesUpdate(commitID, filename, lastCommitSHA string, lastCommitterWhen, lastAuthorWhen time.Time) *api.FileResponse {
encoding := "base64"
content := "VGhpcyBpcyBVUERBVEVEIGNvbnRlbnQgZm9yIHRoZSBSRUFETUUgZmlsZQ=="
selfURL := setting.AppURL + "api/v1/repos/user2/repo1/contents/" + filename + "?ref=master"
@@ -184,18 +222,20 @@ func getExpectedFileResponseForRepofilesUpdate(commitID, filename, lastCommitSHA
downloadURL := setting.AppURL + "user2/repo1/raw/branch/master/" + filename
return &api.FileResponse{
Content: &api.ContentsResponse{
- Name: filename,
- Path: filename,
- SHA: "dbf8d00e022e05b7e5cf7e535de857de57925647",
- LastCommitSHA: lastCommitSHA,
- Type: "file",
- Size: 43,
- Encoding: &encoding,
- Content: &content,
- URL: &selfURL,
- HTMLURL: &htmlURL,
- GitURL: &gitURL,
- DownloadURL: &downloadURL,
+ Name: filename,
+ Path: filename,
+ SHA: "dbf8d00e022e05b7e5cf7e535de857de57925647",
+ LastCommitSHA: util.ToPointer(lastCommitSHA),
+ LastCommitterDate: util.ToPointer(lastCommitterWhen),
+ LastAuthorDate: util.ToPointer(lastAuthorWhen),
+ Type: "file",
+ Size: 43,
+ Encoding: &encoding,
+ Content: &content,
+ URL: &selfURL,
+ HTMLURL: &htmlURL,
+ GitURL: &gitURL,
+ DownloadURL: &downloadURL,
Links: &api.FileLinksResponse{
Self: &selfURL,
GitURL: &gitURL,
@@ -243,6 +283,114 @@ func getExpectedFileResponseForRepofilesUpdate(commitID, filename, lastCommitSHA
}
}
+func getExpectedFileResponseForRepoFilesUpdateRename(commitID, lastCommitSHA string) *api.FilesResponse {
+ details := []struct {
+ filename, sha, content string
+ size int64
+ lfsOid *string
+ lfsSize *int64
+ }{
+ {
+ filename: "README.txt",
+ sha: "8276d2a29779af982c0afa976bdb793b52d442a8",
+ size: 22,
+ content: "IyBBbiBMRlMtZW5hYmxlZCByZXBvCg==",
+ },
+ {
+ filename: "crypt1.bin",
+ sha: "d4a41a0d4db4949e129bd22f871171ea988103ef",
+ size: 129,
+ content: "dmVyc2lvbiBodHRwczovL2dpdC1sZnMuZ2l0aHViLmNvbS9zcGVjL3YxCm9pZCBzaGEyNTY6MmVjY2RiNDM4MjVkMmE0OWQ5OWQ1NDJkYWEyMDA3NWNmZjFkOTdkOWQyMzQ5YTg5NzdlZmU5YzAzNjYxNzM3YwpzaXplIDIwNDgK",
+ lfsOid: util.ToPointer("2eccdb43825d2a49d99d542daa20075cff1d97d9d2349a8977efe9c03661737c"),
+ lfsSize: util.ToPointer(int64(2048)),
+ },
+ {
+ filename: "jpeg.jpeg",
+ sha: "71911bf48766c7181518c1070911019fbb00b1fc",
+ size: 107,
+ content: "/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=",
+ },
+ {
+ filename: "CONTRIBUTING.md.bin",
+ sha: "2b6c6c4eaefa24b22f2092c3d54b263ff26feb58",
+ size: 127,
+ content: "dmVyc2lvbiBodHRwczovL2dpdC1sZnMuZ2l0aHViLmNvbS9zcGVjL3YxCm9pZCBzaGEyNTY6N2I2YjJjODhkYmE5Zjc2MGExYTU4NDY5YjY3ZmVlMmI2OThlZjdlOTM5OWM0Y2E0ZjM0YTE0Y2NiZTM5ZjYyMwpzaXplIDI3Cg==",
+ lfsOid: util.ToPointer("7b6b2c88dba9f760a1a58469b67fee2b698ef7e9399c4ca4f34a14ccbe39f623"),
+ lfsSize: util.ToPointer(int64(27)),
+ },
+ }
+
+ var responses []*api.ContentsResponse
+ for _, detail := range details {
+ selfURL := setting.AppURL + "api/v1/repos/user2/lfs/contents/" + detail.filename + "?ref=master"
+ htmlURL := setting.AppURL + "user2/lfs/src/branch/master/" + detail.filename
+ gitURL := setting.AppURL + "api/v1/repos/user2/lfs/git/blobs/" + detail.sha
+ downloadURL := setting.AppURL + "user2/lfs/raw/branch/master/" + detail.filename
+ // don't set time related fields because there might be different time in one operation
+ responses = append(responses, &api.ContentsResponse{
+ Name: detail.filename,
+ Path: detail.filename,
+ SHA: detail.sha,
+ LastCommitSHA: util.ToPointer(lastCommitSHA),
+ Type: "file",
+ Size: detail.size,
+ Encoding: util.ToPointer("base64"),
+ Content: &detail.content,
+ URL: &selfURL,
+ HTMLURL: &htmlURL,
+ GitURL: &gitURL,
+ DownloadURL: &downloadURL,
+ Links: &api.FileLinksResponse{
+ Self: &selfURL,
+ GitURL: &gitURL,
+ HTMLURL: &htmlURL,
+ },
+ LfsOid: detail.lfsOid,
+ LfsSize: detail.lfsSize,
+ })
+ }
+
+ return &api.FilesResponse{
+ Files: responses,
+ Commit: &api.FileCommitResponse{
+ CommitMeta: api.CommitMeta{
+ URL: setting.AppURL + "api/v1/repos/user2/lfs/git/commits/" + commitID,
+ SHA: commitID,
+ },
+ HTMLURL: setting.AppURL + "user2/lfs/commit/" + commitID,
+ Author: &api.CommitUser{
+ Identity: api.Identity{
+ Name: "User Two",
+ Email: "user2@noreply.example.org",
+ },
+ },
+ Committer: &api.CommitUser{
+ Identity: api.Identity{
+ Name: "User Two",
+ Email: "user2@noreply.example.org",
+ },
+ },
+ Parents: []*api.CommitMeta{
+ {
+ URL: setting.AppURL + "api/v1/repos/user2/lfs/git/commits/73cf03db6ece34e12bf91e8853dc58f678f2f82d",
+ SHA: "73cf03db6ece34e12bf91e8853dc58f678f2f82d",
+ },
+ },
+ Message: "Rename files\n",
+ Tree: &api.CommitMeta{
+ URL: setting.AppURL + "api/v1/repos/user2/lfs/git/trees/5307376dc3a5557dc1c403c29a8984668ca9ecb5",
+ SHA: "5307376dc3a5557dc1c403c29a8984668ca9ecb5",
+ },
+ },
+ Verification: &api.PayloadCommitVerification{
+ Verified: false,
+ Reason: "gpg.error.not_signed_commit",
+ Signature: "",
+ Payload: "",
+ },
+ }
+}
+
func TestChangeRepoFilesForCreate(t *testing.T) {
// setup
onGiteaRun(t, func(t *testing.T, u *url.URL) {
@@ -268,14 +416,14 @@ func TestChangeRepoFilesForCreate(t *testing.T) {
commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch)
lastCommit, _ := gitRepo.GetCommitByPath("new/file.txt")
- expectedFileResponse := getExpectedFileResponseForRepofilesCreate(commitID, lastCommit.ID.String())
+ expectedFileResponse := getExpectedFileResponseForRepoFilesCreate(commitID, lastCommit)
assert.NotNil(t, expectedFileResponse)
if expectedFileResponse != nil {
- assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0])
- assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA)
- assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL)
- assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email)
- assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name)
+ assert.Equal(t, expectedFileResponse.Content, filesResponse.Files[0])
+ assert.Equal(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA)
+ assert.Equal(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL)
+ assert.Equal(t, expectedFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email)
+ assert.Equal(t, expectedFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name)
}
})
}
@@ -305,12 +453,12 @@ func TestChangeRepoFilesForUpdate(t *testing.T) {
commit, _ := gitRepo.GetBranchCommit(opts.NewBranch)
lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath)
- expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String())
- assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0])
- assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA)
- assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL)
- assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email)
- assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name)
+ expectedFileResponse := getExpectedFileResponseForRepoFilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String(), lastCommit.Committer.When, lastCommit.Author.When)
+ assert.Equal(t, expectedFileResponse.Content, filesResponse.Files[0])
+ assert.Equal(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA)
+ assert.Equal(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL)
+ assert.Equal(t, expectedFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email)
+ assert.Equal(t, expectedFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name)
})
}
@@ -341,7 +489,7 @@ func TestChangeRepoFilesForUpdateWithFileMove(t *testing.T) {
commit, _ := gitRepo.GetBranchCommit(opts.NewBranch)
lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath)
- expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String())
+ expectedFileResponse := getExpectedFileResponseForRepoFilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String(), lastCommit.Committer.When, lastCommit.Author.When)
// assert that the old file no longer exists in the last commit of the branch
fromEntry, err := commit.GetTreeEntryByPath(opts.Files[0].FromTreePath)
switch err.(type) {
@@ -355,12 +503,44 @@ func TestChangeRepoFilesForUpdateWithFileMove(t *testing.T) {
assert.Nil(t, fromEntry) // Should no longer exist here
assert.NotNil(t, toEntry) // Should exist here
// assert SHA has remained the same but paths use the new file name
- assert.EqualValues(t, expectedFileResponse.Content.SHA, filesResponse.Files[0].SHA)
- assert.EqualValues(t, expectedFileResponse.Content.Name, filesResponse.Files[0].Name)
- assert.EqualValues(t, expectedFileResponse.Content.Path, filesResponse.Files[0].Path)
- assert.EqualValues(t, expectedFileResponse.Content.URL, filesResponse.Files[0].URL)
- assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA)
- assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL)
+ assert.Equal(t, expectedFileResponse.Content.SHA, filesResponse.Files[0].SHA)
+ assert.Equal(t, expectedFileResponse.Content.Name, filesResponse.Files[0].Name)
+ assert.Equal(t, expectedFileResponse.Content.Path, filesResponse.Files[0].Path)
+ assert.Equal(t, expectedFileResponse.Content.URL, filesResponse.Files[0].URL)
+ assert.Equal(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA)
+ assert.Equal(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL)
+ })
+}
+
+func TestChangeRepoFilesForUpdateWithFileRename(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ ctx, _ := contexttest.MockContext(t, "user2/lfs")
+ ctx.SetPathParam("id", "54")
+ contexttest.LoadRepo(t, ctx, 54)
+ contexttest.LoadRepoCommit(t, ctx)
+ contexttest.LoadUser(t, ctx, 2)
+ contexttest.LoadGitRepo(t, ctx)
+ defer ctx.Repo.GitRepo.Close()
+
+ repo := ctx.Repo.Repository
+ opts := getUpdateRepoFilesRenameOptions(repo)
+
+ // test
+ filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, ctx.Doer, opts)
+
+ // asserts
+ assert.NoError(t, err)
+ gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo)
+ defer gitRepo.Close()
+
+ commit, _ := gitRepo.GetBranchCommit(repo.DefaultBranch)
+ lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath)
+ expectedFileResponse := getExpectedFileResponseForRepoFilesUpdateRename(commit.ID.String(), lastCommit.ID.String())
+ for _, file := range filesResponse.Files {
+ file.LastCommitterDate, file.LastAuthorDate = nil, nil // there might be different time in one operation, so we ignore them
+ }
+ assert.Len(t, filesResponse.Files, 4)
+ assert.Equal(t, expectedFileResponse.Files, filesResponse.Files)
})
}
@@ -392,8 +572,8 @@ func TestChangeRepoFilesWithoutBranchNames(t *testing.T) {
commit, _ := gitRepo.GetBranchCommit(repo.DefaultBranch)
lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath)
- expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String())
- assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0])
+ expectedFileResponse := getExpectedFileResponseForRepoFilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String(), lastCommit.Committer.When, lastCommit.Author.When)
+ assert.Equal(t, expectedFileResponse.Content, filesResponse.Files[0])
})
}
@@ -418,13 +598,13 @@ func testDeleteRepoFiles(t *testing.T, u *url.URL) {
t.Run("Delete README.md file", func(t *testing.T) {
filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts)
assert.NoError(t, err)
- expectedFileResponse := getExpectedFileResponseForRepofilesDelete()
+ expectedFileResponse := getExpectedFileResponseForRepoFilesDelete()
assert.NotNil(t, filesResponse)
assert.Nil(t, filesResponse.Files[0])
- assert.EqualValues(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message)
- assert.EqualValues(t, expectedFileResponse.Commit.Author.Identity, filesResponse.Commit.Author.Identity)
- assert.EqualValues(t, expectedFileResponse.Commit.Committer.Identity, filesResponse.Commit.Committer.Identity)
- assert.EqualValues(t, expectedFileResponse.Verification, filesResponse.Verification)
+ assert.Equal(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message)
+ assert.Equal(t, expectedFileResponse.Commit.Author.Identity, filesResponse.Commit.Author.Identity)
+ assert.Equal(t, expectedFileResponse.Commit.Committer.Identity, filesResponse.Commit.Committer.Identity)
+ assert.Equal(t, expectedFileResponse.Verification, filesResponse.Verification)
})
t.Run("Verify README.md has been deleted", func(t *testing.T) {
@@ -460,13 +640,13 @@ func testDeleteRepoFilesWithoutBranchNames(t *testing.T, u *url.URL) {
t.Run("Delete README.md without Branch Name", func(t *testing.T) {
filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts)
assert.NoError(t, err)
- expectedFileResponse := getExpectedFileResponseForRepofilesDelete()
+ expectedFileResponse := getExpectedFileResponseForRepoFilesDelete()
assert.NotNil(t, filesResponse)
assert.Nil(t, filesResponse.Files[0])
- assert.EqualValues(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message)
- assert.EqualValues(t, expectedFileResponse.Commit.Author.Identity, filesResponse.Commit.Author.Identity)
- assert.EqualValues(t, expectedFileResponse.Commit.Committer.Identity, filesResponse.Commit.Committer.Identity)
- assert.EqualValues(t, expectedFileResponse.Verification, filesResponse.Verification)
+ assert.Equal(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message)
+ assert.Equal(t, expectedFileResponse.Commit.Author.Identity, filesResponse.Commit.Author.Identity)
+ assert.Equal(t, expectedFileResponse.Commit.Committer.Identity, filesResponse.Commit.Committer.Identity)
+ assert.Equal(t, expectedFileResponse.Verification, filesResponse.Verification)
})
}
@@ -490,7 +670,7 @@ func TestChangeRepoFilesErrors(t *testing.T) {
filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts)
assert.Error(t, err)
assert.Nil(t, filesResponse)
- expectedError := "branch does not exist [name: " + opts.OldBranch + "]"
+ expectedError := fmt.Sprintf("branch does not exist [repo_id: %d name: %s]", repo.ID, opts.OldBranch)
assert.EqualError(t, err, expectedError)
})
diff --git a/tests/integration/session_test.go b/tests/integration/session_test.go
index b18a25827d..f72e2e24b7 100644
--- a/tests/integration/session_test.go
+++ b/tests/integration/session_test.go
@@ -27,11 +27,11 @@ func Test_RegenerateSession(t *testing.T) {
sess, err := auth.RegenerateSession(db.DefaultContext, "", key)
assert.NoError(t, err)
- assert.EqualValues(t, key, sess.Key)
+ assert.Equal(t, key, sess.Key)
assert.Empty(t, sess.Data)
sess, err = auth.ReadSession(db.DefaultContext, key2)
assert.NoError(t, err)
- assert.EqualValues(t, key2, sess.Key)
+ assert.Equal(t, key2, sess.Key)
assert.Empty(t, sess.Data)
}
diff --git a/tests/integration/setting_test.go b/tests/integration/setting_test.go
index 9dad9ca716..64fd28c5e9 100644
--- a/tests/integration/setting_test.go
+++ b/tests/integration/setting_test.go
@@ -8,6 +8,7 @@ import (
"testing"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
@@ -92,8 +93,7 @@ func TestSettingShowUserEmailProfile(t *testing.T) {
func TestSettingLandingPage(t *testing.T) {
defer tests.PrepareTestEnv(t)()
-
- landingPage := setting.LandingPageURL
+ defer test.MockVariableValue(&setting.LandingPageURL)()
setting.LandingPageURL = setting.LandingPageHome
req := NewRequest(t, "GET", "/")
@@ -113,6 +113,4 @@ func TestSettingLandingPage(t *testing.T) {
req = NewRequest(t, "GET", "/")
resp = MakeRequest(t, req, http.StatusSeeOther)
assert.Equal(t, "/user/login", resp.Header().Get("Location"))
-
- setting.LandingPageURL = landingPage
}
diff --git a/tests/integration/signin_test.go b/tests/integration/signin_test.go
index d7c0b1bcd3..67af5b5877 100644
--- a/tests/integration/signin_test.go
+++ b/tests/integration/signin_test.go
@@ -15,8 +15,12 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/translation"
+ "code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/routers"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/tests"
+ "github.com/markbates/goth"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -32,7 +36,7 @@ func testLoginFailed(t *testing.T, username, password, message string) {
htmlDoc := NewHTMLParser(t, resp.Body)
resultMsg := htmlDoc.doc.Find(".ui.message>p").Text()
- assert.EqualValues(t, message, resultMsg)
+ assert.Equal(t, message, resultMsg)
}
func TestSignin(t *testing.T) {
@@ -76,7 +80,7 @@ func TestSigninWithRememberMe(t *testing.T) {
})
session.MakeRequest(t, req, http.StatusSeeOther)
- c := session.GetCookie(setting.CookieRememberName)
+ c := session.GetRawCookie(setting.CookieRememberName)
assert.NotNil(t, c)
session = emptyTestSession(t)
@@ -95,19 +99,32 @@ func TestSigninWithRememberMe(t *testing.T) {
session.MakeRequest(t, req, http.StatusOK)
}
-func TestEnablePasswordSignInForm(t *testing.T) {
+func TestEnablePasswordSignInFormAndEnablePasskeyAuth(t *testing.T) {
defer tests.PrepareTestEnv(t)()
+ mockLinkAccount := func(ctx *context.Context) {
+ gothUser := goth.User{Email: "invalid-email", Name: "."}
+ _ = ctx.Session.Set("linkAccountGothUser", gothUser)
+ }
+
t.Run("EnablePasswordSignInForm=false", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
defer test.MockVariableValue(&setting.Service.EnablePasswordSignInForm, false)()
req := NewRequest(t, "GET", "/user/login")
resp := MakeRequest(t, req, http.StatusOK)
- NewHTMLParser(t, resp.Body).AssertElement(t, "form[action='/user/login']", false)
+ doc := NewHTMLParser(t, resp.Body)
+ AssertHTMLElement(t, doc, "form[action='/user/login']", false)
req = NewRequest(t, "POST", "/user/login")
MakeRequest(t, req, http.StatusForbidden)
+
+ req = NewRequest(t, "GET", "/user/link_account")
+ defer web.RouteMockReset()
+ web.RouteMock(web.MockAfterMiddlewares, mockLinkAccount)
+ resp = MakeRequest(t, req, http.StatusOK)
+ doc = NewHTMLParser(t, resp.Body)
+ AssertHTMLElement(t, doc, "form[action='/user/link_account_signin']", false)
})
t.Run("EnablePasswordSignInForm=true", func(t *testing.T) {
@@ -116,9 +133,66 @@ func TestEnablePasswordSignInForm(t *testing.T) {
req := NewRequest(t, "GET", "/user/login")
resp := MakeRequest(t, req, http.StatusOK)
- NewHTMLParser(t, resp.Body).AssertElement(t, "form[action='/user/login']", true)
+ doc := NewHTMLParser(t, resp.Body)
+ AssertHTMLElement(t, doc, "form[action='/user/login']", true)
req = NewRequest(t, "POST", "/user/login")
MakeRequest(t, req, http.StatusOK)
+
+ req = NewRequest(t, "GET", "/user/link_account")
+ defer web.RouteMockReset()
+ web.RouteMock(web.MockAfterMiddlewares, mockLinkAccount)
+ resp = MakeRequest(t, req, http.StatusOK)
+ doc = NewHTMLParser(t, resp.Body)
+ AssertHTMLElement(t, doc, "form[action='/user/link_account_signin']", true)
+ })
+
+ t.Run("EnablePasskeyAuth=false", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+ defer test.MockVariableValue(&setting.Service.EnablePasskeyAuth, false)()
+
+ req := NewRequest(t, "GET", "/user/login")
+ resp := MakeRequest(t, req, http.StatusOK)
+ doc := NewHTMLParser(t, resp.Body)
+ AssertHTMLElement(t, doc, ".signin-passkey", false)
+ })
+
+ t.Run("EnablePasskeyAuth=true", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+ defer test.MockVariableValue(&setting.Service.EnablePasskeyAuth, true)()
+
+ req := NewRequest(t, "GET", "/user/login")
+ resp := MakeRequest(t, req, http.StatusOK)
+ doc := NewHTMLParser(t, resp.Body)
+ AssertHTMLElement(t, doc, ".signin-passkey", true)
+ })
+}
+
+func TestRequireSignInView(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+ t.Run("NoRequireSignInView", func(t *testing.T) {
+ require.False(t, setting.Service.RequireSignInViewStrict)
+ require.False(t, setting.Service.BlockAnonymousAccessExpensive)
+ req := NewRequest(t, "GET", "/user2/repo1/src/branch/master")
+ MakeRequest(t, req, http.StatusOK)
+ })
+ t.Run("RequireSignInView", func(t *testing.T) {
+ defer test.MockVariableValue(&setting.Service.RequireSignInViewStrict, true)()
+ defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())()
+ req := NewRequest(t, "GET", "/user2/repo1/src/branch/master")
+ resp := MakeRequest(t, req, http.StatusSeeOther)
+ assert.Equal(t, "/user/login", resp.Header().Get("Location"))
+ })
+ t.Run("BlockAnonymousAccessExpensive", func(t *testing.T) {
+ defer test.MockVariableValue(&setting.Service.RequireSignInViewStrict, false)()
+ defer test.MockVariableValue(&setting.Service.BlockAnonymousAccessExpensive, true)()
+ defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())()
+
+ req := NewRequest(t, "GET", "/user2/repo1")
+ MakeRequest(t, req, http.StatusOK)
+
+ req = NewRequest(t, "GET", "/user2/repo1/src/branch/master")
+ resp := MakeRequest(t, req, http.StatusSeeOther)
+ assert.Equal(t, "/user/login", resp.Header().Get("Location"))
})
}
diff --git a/tests/integration/signup_test.go b/tests/integration/signup_test.go
index e86851352e..c08f57d33e 100644
--- a/tests/integration/signup_test.go
+++ b/tests/integration/signup_test.go
@@ -22,8 +22,7 @@ import (
func TestSignup(t *testing.T) {
defer tests.PrepareTestEnv(t)()
-
- setting.Service.EnableCaptcha = false
+ defer test.MockVariableValue(&setting.Service.EnableCaptcha, false)()
req := NewRequestWithValues(t, "POST", "/user/sign_up", map[string]string{
"user_name": "exampleUser",
@@ -40,9 +39,8 @@ func TestSignup(t *testing.T) {
func TestSignupAsRestricted(t *testing.T) {
defer tests.PrepareTestEnv(t)()
-
- setting.Service.EnableCaptcha = false
- setting.Service.DefaultUserIsRestricted = true
+ defer test.MockVariableValue(&setting.Service.EnableCaptcha, false)()
+ defer test.MockVariableValue(&setting.Service.DefaultUserIsRestricted, true)()
req := NewRequestWithValues(t, "POST", "/user/sign_up", map[string]string{
"user_name": "restrictedUser",
@@ -62,8 +60,7 @@ func TestSignupAsRestricted(t *testing.T) {
func TestSignupEmailValidation(t *testing.T) {
defer tests.PrepareTestEnv(t)()
-
- setting.Service.EnableCaptcha = false
+ defer test.MockVariableValue(&setting.Service.EnableCaptcha, false)()
tests := []struct {
email string
diff --git a/tests/integration/ssh_key_test.go b/tests/integration/ssh_key_test.go
index eb3a3e926a..b34a986be3 100644
--- a/tests/integration/ssh_key_test.go
+++ b/tests/integration/ssh_key_test.go
@@ -27,7 +27,7 @@ func doCheckRepositoryEmptyStatus(ctx APITestContext, isEmpty bool) func(*testin
func doAddChangesToCheckout(dstPath, filename string) func(*testing.T) {
return func(t *testing.T) {
- assert.NoError(t, os.WriteFile(filepath.Join(dstPath, filename), []byte(fmt.Sprintf("# Testing Repository\n\nOriginally created in: %s at time: %v", dstPath, time.Now())), 0o644))
+ assert.NoError(t, os.WriteFile(filepath.Join(dstPath, filename), fmt.Appendf(nil, "# Testing Repository\n\nOriginally created in: %s at time: %v", dstPath, time.Now()), 0o644))
assert.NoError(t, git.AddChanges(dstPath, true))
signature := git.Signature{
Email: "test@example.com",
@@ -51,7 +51,7 @@ func testPushDeployKeyOnEmptyRepo(t *testing.T, u *url.URL) {
ctx := NewAPITestContext(t, "user2", "deploy-key-empty-repo-1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
ctxWithDeleteRepo := NewAPITestContext(t, "user2", "deploy-key-empty-repo-1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
- keyname := fmt.Sprintf("%s-push", ctx.Reponame)
+ keyname := ctx.Reponame + "-push"
u.Path = ctx.GitPath()
t.Run("CreateEmptyRepository", doAPICreateRepository(ctx, true))
@@ -89,7 +89,7 @@ func testKeyOnlyOneType(t *testing.T, u *url.URL) {
reponame := "ssh-key-test-repo"
username := "user2"
u.Path = fmt.Sprintf("%s/%s.git", username, reponame)
- keyname := fmt.Sprintf("%s-push", reponame)
+ keyname := reponame + "-push"
// OK login
ctx := NewAPITestContext(t, username, reponame, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
diff --git a/tests/integration/timetracking_test.go b/tests/integration/timetracking_test.go
index d459de5df6..4e8109be96 100644
--- a/tests/integration/timetracking_test.go
+++ b/tests/integration/timetracking_test.go
@@ -42,15 +42,15 @@ func testViewTimetrackingControls(t *testing.T, session *TestSession, user, repo
htmlDoc := NewHTMLParser(t, resp.Body)
- htmlDoc.AssertElement(t, ".issue-start-time", canTrackTime)
- htmlDoc.AssertElement(t, ".issue-add-time", canTrackTime)
+ AssertHTMLElement(t, htmlDoc, ".issue-start-time", canTrackTime)
+ AssertHTMLElement(t, htmlDoc, ".issue-add-time", canTrackTime)
issueLink := path.Join(user, repo, "issues", issue)
- req = NewRequestWithValues(t, "POST", path.Join(issueLink, "times", "stopwatch", "toggle"), map[string]string{
+ reqStart := NewRequestWithValues(t, "POST", path.Join(issueLink, "times", "stopwatch", "start"), map[string]string{
"_csrf": htmlDoc.GetCSRF(),
})
if canTrackTime {
- session.MakeRequest(t, req, http.StatusOK)
+ session.MakeRequest(t, reqStart, http.StatusOK)
req = NewRequest(t, "GET", issueLink)
resp = session.MakeRequest(t, req, http.StatusOK)
@@ -59,16 +59,16 @@ func testViewTimetrackingControls(t *testing.T, session *TestSession, user, repo
events := htmlDoc.doc.Find(".event > span.text")
assert.Contains(t, events.Last().Text(), "started working")
- htmlDoc.AssertElement(t, ".issue-stop-time", true)
- htmlDoc.AssertElement(t, ".issue-cancel-time", true)
+ AssertHTMLElement(t, htmlDoc, ".issue-stop-time", true)
+ AssertHTMLElement(t, htmlDoc, ".issue-cancel-time", true)
// Sleep for 1 second to not get wrong order for stopping timer
time.Sleep(time.Second)
- req = NewRequestWithValues(t, "POST", path.Join(issueLink, "times", "stopwatch", "toggle"), map[string]string{
+ reqStop := NewRequestWithValues(t, "POST", path.Join(issueLink, "times", "stopwatch", "stop"), map[string]string{
"_csrf": htmlDoc.GetCSRF(),
})
- session.MakeRequest(t, req, http.StatusOK)
+ session.MakeRequest(t, reqStop, http.StatusOK)
req = NewRequest(t, "GET", issueLink)
resp = session.MakeRequest(t, req, http.StatusOK)
@@ -77,6 +77,6 @@ func testViewTimetrackingControls(t *testing.T, session *TestSession, user, repo
events = htmlDoc.doc.Find(".event > span.text")
assert.Contains(t, events.Last().Text(), "worked for ")
} else {
- session.MakeRequest(t, req, http.StatusNotFound)
+ session.MakeRequest(t, reqStart, http.StatusNotFound)
}
}
diff --git a/tests/integration/user_avatar_test.go b/tests/integration/user_avatar_test.go
index caca9a3e56..14ea012ac8 100644
--- a/tests/integration/user_avatar_test.go
+++ b/tests/integration/user_avatar_test.go
@@ -5,89 +5,87 @@ package integration
import (
"bytes"
- "fmt"
"image/png"
"io"
"mime/multipart"
"net/http"
- "net/url"
"testing"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/avatar"
+ "code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
)
func TestUserAvatar(t *testing.T) {
- onGiteaRun(t, func(t *testing.T, u *url.URL) {
- user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo3, is an org
+ defer tests.PrepareTestEnv(t)()
+ user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo3, is an org
- seed := user2.Email
- if len(seed) == 0 {
- seed = user2.Name
- }
+ seed := user2.Email
+ if len(seed) == 0 {
+ seed = user2.Name
+ }
- img, err := avatar.RandomImage([]byte(seed))
- if err != nil {
- assert.NoError(t, err)
- return
- }
+ img, err := avatar.RandomImage([]byte(seed))
+ if err != nil {
+ assert.NoError(t, err)
+ return
+ }
- session := loginUser(t, "user2")
- csrf := GetUserCSRFToken(t, session)
+ session := loginUser(t, "user2")
+ csrf := GetUserCSRFToken(t, session)
- imgData := &bytes.Buffer{}
+ imgData := &bytes.Buffer{}
- body := &bytes.Buffer{}
+ body := &bytes.Buffer{}
- // Setup multi-part
- writer := multipart.NewWriter(body)
- writer.WriteField("source", "local")
- part, err := writer.CreateFormFile("avatar", "avatar-for-testuseravatar.png")
- if err != nil {
- assert.NoError(t, err)
- return
- }
+ // Setup multi-part
+ writer := multipart.NewWriter(body)
+ writer.WriteField("source", "local")
+ part, err := writer.CreateFormFile("avatar", "avatar-for-testuseravatar.png")
+ if err != nil {
+ assert.NoError(t, err)
+ return
+ }
- if err := png.Encode(imgData, img); err != nil {
- assert.NoError(t, err)
- return
- }
+ if err := png.Encode(imgData, img); err != nil {
+ assert.NoError(t, err)
+ return
+ }
- if _, err := io.Copy(part, imgData); err != nil {
- assert.NoError(t, err)
- return
- }
+ if _, err := io.Copy(part, imgData); err != nil {
+ assert.NoError(t, err)
+ return
+ }
- if err := writer.Close(); err != nil {
- assert.NoError(t, err)
- return
- }
+ if err := writer.Close(); err != nil {
+ assert.NoError(t, err)
+ return
+ }
- req := NewRequestWithBody(t, "POST", "/user/settings/avatar", body)
- req.Header.Add("X-Csrf-Token", csrf)
- req.Header.Add("Content-Type", writer.FormDataContentType())
+ req := NewRequestWithBody(t, "POST", "/user/settings/avatar", body)
+ req.Header.Add("X-Csrf-Token", csrf)
+ req.Header.Add("Content-Type", writer.FormDataContentType())
- session.MakeRequest(t, req, http.StatusSeeOther)
+ session.MakeRequest(t, req, http.StatusSeeOther)
- user2 = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo3, is an org
+ user2 = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo3, is an org
- req = NewRequest(t, "GET", user2.AvatarLinkWithSize(db.DefaultContext, 0))
- _ = session.MakeRequest(t, req, http.StatusOK)
+ req = NewRequest(t, "GET", user2.AvatarLinkWithSize(db.DefaultContext, 0))
+ _ = session.MakeRequest(t, req, http.StatusOK)
- testGetAvatarRedirect(t, user2)
+ testGetAvatarRedirect(t, user2)
- // Can't test if the response matches because the image is re-generated on upload but checking that this at least doesn't give a 404 should be enough.
- })
+ // Can't test if the response matches because the image is re-generated on upload but checking that this at least doesn't give a 404 should be enough.
}
func testGetAvatarRedirect(t *testing.T, user *user_model.User) {
- t.Run(fmt.Sprintf("getAvatarRedirect_%s", user.Name), func(t *testing.T) {
+ t.Run("getAvatarRedirect_"+user.Name, func(t *testing.T) {
req := NewRequestf(t, "GET", "/%s.png", user.Name)
resp := MakeRequest(t, req, http.StatusSeeOther)
- assert.EqualValues(t, fmt.Sprintf("/avatars/%s", user.Avatar), resp.Header().Get("location"))
+ assert.Equal(t, "/avatars/"+user.Avatar, resp.Header().Get("location"))
})
}
diff --git a/tests/integration/user_settings_test.go b/tests/integration/user_settings_test.go
index d8402eb25f..eab1a72ed5 100644
--- a/tests/integration/user_settings_test.go
+++ b/tests/integration/user_settings_test.go
@@ -19,21 +19,21 @@ import (
func assertNavbar(t *testing.T, doc *HTMLDoc) {
// Only show the account page if users can change their email notifications, delete themselves, or manage credentials
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureDeletion, setting.UserFeatureManageCredentials) && !setting.Service.EnableNotifyMail {
- doc.AssertElement(t, ".menu a[href='/user/settings/account']", false)
+ AssertHTMLElement(t, doc, ".menu a[href='/user/settings/account']", false)
} else {
- doc.AssertElement(t, ".menu a[href='/user/settings/account']", true)
+ AssertHTMLElement(t, doc, ".menu a[href='/user/settings/account']", true)
}
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageMFA, setting.UserFeatureManageCredentials) {
- doc.AssertElement(t, ".menu a[href='/user/settings/security']", false)
+ AssertHTMLElement(t, doc, ".menu a[href='/user/settings/security']", false)
} else {
- doc.AssertElement(t, ".menu a[href='/user/settings/security']", true)
+ AssertHTMLElement(t, doc, ".menu a[href='/user/settings/security']", true)
}
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageSSHKeys, setting.UserFeatureManageGPGKeys) {
- doc.AssertElement(t, ".menu a[href='/user/settings/keys']", false)
+ AssertHTMLElement(t, doc, ".menu a[href='/user/settings/keys']", false)
} else {
- doc.AssertElement(t, ".menu a[href='/user/settings/keys']", true)
+ AssertHTMLElement(t, doc, ".menu a[href='/user/settings/keys']", true)
}
}
@@ -64,11 +64,11 @@ func TestUserSettingsAccount(t *testing.T) {
doc := NewHTMLParser(t, resp.Body)
// account navbar should display
- doc.AssertElement(t, ".menu a[href='/user/settings/account']", true)
+ AssertHTMLElement(t, doc, ".menu a[href='/user/settings/account']", true)
- doc.AssertElement(t, "#password", true)
- doc.AssertElement(t, "#email", true)
- doc.AssertElement(t, "#delete-form", true)
+ AssertHTMLElement(t, doc, "#password", true)
+ AssertHTMLElement(t, doc, "#email", true)
+ AssertHTMLElement(t, doc, "#delete-form", true)
})
t.Run("credentials disabled", func(t *testing.T) {
@@ -83,9 +83,9 @@ func TestUserSettingsAccount(t *testing.T) {
assertNavbar(t, doc)
- doc.AssertElement(t, "#password", false)
- doc.AssertElement(t, "#email", false)
- doc.AssertElement(t, "#delete-form", true)
+ AssertHTMLElement(t, doc, "#password", false)
+ AssertHTMLElement(t, doc, "#email", false)
+ AssertHTMLElement(t, doc, "#delete-form", true)
})
t.Run("deletion disabled", func(t *testing.T) {
@@ -100,9 +100,9 @@ func TestUserSettingsAccount(t *testing.T) {
assertNavbar(t, doc)
- doc.AssertElement(t, "#password", true)
- doc.AssertElement(t, "#email", true)
- doc.AssertElement(t, "#delete-form", false)
+ AssertHTMLElement(t, doc, "#password", true)
+ AssertHTMLElement(t, doc, "#email", true)
+ AssertHTMLElement(t, doc, "#delete-form", false)
})
t.Run("deletion, credentials and email notifications are disabled", func(t *testing.T) {
@@ -249,7 +249,7 @@ func TestUserSettingsSecurity(t *testing.T) {
assertNavbar(t, doc)
- doc.AssertElement(t, "#register-webauthn", true)
+ AssertHTMLElement(t, doc, "#register-webauthn", true)
})
t.Run("mfa disabled", func(t *testing.T) {
@@ -263,7 +263,7 @@ func TestUserSettingsSecurity(t *testing.T) {
assertNavbar(t, doc)
- doc.AssertElement(t, "#register-webauthn", false)
+ AssertHTMLElement(t, doc, "#register-webauthn", false)
})
t.Run("credentials and mfa disabled", func(t *testing.T) {
@@ -356,8 +356,8 @@ func TestUserSettingsKeys(t *testing.T) {
assertNavbar(t, doc)
- doc.AssertElement(t, "#add-ssh-button", true)
- doc.AssertElement(t, "#add-gpg-key-panel", true)
+ AssertHTMLElement(t, doc, "#add-ssh-button", true)
+ AssertHTMLElement(t, doc, "#add-gpg-key-panel", true)
})
t.Run("ssh keys disabled", func(t *testing.T) {
@@ -372,8 +372,8 @@ func TestUserSettingsKeys(t *testing.T) {
assertNavbar(t, doc)
- doc.AssertElement(t, "#add-ssh-button", false)
- doc.AssertElement(t, "#add-gpg-key-panel", true)
+ AssertHTMLElement(t, doc, "#add-ssh-button", false)
+ AssertHTMLElement(t, doc, "#add-gpg-key-panel", true)
})
t.Run("gpg keys disabled", func(t *testing.T) {
@@ -388,8 +388,8 @@ func TestUserSettingsKeys(t *testing.T) {
assertNavbar(t, doc)
- doc.AssertElement(t, "#add-ssh-button", true)
- doc.AssertElement(t, "#add-gpg-key-panel", false)
+ AssertHTMLElement(t, doc, "#add-ssh-button", true)
+ AssertHTMLElement(t, doc, "#add-gpg-key-panel", false)
})
t.Run("ssh & gpg keys disabled", func(t *testing.T) {
diff --git a/tests/integration/user_test.go b/tests/integration/user_test.go
index 5b6f28d1ff..34692d9cab 100644
--- a/tests/integration/user_test.go
+++ b/tests/integration/user_test.go
@@ -134,8 +134,7 @@ Note: This user hasn't uploaded any GPG keys.
=twTO
------END PGP PUBLIC KEY BLOCK-----
-`)
+-----END PGP PUBLIC KEY BLOCK-----`)
// Import key
// User1 <user1@example.com>
session := loginUser(t, "user1")
@@ -169,8 +168,7 @@ C0TLXKur6NVYQMn01iyL+FZzRpEWNuYF3f9QeeLJ/+l2DafESNhNTy17+RPmacK6
7XhJ1v6JYuh8kaYaEz8OpZDeh7f6Ho6PzJrsy/TKTKhGgZNINj1iaPFyOkQgKR5M
GrE0MHOxUbc9tbtyk0F1SuzREUBH
=DDXw
------END PGP PUBLIC KEY BLOCK-----
-`)
+-----END PGP PUBLIC KEY BLOCK-----`)
// Export new key
testExportUserGPGKeys(t, "user1", `-----BEGIN PGP PUBLIC KEY BLOCK-----
@@ -201,8 +199,7 @@ C0TLXKur6NVYQMn01iyL+FZzRpEWNuYF3f9QeeLJ/+l2DafESNhNTy17+RPmacK6
7XhJ1v6JYuh8kaYaEz8OpZDeh7f6Ho6PzJrsy/TKTKhGgZNINj1iaPFyOkQgKR5M
GrE0MHOxUbc9tbtyk0F1SuzREUBH
=WFf5
------END PGP PUBLIC KEY BLOCK-----
-`)
+-----END PGP PUBLIC KEY BLOCK-----`)
}
func testExportUserGPGKeys(t *testing.T, user, expected string) {
@@ -220,12 +217,12 @@ func TestGetUserRss(t *testing.T) {
user34 := "the_34-user.with.all.allowedChars"
req := NewRequestf(t, "GET", "/%s.rss", user34)
resp := MakeRequest(t, req, http.StatusOK)
- if assert.EqualValues(t, "application/rss+xml;charset=utf-8", resp.Header().Get("Content-Type")) {
+ if assert.Equal(t, "application/rss+xml;charset=utf-8", resp.Header().Get("Content-Type")) {
rssDoc := NewHTMLParser(t, resp.Body).Find("channel")
title, _ := rssDoc.ChildrenFiltered("title").Html()
- assert.EqualValues(t, "Feed of &#34;the_1-user.with.all.allowedChars&#34;", title)
+ assert.Equal(t, "Feed of &#34;the_1-user.with.all.allowedChars&#34;", title)
description, _ := rssDoc.ChildrenFiltered("description").Html()
- assert.EqualValues(t, "&lt;p dir=&#34;auto&#34;&gt;some &lt;a href=&#34;https://commonmark.org/&#34; rel=&#34;nofollow&#34;&gt;commonmark&lt;/a&gt;!&lt;/p&gt;\n", description)
+ assert.Equal(t, "&lt;p dir=&#34;auto&#34;&gt;some &lt;a href=&#34;https://commonmark.org/&#34; rel=&#34;nofollow&#34;&gt;commonmark&lt;/a&gt;!&lt;/p&gt;\n", description)
}
req = NewRequestf(t, "GET", "/non-existent-user.rss")
@@ -250,18 +247,18 @@ func TestListStopWatches(t *testing.T) {
stopwatch := unittest.AssertExistsAndLoadBean(t, &issues_model.Stopwatch{UserID: owner.ID})
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: stopwatch.IssueID})
if assert.Len(t, apiWatches, 1) {
- assert.EqualValues(t, stopwatch.CreatedUnix.AsTime().Unix(), apiWatches[0].Created.Unix())
- assert.EqualValues(t, issue.Index, apiWatches[0].IssueIndex)
- assert.EqualValues(t, issue.Title, apiWatches[0].IssueTitle)
- assert.EqualValues(t, repo.Name, apiWatches[0].RepoName)
- assert.EqualValues(t, repo.OwnerName, apiWatches[0].RepoOwnerName)
+ assert.Equal(t, stopwatch.CreatedUnix.AsTime().Unix(), apiWatches[0].Created.Unix())
+ assert.Equal(t, issue.Index, apiWatches[0].IssueIndex)
+ assert.Equal(t, issue.Title, apiWatches[0].IssueTitle)
+ assert.Equal(t, repo.Name, apiWatches[0].RepoName)
+ assert.Equal(t, repo.OwnerName, apiWatches[0].RepoOwnerName)
assert.Positive(t, apiWatches[0].Seconds)
}
}
func TestUserLocationMapLink(t *testing.T) {
- setting.Service.UserLocationMapURL = "https://example/foo/"
defer tests.PrepareTestEnv(t)()
+ defer test.MockVariableValue(&setting.Service.UserLocationMapURL, "https://example/foo/")()
session := loginUser(t, "user2")
req := NewRequestWithValues(t, "POST", "/user/settings", map[string]string{
@@ -276,5 +273,5 @@ func TestUserLocationMapLink(t *testing.T) {
req = NewRequest(t, "GET", "/user2/")
resp := session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
- htmlDoc.AssertElement(t, `a[href="https://example/foo/A%2Fb"]`, true)
+ AssertHTMLElement(t, htmlDoc, `a[href="https://example/foo/A%2Fb"]`, true)
}
diff --git a/tests/integration/view_test.go b/tests/integration/view_test.go
index f434446801..9ed3e30857 100644
--- a/tests/integration/view_test.go
+++ b/tests/integration/view_test.go
@@ -25,3 +25,43 @@ func TestRenderFileSVGIsInImgTag(t *testing.T) {
assert.True(t, exists, "The SVG image should be in an <img> tag so that scripts in the SVG are not run")
assert.Equal(t, "/user2/repo2/raw/branch/master/line.svg", src)
}
+
+func TestCommitListActions(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+ session := loginUser(t, "user2")
+
+ t.Run("WikiRevisionList", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ req := NewRequest(t, "GET", "/user2/repo1/wiki/Home?action=_revision")
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ htmlDoc := NewHTMLParser(t, resp.Body)
+ AssertHTMLElement(t, htmlDoc, ".commit-list .copy-commit-id", true)
+ AssertHTMLElement(t, htmlDoc, `.commit-list .view-single-diff`, false)
+ AssertHTMLElement(t, htmlDoc, `.commit-list .view-commit-path`, false)
+ })
+
+ t.Run("RepoCommitList", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ req := NewRequest(t, "GET", "/user2/repo1/commits/branch/master")
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ htmlDoc := NewHTMLParser(t, resp.Body)
+
+ AssertHTMLElement(t, htmlDoc, `.commit-list .copy-commit-id`, true)
+ AssertHTMLElement(t, htmlDoc, `.commit-list .view-single-diff`, false)
+ AssertHTMLElement(t, htmlDoc, `.commit-list .view-commit-path`, true)
+ })
+
+ t.Run("RepoFileHistory", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ req := NewRequest(t, "GET", "/user2/repo1/commits/branch/master/README.md")
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ htmlDoc := NewHTMLParser(t, resp.Body)
+
+ AssertHTMLElement(t, htmlDoc, `.commit-list .copy-commit-id`, true)
+ AssertHTMLElement(t, htmlDoc, `.commit-list .view-single-diff`, true)
+ AssertHTMLElement(t, htmlDoc, `.commit-list .view-commit-path`, true)
+ })
+}
diff --git a/tests/integration/webfinger_test.go b/tests/integration/webfinger_test.go
index a1abc8d32b..757d442cd2 100644
--- a/tests/integration/webfinger_test.go
+++ b/tests/integration/webfinger_test.go
@@ -7,11 +7,13 @@ import (
"fmt"
"net/http"
"net/url"
+ "strconv"
"testing"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
@@ -19,11 +21,7 @@ import (
func TestWebfinger(t *testing.T) {
defer tests.PrepareTestEnv(t)()
-
- setting.Federation.Enabled = true
- defer func() {
- setting.Federation.Enabled = false
- }()
+ defer test.MockVariableValue(&setting.Federation.Enabled, true)()
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
@@ -52,7 +50,7 @@ func TestWebfinger(t *testing.T) {
var jrd webfingerJRD
DecodeJSON(t, resp, &jrd)
assert.Equal(t, "acct:user2@"+appURL.Host, jrd.Subject)
- assert.ElementsMatch(t, []string{user.HTMLURL(), appURL.String() + "api/v1/activitypub/user-id/" + fmt.Sprint(user.ID)}, jrd.Aliases)
+ assert.ElementsMatch(t, []string{user.HTMLURL(), appURL.String() + "api/v1/activitypub/user-id/" + strconv.FormatInt(user.ID, 10)}, jrd.Aliases)
req = NewRequest(t, "GET", fmt.Sprintf("/.well-known/webfinger?resource=acct:%s@%s", user.LowerName, "unknown.host"))
MakeRequest(t, req, http.StatusBadRequest)
@@ -63,6 +61,6 @@ func TestWebfinger(t *testing.T) {
req = NewRequest(t, "GET", fmt.Sprintf("/.well-known/webfinger?resource=acct:%s@%s", "user31", appURL.Host))
session.MakeRequest(t, req, http.StatusOK)
- req = NewRequest(t, "GET", fmt.Sprintf("/.well-known/webfinger?resource=mailto:%s", user.Email))
+ req = NewRequest(t, "GET", "/.well-known/webfinger?resource=mailto:"+user.Email)
MakeRequest(t, req, http.StatusNotFound)
}
diff --git a/tests/integration/wiki_test.go b/tests/integration/wiki_test.go
index bb73f71a45..ac458af378 100644
--- a/tests/integration/wiki_test.go
+++ b/tests/integration/wiki_test.go
@@ -4,8 +4,6 @@
package integration
import (
- "context"
- "fmt"
"net/http"
"net/url"
"os"
@@ -30,7 +28,7 @@ func assertFileExist(t *testing.T, p string) {
func assertFileEqual(t *testing.T, p string, content []byte) {
bs, err := os.ReadFile(p)
assert.NoError(t, err)
- assert.EqualValues(t, content, bs)
+ assert.Equal(t, content, bs)
}
func TestRepoCloneWiki(t *testing.T) {
@@ -39,11 +37,11 @@ func TestRepoCloneWiki(t *testing.T) {
dstPath := t.TempDir()
- r := fmt.Sprintf("%suser2/repo1.wiki.git", u.String())
+ r := u.String() + "user2/repo1.wiki.git"
u, _ = url.Parse(r)
u.User = url.UserPassword("user2", userPassword)
t.Run("Clone", func(t *testing.T) {
- assert.NoError(t, git.CloneWithArgs(context.Background(), git.AllowLFSFiltersArgs(), u.String(), dstPath, git.CloneRepoOptions{}))
+ assert.NoError(t, git.CloneWithArgs(t.Context(), git.AllowLFSFiltersArgs(), u.String(), dstPath, git.CloneRepoOptions{}))
assertFileEqual(t, filepath.Join(dstPath, "Home.md"), []byte("# Home page\n\nThis is the home page!\n"))
assertFileExist(t, filepath.Join(dstPath, "Page-With-Image.md"))
assertFileExist(t, filepath.Join(dstPath, "Page-With-Spaced-Name.md"))
@@ -70,6 +68,6 @@ func Test_RepoWikiPages(t *testing.T) {
href, _ := firstAnchor.Attr("href")
pagePath := strings.TrimPrefix(href, "/user2/repo1/wiki/")
- assert.EqualValues(t, expectedPagePaths[i], pagePath)
+ assert.Equal(t, expectedPagePaths[i], pagePath)
})
}
diff --git a/tests/integration/workflow_run_api_check_test.go b/tests/integration/workflow_run_api_check_test.go
new file mode 100644
index 0000000000..6a80bb5118
--- /dev/null
+++ b/tests/integration/workflow_run_api_check_test.go
@@ -0,0 +1,167 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package integration
+
+import (
+ "fmt"
+ "net/http"
+ "net/url"
+ "testing"
+
+ auth_model "code.gitea.io/gitea/models/auth"
+ api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/tests"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestAPIWorkflowRun(t *testing.T) {
+ t.Run("AdminRuns", func(t *testing.T) {
+ testAPIWorkflowRunBasic(t, "/api/v1/admin/actions", "User1", 802, auth_model.AccessTokenScopeReadAdmin, auth_model.AccessTokenScopeReadRepository)
+ })
+ t.Run("UserRuns", func(t *testing.T) {
+ testAPIWorkflowRunBasic(t, "/api/v1/user/actions", "User2", 803, auth_model.AccessTokenScopeReadUser, auth_model.AccessTokenScopeReadRepository)
+ })
+ t.Run("OrgRuns", func(t *testing.T) {
+ testAPIWorkflowRunBasic(t, "/api/v1/orgs/org3/actions", "User1", 802, auth_model.AccessTokenScopeReadOrganization, auth_model.AccessTokenScopeReadRepository)
+ })
+ t.Run("RepoRuns", func(t *testing.T) {
+ testAPIWorkflowRunBasic(t, "/api/v1/repos/org3/repo5/actions", "User2", 802, auth_model.AccessTokenScopeReadRepository)
+ })
+}
+
+func testAPIWorkflowRunBasic(t *testing.T, apiRootURL, userUsername string, runID int64, scope ...auth_model.AccessTokenScope) {
+ defer tests.PrepareTestEnv(t)()
+ token := getUserToken(t, userUsername, scope...)
+
+ apiRunsURL := fmt.Sprintf("%s/%s", apiRootURL, "runs")
+ req := NewRequest(t, "GET", apiRunsURL).AddTokenAuth(token)
+ runnerListResp := MakeRequest(t, req, http.StatusOK)
+ runnerList := api.ActionWorkflowRunsResponse{}
+ DecodeJSON(t, runnerListResp, &runnerList)
+
+ foundRun := false
+
+ for _, run := range runnerList.Entries {
+ // Verify filtering works
+ verifyWorkflowRunCanbeFoundWithStatusFilter(t, apiRunsURL, token, run.ID, "", run.Status, "", "", "", "")
+ verifyWorkflowRunCanbeFoundWithStatusFilter(t, apiRunsURL, token, run.ID, run.Conclusion, "", "", "", "", "")
+ verifyWorkflowRunCanbeFoundWithStatusFilter(t, apiRunsURL, token, run.ID, "", "", "", run.HeadBranch, "", "")
+ verifyWorkflowRunCanbeFoundWithStatusFilter(t, apiRunsURL, token, run.ID, "", "", run.Event, "", "", "")
+ verifyWorkflowRunCanbeFoundWithStatusFilter(t, apiRunsURL, token, run.ID, "", "", "", "", run.TriggerActor.UserName, "")
+ verifyWorkflowRunCanbeFoundWithStatusFilter(t, apiRunsURL, token, run.ID, "", "", "", "", run.TriggerActor.UserName, run.HeadSha)
+
+ // Verify run url works
+ req := NewRequest(t, "GET", run.URL).AddTokenAuth(token)
+ runResp := MakeRequest(t, req, http.StatusOK)
+ apiRun := api.ActionWorkflowRun{}
+ DecodeJSON(t, runResp, &apiRun)
+ assert.Equal(t, run.ID, apiRun.ID)
+ assert.Equal(t, run.Status, apiRun.Status)
+ assert.Equal(t, run.Conclusion, apiRun.Conclusion)
+ assert.Equal(t, run.Event, apiRun.Event)
+
+ // Verify jobs list works
+ req = NewRequest(t, "GET", fmt.Sprintf("%s/%s", run.URL, "jobs")).AddTokenAuth(token)
+ jobsResp := MakeRequest(t, req, http.StatusOK)
+ jobList := api.ActionWorkflowJobsResponse{}
+ DecodeJSON(t, jobsResp, &jobList)
+
+ if run.ID == runID {
+ foundRun = true
+ assert.Len(t, jobList.Entries, 1)
+ for _, job := range jobList.Entries {
+ // Check the jobs list of the run
+ verifyWorkflowJobCanbeFoundWithStatusFilter(t, fmt.Sprintf("%s/%s", run.URL, "jobs"), token, job.ID, "", job.Status)
+ verifyWorkflowJobCanbeFoundWithStatusFilter(t, fmt.Sprintf("%s/%s", run.URL, "jobs"), token, job.ID, job.Conclusion, "")
+ // Check the run independent job list
+ verifyWorkflowJobCanbeFoundWithStatusFilter(t, fmt.Sprintf("%s/%s", apiRootURL, "jobs"), token, job.ID, "", job.Status)
+ verifyWorkflowJobCanbeFoundWithStatusFilter(t, fmt.Sprintf("%s/%s", apiRootURL, "jobs"), token, job.ID, job.Conclusion, "")
+
+ // Verify job url works
+ req := NewRequest(t, "GET", job.URL).AddTokenAuth(token)
+ jobsResp := MakeRequest(t, req, http.StatusOK)
+ apiJob := api.ActionWorkflowJob{}
+ DecodeJSON(t, jobsResp, &apiJob)
+ assert.Equal(t, job.ID, apiJob.ID)
+ assert.Equal(t, job.RunID, apiJob.RunID)
+ assert.Equal(t, job.Status, apiJob.Status)
+ assert.Equal(t, job.Conclusion, apiJob.Conclusion)
+ }
+ }
+ }
+ assert.True(t, foundRun, "Expected to find run with ID %d", runID)
+}
+
+func verifyWorkflowRunCanbeFoundWithStatusFilter(t *testing.T, runAPIURL, token string, id int64, conclusion, status, event, branch, actor, headSHA string) {
+ filter := url.Values{}
+ if conclusion != "" {
+ filter.Add("status", conclusion)
+ }
+ if status != "" {
+ filter.Add("status", status)
+ }
+ if event != "" {
+ filter.Set("event", event)
+ }
+ if branch != "" {
+ filter.Set("branch", branch)
+ }
+ if actor != "" {
+ filter.Set("actor", actor)
+ }
+ if headSHA != "" {
+ filter.Set("head_sha", headSHA)
+ }
+ req := NewRequest(t, "GET", runAPIURL+"?"+filter.Encode()).AddTokenAuth(token)
+ runResp := MakeRequest(t, req, http.StatusOK)
+ runList := api.ActionWorkflowRunsResponse{}
+ DecodeJSON(t, runResp, &runList)
+
+ found := false
+ for _, run := range runList.Entries {
+ if conclusion != "" {
+ assert.Equal(t, conclusion, run.Conclusion)
+ }
+ if status != "" {
+ assert.Equal(t, status, run.Status)
+ }
+ if event != "" {
+ assert.Equal(t, event, run.Event)
+ }
+ if branch != "" {
+ assert.Equal(t, branch, run.HeadBranch)
+ }
+ if actor != "" {
+ assert.Equal(t, actor, run.Actor.UserName)
+ }
+ found = found || run.ID == id
+ }
+ assert.True(t, found, "Expected to find run with ID %d", id)
+}
+
+func verifyWorkflowJobCanbeFoundWithStatusFilter(t *testing.T, runAPIURL, token string, id int64, conclusion, status string) {
+ filter := conclusion
+ if filter == "" {
+ filter = status
+ }
+ if filter == "" {
+ return
+ }
+ req := NewRequest(t, "GET", runAPIURL+"?status="+filter).AddTokenAuth(token)
+ jobListResp := MakeRequest(t, req, http.StatusOK)
+ jobList := api.ActionWorkflowJobsResponse{}
+ DecodeJSON(t, jobListResp, &jobList)
+
+ found := false
+ for _, job := range jobList.Entries {
+ if conclusion != "" {
+ assert.Equal(t, conclusion, job.Conclusion)
+ } else {
+ assert.Equal(t, status, job.Status)
+ }
+ found = found || job.ID == id
+ }
+ assert.True(t, found, "Expected to find job with ID %d", id)
+}
diff --git a/tests/integration/xss_test.go b/tests/integration/xss_test.go
index a8eaa5fc62..9058fc210a 100644
--- a/tests/integration/xss_test.go
+++ b/tests/integration/xss_test.go
@@ -32,8 +32,8 @@ func TestXSSUserFullName(t *testing.T) {
req = NewRequestf(t, "GET", "/%s", user.Name)
resp := session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
- assert.EqualValues(t, 0, htmlDoc.doc.Find("script.evil").Length())
- assert.EqualValues(t, fullName,
+ assert.Equal(t, 0, htmlDoc.doc.Find("script.evil").Length())
+ assert.Equal(t, fullName,
htmlDoc.doc.Find("div.content").Find(".header.text.center").Text(),
)
}