BigW Consortium Gitlab

branches_spec.rb 13.8 KB
Newer Older
1 2 3
require 'spec_helper'
require 'mime/types'

4
describe API::Branches, api: true  do
5 6 7 8 9
  include ApiHelpers

  let(:user) { create(:user) }
  let(:user2) { create(:user) }
  let!(:project) { create(:project, creator_id: user.id) }
10 11
  let!(:master) { create(:project_member, :master, user: user, project: project) }
  let!(:guest) { create(:project_member, :guest, user: user2, project: project) }
12 13
  let!(:branch_name) { 'feature' }
  let!(:branch_sha) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' }
14 15

  describe "GET /projects/:id/repository/branches" do
16
    it "returns an array of project branches" do
17
      project.repository.expire_all_method_caches
18

19
      get api("/projects/#{project.id}/repository/branches", user)
20
      expect(response).to have_http_status(200)
21
      expect(json_response).to be_an Array
22 23
      branch_names = json_response.map { |x| x['name'] }
      expect(branch_names).to match_array(project.repository.branch_names)
24 25 26 27
    end
  end

  describe "GET /projects/:id/repository/branches/:branch" do
28
    it "returns the branch information for a single branch" do
29
      get api("/projects/#{project.id}/repository/branches/#{branch_name}", user)
30
      expect(response).to have_http_status(200)
31

32 33
      expect(json_response['name']).to eq(branch_name)
      expect(json_response['commit']['id']).to eq(branch_sha)
34
      expect(json_response['merged']).to eq(false)
35
      expect(json_response['protected']).to eq(false)
36
      expect(json_response['developers_can_push']).to eq(false)
37
      expect(json_response['developers_can_merge']).to eq(false)
38 39
    end

40 41 42 43 44 45 46 47 48 49
    context 'on a merged branch' do
      it "returns the branch information for a single branch" do
        get api("/projects/#{project.id}/repository/branches/merge-test", user)

        expect(response).to have_http_status(200)
        expect(json_response['name']).to eq('merge-test')
        expect(json_response['merged']).to eq(true)
      end
    end

50
    it "returns a 403 error if guest" do
51
      get api("/projects/#{project.id}/repository/branches", user2)
52
      expect(response).to have_http_status(403)
53 54
    end

55
    it "returns a 404 error if branch is not available" do
56
      get api("/projects/#{project.id}/repository/branches/unknown", user)
57
      expect(response).to have_http_status(404)
58 59 60
    end
  end

61
  describe 'PUT /projects/:id/repository/branches/:branch/protect' do
62 63 64
    context "when a protected branch doesn't already exist" do
      it 'protects a single branch' do
        put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user)
65

66 67 68 69 70 71 72
        expect(response).to have_http_status(200)
        expect(json_response['name']).to eq(branch_name)
        expect(json_response['commit']['id']).to eq(branch_sha)
        expect(json_response['protected']).to eq(true)
        expect(json_response['developers_can_push']).to eq(false)
        expect(json_response['developers_can_merge']).to eq(false)
      end
73

74 75 76
      it 'protects a single branch and developers can push' do
        put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user),
            developers_can_push: true
77

78 79 80 81 82 83 84
        expect(response).to have_http_status(200)
        expect(json_response['name']).to eq(branch_name)
        expect(json_response['commit']['id']).to eq(branch_sha)
        expect(json_response['protected']).to eq(true)
        expect(json_response['developers_can_push']).to eq(true)
        expect(json_response['developers_can_merge']).to eq(false)
      end
85

86 87 88
      it 'protects a single branch and developers can merge' do
        put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user),
            developers_can_merge: true
89

90 91 92 93 94 95 96
        expect(response).to have_http_status(200)
        expect(json_response['name']).to eq(branch_name)
        expect(json_response['commit']['id']).to eq(branch_sha)
        expect(json_response['protected']).to eq(true)
        expect(json_response['developers_can_push']).to eq(false)
        expect(json_response['developers_can_merge']).to eq(true)
      end
97

98 99 100
      it 'protects a single branch and developers can push and merge' do
        put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user),
            developers_can_push: true, developers_can_merge: true
101

102 103 104 105 106 107 108
        expect(response).to have_http_status(200)
        expect(json_response['name']).to eq(branch_name)
        expect(json_response['commit']['id']).to eq(branch_sha)
        expect(json_response['protected']).to eq(true)
        expect(json_response['developers_can_push']).to eq(true)
        expect(json_response['developers_can_merge']).to eq(true)
      end
109 110
    end

111
    context 'for an existing protected branch' do
112
      before do
113
        project.repository.add_branch(user, protected_branch.name, 'master')
114 115
      end

116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
      context "when developers can push and merge" do
        let(:protected_branch) { create(:protected_branch, :developers_can_push, :developers_can_merge, project: project, name: 'protected_branch') }

        it 'updates that a developer cannot push or merge' do
          put api("/projects/#{project.id}/repository/branches/#{protected_branch.name}/protect", user),
              developers_can_push: false, developers_can_merge: false

          expect(response).to have_http_status(200)
          expect(json_response['name']).to eq(protected_branch.name)
          expect(json_response['protected']).to eq(true)
          expect(json_response['developers_can_push']).to eq(false)
          expect(json_response['developers_can_merge']).to eq(false)
        end

        it "doesn't result in 0 access levels when 'developers_can_push' is switched off" do
          put api("/projects/#{project.id}/repository/branches/#{protected_branch.name}/protect", user),
              developers_can_push: false

          expect(response).to have_http_status(200)
          expect(json_response['name']).to eq(protected_branch.name)
          expect(protected_branch.reload.push_access_levels.first).to be_present
          expect(protected_branch.reload.push_access_levels.first.access_level).to eq(Gitlab::Access::MASTER)
        end

        it "doesn't result in 0 access levels when 'developers_can_merge' is switched off" do
          put api("/projects/#{project.id}/repository/branches/#{protected_branch.name}/protect", user),
              developers_can_merge: false

          expect(response).to have_http_status(200)
          expect(json_response['name']).to eq(protected_branch.name)
          expect(protected_branch.reload.merge_access_levels.first).to be_present
          expect(protected_branch.reload.merge_access_levels.first.access_level).to eq(Gitlab::Access::MASTER)
        end
      end

      context "when developers cannot push or merge" do
        let(:protected_branch) { create(:protected_branch, project: project, name: 'protected_branch') }

        it 'updates that a developer can push and merge' do
          put api("/projects/#{project.id}/repository/branches/#{protected_branch.name}/protect", user),
              developers_can_push: true, developers_can_merge: true

          expect(response).to have_http_status(200)
          expect(json_response['name']).to eq(protected_branch.name)
          expect(json_response['protected']).to eq(true)
          expect(json_response['developers_can_push']).to eq(true)
          expect(json_response['developers_can_merge']).to eq(true)
        end
      end
    end

    context "multiple API calls" do
      it "returns success when `protect` is called twice" do
        put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user)
        put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user)
171 172

        expect(response).to have_http_status(200)
173
        expect(json_response['name']).to eq(branch_name)
174 175
        expect(json_response['protected']).to eq(true)
        expect(json_response['developers_can_push']).to eq(false)
176
        expect(json_response['developers_can_merge']).to eq(false)
177 178
      end

179 180 181
      it "returns success when `protect` is called twice with `developers_can_push` turned on" do
        put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user), developers_can_push: true
        put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user), developers_can_push: true
182 183

        expect(response).to have_http_status(200)
184
        expect(json_response['name']).to eq(branch_name)
185 186
        expect(json_response['protected']).to eq(true)
        expect(json_response['developers_can_push']).to eq(true)
187 188 189 190 191 192 193 194 195 196 197
        expect(json_response['developers_can_merge']).to eq(false)
      end

      it "returns success when `protect` is called twice with `developers_can_merge` turned on" do
        put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user), developers_can_merge: true
        put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user), developers_can_merge: true

        expect(response).to have_http_status(200)
        expect(json_response['name']).to eq(branch_name)
        expect(json_response['protected']).to eq(true)
        expect(json_response['developers_can_push']).to eq(false)
198
        expect(json_response['developers_can_merge']).to eq(true)
199
      end
200 201
    end

202
    it "returns a 404 error if branch not found" do
203
      put api("/projects/#{project.id}/repository/branches/unknown/protect", user)
204
      expect(response).to have_http_status(404)
205 206
    end

207
    it "returns a 403 error if guest" do
208
      put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user2)
209
      expect(response).to have_http_status(403)
210 211 212 213
    end
  end

  describe "PUT /projects/:id/repository/branches/:branch/unprotect" do
214
    it "unprotects a single branch" do
215
      put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user)
216
      expect(response).to have_http_status(200)
217

218 219 220
      expect(json_response['name']).to eq(branch_name)
      expect(json_response['commit']['id']).to eq(branch_sha)
      expect(json_response['protected']).to eq(false)
221 222
    end

223
    it "returns success when unprotect branch" do
224
      put api("/projects/#{project.id}/repository/branches/unknown/unprotect", user)
225
      expect(response).to have_http_status(404)
226 227
    end

228
    it "returns success when unprotect branch again" do
229 230
      put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user)
      put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user)
231
      expect(response).to have_http_status(200)
232 233 234
    end
  end

235
  describe "POST /projects/:id/repository/branches" do
236
    it "creates a new branch" do
237
      post api("/projects/#{project.id}/repository/branches", user),
238 239
           branch_name: 'feature1',
           ref: branch_sha
240

241
      expect(response).to have_http_status(201)
242

243 244
      expect(json_response['name']).to eq('feature1')
      expect(json_response['commit']['id']).to eq(branch_sha)
245 246
    end

247
    it "denies for user without push access" do
248
      post api("/projects/#{project.id}/repository/branches", user2),
249 250
           branch_name: branch_name,
           ref: branch_sha
251
      expect(response).to have_http_status(403)
252
    end
253

254
    it 'returns 400 if branch name is invalid' do
255 256 257
      post api("/projects/#{project.id}/repository/branches", user),
           branch_name: 'new design',
           ref: branch_sha
258
      expect(response).to have_http_status(400)
Douglas Barbosa Alexandre committed
259
      expect(json_response['message']).to eq('Branch name is invalid')
260 261
    end

262
    it 'returns 400 if branch already exists' do
263 264 265
      post api("/projects/#{project.id}/repository/branches", user),
           branch_name: 'new_design1',
           ref: branch_sha
266
      expect(response).to have_http_status(201)
267 268 269 270

      post api("/projects/#{project.id}/repository/branches", user),
           branch_name: 'new_design1',
           ref: branch_sha
271
      expect(response).to have_http_status(400)
272
      expect(json_response['message']).to eq('Branch already exists')
273 274
    end

275
    it 'returns 400 if ref name is invalid' do
276 277 278
      post api("/projects/#{project.id}/repository/branches", user),
           branch_name: 'new_design3',
           ref: 'foo'
279
      expect(response).to have_http_status(400)
280
      expect(json_response['message']).to eq('Invalid reference name')
281
    end
282
  end
283 284

  describe "DELETE /projects/:id/repository/branches/:branch" do
285 286 287
    before do
      allow_any_instance_of(Repository).to receive(:rm_branch).and_return(true)
    end
288

289
    it "removes branch" do
290
      delete api("/projects/#{project.id}/repository/branches/#{branch_name}", user)
291
      expect(response).to have_http_status(200)
292
      expect(json_response['branch_name']).to eq(branch_name)
293 294
    end

295
    it 'returns 404 if branch not exists' do
296
      delete api("/projects/#{project.id}/repository/branches/foobar", user)
297
      expect(response).to have_http_status(404)
298 299
    end

300
    it "removes protected branch" do
301
      create(:protected_branch, project: project, name: branch_name)
302
      delete api("/projects/#{project.id}/repository/branches/#{branch_name}", user)
303
      expect(response).to have_http_status(405)
304
      expect(json_response['message']).to eq('Protected branch cant be removed')
305 306
    end

307
    it "does not remove HEAD branch" do
308
      delete api("/projects/#{project.id}/repository/branches/master", user)
309
      expect(response).to have_http_status(405)
310
      expect(json_response['message']).to eq('Cannot remove HEAD branch')
311 312
    end
  end
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328

  describe "DELETE /projects/:id/repository/merged_branches" do
    before do
      allow_any_instance_of(Repository).to receive(:rm_branch).and_return(true)
    end

    it 'returns 200' do
      delete api("/projects/#{project.id}/repository/merged_branches", user)
      expect(response).to have_http_status(200)
    end

    it 'returns a 403 error if guest' do
      delete api("/projects/#{project.id}/repository/merged_branches", user2)
      expect(response).to have_http_status(403)
    end
  end
329
end