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_pull_test.go 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package integration
  4. import (
  5. "fmt"
  6. "io/ioutil"
  7. "net/http"
  8. "testing"
  9. "code.gitea.io/gitea/models/db"
  10. issues_model "code.gitea.io/gitea/models/issues"
  11. repo_model "code.gitea.io/gitea/models/repo"
  12. "code.gitea.io/gitea/models/unittest"
  13. user_model "code.gitea.io/gitea/models/user"
  14. "code.gitea.io/gitea/modules/setting"
  15. api "code.gitea.io/gitea/modules/structs"
  16. "code.gitea.io/gitea/services/forms"
  17. issue_service "code.gitea.io/gitea/services/issue"
  18. "code.gitea.io/gitea/tests"
  19. "github.com/stretchr/testify/assert"
  20. )
  21. func TestAPIViewPulls(t *testing.T) {
  22. defer tests.PrepareTestEnv(t)()
  23. repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
  24. owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
  25. ctx := NewAPITestContext(t, "user2", repo.Name)
  26. req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/pulls?state=all&token="+ctx.Token, owner.Name, repo.Name)
  27. resp := ctx.Session.MakeRequest(t, req, http.StatusOK)
  28. var pulls []*api.PullRequest
  29. DecodeJSON(t, resp, &pulls)
  30. expectedLen := unittest.GetCount(t, &issues_model.Issue{RepoID: repo.ID}, unittest.Cond("is_pull = ?", true))
  31. assert.Len(t, pulls, expectedLen)
  32. pull := pulls[0]
  33. if assert.EqualValues(t, 5, pull.ID) {
  34. resp = ctx.Session.MakeRequest(t, NewRequest(t, "GET", pull.DiffURL), http.StatusOK)
  35. _, err := ioutil.ReadAll(resp.Body)
  36. assert.NoError(t, err)
  37. // TODO: use diff to generate stats to test against
  38. t.Run(fmt.Sprintf("APIGetPullFiles_%d", pull.ID),
  39. doAPIGetPullFiles(ctx, pull, func(t *testing.T, files []*api.ChangedFile) {
  40. if assert.Len(t, files, 1) {
  41. assert.EqualValues(t, "File-WoW", files[0].Filename)
  42. assert.EqualValues(t, "", files[0].PreviousFilename)
  43. assert.EqualValues(t, 1, files[0].Additions)
  44. assert.EqualValues(t, 1, files[0].Changes)
  45. assert.EqualValues(t, 0, files[0].Deletions)
  46. assert.EqualValues(t, "added", files[0].Status)
  47. }
  48. }))
  49. }
  50. }
  51. // TestAPIMergePullWIP ensures that we can't merge a WIP pull request
  52. func TestAPIMergePullWIP(t *testing.T) {
  53. defer tests.PrepareTestEnv(t)()
  54. repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
  55. owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
  56. pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{Status: issues_model.PullRequestStatusMergeable}, unittest.Cond("has_merged = ?", false))
  57. pr.LoadIssue(db.DefaultContext)
  58. issue_service.ChangeTitle(pr.Issue, owner, setting.Repository.PullRequest.WorkInProgressPrefixes[0]+" "+pr.Issue.Title)
  59. // force reload
  60. pr.LoadAttributes(db.DefaultContext)
  61. assert.Contains(t, pr.Issue.Title, setting.Repository.PullRequest.WorkInProgressPrefixes[0])
  62. session := loginUser(t, owner.Name)
  63. token := getTokenForLoggedInUser(t, session)
  64. req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d/merge?token=%s", owner.Name, repo.Name, pr.Index, token), &forms.MergePullRequestForm{
  65. MergeMessageField: pr.Issue.Title,
  66. Do: string(repo_model.MergeStyleMerge),
  67. })
  68. session.MakeRequest(t, req, http.StatusMethodNotAllowed)
  69. }
  70. func TestAPICreatePullSuccess(t *testing.T) {
  71. defer tests.PrepareTestEnv(t)()
  72. repo10 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10})
  73. // repo10 have code, pulls units.
  74. repo11 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 11})
  75. // repo11 only have code unit but should still create pulls
  76. owner10 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo10.OwnerID})
  77. owner11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo11.OwnerID})
  78. session := loginUser(t, owner11.Name)
  79. token := getTokenForLoggedInUser(t, session)
  80. req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", owner10.Name, repo10.Name, token), &api.CreatePullRequestOption{
  81. Head: fmt.Sprintf("%s:master", owner11.Name),
  82. Base: "master",
  83. Title: "create a failure pr",
  84. })
  85. session.MakeRequest(t, req, http.StatusCreated)
  86. session.MakeRequest(t, req, http.StatusUnprocessableEntity) // second request should fail
  87. }
  88. func TestAPICreatePullWithFieldsSuccess(t *testing.T) {
  89. defer tests.PrepareTestEnv(t)()
  90. // repo10 have code, pulls units.
  91. repo10 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10})
  92. owner10 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo10.OwnerID})
  93. // repo11 only have code unit but should still create pulls
  94. repo11 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 11})
  95. owner11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo11.OwnerID})
  96. session := loginUser(t, owner11.Name)
  97. token := getTokenForLoggedInUser(t, session)
  98. opts := &api.CreatePullRequestOption{
  99. Head: fmt.Sprintf("%s:master", owner11.Name),
  100. Base: "master",
  101. Title: "create a failure pr",
  102. Body: "foobaaar",
  103. Milestone: 5,
  104. Assignees: []string{owner10.Name},
  105. Labels: []int64{5},
  106. }
  107. req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", owner10.Name, repo10.Name, token), opts)
  108. res := session.MakeRequest(t, req, http.StatusCreated)
  109. pull := new(api.PullRequest)
  110. DecodeJSON(t, res, pull)
  111. assert.NotNil(t, pull.Milestone)
  112. assert.EqualValues(t, opts.Milestone, pull.Milestone.ID)
  113. if assert.Len(t, pull.Assignees, 1) {
  114. assert.EqualValues(t, opts.Assignees[0], owner10.Name)
  115. }
  116. assert.NotNil(t, pull.Labels)
  117. assert.EqualValues(t, opts.Labels[0], pull.Labels[0].ID)
  118. }
  119. func TestAPICreatePullWithFieldsFailure(t *testing.T) {
  120. defer tests.PrepareTestEnv(t)()
  121. // repo10 have code, pulls units.
  122. repo10 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10})
  123. owner10 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo10.OwnerID})
  124. // repo11 only have code unit but should still create pulls
  125. repo11 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 11})
  126. owner11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo11.OwnerID})
  127. session := loginUser(t, owner11.Name)
  128. token := getTokenForLoggedInUser(t, session)
  129. opts := &api.CreatePullRequestOption{
  130. Head: fmt.Sprintf("%s:master", owner11.Name),
  131. Base: "master",
  132. }
  133. req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", owner10.Name, repo10.Name, token), opts)
  134. session.MakeRequest(t, req, http.StatusUnprocessableEntity)
  135. opts.Title = "is required"
  136. opts.Milestone = 666
  137. session.MakeRequest(t, req, http.StatusUnprocessableEntity)
  138. opts.Milestone = 5
  139. opts.Assignees = []string{"qweruqweroiuyqweoiruywqer"}
  140. session.MakeRequest(t, req, http.StatusUnprocessableEntity)
  141. opts.Assignees = []string{owner10.LoginName}
  142. opts.Labels = []int64{55555}
  143. session.MakeRequest(t, req, http.StatusUnprocessableEntity)
  144. opts.Labels = []int64{5}
  145. }
  146. func TestAPIEditPull(t *testing.T) {
  147. defer tests.PrepareTestEnv(t)()
  148. repo10 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10})
  149. owner10 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo10.OwnerID})
  150. session := loginUser(t, owner10.Name)
  151. token := getTokenForLoggedInUser(t, session)
  152. req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", owner10.Name, repo10.Name, token), &api.CreatePullRequestOption{
  153. Head: "develop",
  154. Base: "master",
  155. Title: "create a success pr",
  156. })
  157. pull := new(api.PullRequest)
  158. resp := session.MakeRequest(t, req, http.StatusCreated)
  159. DecodeJSON(t, resp, pull)
  160. assert.EqualValues(t, "master", pull.Base.Name)
  161. req = NewRequestWithJSON(t, http.MethodPatch, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d?token=%s", owner10.Name, repo10.Name, pull.Index, token), &api.EditPullRequestOption{
  162. Base: "feature/1",
  163. Title: "edit a this pr",
  164. })
  165. resp = session.MakeRequest(t, req, http.StatusCreated)
  166. DecodeJSON(t, resp, pull)
  167. assert.EqualValues(t, "feature/1", pull.Base.Name)
  168. req = NewRequestWithJSON(t, http.MethodPatch, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d?token=%s", owner10.Name, repo10.Name, pull.Index, token), &api.EditPullRequestOption{
  169. Base: "not-exist",
  170. })
  171. session.MakeRequest(t, req, http.StatusNotFound)
  172. }
  173. func doAPIGetPullFiles(ctx APITestContext, pr *api.PullRequest, callback func(*testing.T, []*api.ChangedFile)) func(*testing.T) {
  174. return func(t *testing.T) {
  175. url := fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d/files?token=%s", ctx.Username, ctx.Reponame, pr.Index, ctx.Token)
  176. req := NewRequest(t, http.MethodGet, url)
  177. if ctx.ExpectedCode == 0 {
  178. ctx.ExpectedCode = http.StatusOK
  179. }
  180. resp := ctx.Session.MakeRequest(t, req, ctx.ExpectedCode)
  181. files := make([]*api.ChangedFile, 0, 1)
  182. DecodeJSON(t, resp, &files)
  183. if callback != nil {
  184. callback(t, files)
  185. }
  186. }
  187. }