projects_spec.rb 29.5 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, user: user, project: project, access_level: ProjectMember::MASTER) }
  let(:project_member2) { create(:project_member, user: user3, project: project, access_level: ProjectMember::DEVELOPER) }
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

68 69 70
      context 'and using search' do
        it 'should return searched project' do
          get api('/projects', user), { search: project.name }
71 72 73
          expect(response.status).to eq(200)
          expect(json_response).to be_an Array
          expect(json_response.length).to eq(1)
74 75 76
        end
      end

77
      context 'and using sorting' do
78 79 80 81 82
        before do
          project2
          project3
        end

83 84
        it 'should return the correct order when sorted by id' do
          get api('/projects', user), { order_by: 'id', sort: 'desc'}
85 86 87
          expect(response.status).to eq(200)
          expect(json_response).to be_an Array
          expect(json_response.first['id']).to eq(project3.id)
88
        end
V
Valery Sizov 已提交
89 90 91 92 93 94 95 96 97

        it 'returns projects in the correct order when ci_enabled_first parameter is passed' do
          [project, project2, project3].each{ |project| project.build_missing_services }
          project2.gitlab_ci_service.update(active: true, token: "token", project_url: "url")
          get api('/projects', user), { ci_enabled_first: 'true'}
          expect(response.status).to eq(200)
          expect(json_response).to be_an Array
          expect(json_response.first['id']).to eq(project2.id)
        end
98
      end
N
Nihad Abbasov 已提交
99 100 101
    end
  end

102
  describe 'GET /projects/all' do
D
Dmitriy Zaporozhets 已提交
103 104
    before { project }

105 106 107
    context 'when unauthenticated' do
      it 'should return authentication error' do
        get api('/projects/all')
108
        expect(response.status).to eq(401)
D
Dmitriy Zaporozhets 已提交
109 110 111
      end
    end

112 113 114
    context 'when authenticated as regular user' do
      it 'should return authentication error' do
        get api('/projects/all', user)
115
        expect(response.status).to eq(403)
D
Dmitriy Zaporozhets 已提交
116 117 118
      end
    end

119 120 121
    context 'when authenticated as admin' do
      it 'should return an array of all projects' do
        get api('/projects/all', admin)
122 123
        expect(response.status).to eq(200)
        expect(json_response).to be_an Array
M
Marin Jankovski 已提交
124

125 126 127 128 129 130
        expect(json_response).to satisfy do |response|
          response.one? do |entry|
            entry['name'] == project.name &&
            entry['owner']['username'] == user.username
          end
        end
D
Dmitriy Zaporozhets 已提交
131 132 133 134
      end
    end
  end

135 136
  describe 'POST /projects' do
    context 'maximum number of projects reached' do
137
      it 'should not create new project and respond with 403' do
138
        allow_any_instance_of(User).to receive(:projects_limit_left).and_return(0)
139 140
        expect { post api('/projects', user2), name: 'foo' }.
          to change {Project.count}.by(0)
141
        expect(response.status).to eq(403)
142 143 144
      end
    end

145 146 147
    it 'should create new project without path and return 201' do
      expect { post api('/projects', user), name: 'foo' }.
        to change { Project.count }.by(1)
148
      expect(response.status).to eq(201)
149 150
    end

151
    it 'should create last project before reaching project limit' do
152
      allow_any_instance_of(User).to receive(:projects_limit_left).and_return(1)
153
      post api('/projects', user2), name: 'foo'
154
      expect(response.status).to eq(201)
155 156
    end

157 158
    it 'should not create new project without name and return 400' do
      expect { post api('/projects', user) }.to_not change { Project.count }
159
      expect(response.status).to eq(400)
160
    end
A
Alex Denisov 已提交
161

162
    it "should assign attributes to project" do
163
      project = attributes_for(:project, {
164
        path: 'camelCasePath',
R
Robert Speicher 已提交
165
        description: FFaker::Lorem.sentence,
166 167 168
        issues_enabled: false,
        merge_requests_enabled: false,
        wiki_enabled: false
A
Alex Denisov 已提交
169 170
      })

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

173
      project.each_pair do |k,v|
174
        expect(json_response[k.to_s]).to eq(v)
A
Alex Denisov 已提交
175
      end
176
    end
177

178
    it 'should set a project as public' do
179
      project = attributes_for(:project, :public)
180
      post api('/projects', user), project
181 182
      expect(json_response['public']).to be_truthy
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
183 184
    end

185
    it 'should set a project as public using :public' do
186
      project = attributes_for(:project, { public: true })
187
      post api('/projects', user), project
188 189
      expect(json_response['public']).to be_truthy
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
190 191
    end

192
    it 'should set a project as internal' do
193
      project = attributes_for(:project, :internal)
194
      post api('/projects', user), project
195 196
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
197 198
    end

199
    it 'should set a project as internal overriding :public' do
200
      project = attributes_for(:project, :internal, { public: true })
201
      post api('/projects', user), project
202 203
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
204 205
    end

206
    it 'should set a project as private' do
207
      project = attributes_for(:project, :private)
208
      post api('/projects', user), project
209 210
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
211 212
    end

213
    it 'should set a project as private using :public' do
214
      project = attributes_for(:project, { public: false })
215
      post api('/projects', user), project
216 217
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
218
    end
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243

    context 'when a visibility level is restricted' do
      before do
        @project = attributes_for(:project, { public: true })
        allow_any_instance_of(ApplicationSetting).to(
          receive(:restricted_visibility_levels).and_return([20])
        )
      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
244 245
  end

246
  describe 'POST /projects/user/:id' do
D
Dmitriy Zaporozhets 已提交
247
    before { project }
A
Angus MacArthur 已提交
248 249
    before { admin }

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

255 256 257 258
    it 'should respond with 400 on failure and not project' do
      expect { post api("/projects/user/#{user.id}", admin) }.
        to_not change { Project.count }

259 260
      expect(response.status).to eq(400)
      expect(json_response['message']['name']).to eq([
J
jubianchi 已提交
261 262
        'can\'t be blank',
        'is too short (minimum is 0 characters)',
D
Douwe Maan 已提交
263
        Gitlab::Regex.project_name_regex_message
264 265
      ])
      expect(json_response['message']['path']).to eq([
J
jubianchi 已提交
266 267
        'can\'t be blank',
        'is too short (minimum is 0 characters)',
D
Douwe Maan 已提交
268
        Gitlab::Regex.send(:project_path_regex_message)
269
      ])
A
Angus MacArthur 已提交
270 271
    end

272
    it 'should assign attributes to project' do
A
Angus MacArthur 已提交
273
      project = attributes_for(:project, {
R
Robert Speicher 已提交
274
        description: FFaker::Lorem.sentence,
275 276 277
        issues_enabled: false,
        merge_requests_enabled: false,
        wiki_enabled: false
A
Angus MacArthur 已提交
278 279 280 281
      })

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

282
      project.each_pair do |k,v|
A
Angus MacArthur 已提交
283
        next if k == :path
284
        expect(json_response[k.to_s]).to eq(v)
A
Angus MacArthur 已提交
285 286
      end
    end
287

288
    it 'should set a project as public' do
289
      project = attributes_for(:project, :public)
290
      post api("/projects/user/#{user.id}", admin), project
291 292
      expect(json_response['public']).to be_truthy
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
293 294
    end

295
    it 'should set a project as public using :public' do
296 297
      project = attributes_for(:project, { public: true })
      post api("/projects/user/#{user.id}", admin), project
298 299
      expect(json_response['public']).to be_truthy
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
300
    end
301

302
    it 'should set a project as internal' do
303
      project = attributes_for(:project, :internal)
304
      post api("/projects/user/#{user.id}", admin), project
305 306
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
307 308
    end

309
    it 'should set a project as internal overriding :public' do
310
      project = attributes_for(:project, :internal, { public: true })
311
      post api("/projects/user/#{user.id}", admin), project
312 313
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
314
    end
315

316
    it 'should set a project as private' do
317
      project = attributes_for(:project, :private)
318
      post api("/projects/user/#{user.id}", admin), project
319 320
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
321 322
    end

323
    it 'should set a project as private using :public' do
324 325
      project = attributes_for(:project, { public: false })
      post api("/projects/user/#{user.id}", admin), project
326 327
      expect(json_response['public']).to be_falsey
      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
328
    end
A
Angus MacArthur 已提交
329 330
  end

331
  describe 'GET /projects/:id' do
D
Dmitriy Zaporozhets 已提交
332
    before { project }
333
    before { project_member }
D
Dmitriy Zaporozhets 已提交
334

335
    it 'should return a project by id' do
R
Robert Speicher 已提交
336
      get api("/projects/#{project.id}", user)
337 338 339
      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 已提交
340
    end
341

342
    it 'should return a project by path name' do
343
      get api("/projects/#{project.id}", user)
344 345
      expect(response.status).to eq(200)
      expect(json_response['name']).to eq(project.name)
346
    end
N
Nihad Abbasov 已提交
347

348 349
    it 'should return a 404 error if not found' do
      get api('/projects/42', user)
350 351
      expect(response.status).to eq(404)
      expect(json_response['message']).to eq('404 Project Not Found')
N
Nihad Abbasov 已提交
352
    end
353

354
    it 'should return a 404 error if user is not a member' do
355 356
      other_user = create(:user)
      get api("/projects/#{project.id}", other_user)
357
      expect(response.status).to eq(404)
358
    end
359 360 361

    describe 'permissions' do
      context 'personal project' do
362
        it 'Sets project access and returns 200' do
D
Dmitriy Zaporozhets 已提交
363 364
          project.team << [user, :master]
          get api("/projects/#{project.id}", user)
365

366 367 368 369 370
          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
371 372 373
      end

      context 'group project' do
374
        it 'should set the owner and return 200' do
375 376 377 378
          project2 = create(:project, group: create(:group))
          project2.group.add_owner(user)
          get api("/projects/#{project2.id}", user)

379 380 381 382 383
          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
384 385
      end
    end
N
Nihad Abbasov 已提交
386 387
  end

388
  describe 'GET /projects/:id/events' do
D
Douwe Maan 已提交
389
    before { project_member2 }
D
Dmitriy Zaporozhets 已提交
390

391
    it 'should return a project events' do
D
Dmitriy Zaporozhets 已提交
392
      get api("/projects/#{project.id}/events", user)
393
      expect(response.status).to eq(200)
D
Dmitriy Zaporozhets 已提交
394 395
      json_event = json_response.first

396 397
      expect(json_event['action_name']).to eq('joined')
      expect(json_event['project_id'].to_i).to eq(project.id)
D
Douwe Maan 已提交
398
      expect(json_event['author_username']).to eq(user3.username)
D
Dmitriy Zaporozhets 已提交
399 400
    end

401 402
    it 'should return a 404 error if not found' do
      get api('/projects/42/events', user)
403 404
      expect(response.status).to eq(404)
      expect(json_response['message']).to eq('404 Project Not Found')
D
Dmitriy Zaporozhets 已提交
405 406
    end

407
    it 'should return a 404 error if user is not a member' do
D
Dmitriy Zaporozhets 已提交
408 409
      other_user = create(:user)
      get api("/projects/#{project.id}/events", other_user)
410
      expect(response.status).to eq(404)
D
Dmitriy Zaporozhets 已提交
411 412 413
    end
  end

414
  describe 'GET /projects/:id/snippets' do
D
Dmitriy Zaporozhets 已提交
415 416
    before { snippet }

417
    it 'should return an array of project snippets' do
418
      get api("/projects/#{project.id}/snippets", user)
419 420 421
      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 已提交
422 423 424
    end
  end

425 426
  describe 'GET /projects/:id/snippets/:snippet_id' do
    it 'should return a project snippet' do
427
      get api("/projects/#{project.id}/snippets/#{snippet.id}", user)
428 429
      expect(response.status).to eq(200)
      expect(json_response['title']).to eq(snippet.title)
N
Nihad Abbasov 已提交
430
    end
431

432
    it 'should return a 404 error if snippet id not found' do
433
      get api("/projects/#{project.id}/snippets/1234", user)
434
      expect(response.status).to eq(404)
435
    end
N
Nihad Abbasov 已提交
436 437
  end

438 439
  describe 'POST /projects/:id/snippets' do
    it 'should create a new project snippet' do
440
      post api("/projects/#{project.id}/snippets", user),
441 442
        title: 'api test', file_name: 'sample.rb', code: 'test',
        visibility_level: '0'
443 444
      expect(response.status).to eq(201)
      expect(json_response['title']).to eq('api test')
N
Nihad Abbasov 已提交
445
    end
446

447 448 449
    it 'should return a 400 error if invalid snippet is given' do
      post api("/projects/#{project.id}/snippets", user)
      expect(status).to eq(400)
450
    end
N
Nihad Abbasov 已提交
451 452
  end

453 454
  describe 'PUT /projects/:id/snippets/:shippet_id' do
    it 'should update an existing project snippet' do
455
      put api("/projects/#{project.id}/snippets/#{snippet.id}", user),
456
        code: 'updated code'
457 458 459
      expect(response.status).to eq(200)
      expect(json_response['title']).to eq('example')
      expect(snippet.reload.content).to eq('updated code')
460
    end
461

462
    it 'should update an existing project snippet with new title' do
463
      put api("/projects/#{project.id}/snippets/#{snippet.id}", user),
464
        title: 'other api test'
465 466
      expect(response.status).to eq(200)
      expect(json_response['title']).to eq('other api test')
467
    end
468 469
  end

470
  describe 'DELETE /projects/:id/snippets/:snippet_id' do
D
Dmitriy Zaporozhets 已提交
471 472
    before { snippet }

473
    it 'should delete existing project snippet' do
N
Nihad Abbasov 已提交
474
      expect {
475
        delete api("/projects/#{project.id}/snippets/#{snippet.id}", user)
476
      }.to change { Snippet.count }.by(-1)
477
      expect(response.status).to eq(200)
478 479
    end

J
jubianchi 已提交
480
    it 'should return 404 when deleting unknown snippet id' do
481
      delete api("/projects/#{project.id}/snippets/1234", user)
482
      expect(response.status).to eq(404)
N
Nihad Abbasov 已提交
483 484
    end
  end
485

486 487
  describe 'GET /projects/:id/snippets/:snippet_id/raw' do
    it 'should get a raw project snippet' do
488
      get api("/projects/#{project.id}/snippets/#{snippet.id}/raw", user)
489
      expect(response.status).to eq(200)
490
    end
491

492
    it 'should return a 404 error if raw project snippet not found' do
493
      get api("/projects/#{project.id}/snippets/5555/raw", user)
494
      expect(response.status).to eq(404)
495
    end
496
  end
497

498 499 500
  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 已提交
501

502
    describe 'GET /projects/:id/keys' do
503
      before { deploy_key }
M
Matt Humphrey 已提交
504

505
      it 'should return array of ssh keys' do
506
        get api("/projects/#{project.id}/keys", user)
507 508 509
        expect(response.status).to eq(200)
        expect(json_response).to be_an Array
        expect(json_response.first['title']).to eq(deploy_key.title)
510
      end
M
Matt Humphrey 已提交
511 512
    end

513 514
    describe 'GET /projects/:id/keys/:key_id' do
      it 'should return a single key' do
515
        get api("/projects/#{project.id}/keys/#{deploy_key.id}", user)
516 517
        expect(response.status).to eq(200)
        expect(json_response['title']).to eq(deploy_key.title)
518
      end
M
Matt Humphrey 已提交
519

520
      it 'should return 404 Not Found with invalid ID' do
521
        get api("/projects/#{project.id}/keys/404", user)
522
        expect(response.status).to eq(404)
523
      end
M
Matt Humphrey 已提交
524 525
    end

526 527 528
    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' }
529 530
        expect(response.status).to eq(400)
        expect(json_response['message']['key']).to eq([
J
jubianchi 已提交
531 532 533
          'can\'t be blank',
          'is too short (minimum is 0 characters)',
          'is invalid'
534
        ])
J
jubianchi 已提交
535 536 537 538
      end

      it 'should not create a key without title' do
        post api("/projects/#{project.id}/keys", user), key: 'some key'
539 540
        expect(response.status).to eq(400)
        expect(json_response['message']['title']).to eq([
J
jubianchi 已提交
541 542
          'can\'t be blank',
          'is too short (minimum is 0 characters)'
543
        ])
544 545
      end

546
      it 'should create new ssh key' do
547 548 549
        key_attrs = attributes_for :key
        expect {
          post api("/projects/#{project.id}/keys", user), key_attrs
550
        }.to change{ project.deploy_keys.count }.by(1)
551
      end
M
Matt Humphrey 已提交
552 553
    end

554
    describe 'DELETE /projects/:id/keys/:key_id' do
555 556
      before { deploy_key }

557
      it 'should delete existing key' do
558 559
        expect {
          delete api("/projects/#{project.id}/keys/#{deploy_key.id}", user)
560
        }.to change{ project.deploy_keys.count }.by(-1)
561 562
      end

563
      it 'should return 404 Not Found with invalid ID' do
564
        delete api("/projects/#{project.id}/keys/404", user)
565
        expect(response.status).to eq(404)
566
      end
M
Matt Humphrey 已提交
567 568
    end
  end
569 570 571

  describe :fork_admin do
    let(:project_fork_target) { create(:project) }
572
    let(:project_fork_source) { create(:project, :public) }
573

574
    describe 'POST /projects/:id/fork/:forked_from_id' do
575
      let(:new_project_fork_source) { create(:project, :public) }
576 577 578

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

582
      it 'should allow project to be forked from an existing project' do
583
        expect(project_fork_target.forked?).not_to be_truthy
584
        post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
585
        expect(response.status).to eq(201)
586
        project_fork_target.reload
587 588 589
        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
590 591
      end

592
      it 'should fail if forked_from project which does not exist' do
593
        post api("/projects/#{project_fork_target.id}/fork/9999", admin)
594
        expect(response.status).to eq(404)
595 596
      end

597
      it 'should fail with 409 if already forked' do
598 599
        post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
        project_fork_target.reload
600
        expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id)
601
        post api("/projects/#{project_fork_target.id}/fork/#{new_project_fork_source.id}", admin)
602
        expect(response.status).to eq(409)
603
        project_fork_target.reload
604 605
        expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id)
        expect(project_fork_target.forked?).to be_truthy
606 607 608
      end
    end

609
    describe 'DELETE /projects/:id/fork' do
610 611 612

      it "shouldn't available for non admin users" do
        delete api("/projects/#{project_fork_target.id}/fork", user)
613
        expect(response.status).to eq(403)
614 615
      end

616
      it 'should make forked project unforked' do
617 618
        post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
        project_fork_target.reload
619 620
        expect(project_fork_target.forked_from_project).not_to be_nil
        expect(project_fork_target.forked?).to be_truthy
621
        delete api("/projects/#{project_fork_target.id}/fork", admin)
622
        expect(response.status).to eq(200)
623
        project_fork_target.reload
624 625
        expect(project_fork_target.forked_from_project).to be_nil
        expect(project_fork_target.forked?).not_to be_truthy
626 627
      end

628
      it 'should be idempotent if not forked' do
629
        expect(project_fork_target.forked_from_project).to be_nil
630
        delete api("/projects/#{project_fork_target.id}/fork", admin)
631 632
        expect(response.status).to eq(200)
        expect(project_fork_target.reload.forked_from_project).to be_nil
633 634 635
      end
    end
  end
636

637
  describe 'GET /projects/search/:query' do
638
    let!(:query) { 'query'}
D
Dmitriy Zaporozhets 已提交
639 640 641 642 643
    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) }
644 645 646 647
    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') }
648

649 650
    context 'when unauthenticated' do
      it 'should return authentication error' do
651
        get api("/projects/search/#{query}")
652
        expect(response.status).to eq(401)
653 654 655
      end
    end

656 657
    context 'when authenticated' do
      it 'should return an array of projects' do
658
        get api("/projects/search/#{query}",user)
659 660 661 662
        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.*/)}
663 664 665
      end
    end

666 667
    context 'when authenticated as a different user' do
      it 'should return matching public projects' do
668
        get api("/projects/search/#{query}", user2)
669 670 671 672
        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/)}
673 674 675
      end
    end
  end
676

677 678 679 680 681 682 683 684 685 686 687 688 689 690
  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
691
        expect(response.status).to eq(401)
692 693 694 695 696 697 698
      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
699
        expect(response.status).to eq(200)
700
        project_param.each_pair do |k, v|
701
          expect(json_response[k.to_s]).to eq(v)
702 703 704 705 706 707
        end
      end

      it 'should update visibility_level' do
        project_param = { visibility_level: 20 }
        put api("/projects/#{project3.id}", user), project_param
708
        expect(response.status).to eq(200)
709
        project_param.each_pair do |k, v|
710
          expect(json_response[k.to_s]).to eq(v)
711 712 713 714 715 716
        end
      end

      it 'should not update name to existing name' do
        project_param = { name: project3.name }
        put api("/projects/#{project.id}", user), project_param
717 718
        expect(response.status).to eq(400)
        expect(json_response['message']['name']).to eq(['has already been taken'])
719 720 721 722 723
      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
724
        expect(response.status).to eq(200)
725
        project_param.each_pair do |k, v|
726
          expect(json_response[k.to_s]).to eq(v)
727 728 729 730 731 732 733 734
        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
735
        expect(response.status).to eq(200)
736
        project_param.each_pair do |k, v|
737
          expect(json_response[k.to_s]).to eq(v)
738 739 740 741 742 743 744 745 746 747 748
        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
749
        expect(response.status).to eq(200)
750
        project_param.each_pair do |k, v|
751
          expect(json_response[k.to_s]).to eq(v)
752 753 754 755 756 757
        end
      end

      it 'should not update path to existing path' do
        project_param = { path: project.path }
        put api("/projects/#{project3.id}", user4), project_param
758 759
        expect(response.status).to eq(400)
        expect(json_response['message']['path']).to eq(['has already been taken'])
760 761 762 763 764
      end

      it 'should not update name' do
        project_param = { name: 'bar' }
        put api("/projects/#{project3.id}", user4), project_param
765
        expect(response.status).to eq(403)
766 767 768 769 770
      end

      it 'should not update visibility_level' do
        project_param = { visibility_level: 20 }
        put api("/projects/#{project3.id}", user4), project_param
771
        expect(response.status).to eq(403)
772 773 774 775 776 777 778 779 780 781 782 783
      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
784
        expect(response.status).to eq(403)
785 786 787 788
      end
    end
  end

789 790 791
  describe 'DELETE /projects/:id' do
    context 'when authenticated as user' do
      it 'should remove project' do
792
        delete api("/projects/#{project.id}", user)
793
        expect(response.status).to eq(200)
794 795
      end

796
      it 'should not remove a project if not an owner' do
797 798 799
        user3 = create(:user)
        project.team << [user3, :developer]
        delete api("/projects/#{project.id}", user3)
800
        expect(response.status).to eq(403)
801 802
      end

803 804
      it 'should not remove a non existing project' do
        delete api('/projects/1328', user)
805
        expect(response.status).to eq(404)
806 807
      end

808
      it 'should not remove a project not attached to user' do
809
        delete api("/projects/#{project.id}", user2)
810
        expect(response.status).to eq(404)
811 812 813
      end
    end

814 815
    context 'when authenticated as admin' do
      it 'should remove any existing project' do
816
        delete api("/projects/#{project.id}", admin)
817
        expect(response.status).to eq(200)
818 819
      end

820 821
      it 'should not remove a non existing project' do
        delete api('/projects/1328', admin)
822
        expect(response.status).to eq(404)
823 824 825
      end
    end
  end
N
Nihad Abbasov 已提交
826
end