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

4
describe API::Projects, 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) }
11 12
  let(:project) { create(:empty_project, creator_id: user.id, namespace: user.namespace) }
  let(:project2) { create(:empty_project, path: 'project2', creator_id: user.id, namespace: user.namespace) }
13
  let(:snippet) { create(:project_snippet, :public, author: user, project: project, title: 'example') }
14 15
  let(:project_member) { create(:project_member, :master, user: user, project: project) }
  let(:project_member2) { create(:project_member, :developer, user: user3, project: project) }
16
  let(:user4) { create(:user) }
17 18
  let(:project3) do
    create(:project,
19
    :private,
20
    :repository,
21 22 23 24 25 26
    name: 'second_project',
    path: 'second_project',
    creator_id: user.id,
    namespace: user.namespace,
    merge_requests_enabled: false,
    issues_enabled: false, wiki_enabled: false,
27
    snippets_enabled: false)
28 29 30 31 32 33 34 35
  end
  let(:project_member3) do
    create(:project_member,
    user: user4,
    project: project3,
    access_level: ProjectMember::MASTER)
  end
  let(:project4) do
36
    create(:empty_project,
37 38 39 40 41 42 43
    name: 'third_project',
    path: 'third_project',
    creator_id: user4.id,
    namespace: user4.namespace)
  end

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

46
    context 'when unauthenticated' do
47
      it 'returns authentication error' do
48
        get api('/projects')
Z
Z.J. van de Weg 已提交
49
        expect(response).to have_http_status(401)
50
      end
N
Nihad Abbasov 已提交
51 52
    end

M
Markus Koller 已提交
53
    context 'when authenticated as regular user' do
54
      it 'returns an array of projects' do
55
        get api('/projects', user)
Z
Z.J. van de Weg 已提交
56
        expect(response).to have_http_status(200)
57 58 59
        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 已提交
60
      end
61

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

69
      it 'includes open_issues_count' do
S
Stan Hu 已提交
70 71 72 73 74 75
        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

76
      it 'does not include open_issues_count' do
F
Felipe Artur 已提交
77
        project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED)
S
Stan Hu 已提交
78 79 80 81 82 83 84

        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

85
      context 'GET /projects?simple=true' do
T
tiagonbotelho 已提交
86
        it 'returns a simplified version of all the projects' do
87
          expected_keys = ["id", "http_url_to_repo", "web_url", "name", "name_with_namespace", "path", "path_with_namespace"]
88

89
          get api('/projects?simple=true', user)
T
tiagonbotelho 已提交
90

91 92
          expect(response).to have_http_status(200)
          expect(json_response).to be_an Array
93
          expect(json_response.first.keys).to match_array expected_keys
94 95 96
        end
      end

97
      context 'and using search' do
98
        it 'returns searched project' do
99
          get api('/projects', user), { search: project.name }
Z
Z.J. van de Weg 已提交
100
          expect(response).to have_http_status(200)
101 102
          expect(json_response).to be_an Array
          expect(json_response.length).to eq(1)
103 104 105
        end
      end

J
Josh Frye 已提交
106
      context 'and using the visibility filter' do
107
        it 'filters based on private visibility param' do
J
Josh Frye 已提交
108
          get api('/projects', user), { visibility: 'private' }
Z
Z.J. van de Weg 已提交
109
          expect(response).to have_http_status(200)
J
Josh Frye 已提交
110 111 112 113
          expect(json_response).to be_an Array
          expect(json_response.length).to eq(user.namespace.projects.where(visibility_level: Gitlab::VisibilityLevel::PRIVATE).count)
        end

114
        it 'filters based on internal visibility param' do
J
Josh Frye 已提交
115
          get api('/projects', user), { visibility: 'internal' }
Z
Z.J. van de Weg 已提交
116
          expect(response).to have_http_status(200)
J
Josh Frye 已提交
117 118 119 120
          expect(json_response).to be_an Array
          expect(json_response.length).to eq(user.namespace.projects.where(visibility_level: Gitlab::VisibilityLevel::INTERNAL).count)
        end

121
        it 'filters based on public visibility param' do
J
Josh Frye 已提交
122
          get api('/projects', user), { visibility: 'public' }
Z
Z.J. van de Weg 已提交
123
          expect(response).to have_http_status(200)
J
Josh Frye 已提交
124 125 126 127 128
          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

129
      context 'and using sorting' do
130 131 132 133 134
        before do
          project2
          project3
        end

135
        it 'returns the correct order when sorted by id' do
136
          get api('/projects', user), { order_by: 'id', sort: 'desc' }
Z
Z.J. van de Weg 已提交
137
          expect(response).to have_http_status(200)
138 139
          expect(json_response).to be_an Array
          expect(json_response.first['id']).to eq(project3.id)
140 141
        end
      end
N
Nihad Abbasov 已提交
142 143 144
    end
  end

145
  describe 'GET /projects/all' do
D
Dmitriy Zaporozhets 已提交
146 147
    before { project }

148
    context 'when unauthenticated' do
149
      it 'returns authentication error' do
150
        get api('/projects/all')
Z
Z.J. van de Weg 已提交
151
        expect(response).to have_http_status(401)
D
Dmitriy Zaporozhets 已提交
152 153 154
      end
    end

155
    context 'when authenticated as regular user' do
156
      it 'returns authentication error' do
157
        get api('/projects/all', user)
Z
Z.J. van de Weg 已提交
158
        expect(response).to have_http_status(403)
D
Dmitriy Zaporozhets 已提交
159 160 161
      end
    end

162
    context 'when authenticated as admin' do
163
      it 'returns an array of all projects' do
164
        get api('/projects/all', admin)
Z
Z.J. van de Weg 已提交
165
        expect(response).to have_http_status(200)
166
        expect(json_response).to be_an Array
M
Marin Jankovski 已提交
167

168 169
        expect(json_response).to satisfy do |response|
          response.one? do |entry|
170
            entry.has_key?('permissions') &&
171
              entry['name'] == project.name &&
172
              entry['owner']['username'] == user.username
173 174
          end
        end
D
Dmitriy Zaporozhets 已提交
175
      end
M
Markus Koller 已提交
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191

      it "does not include statistics by default" do
        get api('/projects/all', admin)

        expect(response).to have_http_status(200)
        expect(json_response).to be_an Array
        expect(json_response.first).not_to include('statistics')
      end

      it "includes statistics if requested" do
        get api('/projects/all', admin), statistics: true

        expect(response).to have_http_status(200)
        expect(json_response).to be_an Array
        expect(json_response.first).to include 'statistics'
      end
D
Dmitriy Zaporozhets 已提交
192 193 194
    end
  end

195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
  describe 'GET /projects/owned' do
    before do
      project3
      project4
    end

    context 'when unauthenticated' do
      it 'returns authentication error' do
        get api('/projects/owned')
        expect(response).to have_http_status(401)
      end
    end

    context 'when authenticated as project owner' do
      it 'returns an array of projects the user owns' do
        get api('/projects/owned', user4)
        expect(response).to have_http_status(200)
        expect(json_response).to be_an Array
        expect(json_response.first['name']).to eq(project4.name)
        expect(json_response.first['owner']['username']).to eq(user4.username)
      end
M
Markus Koller 已提交
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241

      it "does not include statistics by default" do
        get api('/projects/owned', user4)

        expect(response).to have_http_status(200)
        expect(json_response).to be_an Array
        expect(json_response.first).not_to include('statistics')
      end

      it "includes statistics if requested" do
        attributes = {
          commit_count: 23,
          storage_size: 702,
          repository_size: 123,
          lfs_objects_size: 234,
          build_artifacts_size: 345,
        }

        project4.statistics.update!(attributes)

        get api('/projects/owned', user4), statistics: true

        expect(response).to have_http_status(200)
        expect(json_response).to be_an Array
        expect(json_response.first['statistics']).to eq attributes.stringify_keys
      end
242 243 244
    end
  end

245
  describe 'GET /projects/visible' do
246 247 248 249 250 251 252 253 254
    shared_examples_for 'visible projects response' do
      it 'returns the visible projects' do
        get api('/projects/visible', current_user)

        expect(response).to have_http_status(200)
        expect(json_response).to be_an Array
        expect(json_response.map { |p| p['id'] }).to contain_exactly(*projects.map(&:id))
      end
    end
255

256
    let!(:public_project) { create(:empty_project, :public) }
257 258 259 260 261 262 263
    before do
      project
      project2
      project3
      project4
    end

264 265 266 267 268
    context 'when unauthenticated' do
      it_behaves_like 'visible projects response' do
        let(:current_user) { nil }
        let(:projects) { [public_project] }
      end
269 270
    end

271 272 273 274 275 276
    context 'when authenticated' do
      it_behaves_like 'visible projects response' do
        let(:current_user) { user }
        let(:projects) { [public_project, project, project2, project3] }
      end
    end
277

278 279 280 281 282
    context 'when authenticated as a different user' do
      it_behaves_like 'visible projects response' do
        let(:current_user) { user2 }
        let(:projects) { [public_project] }
      end
283 284 285
    end
  end

286
  describe 'GET /projects/starred' do
287
    let(:public_project) { create(:empty_project, :public) }
288

289
    before do
290 291
      project_member2
      user3.update_attributes(starred_projects: [project, project2, project3, public_project])
292 293
    end

294
    it 'returns the starred projects viewable by the user' do
295
      get api('/projects/starred', user3)
Z
Z.J. van de Weg 已提交
296
      expect(response).to have_http_status(200)
297
      expect(json_response).to be_an Array
298
      expect(json_response.map { |project| project['id'] }).to contain_exactly(project.id, public_project.id)
299 300 301
    end
  end

302 303
  describe 'POST /projects' do
    context 'maximum number of projects reached' do
304
      it 'does not create new project and respond with 403' do
305
        allow_any_instance_of(User).to receive(:projects_limit_left).and_return(0)
306 307
        expect { post api('/projects', user2), name: 'foo' }.
          to change {Project.count}.by(0)
Z
Z.J. van de Weg 已提交
308
        expect(response).to have_http_status(403)
309 310 311
      end
    end

312
    it 'creates new project without path and return 201' do
313 314
      expect { post api('/projects', user), name: 'foo' }.
        to change { Project.count }.by(1)
Z
Z.J. van de Weg 已提交
315
      expect(response).to have_http_status(201)
316 317
    end

318
    it 'creates last project before reaching project limit' do
319
      allow_any_instance_of(User).to receive(:projects_limit_left).and_return(1)
320
      post api('/projects', user2), name: 'foo'
Z
Z.J. van de Weg 已提交
321
      expect(response).to have_http_status(201)
322 323
    end

324
    it 'does not create new project without name and return 400' do
325
      expect { post api('/projects', user) }.not_to change { Project.count }
Z
Z.J. van de Weg 已提交
326
      expect(response).to have_http_status(400)
327
    end
A
Alex Denisov 已提交
328

329
    it "assigns attributes to project" do
330
      project = attributes_for(:project, {
331
        path: 'camelCasePath',
R
Robert Speicher 已提交
332
        description: FFaker::Lorem.sentence,
333 334
        issues_enabled: false,
        merge_requests_enabled: false,
335
        wiki_enabled: false,
336
        only_allow_merge_if_build_succeeds: false,
337 338
        request_access_enabled: true,
        only_allow_merge_if_all_discussions_are_resolved: false
A
Alex Denisov 已提交
339 340
      })

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

343
      project.each_pair do |k, v|
344
        next if %i[has_external_issue_tracker issues_enabled merge_requests_enabled wiki_enabled].include?(k)
345
        expect(json_response[k.to_s]).to eq(v)
A
Alex Denisov 已提交
346
      end
F
Felipe Artur 已提交
347 348 349 350 351 352

      # Check feature permissions attributes
      project = Project.find_by_path(project[:path])
      expect(project.project_feature.issues_access_level).to eq(ProjectFeature::DISABLED)
      expect(project.project_feature.merge_requests_access_level).to eq(ProjectFeature::DISABLED)
      expect(project.project_feature.wiki_access_level).to eq(ProjectFeature::DISABLED)
353
    end
354

355
    it 'sets a project as public' do
356
      project = attributes_for(:project, :public)
357
      post api('/projects', user), project
358 359
      expect(json_response['public']).to be_truthy
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
360 361
    end

362
    it 'sets a project as internal' do
363
      project = attributes_for(:project, :internal)
364
      post api('/projects', user), project
365 366
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
367 368
    end

369
    it 'sets a project as private' do
370
      project = attributes_for(:project, :private)
371
      post api('/projects', user), project
372 373
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
374 375
    end

376 377 378 379 380 381 382 383 384 385 386 387
    it 'sets a project as allowing merge even if build fails' do
      project = attributes_for(:project, { only_allow_merge_if_build_succeeds: false })
      post api('/projects', user), project
      expect(json_response['only_allow_merge_if_build_succeeds']).to be_falsey
    end

    it 'sets a project as allowing merge only if build succeeds' do
      project = attributes_for(:project, { only_allow_merge_if_build_succeeds: true })
      post api('/projects', user), project
      expect(json_response['only_allow_merge_if_build_succeeds']).to be_truthy
    end

388 389 390 391 392 393 394 395
    it 'sets a project as allowing merge even if discussions are unresolved' do
      project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: false })

      post api('/projects', user), project

      expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_falsey
    end

396 397 398 399 400 401 402 403
    it 'sets a project as allowing merge if only_allow_merge_if_all_discussions_are_resolved is nil' do
      project = attributes_for(:project, only_allow_merge_if_all_discussions_are_resolved: nil)

      post api('/projects', user), project

      expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_falsey
    end

404 405 406 407 408 409 410 411
    it 'sets a project as allowing merge only if all discussions are resolved' do
      project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: true })

      post api('/projects', user), project

      expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_truthy
    end

412
    context 'when a visibility level is restricted' do
413 414
      let(:project_param) { attributes_for(:project, :public) }

415
      before do
416
        stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
417 418
      end

419
      it 'does not allow a non-admin to use a restricted visibility level' do
420
        post api('/projects', user), project_param
F
Felipe Artur 已提交
421

Z
Z.J. van de Weg 已提交
422
        expect(response).to have_http_status(400)
423 424 425 426 427
        expect(json_response['message']['visibility_level'].first).to(
          match('restricted by your GitLab administrator')
        )
      end

428
      it 'allows an admin to override restricted visibility settings' do
429 430
        post api('/projects', admin), project_param

431 432 433 434 435 436
        expect(json_response['public']).to be_truthy
        expect(json_response['visibility_level']).to(
          eq(Gitlab::VisibilityLevel::PUBLIC)
        )
      end
    end
437 438
  end

439
  describe 'POST /projects/user/:id' do
D
Dmitriy Zaporozhets 已提交
440
    before { project }
A
Angus MacArthur 已提交
441 442
    before { admin }

V
Valery Sizov 已提交
443
    it 'creates new project without path and return 201' do
444
      expect { post api("/projects/user/#{user.id}", admin), name: 'foo' }.to change {Project.count}.by(1)
Z
Z.J. van de Weg 已提交
445
      expect(response).to have_http_status(201)
A
Angus MacArthur 已提交
446 447
    end

448
    it 'responds with 400 on failure and not project' do
449
      expect { post api("/projects/user/#{user.id}", admin) }.
450
        not_to change { Project.count }
451

Z
Z.J. van de Weg 已提交
452
      expect(response).to have_http_status(400)
R
Robert Schilling 已提交
453
      expect(json_response['error']).to eq('name is missing')
A
Angus MacArthur 已提交
454 455
    end

456
    it 'assigns attributes to project' do
A
Angus MacArthur 已提交
457
      project = attributes_for(:project, {
R
Robert Speicher 已提交
458
        description: FFaker::Lorem.sentence,
459 460
        issues_enabled: false,
        merge_requests_enabled: false,
461 462
        wiki_enabled: false,
        request_access_enabled: true
A
Angus MacArthur 已提交
463 464 465 466
      })

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

R
Robert Schilling 已提交
467
      expect(response).to have_http_status(201)
468
      project.each_pair do |k, v|
469
        next if %i[has_external_issue_tracker path].include?(k)
470
        expect(json_response[k.to_s]).to eq(v)
A
Angus MacArthur 已提交
471 472
      end
    end
473

474
    it 'sets a project as public' do
475
      project = attributes_for(:project, :public)
476
      post api("/projects/user/#{user.id}", admin), project
R
Robert Schilling 已提交
477 478

      expect(response).to have_http_status(201)
479 480
      expect(json_response['public']).to be_truthy
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
481 482
    end

483
    it 'sets a project as internal' do
484
      project = attributes_for(:project, :internal)
485
      post api("/projects/user/#{user.id}", admin), project
R
Robert Schilling 已提交
486 487

      expect(response).to have_http_status(201)
488 489
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
490 491
    end

492
    it 'sets a project as private' do
493
      project = attributes_for(:project, :private)
494
      post api("/projects/user/#{user.id}", admin), project
495 496
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
497 498
    end

499 500 501 502 503 504 505 506 507 508 509
    it 'sets a project as allowing merge even if build fails' do
      project = attributes_for(:project, { only_allow_merge_if_build_succeeds: false })
      post api("/projects/user/#{user.id}", admin), project
      expect(json_response['only_allow_merge_if_build_succeeds']).to be_falsey
    end

    it 'sets a project as allowing merge only if build succeeds' do
      project = attributes_for(:project, { only_allow_merge_if_build_succeeds: true })
      post api("/projects/user/#{user.id}", admin), project
      expect(json_response['only_allow_merge_if_build_succeeds']).to be_truthy
    end
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525

    it 'sets a project as allowing merge even if discussions are unresolved' do
      project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: false })

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

      expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_falsey
    end

    it 'sets a project as allowing merge only if all discussions are resolved' do
      project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: true })

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

      expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_truthy
    end
A
Angus MacArthur 已提交
526 527
  end

D
Douwe Maan 已提交
528 529 530 531 532 533
  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")

Z
Z.J. van de Weg 已提交
534
      expect(response).to have_http_status(201)
D
Douwe Maan 已提交
535 536 537 538 539 540
      expect(json_response['alt']).to eq("dk")
      expect(json_response['url']).to start_with("/uploads/")
      expect(json_response['url']).to end_with("/dk.png")
    end
  end

541
  describe 'GET /projects/:id' do
542 543
    context 'when unauthenticated' do
      it 'returns the public projects' do
544
        public_project = create(:empty_project, :public)
545

546
        get api("/projects/#{public_project.id}")
547

548 549 550 551 552
        expect(response).to have_http_status(200)
        expect(json_response['id']).to eq(public_project.id)
        expect(json_response['description']).to eq(public_project.description)
        expect(json_response.keys).not_to include('permissions')
      end
553
    end
N
Nihad Abbasov 已提交
554

555 556 557 558 559
    context 'when authenticated' do
      before do
        project
        project_member
      end
560

561 562 563
      it 'returns a project by id' do
        group = create(:group)
        link = create(:project_group_link, project: project, group: group)
564

565
        get api("/projects/#{project.id}", user)
566

567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
        expect(response).to have_http_status(200)
        expect(json_response['id']).to eq(project.id)
        expect(json_response['description']).to eq(project.description)
        expect(json_response['default_branch']).to eq(project.default_branch)
        expect(json_response['tag_list']).to be_an Array
        expect(json_response['public']).to be_falsey
        expect(json_response['archived']).to be_falsey
        expect(json_response['visibility_level']).to be_present
        expect(json_response['ssh_url_to_repo']).to be_present
        expect(json_response['http_url_to_repo']).to be_present
        expect(json_response['web_url']).to be_present
        expect(json_response['owner']).to be_a Hash
        expect(json_response['owner']).to be_a Hash
        expect(json_response['name']).to eq(project.name)
        expect(json_response['path']).to be_present
        expect(json_response['issues_enabled']).to be_present
        expect(json_response['merge_requests_enabled']).to be_present
        expect(json_response['wiki_enabled']).to be_present
        expect(json_response['builds_enabled']).to be_present
        expect(json_response['snippets_enabled']).to be_present
        expect(json_response['container_registry_enabled']).to be_present
        expect(json_response['created_at']).to be_present
        expect(json_response['last_activity_at']).to be_present
        expect(json_response['shared_runners_enabled']).to be_present
        expect(json_response['creator_id']).to be_present
        expect(json_response['namespace']).to be_present
        expect(json_response['avatar_url']).to be_nil
        expect(json_response['star_count']).to be_present
        expect(json_response['forks_count']).to be_present
        expect(json_response['public_builds']).to be_present
        expect(json_response['shared_with_groups']).to be_an Array
        expect(json_response['shared_with_groups'].length).to eq(1)
        expect(json_response['shared_with_groups'][0]['group_id']).to eq(group.id)
        expect(json_response['shared_with_groups'][0]['group_name']).to eq(group.name)
        expect(json_response['shared_with_groups'][0]['group_access_level']).to eq(link.group_access)
        expect(json_response['only_allow_merge_if_build_succeeds']).to eq(project.only_allow_merge_if_build_succeeds)
        expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to eq(project.only_allow_merge_if_all_discussions_are_resolved)
      end
605

606 607 608 609 610
      it 'returns a project by path name' do
        get api("/projects/#{project.id}", user)
        expect(response).to have_http_status(200)
        expect(json_response['name']).to eq(project.name)
      end
611

612 613 614 615 616
      it 'returns a 404 error if not found' do
        get api('/projects/42', user)
        expect(response).to have_http_status(404)
        expect(json_response['message']).to eq('404 Project Not Found')
      end
617

618 619 620 621
      it 'returns a 404 error if user is not a member' do
        other_user = create(:user)
        get api("/projects/#{project.id}", other_user)
        expect(response).to have_http_status(404)
622 623
      end

624 625
      it 'handles users with dots' do
        dot_user = create(:user, username: 'dot.user')
626
        project = create(:empty_project, creator_id: dot_user.id, namespace: dot_user.namespace)
627

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

633 634 635 636 637 638 639 640 641 642 643 644
      it 'exposes namespace fields' do
        get api("/projects/#{project.id}", user)

        expect(response).to have_http_status(200)
        expect(json_response['namespace']).to eq({
          'id' => user.namespace.id,
          'name' => user.namespace.name,
          'path' => user.namespace.path,
          'kind' => user.namespace.kind,
        })
      end

645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
      describe 'permissions' do
        context 'all projects' do
          before { project.team << [user, :master] }

          it 'contains permission information' do
            get api("/projects", user)

            expect(response).to have_http_status(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

        context 'personal project' do
          it 'sets project access and returns 200' do
            project.team << [user, :master]
            get api("/projects/#{project.id}", user)

            expect(response).to have_http_status(200)
            expect(json_response['permissions']['project_access']['access_level']).
666
            to eq(Gitlab::Access::MASTER)
667 668
            expect(json_response['permissions']['group_access']).to be_nil
          end
669
        end
670

671
        context 'group project' do
672
          let(:project2) { create(:empty_project, group: create(:group)) }
673

674
          before { project2.group.add_owner(user) }
675

676 677
          it 'sets the owner and return 200' do
            get api("/projects/#{project2.id}", user)
678

679 680 681
            expect(response).to have_http_status(200)
            expect(json_response['permissions']['project_access']).to be_nil
            expect(json_response['permissions']['group_access']['access_level']).
682
            to eq(Gitlab::Access::OWNER)
683
          end
684
        end
685 686
      end
    end
N
Nihad Abbasov 已提交
687 688
  end

689
  describe 'GET /projects/:id/events' do
690 691 692 693
    shared_examples_for 'project events response' do
      it 'returns the project events' do
        member = create(:user)
        create(:project_member, :developer, user: member, project: project)
D
Dmitriy Zaporozhets 已提交
694 695 696
        note = create(:note_on_issue, note: 'What an awesome day!', project: project)
        EventCreateService.new.leave_note(note, note.author)

697
        get api("/projects/#{project.id}/events", current_user)
D
Dmitriy Zaporozhets 已提交
698

699
        expect(response).to have_http_status(200)
D
Dmitriy Zaporozhets 已提交
700

701
        first_event = json_response.first
D
Dmitriy Zaporozhets 已提交
702

703 704
        expect(first_event['action_name']).to eq('commented on')
        expect(first_event['note']['body']).to eq('What an awesome day!')
D
Dmitriy Zaporozhets 已提交
705

706 707 708 709
        last_event = json_response.last

        expect(last_event['action_name']).to eq('joined')
        expect(last_event['project_id'].to_i).to eq(project.id)
710 711
        expect(last_event['author_username']).to eq(member.username)
        expect(last_event['author']['name']).to eq(member.name)
D
Dmitriy Zaporozhets 已提交
712
      end
D
Dmitriy Zaporozhets 已提交
713 714
    end

715 716
    context 'when unauthenticated' do
      it_behaves_like 'project events response' do
717
        let(:project) { create(:empty_project, :public) }
718 719 720
        let(:current_user) { nil }
      end
    end
721

722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742
    context 'when authenticated' do
      context 'valid request' do
        it_behaves_like 'project events response' do
          let(:current_user) { user }
        end
      end

      it 'returns a 404 error if not found' do
        get api('/projects/42/events', user)

        expect(response).to have_http_status(404)
        expect(json_response['message']).to eq('404 Project Not Found')
      end

      it 'returns a 404 error if user is not a member' do
        other_user = create(:user)

        get api("/projects/#{project.id}/events", other_user)

        expect(response).to have_http_status(404)
      end
D
Dmitriy Zaporozhets 已提交
743
    end
744
  end
D
Dmitriy Zaporozhets 已提交
745

746 747 748 749 750
  describe 'GET /projects/:id/users' do
    shared_examples_for 'project users response' do
      it 'returns the project users' do
        member = create(:user)
        create(:project_member, :developer, user: member, project: project)
751

752
        get api("/projects/#{project.id}/users", current_user)
753

754 755 756 757 758 759 760 761 762 763 764 765 766 767
        expect(response).to have_http_status(200)
        expect(json_response).to be_an Array
        expect(json_response.size).to eq(1)

        first_user = json_response.first

        expect(first_user['username']).to eq(member.username)
        expect(first_user['name']).to eq(member.name)
        expect(first_user.keys).to contain_exactly(*%w[name username id state avatar_url web_url])
      end
    end

    context 'when unauthenticated' do
      it_behaves_like 'project users response' do
768
        let(:project) { create(:empty_project, :public) }
769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793
        let(:current_user) { nil }
      end
    end

    context 'when authenticated' do
      context 'valid request' do
        it_behaves_like 'project users response' do
          let(:current_user) { user }
        end
      end

      it 'returns a 404 error if not found' do
        get api('/projects/42/users', user)

        expect(response).to have_http_status(404)
        expect(json_response['message']).to eq('404 Project Not Found')
      end

      it 'returns a 404 error if user is not a member' do
        other_user = create(:user)

        get api("/projects/#{project.id}/users", other_user)

        expect(response).to have_http_status(404)
      end
D
Dmitriy Zaporozhets 已提交
794 795 796
    end
  end

797
  describe 'GET /projects/:id/snippets' do
D
Dmitriy Zaporozhets 已提交
798 799
    before { snippet }

800
    it 'returns an array of project snippets' do
801
      get api("/projects/#{project.id}/snippets", user)
Z
Z.J. van de Weg 已提交
802
      expect(response).to have_http_status(200)
803 804
      expect(json_response).to be_an Array
      expect(json_response.first['title']).to eq(snippet.title)
N
Nihad Abbasov 已提交
805 806 807
    end
  end

808
  describe 'GET /projects/:id/snippets/:snippet_id' do
809
    it 'returns a project snippet' do
810
      get api("/projects/#{project.id}/snippets/#{snippet.id}", user)
Z
Z.J. van de Weg 已提交
811
      expect(response).to have_http_status(200)
812
      expect(json_response['title']).to eq(snippet.title)
N
Nihad Abbasov 已提交
813
    end
814

815
    it 'returns a 404 error if snippet id not found' do
816
      get api("/projects/#{project.id}/snippets/1234", user)
Z
Z.J. van de Weg 已提交
817
      expect(response).to have_http_status(404)
818
    end
N
Nihad Abbasov 已提交
819 820
  end

821
  describe 'POST /projects/:id/snippets' do
822
    it 'creates a new project snippet' do
823
      post api("/projects/#{project.id}/snippets", user),
824
        title: 'api test', file_name: 'sample.rb', code: 'test',
825
        visibility_level: Gitlab::VisibilityLevel::PRIVATE
Z
Z.J. van de Weg 已提交
826
      expect(response).to have_http_status(201)
827
      expect(json_response['title']).to eq('api test')
N
Nihad Abbasov 已提交
828
    end
829

830
    it 'returns a 400 error if invalid snippet is given' do
831 832
      post api("/projects/#{project.id}/snippets", user)
      expect(status).to eq(400)
833
    end
N
Nihad Abbasov 已提交
834 835
  end

836
  describe 'PUT /projects/:id/snippets/:snippet_id' do
837
    it 'updates an existing project snippet' do
838
      put api("/projects/#{project.id}/snippets/#{snippet.id}", user),
839
        code: 'updated code'
Z
Z.J. van de Weg 已提交
840
      expect(response).to have_http_status(200)
841 842
      expect(json_response['title']).to eq('example')
      expect(snippet.reload.content).to eq('updated code')
843
    end
844

845
    it 'updates an existing project snippet with new title' do
846
      put api("/projects/#{project.id}/snippets/#{snippet.id}", user),
847
        title: 'other api test'
Z
Z.J. van de Weg 已提交
848
      expect(response).to have_http_status(200)
849
      expect(json_response['title']).to eq('other api test')
850
    end
851 852
  end

853
  describe 'DELETE /projects/:id/snippets/:snippet_id' do
D
Dmitriy Zaporozhets 已提交
854 855
    before { snippet }

856
    it 'deletes existing project snippet' do
857
      expect do
858
        delete api("/projects/#{project.id}/snippets/#{snippet.id}", user)
859
      end.to change { Snippet.count }.by(-1)
Z
Z.J. van de Weg 已提交
860
      expect(response).to have_http_status(200)
861 862
    end

863
    it 'returns 404 when deleting unknown snippet id' do
864
      delete api("/projects/#{project.id}/snippets/1234", user)
Z
Z.J. van de Weg 已提交
865
      expect(response).to have_http_status(404)
N
Nihad Abbasov 已提交
866 867
    end
  end
868

869
  describe 'GET /projects/:id/snippets/:snippet_id/raw' do
870
    it 'gets a raw project snippet' do
871
      get api("/projects/#{project.id}/snippets/#{snippet.id}/raw", user)
Z
Z.J. van de Weg 已提交
872
      expect(response).to have_http_status(200)
873
    end
874

875
    it 'returns a 404 error if raw project snippet not found' do
876
      get api("/projects/#{project.id}/snippets/5555/raw", user)
Z
Z.J. van de Weg 已提交
877
      expect(response).to have_http_status(404)
878
    end
879
  end
880

881
  describe :fork_admin do
882 883
    let(:project_fork_target) { create(:empty_project) }
    let(:project_fork_source) { create(:empty_project, :public) }
884

885
    describe 'POST /projects/:id/fork/:forked_from_id' do
886
      let(:new_project_fork_source) { create(:empty_project, :public) }
887

888
      it "is not available for non admin users" do
889
        post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", user)
Z
Z.J. van de Weg 已提交
890
        expect(response).to have_http_status(403)
891 892
      end

893
      it 'allows project to be forked from an existing project' do
894
        expect(project_fork_target.forked?).not_to be_truthy
895
        post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
Z
Z.J. van de Weg 已提交
896
        expect(response).to have_http_status(201)
897
        project_fork_target.reload
898 899 900
        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
901 902
      end

903
      it 'fails if forked_from project which does not exist' do
904
        post api("/projects/#{project_fork_target.id}/fork/9999", admin)
Z
Z.J. van de Weg 已提交
905
        expect(response).to have_http_status(404)
906 907
      end

908
      it 'fails with 409 if already forked' do
909 910
        post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
        project_fork_target.reload
911
        expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id)
912
        post api("/projects/#{project_fork_target.id}/fork/#{new_project_fork_source.id}", admin)
Z
Z.J. van de Weg 已提交
913
        expect(response).to have_http_status(409)
914
        project_fork_target.reload
915 916
        expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id)
        expect(project_fork_target.forked?).to be_truthy
917 918 919
      end
    end

920
    describe 'DELETE /projects/:id/fork' do
921
      it "is not visible to users outside group" do
922
        delete api("/projects/#{project_fork_target.id}/fork", user)
Z
Z.J. van de Weg 已提交
923
        expect(response).to have_http_status(404)
924 925
      end

926
      context 'when users belong to project group' do
927
        let(:project_fork_target) { create(:empty_project, group: create(:group)) }
928

929 930 931 932 933
        before do
          project_fork_target.group.add_owner user
          project_fork_target.group.add_developer user2
        end

934
        it 'is forbidden to non-owner users' do
935
          delete api("/projects/#{project_fork_target.id}/fork", user2)
Z
Z.J. van de Weg 已提交
936
          expect(response).to have_http_status(403)
937 938
        end

939
        it 'makes forked project unforked' do
940 941 942 943 944
          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)
Z
Z.J. van de Weg 已提交
945
          expect(response).to have_http_status(200)
946 947 948 949 950
          project_fork_target.reload
          expect(project_fork_target.forked_from_project).to be_nil
          expect(project_fork_target.forked?).not_to be_truthy
        end

951
        it 'is idempotent if not forked' do
952 953
          expect(project_fork_target.forked_from_project).to be_nil
          delete api("/projects/#{project_fork_target.id}/fork", admin)
R
Robert Schilling 已提交
954
          expect(response).to have_http_status(304)
955 956
          expect(project_fork_target.reload.forked_from_project).to be_nil
        end
957 958 959
      end
    end
  end
960

961 962 963
  describe "POST /projects/:id/share" do
    let(:group) { create(:group) }

964
    it "shares project with group" do
965 966
      expires_at = 10.days.from_now.to_date

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

R
Robert Schilling 已提交
971
      expect(response).to have_http_status(201)
972 973 974
      expect(json_response['group_id']).to eq(group.id)
      expect(json_response['group_access']).to eq(Gitlab::Access::DEVELOPER)
      expect(json_response['expires_at']).to eq(expires_at.to_s)
975 976
    end

977
    it "returns a 400 error when group id is not given" do
978
      post api("/projects/#{project.id}/share", user), group_access: Gitlab::Access::DEVELOPER
R
Robert Schilling 已提交
979
      expect(response).to have_http_status(400)
980 981
    end

982
    it "returns a 400 error when access level is not given" do
983
      post api("/projects/#{project.id}/share", user), group_id: group.id
R
Robert Schilling 已提交
984
      expect(response).to have_http_status(400)
985 986
    end

987
    it "returns a 400 error when sharing is disabled" do
988 989
      project.namespace.update(share_with_group_lock: true)
      post api("/projects/#{project.id}/share", user), group_id: group.id, group_access: Gitlab::Access::DEVELOPER
R
Robert Schilling 已提交
990
      expect(response).to have_http_status(400)
991 992
    end

993 994 995 996 997
    it 'returns a 404 error when user cannot read group' do
      private_group = create(:group, :private)

      post api("/projects/#{project.id}/share", user), group_id: private_group.id, group_access: Gitlab::Access::DEVELOPER

R
Robert Schilling 已提交
998
      expect(response).to have_http_status(404)
999 1000 1001 1002 1003
    end

    it 'returns a 404 error when group does not exist' do
      post api("/projects/#{project.id}/share", user), group_id: 1234, group_access: Gitlab::Access::DEVELOPER

R
Robert Schilling 已提交
1004
      expect(response).to have_http_status(404)
1005 1006
    end

R
Robert Schilling 已提交
1007
    it "returns a 400 error when wrong params passed" do
1008
      post api("/projects/#{project.id}/share", user), group_id: group.id, group_access: 1234
R
Robert Schilling 已提交
1009 1010 1011

      expect(response).to have_http_status(400)
      expect(json_response['error']).to eq 'group_access does not have a valid value'
1012 1013 1014
    end
  end

1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
  describe 'DELETE /projects/:id/share/:group_id' do
    it 'returns 204 when deleting a group share' do
      group = create(:group, :public)
      create(:project_group_link, group: group, project: project)

      delete api("/projects/#{project.id}/share/#{group.id}", user)

      expect(response).to have_http_status(204)
      expect(project.project_group_links).to be_empty
    end

    it 'returns a 400 when group id is not an integer' do
      delete api("/projects/#{project.id}/share/foo", user)

      expect(response).to have_http_status(400)
    end

    it 'returns a 404 error when group link does not exist' do
      delete api("/projects/#{project.id}/share/1234", user)

      expect(response).to have_http_status(404)
    end

    it 'returns a 404 error when project does not exist' do
      delete api("/projects/123/share/1234", user)

      expect(response).to have_http_status(404)
    end
  end

1045
  describe 'PUT /projects/:id' do
1046 1047 1048 1049 1050 1051 1052 1053 1054 1055
    before { project }
    before { user }
    before { user3 }
    before { user4 }
    before { project3 }
    before { project4 }
    before { project_member3 }
    before { project_member2 }

    context 'when unauthenticated' do
1056
      it 'returns authentication error' do
1057 1058
        project_param = { name: 'bar' }
        put api("/projects/#{project.id}"), project_param
Z
Z.J. van de Weg 已提交
1059
        expect(response).to have_http_status(401)
1060 1061 1062 1063
      end
    end

    context 'when authenticated as project owner' do
1064
      it 'updates name' do
1065 1066
        project_param = { name: 'bar' }
        put api("/projects/#{project.id}", user), project_param
Z
Z.J. van de Weg 已提交
1067
        expect(response).to have_http_status(200)
1068
        project_param.each_pair do |k, v|
1069
          expect(json_response[k.to_s]).to eq(v)
1070 1071 1072
        end
      end

1073
      it 'updates visibility_level' do
1074
        project_param = { visibility_level: Gitlab::VisibilityLevel::PUBLIC }
1075
        put api("/projects/#{project3.id}", user), project_param
Z
Z.J. van de Weg 已提交
1076
        expect(response).to have_http_status(200)
1077
        project_param.each_pair do |k, v|
1078
          expect(json_response[k.to_s]).to eq(v)
1079 1080 1081
        end
      end

1082
      it 'updates visibility_level from public to private' do
1083
        project3.update_attributes({ visibility_level: Gitlab::VisibilityLevel::PUBLIC })
1084
        project_param = { visibility_level: Gitlab::VisibilityLevel::PRIVATE }
1085
        put api("/projects/#{project3.id}", user), project_param
Z
Z.J. van de Weg 已提交
1086
        expect(response).to have_http_status(200)
1087 1088 1089 1090 1091 1092
        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

1093
      it 'does not update name to existing name' do
1094 1095
        project_param = { name: project3.name }
        put api("/projects/#{project.id}", user), project_param
Z
Z.J. van de Weg 已提交
1096
        expect(response).to have_http_status(400)
1097
        expect(json_response['message']['name']).to eq(['has already been taken'])
1098 1099
      end

1100 1101 1102 1103 1104 1105 1106 1107 1108
      it 'updates request_access_enabled' do
        project_param = { request_access_enabled: false }

        put api("/projects/#{project.id}", user), project_param

        expect(response).to have_http_status(200)
        expect(json_response['request_access_enabled']).to eq(false)
      end

1109
      it 'updates path & name to existing path & name in different namespace' do
1110 1111
        project_param = { path: project4.path, name: project4.name }
        put api("/projects/#{project3.id}", user), project_param
Z
Z.J. van de Weg 已提交
1112
        expect(response).to have_http_status(200)
1113
        project_param.each_pair do |k, v|
1114
          expect(json_response[k.to_s]).to eq(v)
1115 1116 1117 1118 1119
        end
      end
    end

    context 'when authenticated as project master' do
1120
      it 'updates path' do
1121 1122
        project_param = { path: 'bar' }
        put api("/projects/#{project3.id}", user4), project_param
Z
Z.J. van de Weg 已提交
1123
        expect(response).to have_http_status(200)
1124
        project_param.each_pair do |k, v|
1125
          expect(json_response[k.to_s]).to eq(v)
1126 1127 1128
        end
      end

1129
      it 'updates other attributes' do
1130 1131 1132 1133 1134 1135 1136
        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
Z
Z.J. van de Weg 已提交
1137
        expect(response).to have_http_status(200)
1138
        project_param.each_pair do |k, v|
1139
          expect(json_response[k.to_s]).to eq(v)
1140 1141 1142
        end
      end

1143
      it 'does not update path to existing path' do
1144 1145
        project_param = { path: project.path }
        put api("/projects/#{project3.id}", user4), project_param
Z
Z.J. van de Weg 已提交
1146
        expect(response).to have_http_status(400)
1147
        expect(json_response['message']['path']).to eq(['has already been taken'])
1148 1149
      end

1150
      it 'does not update name' do
1151 1152
        project_param = { name: 'bar' }
        put api("/projects/#{project3.id}", user4), project_param
Z
Z.J. van de Weg 已提交
1153
        expect(response).to have_http_status(403)
1154 1155
      end

1156
      it 'does not update visibility_level' do
1157
        project_param = { visibility_level: Gitlab::VisibilityLevel::PUBLIC }
1158
        put api("/projects/#{project3.id}", user4), project_param
Z
Z.J. van de Weg 已提交
1159
        expect(response).to have_http_status(403)
1160 1161 1162 1163
      end
    end

    context 'when authenticated as project developer' do
1164
      it 'does not update other attributes' do
1165 1166 1167 1168 1169
        project_param = { path: 'bar',
                          issues_enabled: true,
                          wiki_enabled: true,
                          snippets_enabled: true,
                          merge_requests_enabled: true,
1170 1171
                          description: 'new description',
                          request_access_enabled: true }
1172
        put api("/projects/#{project.id}", user3), project_param
Z
Z.J. van de Weg 已提交
1173
        expect(response).to have_http_status(403)
1174 1175 1176 1177
      end
    end
  end

1178
  describe 'POST /projects/:id/archive' do
1179 1180
    context 'on an unarchived project' do
      it 'archives the project' do
1181
        post api("/projects/#{project.id}/archive", user)
1182

Z
Z.J. van de Weg 已提交
1183
        expect(response).to have_http_status(201)
1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
        expect(json_response['archived']).to be_truthy
      end
    end

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

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

Z
Z.J. van de Weg 已提交
1196
        expect(response).to have_http_status(201)
1197 1198
        expect(json_response['archived']).to be_truthy
      end
1199
    end
1200

1201 1202 1203 1204
    context 'user without archiving rights to the project' do
      before do
        project.team << [user3, :developer]
      end
1205

1206 1207 1208
      it 'rejects the action' do
        post api("/projects/#{project.id}/archive", user3)

Z
Z.J. van de Weg 已提交
1209
        expect(response).to have_http_status(403)
1210 1211 1212 1213
      end
    end
  end

1214
  describe 'POST /projects/:id/unarchive' do
1215 1216
    context 'on an unarchived project' do
      it 'remains unarchived' do
1217
        post api("/projects/#{project.id}/unarchive", user)
1218

Z
Z.J. van de Weg 已提交
1219
        expect(response).to have_http_status(201)
1220 1221 1222 1223 1224 1225 1226 1227 1228
        expect(json_response['archived']).to be_falsey
      end
    end

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

1229 1230
      it 'unarchives the project' do
        post api("/projects/#{project.id}/unarchive", user)
1231

Z
Z.J. van de Weg 已提交
1232
        expect(response).to have_http_status(201)
1233 1234
        expect(json_response['archived']).to be_falsey
      end
1235
    end
1236

1237 1238 1239 1240
    context 'user without archiving rights to the project' do
      before do
        project.team << [user3, :developer]
      end
1241

1242 1243 1244
      it 'rejects the action' do
        post api("/projects/#{project.id}/unarchive", user3)

Z
Z.J. van de Weg 已提交
1245
        expect(response).to have_http_status(403)
1246 1247 1248 1249
      end
    end
  end

1250 1251 1252
  describe 'POST /projects/:id/star' do
    context 'on an unstarred project' do
      it 'stars the project' do
1253
        expect { post api("/projects/#{project.id}/star", user) }.to change { project.reload.star_count }.by(1)
1254

Z
Z.J. van de Weg 已提交
1255
        expect(response).to have_http_status(201)
1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266
        expect(json_response['star_count']).to eq(1)
      end
    end

    context 'on a starred project' do
      before do
        user.toggle_star(project)
        project.reload
      end

      it 'does not modify the star count' do
1267
        expect { post api("/projects/#{project.id}/star", user) }.not_to change { project.reload.star_count }
1268

Z
Z.J. van de Weg 已提交
1269
        expect(response).to have_http_status(304)
1270 1271 1272 1273
      end
    end
  end

R
Robert Schilling 已提交
1274
  describe 'DELETE /projects/:id/star' do
1275 1276 1277 1278 1279 1280 1281
    context 'on a starred project' do
      before do
        user.toggle_star(project)
        project.reload
      end

      it 'unstars the project' do
1282
        expect { delete api("/projects/#{project.id}/star", user) }.to change { project.reload.star_count }.by(-1)
1283

Z
Z.J. van de Weg 已提交
1284
        expect(response).to have_http_status(200)
1285 1286 1287 1288 1289 1290
        expect(json_response['star_count']).to eq(0)
      end
    end

    context 'on an unstarred project' do
      it 'does not modify the star count' do
1291
        expect { delete api("/projects/#{project.id}/star", user) }.not_to change { project.reload.star_count }
1292

Z
Z.J. van de Weg 已提交
1293
        expect(response).to have_http_status(304)
1294 1295 1296 1297
      end
    end
  end

1298 1299
  describe 'DELETE /projects/:id' do
    context 'when authenticated as user' do
1300
      it 'removes project' do
1301
        delete api("/projects/#{project.id}", user)
Z
Z.J. van de Weg 已提交
1302
        expect(response).to have_http_status(200)
1303 1304
      end

1305
      it 'does not remove a project if not an owner' do
1306 1307 1308
        user3 = create(:user)
        project.team << [user3, :developer]
        delete api("/projects/#{project.id}", user3)
Z
Z.J. van de Weg 已提交
1309
        expect(response).to have_http_status(403)
1310 1311
      end

1312
      it 'does not remove a non existing project' do
1313
        delete api('/projects/1328', user)
Z
Z.J. van de Weg 已提交
1314
        expect(response).to have_http_status(404)
1315 1316
      end

1317
      it 'does not remove a project not attached to user' do
1318
        delete api("/projects/#{project.id}", user2)
Z
Z.J. van de Weg 已提交
1319
        expect(response).to have_http_status(404)
1320 1321 1322
      end
    end

1323
    context 'when authenticated as admin' do
1324
      it 'removes any existing project' do
1325
        delete api("/projects/#{project.id}", admin)
Z
Z.J. van de Weg 已提交
1326
        expect(response).to have_http_status(200)
1327 1328
      end

1329
      it 'does not remove a non existing project' do
1330
        delete api('/projects/1328', admin)
Z
Z.J. van de Weg 已提交
1331
        expect(response).to have_http_status(404)
1332 1333 1334
      end
    end
  end
N
Nihad Abbasov 已提交
1335
end