projects_spec.rb 37.2 KB
Newer Older
1
# -*- coding: utf-8 -*-
N
Nihad Abbasov 已提交
2 3
require 'spec_helper'

J
Jeroen van Baarsen 已提交
4
describe API::API, api: true  do
5
  include ApiHelpers
6
  include Gitlab::CurrentSettings
7 8 9
  let(:user) { create(:user) }
  let(:user2) { create(:user) }
  let(:user3) { create(:user) }
A
Angus MacArthur 已提交
10
  let(:admin) { create(:admin) }
D
Dmitriy Zaporozhets 已提交
11
  let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) }
12 13
  let(:project2) { create(:project, path: 'project2', creator_id: user.id, namespace: user.namespace) }
  let(:project3) { create(:project, path: 'project3', creator_id: user.id, namespace: user.namespace) }
D
Dmitriy Zaporozhets 已提交
14
  let(:snippet) { create(:project_snippet, author: user, project: project, title: 'example') }
15 16
  let(:project_member) { create(:project_member, :master, user: user, project: project) }
  let(:project_member2) { create(:project_member, :developer, user: user3, project: project) }
17
  let(:user4) { create(:user) }
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
  let(:project3) do
    create(:project,
    name: 'second_project',
    path: 'second_project',
    creator_id: user.id,
    namespace: user.namespace,
    merge_requests_enabled: false,
    issues_enabled: false, wiki_enabled: false,
    snippets_enabled: false, visibility_level: 0)
  end
  let(:project_member3) do
    create(:project_member,
    user: user4,
    project: project3,
    access_level: ProjectMember::MASTER)
  end
  let(:project4) do
    create(:project,
    name: 'third_project',
    path: 'third_project',
    creator_id: user4.id,
    namespace: user4.namespace)
  end

  describe 'GET /projects' do
D
Dmitriy Zaporozhets 已提交
43 44
    before { project }

45 46 47
    context 'when unauthenticated' do
      it 'should return authentication error' do
        get api('/projects')
48
        expect(response.status).to eq(401)
49
      end
N
Nihad Abbasov 已提交
50 51
    end

52 53 54
    context 'when authenticated' do
      it 'should return an array of projects' do
        get api('/projects', user)
55 56 57 58
        expect(response.status).to eq(200)
        expect(json_response).to be_an Array
        expect(json_response.first['name']).to eq(project.name)
        expect(json_response.first['owner']['username']).to eq(user.username)
N
Nihad Abbasov 已提交
59
      end
60

61 62
      it 'should include the project labels as the tag_list' do
        get api('/projects', user)
63 64 65
        expect(response.status).to eq 200
        expect(json_response).to be_an Array
        expect(json_response.first.keys).to include('tag_list')
66
      end
67

S
Stan Hu 已提交
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
      it 'should include open_issues_count' do
        get api('/projects', user)
        expect(response.status).to eq 200
        expect(json_response).to be_an Array
        expect(json_response.first.keys).to include('open_issues_count')
      end

      it 'should not include open_issues_count' do
        project.update_attributes( { issues_enabled: false } )

        get api('/projects', user)
        expect(response.status).to eq 200
        expect(json_response).to be_an Array
        expect(json_response.first.keys).not_to include('open_issues_count')
      end

84 85 86
      context 'and using search' do
        it 'should return searched project' do
          get api('/projects', user), { search: project.name }
87 88 89
          expect(response.status).to eq(200)
          expect(json_response).to be_an Array
          expect(json_response.length).to eq(1)
90 91 92
        end
      end

J
Josh Frye 已提交
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
      context 'and using the visibility filter' do
        it 'should filter based on private visibility param' do
          get api('/projects', user), { visibility: 'private' }
          expect(response.status).to eq(200)
          expect(json_response).to be_an Array
          expect(json_response.length).to eq(user.namespace.projects.where(visibility_level: Gitlab::VisibilityLevel::PRIVATE).count)
        end

        it 'should filter based on internal visibility param' do
          get api('/projects', user), { visibility: 'internal' }
          expect(response.status).to eq(200)
          expect(json_response).to be_an Array
          expect(json_response.length).to eq(user.namespace.projects.where(visibility_level: Gitlab::VisibilityLevel::INTERNAL).count)
        end

        it 'should filter based on public visibility param' do
          get api('/projects', user), { visibility: 'public' }
          expect(response.status).to eq(200)
          expect(json_response).to be_an Array
          expect(json_response.length).to eq(user.namespace.projects.where(visibility_level: Gitlab::VisibilityLevel::PUBLIC).count)
        end
      end

116
      context 'and using sorting' do
117 118 119 120 121
        before do
          project2
          project3
        end

122
        it 'should return the correct order when sorted by id' do
123
          get api('/projects', user), { order_by: 'id', sort: 'desc' }
124 125 126
          expect(response.status).to eq(200)
          expect(json_response).to be_an Array
          expect(json_response.first['id']).to eq(project3.id)
127 128
        end
      end
N
Nihad Abbasov 已提交
129 130 131
    end
  end

132
  describe 'GET /projects/all' do
D
Dmitriy Zaporozhets 已提交
133 134
    before { project }

135 136 137
    context 'when unauthenticated' do
      it 'should return authentication error' do
        get api('/projects/all')
138
        expect(response.status).to eq(401)
D
Dmitriy Zaporozhets 已提交
139 140 141
      end
    end

142 143 144
    context 'when authenticated as regular user' do
      it 'should return authentication error' do
        get api('/projects/all', user)
145
        expect(response.status).to eq(403)
D
Dmitriy Zaporozhets 已提交
146 147 148
      end
    end

149 150 151
    context 'when authenticated as admin' do
      it 'should return an array of all projects' do
        get api('/projects/all', admin)
152 153
        expect(response.status).to eq(200)
        expect(json_response).to be_an Array
M
Marin Jankovski 已提交
154

155 156
        expect(json_response).to satisfy do |response|
          response.one? do |entry|
157
            entry.has_key?('permissions') &&
158
            entry['name'] == project.name &&
159
              entry['owner']['username'] == user.username
160 161
          end
        end
D
Dmitriy Zaporozhets 已提交
162 163 164 165
      end
    end
  end

166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
  describe 'GET /projects/starred' do
    before do
      admin.starred_projects << project
      admin.save!
    end

    it 'should return the starred projects' do
      get api('/projects/all', admin)
      expect(response.status).to eq(200)
      expect(json_response).to be_an Array

      expect(json_response).to satisfy do |response|
        response.one? do |entry|
          entry['name'] == project.name
        end
      end
    end
  end

185 186
  describe 'POST /projects' do
    context 'maximum number of projects reached' do
187
      it 'should not create new project and respond with 403' do
188
        allow_any_instance_of(User).to receive(:projects_limit_left).and_return(0)
189 190
        expect { post api('/projects', user2), name: 'foo' }.
          to change {Project.count}.by(0)
191
        expect(response.status).to eq(403)
192 193 194
      end
    end

195 196 197
    it 'should create new project without path and return 201' do
      expect { post api('/projects', user), name: 'foo' }.
        to change { Project.count }.by(1)
198
      expect(response.status).to eq(201)
199 200
    end

201
    it 'should create last project before reaching project limit' do
202
      allow_any_instance_of(User).to receive(:projects_limit_left).and_return(1)
203
      post api('/projects', user2), name: 'foo'
204
      expect(response.status).to eq(201)
205 206
    end

207
    it 'should not create new project without name and return 400' do
208
      expect { post api('/projects', user) }.not_to change { Project.count }
209
      expect(response.status).to eq(400)
210
    end
A
Alex Denisov 已提交
211

212
    it "should assign attributes to project" do
213
      project = attributes_for(:project, {
214
        path: 'camelCasePath',
R
Robert Speicher 已提交
215
        description: FFaker::Lorem.sentence,
216 217 218
        issues_enabled: false,
        merge_requests_enabled: false,
        wiki_enabled: false
A
Alex Denisov 已提交
219 220
      })

221
      post api('/projects', user), project
A
Alex Denisov 已提交
222

223
      project.each_pair do |k,v|
224
        expect(json_response[k.to_s]).to eq(v)
A
Alex Denisov 已提交
225
      end
226
    end
227

228
    it 'should set a project as public' do
229
      project = attributes_for(:project, :public)
230
      post api('/projects', user), project
231 232
      expect(json_response['public']).to be_truthy
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
233 234
    end

235
    it 'should set a project as public using :public' do
236
      project = attributes_for(:project, { public: true })
237
      post api('/projects', user), project
238 239
      expect(json_response['public']).to be_truthy
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
240 241
    end

242
    it 'should set a project as internal' do
243
      project = attributes_for(:project, :internal)
244
      post api('/projects', user), project
245 246
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
247 248
    end

249
    it 'should set a project as internal overriding :public' do
250
      project = attributes_for(:project, :internal, { public: true })
251
      post api('/projects', user), project
252 253
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
254 255
    end

256
    it 'should set a project as private' do
257
      project = attributes_for(:project, :private)
258
      post api('/projects', user), project
259 260
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
261 262
    end

263
    it 'should set a project as private using :public' do
264
      project = attributes_for(:project, { public: false })
265
      post api('/projects', user), project
266 267
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
268
    end
269 270 271 272

    context 'when a visibility level is restricted' do
      before do
        @project = attributes_for(:project, { public: true })
273
        stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
274 275 276 277
      end

      it 'should not allow a non-admin to use a restricted visibility level' do
        post api('/projects', user), @project
F
Felipe Artur 已提交
278

279 280 281 282 283 284 285 286 287 288 289 290 291 292
        expect(response.status).to eq(400)
        expect(json_response['message']['visibility_level'].first).to(
          match('restricted by your GitLab administrator')
        )
      end

      it 'should allow an admin to override restricted visibility settings' do
        post api('/projects', admin), @project
        expect(json_response['public']).to be_truthy
        expect(json_response['visibility_level']).to(
          eq(Gitlab::VisibilityLevel::PUBLIC)
        )
      end
    end
293 294
  end

295
  describe 'POST /projects/user/:id' do
D
Dmitriy Zaporozhets 已提交
296
    before { project }
A
Angus MacArthur 已提交
297 298
    before { admin }

299
    it 'should create new project without path and return 201' do
300
      expect { post api("/projects/user/#{user.id}", admin), name: 'foo' }.to change {Project.count}.by(1)
301
      expect(response.status).to eq(201)
A
Angus MacArthur 已提交
302 303
    end

304 305
    it 'should respond with 400 on failure and not project' do
      expect { post api("/projects/user/#{user.id}", admin) }.
306
        not_to change { Project.count }
307

308 309
      expect(response.status).to eq(400)
      expect(json_response['message']['name']).to eq([
J
jubianchi 已提交
310 311
        'can\'t be blank',
        'is too short (minimum is 0 characters)',
D
Douwe Maan 已提交
312
        Gitlab::Regex.project_name_regex_message
313 314
      ])
      expect(json_response['message']['path']).to eq([
J
jubianchi 已提交
315 316
        'can\'t be blank',
        'is too short (minimum is 0 characters)',
D
Douwe Maan 已提交
317
        Gitlab::Regex.send(:project_path_regex_message)
318
      ])
A
Angus MacArthur 已提交
319 320
    end

321
    it 'should assign attributes to project' do
A
Angus MacArthur 已提交
322
      project = attributes_for(:project, {
R
Robert Speicher 已提交
323
        description: FFaker::Lorem.sentence,
324 325 326
        issues_enabled: false,
        merge_requests_enabled: false,
        wiki_enabled: false
A
Angus MacArthur 已提交
327 328 329 330
      })

      post api("/projects/user/#{user.id}", admin), project

331
      project.each_pair do |k,v|
A
Angus MacArthur 已提交
332
        next if k == :path
333
        expect(json_response[k.to_s]).to eq(v)
A
Angus MacArthur 已提交
334 335
      end
    end
336

337
    it 'should set a project as public' do
338
      project = attributes_for(:project, :public)
339
      post api("/projects/user/#{user.id}", admin), project
340 341
      expect(json_response['public']).to be_truthy
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
342 343
    end

344
    it 'should set a project as public using :public' do
345 346
      project = attributes_for(:project, { public: true })
      post api("/projects/user/#{user.id}", admin), project
347 348
      expect(json_response['public']).to be_truthy
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
349
    end
350

351
    it 'should set a project as internal' do
352
      project = attributes_for(:project, :internal)
353
      post api("/projects/user/#{user.id}", admin), project
354 355
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
356 357
    end

358
    it 'should set a project as internal overriding :public' do
359
      project = attributes_for(:project, :internal, { public: true })
360
      post api("/projects/user/#{user.id}", admin), project
361 362
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
363
    end
364

365
    it 'should set a project as private' do
366
      project = attributes_for(:project, :private)
367
      post api("/projects/user/#{user.id}", admin), project
368 369
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
370 371
    end

372
    it 'should set a project as private using :public' do
373 374
      project = attributes_for(:project, { public: false })
      post api("/projects/user/#{user.id}", admin), project
375 376
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
377
    end
A
Angus MacArthur 已提交
378 379
  end

D
Douwe Maan 已提交
380 381 382 383 384 385 386 387 388 389 390 391 392 393
  describe "POST /projects/:id/uploads" do
    before { project }

    it "uploads the file and returns its info" do
      post api("/projects/#{project.id}/uploads", user), file: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")

      expect(response.status).to be(201)
      expect(json_response['alt']).to eq("dk")
      expect(json_response['url']).to start_with("/uploads/")
      expect(json_response['url']).to end_with("/dk.png")
      expect(json_response['is_image']).to eq(true)
    end
  end

394
  describe 'GET /projects/:id' do
D
Dmitriy Zaporozhets 已提交
395
    before { project }
396
    before { project_member }
D
Dmitriy Zaporozhets 已提交
397

398
    it 'should return a project by id' do
R
Robert Speicher 已提交
399
      get api("/projects/#{project.id}", user)
400 401 402
      expect(response.status).to eq(200)
      expect(json_response['name']).to eq(project.name)
      expect(json_response['owner']['username']).to eq(user.username)
N
Nihad Abbasov 已提交
403
    end
404

405
    it 'should return a project by path name' do
406
      get api("/projects/#{project.id}", user)
407 408
      expect(response.status).to eq(200)
      expect(json_response['name']).to eq(project.name)
409
    end
N
Nihad Abbasov 已提交
410

411 412
    it 'should return a 404 error if not found' do
      get api('/projects/42', user)
413 414
      expect(response.status).to eq(404)
      expect(json_response['message']).to eq('404 Project Not Found')
N
Nihad Abbasov 已提交
415
    end
416

417
    it 'should return a 404 error if user is not a member' do
418 419
      other_user = create(:user)
      get api("/projects/#{project.id}", other_user)
420
      expect(response.status).to eq(404)
421
    end
422

423 424 425 426 427 428 429 430 431
    it 'should handle users with dots' do
      dot_user = create(:user, username: 'dot.user')
      project = create(:project, creator_id: dot_user.id, namespace: dot_user.namespace)

      get api("/projects/#{dot_user.namespace.name}%2F#{project.path}", dot_user)
      expect(response.status).to eq(200)
      expect(json_response['name']).to eq(project.name)
    end

432
    describe 'permissions' do
433 434 435 436 437 438 439 440 441 442 443 444
      context 'all projects' do
        it 'Contains permission information' do
          project.team << [user, :master]
          get api("/projects", user)

          expect(response.status).to eq(200)
          expect(json_response.first['permissions']['project_access']['access_level']).
              to eq(Gitlab::Access::MASTER)
          expect(json_response.first['permissions']['group_access']).to be_nil
        end
      end

445
      context 'personal project' do
446
        it 'Sets project access and returns 200' do
D
Dmitriy Zaporozhets 已提交
447 448
          project.team << [user, :master]
          get api("/projects/#{project.id}", user)
449

450 451 452 453 454
          expect(response.status).to eq(200)
          expect(json_response['permissions']['project_access']['access_level']).
            to eq(Gitlab::Access::MASTER)
          expect(json_response['permissions']['group_access']).to be_nil
        end
455 456 457
      end

      context 'group project' do
458
        it 'should set the owner and return 200' do
459 460 461 462
          project2 = create(:project, group: create(:group))
          project2.group.add_owner(user)
          get api("/projects/#{project2.id}", user)

463 464 465 466 467
          expect(response.status).to eq(200)
          expect(json_response['permissions']['project_access']).to be_nil
          expect(json_response['permissions']['group_access']['access_level']).
            to eq(Gitlab::Access::OWNER)
        end
468 469
      end
    end
N
Nihad Abbasov 已提交
470 471
  end

472
  describe 'GET /projects/:id/events' do
D
Douwe Maan 已提交
473
    before { project_member2 }
D
Dmitriy Zaporozhets 已提交
474

D
Dmitriy Zaporozhets 已提交
475 476 477 478 479 480 481 482 483 484 485
    context 'valid request' do
      before do
        note = create(:note_on_issue, note: 'What an awesome day!', project: project)
        EventCreateService.new.leave_note(note, note.author)
        get api("/projects/#{project.id}/events", user)
      end

      it { expect(response.status).to eq(200) }

      context 'joined event' do
        let(:json_event) { json_response[1] }
D
Dmitriy Zaporozhets 已提交
486

D
Dmitriy Zaporozhets 已提交
487 488 489 490 491 492 493 494 495 496 497 498
        it { expect(json_event['action_name']).to eq('joined') }
        it { expect(json_event['project_id'].to_i).to eq(project.id) }
        it { expect(json_event['author_username']).to eq(user3.username) }
        it { expect(json_event['author']['name']).to eq(user3.name) }
      end

      context 'comment event' do
        let(:json_event) { json_response.first }

        it { expect(json_event['action_name']).to eq('commented on') }
        it { expect(json_event['note']['body']).to eq('What an awesome day!') }
      end
D
Dmitriy Zaporozhets 已提交
499 500
    end

501 502
    it 'should return a 404 error if not found' do
      get api('/projects/42/events', user)
503 504
      expect(response.status).to eq(404)
      expect(json_response['message']).to eq('404 Project Not Found')
D
Dmitriy Zaporozhets 已提交
505 506
    end

507
    it 'should return a 404 error if user is not a member' do
D
Dmitriy Zaporozhets 已提交
508 509
      other_user = create(:user)
      get api("/projects/#{project.id}/events", other_user)
510
      expect(response.status).to eq(404)
D
Dmitriy Zaporozhets 已提交
511 512 513
    end
  end

514
  describe 'GET /projects/:id/snippets' do
D
Dmitriy Zaporozhets 已提交
515 516
    before { snippet }

517
    it 'should return an array of project snippets' do
518
      get api("/projects/#{project.id}/snippets", user)
519 520 521
      expect(response.status).to eq(200)
      expect(json_response).to be_an Array
      expect(json_response.first['title']).to eq(snippet.title)
N
Nihad Abbasov 已提交
522 523 524
    end
  end

525 526
  describe 'GET /projects/:id/snippets/:snippet_id' do
    it 'should return a project snippet' do
527
      get api("/projects/#{project.id}/snippets/#{snippet.id}", user)
528 529
      expect(response.status).to eq(200)
      expect(json_response['title']).to eq(snippet.title)
N
Nihad Abbasov 已提交
530
    end
531

532
    it 'should return a 404 error if snippet id not found' do
533
      get api("/projects/#{project.id}/snippets/1234", user)
534
      expect(response.status).to eq(404)
535
    end
N
Nihad Abbasov 已提交
536 537
  end

538 539
  describe 'POST /projects/:id/snippets' do
    it 'should create a new project snippet' do
540
      post api("/projects/#{project.id}/snippets", user),
541 542
        title: 'api test', file_name: 'sample.rb', code: 'test',
        visibility_level: '0'
543 544
      expect(response.status).to eq(201)
      expect(json_response['title']).to eq('api test')
N
Nihad Abbasov 已提交
545
    end
546

547 548 549
    it 'should return a 400 error if invalid snippet is given' do
      post api("/projects/#{project.id}/snippets", user)
      expect(status).to eq(400)
550
    end
N
Nihad Abbasov 已提交
551 552
  end

553
  describe 'PUT /projects/:id/snippets/:snippet_id' do
554
    it 'should update an existing project snippet' do
555
      put api("/projects/#{project.id}/snippets/#{snippet.id}", user),
556
        code: 'updated code'
557 558 559
      expect(response.status).to eq(200)
      expect(json_response['title']).to eq('example')
      expect(snippet.reload.content).to eq('updated code')
560
    end
561

562
    it 'should update an existing project snippet with new title' do
563
      put api("/projects/#{project.id}/snippets/#{snippet.id}", user),
564
        title: 'other api test'
565 566
      expect(response.status).to eq(200)
      expect(json_response['title']).to eq('other api test')
567
    end
568 569
  end

570
  describe 'DELETE /projects/:id/snippets/:snippet_id' do
D
Dmitriy Zaporozhets 已提交
571 572
    before { snippet }

573
    it 'should delete existing project snippet' do
574
      expect do
575
        delete api("/projects/#{project.id}/snippets/#{snippet.id}", user)
576
      end.to change { Snippet.count }.by(-1)
577
      expect(response.status).to eq(200)
578 579
    end

J
jubianchi 已提交
580
    it 'should return 404 when deleting unknown snippet id' do
581
      delete api("/projects/#{project.id}/snippets/1234", user)
582
      expect(response.status).to eq(404)
N
Nihad Abbasov 已提交
583 584
    end
  end
585

586 587
  describe 'GET /projects/:id/snippets/:snippet_id/raw' do
    it 'should get a raw project snippet' do
588
      get api("/projects/#{project.id}/snippets/#{snippet.id}/raw", user)
589
      expect(response.status).to eq(200)
590
    end
591

592
    it 'should return a 404 error if raw project snippet not found' do
593
      get api("/projects/#{project.id}/snippets/5555/raw", user)
594
      expect(response.status).to eq(404)
595
    end
596
  end
597

598 599 600
  describe :deploy_keys do
    let(:deploy_keys_project) { create(:deploy_keys_project, project: project) }
    let(:deploy_key) { deploy_keys_project.deploy_key }
M
Matt Humphrey 已提交
601

602
    describe 'GET /projects/:id/keys' do
603
      before { deploy_key }
M
Matt Humphrey 已提交
604

605
      it 'should return array of ssh keys' do
606
        get api("/projects/#{project.id}/keys", user)
607 608 609
        expect(response.status).to eq(200)
        expect(json_response).to be_an Array
        expect(json_response.first['title']).to eq(deploy_key.title)
610
      end
M
Matt Humphrey 已提交
611 612
    end

613 614
    describe 'GET /projects/:id/keys/:key_id' do
      it 'should return a single key' do
615
        get api("/projects/#{project.id}/keys/#{deploy_key.id}", user)
616 617
        expect(response.status).to eq(200)
        expect(json_response['title']).to eq(deploy_key.title)
618
      end
M
Matt Humphrey 已提交
619

620
      it 'should return 404 Not Found with invalid ID' do
621
        get api("/projects/#{project.id}/keys/404", user)
622
        expect(response.status).to eq(404)
623
      end
M
Matt Humphrey 已提交
624 625
    end

626 627 628
    describe 'POST /projects/:id/keys' do
      it 'should not create an invalid ssh key' do
        post api("/projects/#{project.id}/keys", user), { title: 'invalid key' }
629 630
        expect(response.status).to eq(400)
        expect(json_response['message']['key']).to eq([
J
jubianchi 已提交
631 632 633
          'can\'t be blank',
          'is too short (minimum is 0 characters)',
          'is invalid'
634
        ])
J
jubianchi 已提交
635 636 637 638
      end

      it 'should not create a key without title' do
        post api("/projects/#{project.id}/keys", user), key: 'some key'
639 640
        expect(response.status).to eq(400)
        expect(json_response['message']['title']).to eq([
J
jubianchi 已提交
641 642
          'can\'t be blank',
          'is too short (minimum is 0 characters)'
643
        ])
644 645
      end

646
      it 'should create new ssh key' do
647
        key_attrs = attributes_for :key
648
        expect do
649
          post api("/projects/#{project.id}/keys", user), key_attrs
650
        end.to change{ project.deploy_keys.count }.by(1)
651
      end
M
Matt Humphrey 已提交
652 653
    end

654
    describe 'DELETE /projects/:id/keys/:key_id' do
655 656
      before { deploy_key }

657
      it 'should delete existing key' do
658
        expect do
659
          delete api("/projects/#{project.id}/keys/#{deploy_key.id}", user)
660
        end.to change{ project.deploy_keys.count }.by(-1)
661 662
      end

663
      it 'should return 404 Not Found with invalid ID' do
664
        delete api("/projects/#{project.id}/keys/404", user)
665
        expect(response.status).to eq(404)
666
      end
M
Matt Humphrey 已提交
667 668
    end
  end
669 670 671

  describe :fork_admin do
    let(:project_fork_target) { create(:project) }
672
    let(:project_fork_source) { create(:project, :public) }
673

674
    describe 'POST /projects/:id/fork/:forked_from_id' do
675
      let(:new_project_fork_source) { create(:project, :public) }
676 677 678

      it "shouldn't available for non admin users" do
        post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", user)
679
        expect(response.status).to eq(403)
680 681
      end

682
      it 'should allow project to be forked from an existing project' do
683
        expect(project_fork_target.forked?).not_to be_truthy
684
        post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
685
        expect(response.status).to eq(201)
686
        project_fork_target.reload
687 688 689
        expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id)
        expect(project_fork_target.forked_project_link).not_to be_nil
        expect(project_fork_target.forked?).to be_truthy
690 691
      end

692
      it 'should fail if forked_from project which does not exist' do
693
        post api("/projects/#{project_fork_target.id}/fork/9999", admin)
694
        expect(response.status).to eq(404)
695 696
      end

697
      it 'should fail with 409 if already forked' do
698 699
        post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
        project_fork_target.reload
700
        expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id)
701
        post api("/projects/#{project_fork_target.id}/fork/#{new_project_fork_source.id}", admin)
702
        expect(response.status).to eq(409)
703
        project_fork_target.reload
704 705
        expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id)
        expect(project_fork_target.forked?).to be_truthy
706 707 708
      end
    end

709
    describe 'DELETE /projects/:id/fork' do
710

711
      it "shouldn't be visible to users outside group" do
712
        delete api("/projects/#{project_fork_target.id}/fork", user)
713
        expect(response.status).to eq(404)
714 715
      end

716 717
      context 'when users belong to project group' do
        let(:project_fork_target) { create(:project, group: create(:group)) }
718

719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
        before do
          project_fork_target.group.add_owner user
          project_fork_target.group.add_developer user2
        end

        it 'should be forbidden to non-owner users' do
          delete api("/projects/#{project_fork_target.id}/fork", user2)
          expect(response.status).to eq(403)
        end

        it 'should make forked project unforked' do
          post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
          project_fork_target.reload
          expect(project_fork_target.forked_from_project).not_to be_nil
          expect(project_fork_target.forked?).to be_truthy
          delete api("/projects/#{project_fork_target.id}/fork", admin)
          expect(response.status).to eq(200)
          project_fork_target.reload
          expect(project_fork_target.forked_from_project).to be_nil
          expect(project_fork_target.forked?).not_to be_truthy
        end

        it 'should be idempotent if not forked' do
          expect(project_fork_target.forked_from_project).to be_nil
          delete api("/projects/#{project_fork_target.id}/fork", admin)
          expect(response.status).to eq(200)
          expect(project_fork_target.reload.forked_from_project).to be_nil
        end
747 748 749
      end
    end
  end
750

751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
  describe "POST /projects/:id/share" do
    let(:group) { create(:group) }

    it "should share project with group" do
      expect do
        post api("/projects/#{project.id}/share", user), group_id: group.id, group_access: Gitlab::Access::DEVELOPER
      end.to change { ProjectGroupLink.count }.by(1)

      expect(response.status).to eq 201
      expect(json_response['group_id']).to eq group.id
      expect(json_response['group_access']).to eq Gitlab::Access::DEVELOPER
    end

    it "should return a 400 error when group id is not given" do
      post api("/projects/#{project.id}/share", user), group_access: Gitlab::Access::DEVELOPER
      expect(response.status).to eq 400
    end

    it "should return a 400 error when access level is not given" do
      post api("/projects/#{project.id}/share", user), group_id: group.id
      expect(response.status).to eq 400
    end

    it "should return a 400 error when sharing is disabled" do
      project.namespace.update(share_with_group_lock: true)
      post api("/projects/#{project.id}/share", user), group_id: group.id, group_access: Gitlab::Access::DEVELOPER
      expect(response.status).to eq 400
    end

    it "should return a 409 error when wrong params passed" do
      post api("/projects/#{project.id}/share", user), group_id: group.id, group_access: 1234
      expect(response.status).to eq 409
      expect(json_response['message']).to eq 'Group access is not included in the list'
    end
  end

787
  describe 'GET /projects/search/:query' do
788
    let!(:query) { 'query'}
D
Dmitriy Zaporozhets 已提交
789 790 791 792 793
    let!(:search)           { create(:empty_project, name: query, creator_id: user.id, namespace: user.namespace) }
    let!(:pre)              { create(:empty_project, name: "pre_#{query}", creator_id: user.id, namespace: user.namespace) }
    let!(:post)             { create(:empty_project, name: "#{query}_post", creator_id: user.id, namespace: user.namespace) }
    let!(:pre_post)         { create(:empty_project, name: "pre_#{query}_post", creator_id: user.id, namespace: user.namespace) }
    let!(:unfound)          { create(:empty_project, name: 'unfound', creator_id: user.id, namespace: user.namespace) }
794 795 796 797
    let!(:internal)         { create(:empty_project, :internal, name: "internal #{query}") }
    let!(:unfound_internal) { create(:empty_project, :internal, name: 'unfound internal') }
    let!(:public)           { create(:empty_project, :public, name: "public #{query}") }
    let!(:unfound_public)   { create(:empty_project, :public, name: 'unfound public') }
798

799 800
    context 'when unauthenticated' do
      it 'should return authentication error' do
801
        get api("/projects/search/#{query}")
802
        expect(response.status).to eq(401)
803 804 805
      end
    end

806 807
    context 'when authenticated' do
      it 'should return an array of projects' do
808
        get api("/projects/search/#{query}",user)
809 810 811 812
        expect(response.status).to eq(200)
        expect(json_response).to be_an Array
        expect(json_response.size).to eq(6)
        json_response.each {|project| expect(project['name']).to match(/.*query.*/)}
813 814 815
      end
    end

816 817
    context 'when authenticated as a different user' do
      it 'should return matching public projects' do
818
        get api("/projects/search/#{query}", user2)
819 820 821 822
        expect(response.status).to eq(200)
        expect(json_response).to be_an Array
        expect(json_response.size).to eq(2)
        json_response.each {|project| expect(project['name']).to match(/(internal|public) query/)}
823 824 825
      end
    end
  end
826

827 828 829 830 831 832 833 834 835 836 837 838 839 840
  describe 'PUT /projects/:id̈́' do
    before { project }
    before { user }
    before { user3 }
    before { user4 }
    before { project3 }
    before { project4 }
    before { project_member3 }
    before { project_member2 }

    context 'when unauthenticated' do
      it 'should return authentication error' do
        project_param = { name: 'bar' }
        put api("/projects/#{project.id}"), project_param
841
        expect(response.status).to eq(401)
842 843 844 845 846 847 848
      end
    end

    context 'when authenticated as project owner' do
      it 'should update name' do
        project_param = { name: 'bar' }
        put api("/projects/#{project.id}", user), project_param
849
        expect(response.status).to eq(200)
850
        project_param.each_pair do |k, v|
851
          expect(json_response[k.to_s]).to eq(v)
852 853 854 855 856 857
        end
      end

      it 'should update visibility_level' do
        project_param = { visibility_level: 20 }
        put api("/projects/#{project3.id}", user), project_param
858
        expect(response.status).to eq(200)
859
        project_param.each_pair do |k, v|
860
          expect(json_response[k.to_s]).to eq(v)
861 862 863
        end
      end

864 865 866 867 868 869 870 871 872 873 874 875
      it 'should update visibility_level from public to private' do
        project3.update_attributes({ visibility_level: Gitlab::VisibilityLevel::PUBLIC })

        project_param = { public: false }
        put api("/projects/#{project3.id}", user), project_param
        expect(response.status).to eq(200)
        project_param.each_pair do |k, v|
          expect(json_response[k.to_s]).to eq(v)
        end
        expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
      end

876 877 878
      it 'should not update name to existing name' do
        project_param = { name: project3.name }
        put api("/projects/#{project.id}", user), project_param
879 880
        expect(response.status).to eq(400)
        expect(json_response['message']['name']).to eq(['has already been taken'])
881 882 883 884 885
      end

      it 'should update path & name to existing path & name in different namespace' do
        project_param = { path: project4.path, name: project4.name }
        put api("/projects/#{project3.id}", user), project_param
886
        expect(response.status).to eq(200)
887
        project_param.each_pair do |k, v|
888
          expect(json_response[k.to_s]).to eq(v)
889 890 891 892 893 894 895 896
        end
      end
    end

    context 'when authenticated as project master' do
      it 'should update path' do
        project_param = { path: 'bar' }
        put api("/projects/#{project3.id}", user4), project_param
897
        expect(response.status).to eq(200)
898
        project_param.each_pair do |k, v|
899
          expect(json_response[k.to_s]).to eq(v)
900 901 902 903 904 905 906 907 908 909 910
        end
      end

      it 'should update other attributes' do
        project_param = { issues_enabled: true,
                          wiki_enabled: true,
                          snippets_enabled: true,
                          merge_requests_enabled: true,
                          description: 'new description' }

        put api("/projects/#{project3.id}", user4), project_param
911
        expect(response.status).to eq(200)
912
        project_param.each_pair do |k, v|
913
          expect(json_response[k.to_s]).to eq(v)
914 915 916 917 918 919
        end
      end

      it 'should not update path to existing path' do
        project_param = { path: project.path }
        put api("/projects/#{project3.id}", user4), project_param
920 921
        expect(response.status).to eq(400)
        expect(json_response['message']['path']).to eq(['has already been taken'])
922 923 924 925 926
      end

      it 'should not update name' do
        project_param = { name: 'bar' }
        put api("/projects/#{project3.id}", user4), project_param
927
        expect(response.status).to eq(403)
928 929 930 931 932
      end

      it 'should not update visibility_level' do
        project_param = { visibility_level: 20 }
        put api("/projects/#{project3.id}", user4), project_param
933
        expect(response.status).to eq(403)
934 935 936 937 938 939 940 941 942 943 944 945
      end
    end

    context 'when authenticated as project developer' do
      it 'should not update other attributes' do
        project_param = { path: 'bar',
                          issues_enabled: true,
                          wiki_enabled: true,
                          snippets_enabled: true,
                          merge_requests_enabled: true,
                          description: 'new description' }
        put api("/projects/#{project.id}", user3), project_param
946
        expect(response.status).to eq(403)
947 948 949 950
      end
    end
  end

951
  describe 'POST /projects/:id/archive' do
952 953
    context 'on an unarchived project' do
      it 'archives the project' do
954
        post api("/projects/#{project.id}/archive", user)
955

956
        expect(response.status).to eq(201)
957 958 959 960 961 962 963 964 965 966
        expect(json_response['archived']).to be_truthy
      end
    end

    context 'on an archived project' do
      before do
        project.archive!
      end

      it 'remains archived' do
967
        post api("/projects/#{project.id}/archive", user)
968

969
        expect(response.status).to eq(201)
970 971
        expect(json_response['archived']).to be_truthy
      end
972
    end
973

974 975 976 977
    context 'user without archiving rights to the project' do
      before do
        project.team << [user3, :developer]
      end
978

979 980 981 982
      it 'rejects the action' do
        post api("/projects/#{project.id}/archive", user3)

        expect(response.status).to eq(403)
983 984 985 986
      end
    end
  end

987
  describe 'POST /projects/:id/unarchive' do
988 989
    context 'on an unarchived project' do
      it 'remains unarchived' do
990
        post api("/projects/#{project.id}/unarchive", user)
991

992
        expect(response.status).to eq(201)
993 994 995 996 997 998 999 1000 1001
        expect(json_response['archived']).to be_falsey
      end
    end

    context 'on an archived project' do
      before do
        project.archive!
      end

1002 1003
      it 'unarchives the project' do
        post api("/projects/#{project.id}/unarchive", user)
1004

1005
        expect(response.status).to eq(201)
1006 1007
        expect(json_response['archived']).to be_falsey
      end
1008
    end
1009

1010 1011 1012 1013
    context 'user without archiving rights to the project' do
      before do
        project.team << [user3, :developer]
      end
1014

1015 1016 1017 1018
      it 'rejects the action' do
        post api("/projects/#{project.id}/unarchive", user3)

        expect(response.status).to eq(403)
1019 1020 1021 1022
      end
    end
  end

1023 1024 1025
  describe 'DELETE /projects/:id' do
    context 'when authenticated as user' do
      it 'should remove project' do
1026
        delete api("/projects/#{project.id}", user)
1027
        expect(response.status).to eq(200)
1028 1029
      end

1030
      it 'should not remove a project if not an owner' do
1031 1032 1033
        user3 = create(:user)
        project.team << [user3, :developer]
        delete api("/projects/#{project.id}", user3)
1034
        expect(response.status).to eq(403)
1035 1036
      end

1037 1038
      it 'should not remove a non existing project' do
        delete api('/projects/1328', user)
1039
        expect(response.status).to eq(404)
1040 1041
      end

1042
      it 'should not remove a project not attached to user' do
1043
        delete api("/projects/#{project.id}", user2)
1044
        expect(response.status).to eq(404)
1045 1046 1047
      end
    end

1048 1049
    context 'when authenticated as admin' do
      it 'should remove any existing project' do
1050
        delete api("/projects/#{project.id}", admin)
1051
        expect(response.status).to eq(200)
1052 1053
      end

1054 1055
      it 'should not remove a non existing project' do
        delete api('/projects/1328', admin)
1056
        expect(response.status).to eq(404)
1057 1058 1059
      end
    end
  end
N
Nihad Abbasov 已提交
1060
end