OSDN Git Service

fix API route to delete project hook
[wvm/gitlab.git] / spec / requests / api / projects_spec.rb
1 require 'spec_helper'
2
3 describe Gitlab::API do
4   include ApiHelpers
5   before(:each) { enable_observers }
6
7   let(:user) { create(:user) }
8   let(:user2) { create(:user) }
9   let(:user3) { create(:user) }
10   let(:admin) { create(:admin) }
11   let!(:project) { create(:project_with_code, creator_id: user.id) }
12   let!(:hook) { create(:project_hook, project: project, url: "http://example.com") }
13   let!(:snippet) { create(:snippet, author: user, project: project, title: 'example') }
14   let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
15   let!(:users_project2) { create(:users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER) }
16
17   before { project.team << [user, :reporter] }
18
19   describe "GET /projects" do
20     context "when unauthenticated" do
21       it "should return authentication error" do
22         get api("/projects")
23         response.status.should == 401
24       end
25     end
26
27     context "when authenticated" do
28       it "should return an array of projects" do
29         get api("/projects", user)
30         response.status.should == 200
31         json_response.should be_an Array
32         json_response.first['name'].should == project.name
33         json_response.first['owner']['email'].should == user.email
34       end
35     end
36   end
37
38   describe "POST /projects" do
39     context "maximum number of projects reached" do
40       before do
41         (1..user2.projects_limit).each do |project|
42           post api("/projects", user2), name: "foo#{project}"
43         end
44       end
45
46       it "should not create new project" do
47         expect {
48           post api("/projects", user2), name: 'foo'
49         }.to change {Project.count}.by(0)
50       end
51     end
52
53     it "should create new project without path" do
54       expect { post api("/projects", user), name: 'foo' }.to change {Project.count}.by(1)
55     end
56
57     it "should not create new project without name" do
58       expect { post api("/projects", user) }.to_not change {Project.count}
59     end
60
61     it "should return a 400 error if name not given" do
62       post api("/projects", user)
63       response.status.should == 400
64     end
65
66     it "should create last project before reaching project limit" do
67       (1..user2.projects_limit-1).each { |p| post api("/projects", user2), name: "foo#{p}" }
68       post api("/projects", user2), name: "foo"
69       response.status.should == 201
70     end
71
72     it "should respond with 201 on success" do
73       post api("/projects", user), name: 'foo'
74       response.status.should == 201
75     end
76
77     it "should respond with 400 if name is not given" do
78       post api("/projects", user)
79       response.status.should == 400
80     end
81
82     it "should return a 403 error if project limit reached" do
83       (1..user.projects_limit).each do |p|
84         post api("/projects", user), name: "foo#{p}"
85       end
86       post api("/projects", user), name: 'bar'
87       response.status.should == 403
88     end
89
90     it "should assign attributes to project" do
91       project = attributes_for(:project, {
92         description: Faker::Lorem.sentence,
93         default_branch: 'stable',
94         issues_enabled: false,
95         wall_enabled: false,
96         merge_requests_enabled: false,
97         wiki_enabled: false
98       })
99
100       post api("/projects", user), project
101
102       project.each_pair do |k,v|
103         next if k == :path
104         json_response[k.to_s].should == v
105       end
106     end
107   end
108
109   describe "POST /projects/user/:id" do
110     before { admin }
111
112     it "should create new project without path" do
113       expect { post api("/projects/user/#{user.id}", admin), name: 'foo' }.to change {Project.count}.by(1)
114     end
115
116     it "should not create new project without name" do
117       expect { post api("/projects/user/#{user.id}", admin) }.to_not change {Project.count}
118     end
119
120     it "should respond with 201 on success" do
121       post api("/projects/user/#{user.id}", admin), name: 'foo'
122       response.status.should == 201
123     end
124
125     it "should respond with 404 on failure" do
126       post api("/projects/user/#{user.id}", admin)
127       response.status.should == 404
128     end
129
130     it "should assign attributes to project" do
131       project = attributes_for(:project, {
132         description: Faker::Lorem.sentence,
133         default_branch: 'stable',
134         issues_enabled: false,
135         wall_enabled: false,
136         merge_requests_enabled: false,
137         wiki_enabled: false
138       })
139
140       post api("/projects/user/#{user.id}", admin), project
141
142       project.each_pair do |k,v|
143         next if k == :path
144         json_response[k.to_s].should == v
145       end
146     end
147   end
148
149   describe "GET /projects/:id" do
150     it "should return a project by id" do
151       get api("/projects/#{project.id}", user)
152       response.status.should == 200
153       json_response['name'].should == project.name
154       json_response['owner']['email'].should == user.email
155     end
156
157     it "should return a project by path name" do
158       get api("/projects/#{project.id}", user)
159       response.status.should == 200
160       json_response['name'].should == project.name
161     end
162
163     it "should return a 404 error if not found" do
164       get api("/projects/42", user)
165       response.status.should == 404
166       json_response['message'].should == '404 Not Found'
167     end
168
169     it "should return a 404 error if user is not a member" do
170       other_user = create(:user)
171       get api("/projects/#{project.id}", other_user)
172       response.status.should == 404
173     end
174   end
175
176   describe "GET /projects/:id/repository/branches" do
177     it "should return an array of project branches" do
178       get api("/projects/#{project.id}/repository/branches", user)
179       response.status.should == 200
180       json_response.should be_an Array
181       json_response.first['name'].should == project.repo.heads.sort_by(&:name).first.name
182     end
183   end
184
185   describe "GET /projects/:id/repository/branches/:branch" do
186     it "should return the branch information for a single branch" do
187       get api("/projects/#{project.id}/repository/branches/new_design", user)
188       response.status.should == 200
189
190       json_response['name'].should == 'new_design'
191       json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1'
192       json_response['protected'].should == false
193     end
194
195     it "should return a 404 error if branch is not available" do
196       get api("/projects/#{project.id}/repository/branches/unknown", user)
197       response.status.should == 404
198     end
199   end
200
201   describe "PUT /projects/:id/repository/branches/:branch/protect" do
202     it "should protect a single branch" do
203       put api("/projects/#{project.id}/repository/branches/new_design/protect", user)
204       response.status.should == 200
205
206       json_response['name'].should == 'new_design'
207       json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1'
208       json_response['protected'].should == true
209     end
210
211     it "should return a 404 error if branch not found" do
212       put api("/projects/#{project.id}/repository/branches/unknown/protect", user)
213       response.status.should == 404
214     end
215
216     it "should return success when protect branch again" do
217       put api("/projects/#{project.id}/repository/branches/new_design/protect", user)
218       put api("/projects/#{project.id}/repository/branches/new_design/protect", user)
219       response.status.should == 200
220     end
221   end
222
223   describe "PUT /projects/:id/repository/branches/:branch/unprotect" do
224     it "should unprotect a single branch" do
225       put api("/projects/#{project.id}/repository/branches/new_design/unprotect", user)
226       response.status.should == 200
227
228       json_response['name'].should == 'new_design'
229       json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1'
230       json_response['protected'].should == false
231     end
232
233     it "should return success when unprotect branch" do
234       put api("/projects/#{project.id}/repository/branches/unknown/unprotect", user)
235       response.status.should == 404
236     end
237
238     it "should return success when unprotect branch again" do
239       put api("/projects/#{project.id}/repository/branches/new_design/unprotect", user)
240       put api("/projects/#{project.id}/repository/branches/new_design/unprotect", user)
241       response.status.should == 200
242     end
243   end
244
245   describe "GET /projects/:id/members" do
246     it "should return project team members" do
247       get api("/projects/#{project.id}/members", user)
248       response.status.should == 200
249       json_response.should be_an Array
250       json_response.count.should == 2
251       json_response.map { |u| u['email'] }.should include user.email
252     end
253
254     it "finds team members with query string" do
255       get api("/projects/#{project.id}/members", user), query: user.username
256       response.status.should == 200
257       json_response.should be_an Array
258       json_response.count.should == 1
259       json_response.first['email'].should == user.email
260     end
261
262     it "should return a 404 error if id not found" do
263       get api("/projects/9999/members", user)
264       response.status.should == 404
265     end
266   end
267
268   describe "GET /projects/:id/members/:user_id" do
269     it "should return project team member" do
270       get api("/projects/#{project.id}/members/#{user.id}", user)
271       response.status.should == 200
272       json_response['email'].should == user.email
273       json_response['access_level'].should == UsersProject::MASTER
274     end
275
276     it "should return a 404 error if user id not found" do
277       get api("/projects/#{project.id}/members/1234", user)
278       response.status.should == 404
279     end
280   end
281
282   describe "POST /projects/:id/members" do
283     it "should add user to project team" do
284       expect {
285         post api("/projects/#{project.id}/members", user), user_id: user2.id,
286           access_level: UsersProject::DEVELOPER
287       }.to change { UsersProject.count }.by(1)
288
289       response.status.should == 201
290       json_response['email'].should == user2.email
291       json_response['access_level'].should == UsersProject::DEVELOPER
292     end
293
294     it "should return a 201 status if user is already project member" do
295       post api("/projects/#{project.id}/members", user), user_id: user2.id,
296         access_level: UsersProject::DEVELOPER
297       expect {
298         post api("/projects/#{project.id}/members", user), user_id: user2.id,
299           access_level: UsersProject::DEVELOPER
300       }.not_to change { UsersProject.count }.by(1)
301
302       response.status.should == 201
303       json_response['email'].should == user2.email
304       json_response['access_level'].should == UsersProject::DEVELOPER
305     end
306
307     it "should return a 400 error when user id is not given" do
308       post api("/projects/#{project.id}/members", user), access_level: UsersProject::MASTER
309       response.status.should == 400
310     end
311
312     it "should return a 400 error when access level is not given" do
313       post api("/projects/#{project.id}/members", user), user_id: user2.id
314       response.status.should == 400
315     end
316
317     it "should return a 422 error when access level is not known" do
318       post api("/projects/#{project.id}/members", user), user_id: user2.id, access_level: 1234
319       response.status.should == 422
320     end
321   end
322
323   describe "PUT /projects/:id/members/:user_id" do
324     it "should update project team member" do
325       put api("/projects/#{project.id}/members/#{user3.id}", user), access_level: UsersProject::MASTER
326       response.status.should == 200
327       json_response['email'].should == user3.email
328       json_response['access_level'].should == UsersProject::MASTER
329     end
330
331     it "should return a 404 error if user_id is not found" do
332       put api("/projects/#{project.id}/members/1234", user), access_level: UsersProject::MASTER
333       response.status.should == 404
334     end
335
336     it "should return a 400 error when access level is not given" do
337       put api("/projects/#{project.id}/members/#{user3.id}", user)
338       response.status.should == 400
339     end
340
341     it "should return a 422 error when access level is not known" do
342       put api("/projects/#{project.id}/members/#{user3.id}", user), access_level: 123
343       response.status.should == 422
344     end
345   end
346
347   describe "DELETE /projects/:id/members/:user_id" do
348     it "should remove user from project team" do
349       expect {
350         delete api("/projects/#{project.id}/members/#{user3.id}", user)
351       }.to change { UsersProject.count }.by(-1)
352     end
353
354     it "should return 200 if team member is not part of a project" do
355       delete api("/projects/#{project.id}/members/#{user3.id}", user)
356       expect {
357         delete api("/projects/#{project.id}/members/#{user3.id}", user)
358       }.to_not change { UsersProject.count }.by(1)
359     end
360
361     it "should return 200 if team member already removed" do
362       delete api("/projects/#{project.id}/members/#{user3.id}", user)
363       delete api("/projects/#{project.id}/members/#{user3.id}", user)
364       response.status.should == 200
365     end
366   end
367
368   describe "DELETE /projects/:id/members/:user_id" do
369     it "should return 200 OK when the user was not member" do
370       expect {
371         delete api("/projects/#{project.id}/members/1000000", user)
372       }.to change { UsersProject.count }.by(0)
373       response.status.should == 200
374       json_response['message'].should == "Access revoked"
375       json_response['id'].should == 1000000
376     end
377   end
378
379   describe "GET /projects/:id/hooks" do
380     context "authorized user" do
381       it "should return project hooks" do
382         get api("/projects/#{project.id}/hooks", user)
383         response.status.should == 200
384
385         json_response.should be_an Array
386         json_response.count.should == 1
387         json_response.first['url'].should == "http://example.com"
388       end
389     end
390
391     context "unauthorized user" do
392       it "should not access project hooks" do
393         get api("/projects/#{project.id}/hooks", user3)
394         response.status.should == 403
395       end
396     end
397   end
398
399   describe "GET /projects/:id/hooks/:hook_id" do
400     context "authorized user" do
401       it "should return a project hook" do
402         get api("/projects/#{project.id}/hooks/#{hook.id}", user)
403         response.status.should == 200
404         json_response['url'].should == hook.url
405       end
406
407       it "should return a 404 error if hook id is not available" do
408         get api("/projects/#{project.id}/hooks/1234", user)
409         response.status.should == 404
410       end
411     end
412
413     context "unauthorized user" do
414       it "should not access an existing hook" do
415         get api("/projects/#{project.id}/hooks/#{hook.id}", user3)
416         response.status.should == 403
417       end
418     end
419
420     it "should return a 404 error if hook id is not available" do
421       get api("/projects/#{project.id}/hooks/1234", user)
422       response.status.should == 404
423     end
424   end
425
426   describe "POST /projects/:id/hooks" do
427     it "should add hook to project" do
428       expect {
429         post api("/projects/#{project.id}/hooks", user),
430           url: "http://example.com"
431       }.to change {project.hooks.count}.by(1)
432       response.status.should == 201
433     end
434
435     it "should return a 400 error if url not given" do
436       post api("/projects/#{project.id}/hooks", user)
437       response.status.should == 400
438     end
439
440     it "should return a 422 error if url not valid" do
441       post api("/projects/#{project.id}/hooks", user), "url" => "ftp://example.com"
442       response.status.should == 422
443     end
444   end
445
446   describe "PUT /projects/:id/hooks/:hook_id" do
447     it "should update an existing project hook" do
448       put api("/projects/#{project.id}/hooks/#{hook.id}", user),
449         url: 'http://example.org'
450       response.status.should == 200
451       json_response['url'].should == 'http://example.org'
452     end
453
454     it "should return 404 error if hook id not found" do
455       put api("/projects/#{project.id}/hooks/1234", user), url: 'http://example.org'
456       response.status.should == 404
457     end
458
459     it "should return 400 error if url is not given" do
460       put api("/projects/#{project.id}/hooks/#{hook.id}", user)
461       response.status.should == 400
462     end
463
464     it "should return a 422 error if url is not valid" do
465       put api("/projects/#{project.id}/hooks/#{hook.id}", user), url: 'ftp://example.com'
466       response.status.should == 422
467     end
468   end
469
470   describe "DELETE /projects/:id/hooks/:hook_id" do
471     it "should delete hook from project" do
472       expect {
473         delete api("/projects/#{project.id}/hooks/#{hook.id}", user)
474       }.to change {project.hooks.count}.by(-1)
475       response.status.should == 200
476     end
477
478     it "should return success when deleting hook" do
479       delete api("/projects/#{project.id}/hooks/#{hook.id}", user)
480       response.status.should == 200
481     end
482
483     it "should return success when deleting non existent hook" do
484       delete api("/projects/#{project.id}/hooks/42", user)
485       response.status.should == 200
486     end
487
488     it "should return a 400 error if hook id not given" do
489       delete api("/projects/#{project.id}/hooks", user)
490       response.status.should == 400
491     end
492   end
493
494   describe "GET /projects/:id/repository/tags" do
495     it "should return an array of project tags" do
496       get api("/projects/#{project.id}/repository/tags", user)
497       response.status.should == 200
498       json_response.should be_an Array
499       json_response.first['name'].should == project.repo.tags.sort_by(&:name).reverse.first.name
500     end
501   end
502
503   describe "GET /projects/:id/repository/commits" do
504     context "authorized user" do
505       before { project.team << [user2, :reporter] }
506
507       it "should return project commits" do
508         get api("/projects/#{project.id}/repository/commits", user)
509         response.status.should == 200
510
511         json_response.should be_an Array
512         json_response.first['id'].should == project.repository.commit.id
513       end
514     end
515
516     context "unauthorized user" do
517       it "should not return project commits" do
518         get api("/projects/#{project.id}/repository/commits")
519         response.status.should == 401
520       end
521     end
522   end
523
524   describe "GET /projects/:id/snippets" do
525     it "should return an array of project snippets" do
526       get api("/projects/#{project.id}/snippets", user)
527       response.status.should == 200
528       json_response.should be_an Array
529       json_response.first['title'].should == snippet.title
530     end
531   end
532
533   describe "GET /projects/:id/snippets/:snippet_id" do
534     it "should return a project snippet" do
535       get api("/projects/#{project.id}/snippets/#{snippet.id}", user)
536       response.status.should == 200
537       json_response['title'].should == snippet.title
538     end
539
540     it "should return a 404 error if snippet id not found" do
541       get api("/projects/#{project.id}/snippets/1234", user)
542       response.status.should == 404
543     end
544   end
545
546   describe "POST /projects/:id/snippets" do
547     it "should create a new project snippet" do
548       post api("/projects/#{project.id}/snippets", user),
549         title: 'api test', file_name: 'sample.rb', code: 'test'
550       response.status.should == 201
551       json_response['title'].should == 'api test'
552     end
553
554     it "should return a 400 error if title is not given" do
555       post api("/projects/#{project.id}/snippets", user),
556         file_name: 'sample.rb', code: 'test'
557       response.status.should == 400
558     end
559
560     it "should return a 400 error if file_name not given" do
561       post api("/projects/#{project.id}/snippets", user),
562         title: 'api test', code: 'test'
563       response.status.should == 400
564     end
565
566     it "should return a 400 error if code not given" do
567       post api("/projects/#{project.id}/snippets", user),
568         title: 'api test', file_name: 'sample.rb'
569       response.status.should == 400
570     end
571   end
572
573   describe "PUT /projects/:id/snippets/:shippet_id" do
574     it "should update an existing project snippet" do
575       put api("/projects/#{project.id}/snippets/#{snippet.id}", user),
576         code: 'updated code'
577       response.status.should == 200
578       json_response['title'].should == 'example'
579       snippet.reload.content.should == 'updated code'
580     end
581
582     it "should update an existing project snippet with new title" do
583       put api("/projects/#{project.id}/snippets/#{snippet.id}", user),
584         title: 'other api test'
585       response.status.should == 200
586       json_response['title'].should == 'other api test'
587     end
588   end
589
590   describe "DELETE /projects/:id/snippets/:snippet_id" do
591     it "should delete existing project snippet" do
592       expect {
593         delete api("/projects/#{project.id}/snippets/#{snippet.id}", user)
594       }.to change { Snippet.count }.by(-1)
595       response.status.should == 200
596     end
597
598     it "should return success when deleting unknown snippet id" do
599       delete api("/projects/#{project.id}/snippets/1234", user)
600       response.status.should == 200
601     end
602   end
603
604   describe "GET /projects/:id/snippets/:snippet_id/raw" do
605     it "should get a raw project snippet" do
606       get api("/projects/#{project.id}/snippets/#{snippet.id}/raw", user)
607       response.status.should == 200
608     end
609
610     it "should return a 404 error if raw project snippet not found" do
611       get api("/projects/#{project.id}/snippets/5555/raw", user)
612       response.status.should == 404
613     end
614   end
615
616   describe "GET /projects/:id/repository/commits/:sha/blob" do
617     it "should get the raw file contents" do
618       get api("/projects/#{project.id}/repository/commits/master/blob?filepath=README.md", user)
619       response.status.should == 200
620     end
621
622     it "should return 404 for invalid branch_name" do
623       get api("/projects/#{project.id}/repository/commits/invalid_branch_name/blob?filepath=README.md", user)
624       response.status.should == 404
625     end
626
627     it "should return 404 for invalid file" do
628       get api("/projects/#{project.id}/repository/commits/master/blob?filepath=README.invalid", user)
629       response.status.should == 404
630     end
631
632     it "should return a 400 error if filepath is missing" do
633       get api("/projects/#{project.id}/repository/commits/master/blob", user)
634       response.status.should == 400
635     end
636   end
637
638   describe :deploy_keys do
639     let(:deploy_keys_project) { create(:deploy_keys_project, project: project) }
640     let(:deploy_key) { deploy_keys_project.deploy_key }
641
642     describe "GET /projects/:id/keys" do
643       before { deploy_key }
644
645       it "should return array of ssh keys" do
646         get api("/projects/#{project.id}/keys", user)
647         response.status.should == 200
648         json_response.should be_an Array
649         json_response.first['title'].should == deploy_key.title
650       end
651     end
652
653     describe "GET /projects/:id/keys/:key_id" do
654       it "should return a single key" do
655         get api("/projects/#{project.id}/keys/#{deploy_key.id}", user)
656         response.status.should == 200
657         json_response['title'].should == deploy_key.title
658       end
659
660       it "should return 404 Not Found with invalid ID" do
661         get api("/projects/#{project.id}/keys/404", user)
662         response.status.should == 404
663       end
664     end
665
666     describe "POST /projects/:id/keys" do
667       it "should not create an invalid ssh key" do
668         post api("/projects/#{project.id}/keys", user), { title: "invalid key" }
669         response.status.should == 404
670       end
671
672       it "should create new ssh key" do
673         key_attrs = attributes_for :key
674         expect {
675           post api("/projects/#{project.id}/keys", user), key_attrs
676         }.to change{ project.deploy_keys.count }.by(1)
677       end
678     end
679
680     describe "DELETE /projects/:id/keys/:key_id" do
681       before { deploy_key }
682
683       it "should delete existing key" do
684         expect {
685           delete api("/projects/#{project.id}/keys/#{deploy_key.id}", user)
686         }.to change{ project.deploy_keys.count }.by(-1)
687       end
688
689       it "should return 404 Not Found with invalid ID" do
690         delete api("/projects/#{project.id}/keys/404", user)
691         response.status.should == 404
692       end
693     end
694   end
695 end