PageRenderTime 1432ms CodeModel.GetById 29ms RepoModel.GetById 3ms app.codeStats 0ms

/spec/requests/api/branches_spec.rb

https://gitlab.com/damienadermann/gitlab-ce
Ruby | 302 lines | 291 code | 11 blank | 0 comment | 7 complexity | 9eab94a3ed5128a6e282d2e29c8a30d4 MD5 | raw file
  1. require 'spec_helper'
  2. require 'mime/types'
  3. describe API::API, api: true do
  4. include ApiHelpers
  5. let(:user) { create(:user) }
  6. let(:user2) { create(:user) }
  7. let!(:project) { create(:project, creator_id: user.id) }
  8. let!(:master) { create(:project_member, :master, user: user, project: project) }
  9. let!(:guest) { create(:project_member, :guest, user: user2, project: project) }
  10. let!(:branch_name) { 'feature' }
  11. let!(:branch_sha) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' }
  12. describe "GET /projects/:id/repository/branches" do
  13. it "returns an array of project branches" do
  14. project.repository.expire_cache
  15. get api("/projects/#{project.id}/repository/branches", user)
  16. expect(response).to have_http_status(200)
  17. expect(json_response).to be_an Array
  18. branch_names = json_response.map { |x| x['name'] }
  19. expect(branch_names).to match_array(project.repository.branch_names)
  20. end
  21. end
  22. describe "GET /projects/:id/repository/branches/:branch" do
  23. it "returns the branch information for a single branch" do
  24. get api("/projects/#{project.id}/repository/branches/#{branch_name}", user)
  25. expect(response).to have_http_status(200)
  26. expect(json_response['name']).to eq(branch_name)
  27. expect(json_response['commit']['id']).to eq(branch_sha)
  28. expect(json_response['protected']).to eq(false)
  29. expect(json_response['developers_can_push']).to eq(false)
  30. expect(json_response['developers_can_merge']).to eq(false)
  31. end
  32. it "returns a 403 error if guest" do
  33. get api("/projects/#{project.id}/repository/branches", user2)
  34. expect(response).to have_http_status(403)
  35. end
  36. it "returns a 404 error if branch is not available" do
  37. get api("/projects/#{project.id}/repository/branches/unknown", user)
  38. expect(response).to have_http_status(404)
  39. end
  40. end
  41. describe 'PUT /projects/:id/repository/branches/:branch/protect' do
  42. context "when a protected branch doesn't already exist" do
  43. it 'protects a single branch' do
  44. put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user)
  45. expect(response).to have_http_status(200)
  46. expect(json_response['name']).to eq(branch_name)
  47. expect(json_response['commit']['id']).to eq(branch_sha)
  48. expect(json_response['protected']).to eq(true)
  49. expect(json_response['developers_can_push']).to eq(false)
  50. expect(json_response['developers_can_merge']).to eq(false)
  51. end
  52. it 'protects a single branch and developers can push' do
  53. put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user),
  54. developers_can_push: true
  55. expect(response).to have_http_status(200)
  56. expect(json_response['name']).to eq(branch_name)
  57. expect(json_response['commit']['id']).to eq(branch_sha)
  58. expect(json_response['protected']).to eq(true)
  59. expect(json_response['developers_can_push']).to eq(true)
  60. expect(json_response['developers_can_merge']).to eq(false)
  61. end
  62. it 'protects a single branch and developers can merge' do
  63. put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user),
  64. developers_can_merge: true
  65. expect(response).to have_http_status(200)
  66. expect(json_response['name']).to eq(branch_name)
  67. expect(json_response['commit']['id']).to eq(branch_sha)
  68. expect(json_response['protected']).to eq(true)
  69. expect(json_response['developers_can_push']).to eq(false)
  70. expect(json_response['developers_can_merge']).to eq(true)
  71. end
  72. it 'protects a single branch and developers can push and merge' do
  73. put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user),
  74. developers_can_push: true, developers_can_merge: true
  75. expect(response).to have_http_status(200)
  76. expect(json_response['name']).to eq(branch_name)
  77. expect(json_response['commit']['id']).to eq(branch_sha)
  78. expect(json_response['protected']).to eq(true)
  79. expect(json_response['developers_can_push']).to eq(true)
  80. expect(json_response['developers_can_merge']).to eq(true)
  81. end
  82. end
  83. context 'for an existing protected branch' do
  84. before do
  85. project.repository.add_branch(user, protected_branch.name, 'master')
  86. end
  87. context "when developers can push and merge" do
  88. let(:protected_branch) { create(:protected_branch, :developers_can_push, :developers_can_merge, project: project, name: 'protected_branch') }
  89. it 'updates that a developer cannot push or merge' do
  90. put api("/projects/#{project.id}/repository/branches/#{protected_branch.name}/protect", user),
  91. developers_can_push: false, developers_can_merge: false
  92. expect(response).to have_http_status(200)
  93. expect(json_response['name']).to eq(protected_branch.name)
  94. expect(json_response['protected']).to eq(true)
  95. expect(json_response['developers_can_push']).to eq(false)
  96. expect(json_response['developers_can_merge']).to eq(false)
  97. end
  98. it "doesn't result in 0 access levels when 'developers_can_push' is switched off" do
  99. put api("/projects/#{project.id}/repository/branches/#{protected_branch.name}/protect", user),
  100. developers_can_push: false
  101. expect(response).to have_http_status(200)
  102. expect(json_response['name']).to eq(protected_branch.name)
  103. expect(protected_branch.reload.push_access_levels.first).to be_present
  104. expect(protected_branch.reload.push_access_levels.first.access_level).to eq(Gitlab::Access::MASTER)
  105. end
  106. it "doesn't result in 0 access levels when 'developers_can_merge' is switched off" do
  107. put api("/projects/#{project.id}/repository/branches/#{protected_branch.name}/protect", user),
  108. developers_can_merge: false
  109. expect(response).to have_http_status(200)
  110. expect(json_response['name']).to eq(protected_branch.name)
  111. expect(protected_branch.reload.merge_access_levels.first).to be_present
  112. expect(protected_branch.reload.merge_access_levels.first.access_level).to eq(Gitlab::Access::MASTER)
  113. end
  114. end
  115. context "when developers cannot push or merge" do
  116. let(:protected_branch) { create(:protected_branch, project: project, name: 'protected_branch') }
  117. it 'updates that a developer can push and merge' do
  118. put api("/projects/#{project.id}/repository/branches/#{protected_branch.name}/protect", user),
  119. developers_can_push: true, developers_can_merge: true
  120. expect(response).to have_http_status(200)
  121. expect(json_response['name']).to eq(protected_branch.name)
  122. expect(json_response['protected']).to eq(true)
  123. expect(json_response['developers_can_push']).to eq(true)
  124. expect(json_response['developers_can_merge']).to eq(true)
  125. end
  126. end
  127. end
  128. context "multiple API calls" do
  129. it "returns success when `protect` is called twice" do
  130. put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user)
  131. put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user)
  132. expect(response).to have_http_status(200)
  133. expect(json_response['name']).to eq(branch_name)
  134. expect(json_response['protected']).to eq(true)
  135. expect(json_response['developers_can_push']).to eq(false)
  136. expect(json_response['developers_can_merge']).to eq(false)
  137. end
  138. it "returns success when `protect` is called twice with `developers_can_push` turned on" do
  139. put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user), developers_can_push: true
  140. put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user), developers_can_push: true
  141. expect(response).to have_http_status(200)
  142. expect(json_response['name']).to eq(branch_name)
  143. expect(json_response['protected']).to eq(true)
  144. expect(json_response['developers_can_push']).to eq(true)
  145. expect(json_response['developers_can_merge']).to eq(false)
  146. end
  147. it "returns success when `protect` is called twice with `developers_can_merge` turned on" do
  148. put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user), developers_can_merge: true
  149. put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user), developers_can_merge: true
  150. expect(response).to have_http_status(200)
  151. expect(json_response['name']).to eq(branch_name)
  152. expect(json_response['protected']).to eq(true)
  153. expect(json_response['developers_can_push']).to eq(false)
  154. expect(json_response['developers_can_merge']).to eq(true)
  155. end
  156. end
  157. it "returns a 404 error if branch not found" do
  158. put api("/projects/#{project.id}/repository/branches/unknown/protect", user)
  159. expect(response).to have_http_status(404)
  160. end
  161. it "returns a 403 error if guest" do
  162. put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user2)
  163. expect(response).to have_http_status(403)
  164. end
  165. end
  166. describe "PUT /projects/:id/repository/branches/:branch/unprotect" do
  167. it "unprotects a single branch" do
  168. put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user)
  169. expect(response).to have_http_status(200)
  170. expect(json_response['name']).to eq(branch_name)
  171. expect(json_response['commit']['id']).to eq(branch_sha)
  172. expect(json_response['protected']).to eq(false)
  173. end
  174. it "returns success when unprotect branch" do
  175. put api("/projects/#{project.id}/repository/branches/unknown/unprotect", user)
  176. expect(response).to have_http_status(404)
  177. end
  178. it "returns success when unprotect branch again" do
  179. put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user)
  180. put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user)
  181. expect(response).to have_http_status(200)
  182. end
  183. end
  184. describe "POST /projects/:id/repository/branches" do
  185. it "creates a new branch" do
  186. post api("/projects/#{project.id}/repository/branches", user),
  187. branch_name: 'feature1',
  188. ref: branch_sha
  189. expect(response).to have_http_status(201)
  190. expect(json_response['name']).to eq('feature1')
  191. expect(json_response['commit']['id']).to eq(branch_sha)
  192. end
  193. it "denies for user without push access" do
  194. post api("/projects/#{project.id}/repository/branches", user2),
  195. branch_name: branch_name,
  196. ref: branch_sha
  197. expect(response).to have_http_status(403)
  198. end
  199. it 'returns 400 if branch name is invalid' do
  200. post api("/projects/#{project.id}/repository/branches", user),
  201. branch_name: 'new design',
  202. ref: branch_sha
  203. expect(response).to have_http_status(400)
  204. expect(json_response['message']).to eq('Branch name is invalid')
  205. end
  206. it 'returns 400 if branch already exists' do
  207. post api("/projects/#{project.id}/repository/branches", user),
  208. branch_name: 'new_design1',
  209. ref: branch_sha
  210. expect(response).to have_http_status(201)
  211. post api("/projects/#{project.id}/repository/branches", user),
  212. branch_name: 'new_design1',
  213. ref: branch_sha
  214. expect(response).to have_http_status(400)
  215. expect(json_response['message']).to eq('Branch already exists')
  216. end
  217. it 'returns 400 if ref name is invalid' do
  218. post api("/projects/#{project.id}/repository/branches", user),
  219. branch_name: 'new_design3',
  220. ref: 'foo'
  221. expect(response).to have_http_status(400)
  222. expect(json_response['message']).to eq('Invalid reference name')
  223. end
  224. end
  225. describe "DELETE /projects/:id/repository/branches/:branch" do
  226. before do
  227. allow_any_instance_of(Repository).to receive(:rm_branch).and_return(true)
  228. end
  229. it "removes branch" do
  230. delete api("/projects/#{project.id}/repository/branches/#{branch_name}", user)
  231. expect(response).to have_http_status(200)
  232. expect(json_response['branch_name']).to eq(branch_name)
  233. end
  234. it 'returns 404 if branch not exists' do
  235. delete api("/projects/#{project.id}/repository/branches/foobar", user)
  236. expect(response).to have_http_status(404)
  237. end
  238. it "removes protected branch" do
  239. create(:protected_branch, project: project, name: branch_name)
  240. delete api("/projects/#{project.id}/repository/branches/#{branch_name}", user)
  241. expect(response).to have_http_status(405)
  242. expect(json_response['message']).to eq('Protected branch cant be removed')
  243. end
  244. it "does not remove HEAD branch" do
  245. delete api("/projects/#{project.id}/repository/branches/master", user)
  246. expect(response).to have_http_status(405)
  247. expect(json_response['message']).to eq('Cannot remove HEAD branch')
  248. end
  249. end
  250. end