projects_spec.rb 35.4 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 278 279 280 281 282 283 284 285 286 287 288 289 290 291
      end

      it 'should not allow a non-admin to use a restricted visibility level' do
        post api('/projects', user), @project
        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
292 293
  end

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

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

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

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

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

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

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

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

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

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

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

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

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

D
Douwe Maan 已提交
379 380 381 382 383 384 385 386 387 388 389 390 391 392
  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

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

397
    it 'should return a project by id' do
R
Robert Speicher 已提交
398
      get api("/projects/#{project.id}", user)
399 400 401
      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 已提交
402
    end
403

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

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

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

422 423 424 425 426 427 428 429 430
    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

431
    describe 'permissions' do
432 433 434 435 436 437 438 439 440 441 442 443
      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

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

449 450 451 452 453
          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
454 455 456
      end

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

462 463 464 465 466
          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
467 468
      end
    end
N
Nihad Abbasov 已提交
469 470
  end

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

D
Dmitriy Zaporozhets 已提交
474 475 476 477 478 479 480 481 482 483 484
    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 已提交
485

D
Dmitriy Zaporozhets 已提交
486 487 488 489 490 491 492 493 494 495 496 497
        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 已提交
498 499
    end

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

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

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

516
    it 'should return an array of project snippets' do
517
      get api("/projects/#{project.id}/snippets", user)
518 519 520
      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 已提交
521 522 523
    end
  end

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

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

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

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

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

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

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

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

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

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

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

597 598 599
  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 已提交
600

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

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

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

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

625 626 627
    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' }
628 629
        expect(response.status).to eq(400)
        expect(json_response['message']['key']).to eq([
J
jubianchi 已提交
630 631 632
          'can\'t be blank',
          'is too short (minimum is 0 characters)',
          'is invalid'
633
        ])
J
jubianchi 已提交
634 635 636 637
      end

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

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

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

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

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

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

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

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

681
      it 'should allow project to be forked from an existing project' do
682
        expect(project_fork_target.forked?).not_to be_truthy
683
        post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
684
        expect(response.status).to eq(201)
685
        project_fork_target.reload
686 687 688
        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
689 690
      end

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

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

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

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

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

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
        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
746 747 748
      end
    end
  end
749

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
  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

786
  describe 'GET /projects/search/:query' do
787
    let!(:query) { 'query'}
D
Dmitriy Zaporozhets 已提交
788 789 790 791 792
    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) }
793 794 795 796
    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') }
797

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

805 806
    context 'when authenticated' do
      it 'should return an array of projects' do
807
        get api("/projects/search/#{query}",user)
808 809 810 811
        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.*/)}
812 813 814
      end
    end

815 816
    context 'when authenticated as a different user' do
      it 'should return matching public projects' do
817
        get api("/projects/search/#{query}", user2)
818 819 820 821
        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/)}
822 823 824
      end
    end
  end
825

826 827 828 829 830 831 832 833 834 835 836 837 838 839
  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
840
        expect(response.status).to eq(401)
841 842 843 844 845 846 847
      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
848
        expect(response.status).to eq(200)
849
        project_param.each_pair do |k, v|
850
          expect(json_response[k.to_s]).to eq(v)
851 852 853 854 855 856
        end
      end

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

863 864 865 866 867 868 869 870 871 872 873 874
      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

875 876 877
      it 'should not update name to existing name' do
        project_param = { name: project3.name }
        put api("/projects/#{project.id}", user), project_param
878 879
        expect(response.status).to eq(400)
        expect(json_response['message']['name']).to eq(['has already been taken'])
880 881 882 883 884
      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
885
        expect(response.status).to eq(200)
886
        project_param.each_pair do |k, v|
887
          expect(json_response[k.to_s]).to eq(v)
888 889 890 891 892 893 894 895
        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
896
        expect(response.status).to eq(200)
897
        project_param.each_pair do |k, v|
898
          expect(json_response[k.to_s]).to eq(v)
899 900 901 902 903 904 905 906 907 908 909
        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
910
        expect(response.status).to eq(200)
911
        project_param.each_pair do |k, v|
912
          expect(json_response[k.to_s]).to eq(v)
913 914 915 916 917 918
        end
      end

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

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

      it 'should not update visibility_level' do
        project_param = { visibility_level: 20 }
        put api("/projects/#{project3.id}", user4), project_param
932
        expect(response.status).to eq(403)
933 934 935 936 937 938 939 940 941 942 943 944
      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
945
        expect(response.status).to eq(403)
946 947 948 949
      end
    end
  end

950 951 952
  describe 'DELETE /projects/:id' do
    context 'when authenticated as user' do
      it 'should remove project' do
953
        delete api("/projects/#{project.id}", user)
954
        expect(response.status).to eq(200)
955 956
      end

957
      it 'should not remove a project if not an owner' do
958 959 960
        user3 = create(:user)
        project.team << [user3, :developer]
        delete api("/projects/#{project.id}", user3)
961
        expect(response.status).to eq(403)
962 963
      end

964 965
      it 'should not remove a non existing project' do
        delete api('/projects/1328', user)
966
        expect(response.status).to eq(404)
967 968
      end

969
      it 'should not remove a project not attached to user' do
970
        delete api("/projects/#{project.id}", user2)
971
        expect(response.status).to eq(404)
972 973 974
      end
    end

975 976
    context 'when authenticated as admin' do
      it 'should remove any existing project' do
977
        delete api("/projects/#{project.id}", admin)
978
        expect(response.status).to eq(200)
979 980
      end

981 982
      it 'should not remove a non existing project' do
        delete api('/projects/1328', admin)
983
        expect(response.status).to eq(404)
984 985 986
      end
    end
  end
N
Nihad Abbasov 已提交
987
end