You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

api_branch_test.go 8.5KB

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