code.gitea.io/gitea@v1.21.7/tests/integration/api_branch_test.go (about) 1 // Copyright 2017 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package integration 5 6 import ( 7 "net/http" 8 "net/url" 9 "testing" 10 11 auth_model "code.gitea.io/gitea/models/auth" 12 "code.gitea.io/gitea/models/db" 13 git_model "code.gitea.io/gitea/models/git" 14 api "code.gitea.io/gitea/modules/structs" 15 "code.gitea.io/gitea/tests" 16 17 "github.com/stretchr/testify/assert" 18 ) 19 20 func testAPIGetBranch(t *testing.T, branchName string, exists bool) { 21 token := getUserToken(t, "user2", auth_model.AccessTokenScopeReadRepository) 22 req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/branches/%s?token=%s", branchName, token) 23 resp := MakeRequest(t, req, NoExpectedStatus) 24 if !exists { 25 assert.EqualValues(t, http.StatusNotFound, resp.Code) 26 return 27 } 28 assert.EqualValues(t, http.StatusOK, resp.Code) 29 var branch api.Branch 30 DecodeJSON(t, resp, &branch) 31 assert.EqualValues(t, branchName, branch.Name) 32 assert.True(t, branch.UserCanPush) 33 assert.True(t, branch.UserCanMerge) 34 } 35 36 func testAPIGetBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) *api.BranchProtection { 37 token := getUserToken(t, "user2", auth_model.AccessTokenScopeReadRepository) 38 req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/branch_protections/%s?token=%s", branchName, token) 39 resp := MakeRequest(t, req, expectedHTTPStatus) 40 41 if resp.Code == http.StatusOK { 42 var branchProtection api.BranchProtection 43 DecodeJSON(t, resp, &branchProtection) 44 assert.EqualValues(t, branchName, branchProtection.RuleName) 45 return &branchProtection 46 } 47 return nil 48 } 49 50 func testAPICreateBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) { 51 token := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteRepository) 52 req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/branch_protections?token="+token, &api.BranchProtection{ 53 RuleName: branchName, 54 }) 55 resp := MakeRequest(t, req, expectedHTTPStatus) 56 57 if resp.Code == http.StatusCreated { 58 var branchProtection api.BranchProtection 59 DecodeJSON(t, resp, &branchProtection) 60 assert.EqualValues(t, branchName, branchProtection.RuleName) 61 } 62 } 63 64 func testAPIEditBranchProtection(t *testing.T, branchName string, body *api.BranchProtection, expectedHTTPStatus int) { 65 token := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteRepository) 66 req := NewRequestWithJSON(t, "PATCH", "/api/v1/repos/user2/repo1/branch_protections/"+branchName+"?token="+token, body) 67 resp := MakeRequest(t, req, expectedHTTPStatus) 68 69 if resp.Code == http.StatusOK { 70 var branchProtection api.BranchProtection 71 DecodeJSON(t, resp, &branchProtection) 72 assert.EqualValues(t, branchName, branchProtection.RuleName) 73 } 74 } 75 76 func testAPIDeleteBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) { 77 token := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteRepository) 78 req := NewRequestf(t, "DELETE", "/api/v1/repos/user2/repo1/branch_protections/%s?token=%s", branchName, token) 79 MakeRequest(t, req, expectedHTTPStatus) 80 } 81 82 func testAPIDeleteBranch(t *testing.T, branchName string, expectedHTTPStatus int) { 83 token := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteRepository) 84 req := NewRequestf(t, "DELETE", "/api/v1/repos/user2/repo1/branches/%s?token=%s", branchName, token) 85 MakeRequest(t, req, expectedHTTPStatus) 86 } 87 88 func TestAPIGetBranch(t *testing.T) { 89 defer tests.PrepareTestEnv(t)() 90 for _, test := range []struct { 91 BranchName string 92 Exists bool 93 }{ 94 {"master", true}, 95 {"master/doesnotexist", false}, 96 {"feature/1", true}, 97 {"feature/1/doesnotexist", false}, 98 } { 99 testAPIGetBranch(t, test.BranchName, test.Exists) 100 } 101 } 102 103 func TestAPICreateBranch(t *testing.T) { 104 onGiteaRun(t, testAPICreateBranches) 105 } 106 107 func testAPICreateBranches(t *testing.T, giteaURL *url.URL) { 108 username := "user2" 109 ctx := NewAPITestContext(t, username, "my-noo-repo", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) 110 giteaURL.Path = ctx.GitPath() 111 112 t.Run("CreateRepo", doAPICreateRepository(ctx, false)) 113 testCases := []struct { 114 OldBranch string 115 NewBranch string 116 ExpectedHTTPStatus int 117 }{ 118 // Creating branch from default branch 119 { 120 OldBranch: "", 121 NewBranch: "new_branch_from_default_branch", 122 ExpectedHTTPStatus: http.StatusCreated, 123 }, 124 // Creating branch from master 125 { 126 OldBranch: "master", 127 NewBranch: "new_branch_from_master_1", 128 ExpectedHTTPStatus: http.StatusCreated, 129 }, 130 // Trying to create from master but already exists 131 { 132 OldBranch: "master", 133 NewBranch: "new_branch_from_master_1", 134 ExpectedHTTPStatus: http.StatusConflict, 135 }, 136 // Trying to create from other branch (not default branch) 137 { 138 OldBranch: "new_branch_from_master_1", 139 NewBranch: "branch_2", 140 ExpectedHTTPStatus: http.StatusCreated, 141 }, 142 // Trying to create from a branch which does not exist 143 { 144 OldBranch: "does_not_exist", 145 NewBranch: "new_branch_from_non_existent", 146 ExpectedHTTPStatus: http.StatusNotFound, 147 }, 148 } 149 for _, test := range testCases { 150 session := ctx.Session 151 testAPICreateBranch(t, session, "user2", "my-noo-repo", test.OldBranch, test.NewBranch, test.ExpectedHTTPStatus) 152 } 153 } 154 155 func testAPICreateBranch(t testing.TB, session *TestSession, user, repo, oldBranch, newBranch string, status int) bool { 156 token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) 157 req := NewRequestWithJSON(t, "POST", "/api/v1/repos/"+user+"/"+repo+"/branches?token="+token, &api.CreateBranchRepoOption{ 158 BranchName: newBranch, 159 OldBranchName: oldBranch, 160 }) 161 resp := MakeRequest(t, req, status) 162 163 var branch api.Branch 164 DecodeJSON(t, resp, &branch) 165 166 if status == http.StatusCreated { 167 assert.EqualValues(t, newBranch, branch.Name) 168 } 169 170 return resp.Result().StatusCode == status 171 } 172 173 func TestAPIBranchProtection(t *testing.T) { 174 defer tests.PrepareTestEnv(t)() 175 176 // Branch protection on branch that not exist 177 testAPICreateBranchProtection(t, "master/doesnotexist", http.StatusCreated) 178 // Get branch protection on branch that exist but not branch protection 179 testAPIGetBranchProtection(t, "master", http.StatusNotFound) 180 181 testAPICreateBranchProtection(t, "master", http.StatusCreated) 182 // Can only create once 183 testAPICreateBranchProtection(t, "master", http.StatusForbidden) 184 185 // Can't delete a protected branch 186 testAPIDeleteBranch(t, "master", http.StatusForbidden) 187 188 testAPIGetBranchProtection(t, "master", http.StatusOK) 189 testAPIEditBranchProtection(t, "master", &api.BranchProtection{ 190 EnablePush: true, 191 }, http.StatusOK) 192 193 // enable status checks, require the "test1" check to pass 194 testAPIEditBranchProtection(t, "master", &api.BranchProtection{ 195 EnableStatusCheck: true, 196 StatusCheckContexts: []string{"test1"}, 197 }, http.StatusOK) 198 bp := testAPIGetBranchProtection(t, "master", http.StatusOK) 199 assert.Equal(t, true, bp.EnableStatusCheck) 200 assert.Equal(t, []string{"test1"}, bp.StatusCheckContexts) 201 202 // disable status checks, clear the list of required checks 203 testAPIEditBranchProtection(t, "master", &api.BranchProtection{ 204 EnableStatusCheck: false, 205 StatusCheckContexts: []string{}, 206 }, http.StatusOK) 207 bp = testAPIGetBranchProtection(t, "master", http.StatusOK) 208 assert.Equal(t, false, bp.EnableStatusCheck) 209 assert.Equal(t, []string{}, bp.StatusCheckContexts) 210 211 testAPIDeleteBranchProtection(t, "master", http.StatusNoContent) 212 213 // Test branch deletion 214 testAPIDeleteBranch(t, "master", http.StatusForbidden) 215 testAPIDeleteBranch(t, "branch2", http.StatusNoContent) 216 } 217 218 func TestAPICreateBranchWithSyncBranches(t *testing.T) { 219 defer tests.PrepareTestEnv(t)() 220 221 branches, err := git_model.FindBranches(db.DefaultContext, git_model.FindBranchOptions{ 222 RepoID: 1, 223 }) 224 assert.NoError(t, err) 225 assert.Len(t, branches, 4) 226 227 // make a broke repository with no branch on database 228 _, err = db.DeleteByBean(db.DefaultContext, git_model.Branch{RepoID: 1}) 229 assert.NoError(t, err) 230 231 onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { 232 ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) 233 giteaURL.Path = ctx.GitPath() 234 235 testAPICreateBranch(t, ctx.Session, "user2", "repo1", "", "new_branch", http.StatusCreated) 236 }) 237 238 branches, err = git_model.FindBranches(db.DefaultContext, git_model.FindBranchOptions{ 239 RepoID: 1, 240 }) 241 assert.NoError(t, err) 242 assert.Len(t, branches, 5) 243 244 branches, err = git_model.FindBranches(db.DefaultContext, git_model.FindBranchOptions{ 245 RepoID: 1, 246 Keyword: "new_branch", 247 }) 248 assert.NoError(t, err) 249 assert.Len(t, branches, 1) 250 }