Mercurial > hg > soundsoftware-site
comparison .svn/pristine/2b/2b0a9f999f6063790f2925cfcbf5bec32cb0108e.svn-base @ 909:cbb26bc654de redmine-1.3
Update to Redmine 1.3-stable branch (Redmine SVN rev 8964)
author | Chris Cannam |
---|---|
date | Fri, 24 Feb 2012 19:09:32 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
908:c6c2cbd0afee | 909:cbb26bc654de |
---|---|
1 # Redmine - project management software | |
2 # Copyright (C) 2006-2011 Jean-Philippe Lang | |
3 # | |
4 # This program is free software; you can redistribute it and/or | |
5 # modify it under the terms of the GNU General Public License | |
6 # as published by the Free Software Foundation; either version 2 | |
7 # of the License, or (at your option) any later version. | |
8 # | |
9 # This program is distributed in the hope that it will be useful, | |
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 # GNU General Public License for more details. | |
13 # | |
14 # You should have received a copy of the GNU General Public License | |
15 # along with this program; if not, write to the Free Software | |
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
17 | |
18 require File.expand_path('../../../test_helper', __FILE__) | |
19 | |
20 class ApiTest::IssuesTest < ActionController::IntegrationTest | |
21 fixtures :projects, | |
22 :users, | |
23 :roles, | |
24 :members, | |
25 :member_roles, | |
26 :issues, | |
27 :issue_statuses, | |
28 :versions, | |
29 :trackers, | |
30 :projects_trackers, | |
31 :issue_categories, | |
32 :enabled_modules, | |
33 :enumerations, | |
34 :attachments, | |
35 :workflows, | |
36 :custom_fields, | |
37 :custom_values, | |
38 :custom_fields_projects, | |
39 :custom_fields_trackers, | |
40 :time_entries, | |
41 :journals, | |
42 :journal_details, | |
43 :queries, | |
44 :attachments | |
45 | |
46 def setup | |
47 Setting.rest_api_enabled = '1' | |
48 end | |
49 | |
50 context "/issues" do | |
51 # Use a private project to make sure auth is really working and not just | |
52 # only showing public issues. | |
53 should_allow_api_authentication(:get, "/projects/private-child/issues.xml") | |
54 | |
55 should "contain metadata" do | |
56 get '/issues.xml' | |
57 | |
58 assert_tag :tag => 'issues', | |
59 :attributes => { | |
60 :type => 'array', | |
61 :total_count => assigns(:issue_count), | |
62 :limit => 25, | |
63 :offset => 0 | |
64 } | |
65 end | |
66 | |
67 context "with offset and limit" do | |
68 should "use the params" do | |
69 get '/issues.xml?offset=2&limit=3' | |
70 | |
71 assert_equal 3, assigns(:limit) | |
72 assert_equal 2, assigns(:offset) | |
73 assert_tag :tag => 'issues', :children => {:count => 3, :only => {:tag => 'issue'}} | |
74 end | |
75 end | |
76 | |
77 context "with nometa param" do | |
78 should "not contain metadata" do | |
79 get '/issues.xml?nometa=1' | |
80 | |
81 assert_tag :tag => 'issues', | |
82 :attributes => { | |
83 :type => 'array', | |
84 :total_count => nil, | |
85 :limit => nil, | |
86 :offset => nil | |
87 } | |
88 end | |
89 end | |
90 | |
91 context "with nometa header" do | |
92 should "not contain metadata" do | |
93 get '/issues.xml', {}, {'X-Redmine-Nometa' => '1'} | |
94 | |
95 assert_tag :tag => 'issues', | |
96 :attributes => { | |
97 :type => 'array', | |
98 :total_count => nil, | |
99 :limit => nil, | |
100 :offset => nil | |
101 } | |
102 end | |
103 end | |
104 | |
105 context "with relations" do | |
106 should "display relations" do | |
107 get '/issues.xml?include=relations' | |
108 | |
109 assert_response :success | |
110 assert_equal 'application/xml', @response.content_type | |
111 assert_tag 'relations', | |
112 :parent => {:tag => 'issue', :child => {:tag => 'id', :content => '3'}}, | |
113 :children => {:count => 1}, | |
114 :child => { | |
115 :tag => 'relation', | |
116 :attributes => {:id => '2', :issue_id => '2', :issue_to_id => '3', :relation_type => 'relates'} | |
117 } | |
118 assert_tag 'relations', | |
119 :parent => {:tag => 'issue', :child => {:tag => 'id', :content => '1'}}, | |
120 :children => {:count => 0} | |
121 end | |
122 end | |
123 | |
124 context "with invalid query params" do | |
125 should "return errors" do | |
126 get '/issues.xml', {:f => ['start_date'], :op => {:start_date => '='}} | |
127 | |
128 assert_response :unprocessable_entity | |
129 assert_equal 'application/xml', @response.content_type | |
130 assert_tag 'errors', :child => {:tag => 'error', :content => "Start date can't be blank"} | |
131 end | |
132 end | |
133 | |
134 context "with custom field filter" do | |
135 should "show only issues with the custom field value" do | |
136 get '/issues.xml', { :set_filter => 1, :f => ['cf_1'], :op => {:cf_1 => '='}, :v => {:cf_1 => ['MySQL']}} | |
137 | |
138 expected_ids = Issue.visible.all( | |
139 :include => :custom_values, | |
140 :conditions => {:custom_values => {:custom_field_id => 1, :value => 'MySQL'}}).map(&:id) | |
141 | |
142 assert_select 'issues > issue > id', :count => expected_ids.count do |ids| | |
143 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) } | |
144 end | |
145 end | |
146 end | |
147 | |
148 context "with custom field filter (shorthand method)" do | |
149 should "show only issues with the custom field value" do | |
150 get '/issues.xml', { :cf_1 => 'MySQL' } | |
151 | |
152 expected_ids = Issue.visible.all( | |
153 :include => :custom_values, | |
154 :conditions => {:custom_values => {:custom_field_id => 1, :value => 'MySQL'}}).map(&:id) | |
155 | |
156 assert_select 'issues > issue > id', :count => expected_ids.count do |ids| | |
157 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) } | |
158 end | |
159 end | |
160 end | |
161 end | |
162 | |
163 context "/index.json" do | |
164 should_allow_api_authentication(:get, "/projects/private-child/issues.json") | |
165 end | |
166 | |
167 context "/index.xml with filter" do | |
168 should "show only issues with the status_id" do | |
169 get '/issues.xml?status_id=5' | |
170 | |
171 expected_ids = Issue.visible.all(:conditions => {:status_id => 5}).map(&:id) | |
172 | |
173 assert_select 'issues > issue > id', :count => expected_ids.count do |ids| | |
174 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) } | |
175 end | |
176 end | |
177 end | |
178 | |
179 context "/index.json with filter" do | |
180 should "show only issues with the status_id" do | |
181 get '/issues.json?status_id=5' | |
182 | |
183 json = ActiveSupport::JSON.decode(response.body) | |
184 status_ids_used = json['issues'].collect {|j| j['status']['id'] } | |
185 assert_equal 3, status_ids_used.length | |
186 assert status_ids_used.all? {|id| id == 5 } | |
187 end | |
188 | |
189 end | |
190 | |
191 # Issue 6 is on a private project | |
192 context "/issues/6.xml" do | |
193 should_allow_api_authentication(:get, "/issues/6.xml") | |
194 end | |
195 | |
196 context "/issues/6.json" do | |
197 should_allow_api_authentication(:get, "/issues/6.json") | |
198 end | |
199 | |
200 context "GET /issues/:id" do | |
201 context "with journals" do | |
202 context ".xml" do | |
203 should "display journals" do | |
204 get '/issues/1.xml?include=journals' | |
205 | |
206 assert_tag :tag => 'issue', | |
207 :child => { | |
208 :tag => 'journals', | |
209 :attributes => { :type => 'array' }, | |
210 :child => { | |
211 :tag => 'journal', | |
212 :attributes => { :id => '1'}, | |
213 :child => { | |
214 :tag => 'details', | |
215 :attributes => { :type => 'array' }, | |
216 :child => { | |
217 :tag => 'detail', | |
218 :attributes => { :name => 'status_id' }, | |
219 :child => { | |
220 :tag => 'old_value', | |
221 :content => '1', | |
222 :sibling => { | |
223 :tag => 'new_value', | |
224 :content => '2' | |
225 } | |
226 } | |
227 } | |
228 } | |
229 } | |
230 } | |
231 end | |
232 end | |
233 end | |
234 | |
235 context "with custom fields" do | |
236 context ".xml" do | |
237 should "display custom fields" do | |
238 get '/issues/3.xml' | |
239 | |
240 assert_tag :tag => 'issue', | |
241 :child => { | |
242 :tag => 'custom_fields', | |
243 :attributes => { :type => 'array' }, | |
244 :child => { | |
245 :tag => 'custom_field', | |
246 :attributes => { :id => '1'}, | |
247 :child => { | |
248 :tag => 'value', | |
249 :content => 'MySQL' | |
250 } | |
251 } | |
252 } | |
253 | |
254 assert_nothing_raised do | |
255 Hash.from_xml(response.body).to_xml | |
256 end | |
257 end | |
258 end | |
259 end | |
260 | |
261 context "with attachments" do | |
262 context ".xml" do | |
263 should "display attachments" do | |
264 get '/issues/3.xml?include=attachments' | |
265 | |
266 assert_tag :tag => 'issue', | |
267 :child => { | |
268 :tag => 'attachments', | |
269 :children => {:count => 5}, | |
270 :child => { | |
271 :tag => 'attachment', | |
272 :child => { | |
273 :tag => 'filename', | |
274 :content => 'source.rb', | |
275 :sibling => { | |
276 :tag => 'content_url', | |
277 :content => 'http://www.example.com/attachments/download/4/source.rb' | |
278 } | |
279 } | |
280 } | |
281 } | |
282 end | |
283 end | |
284 end | |
285 | |
286 context "with subtasks" do | |
287 setup do | |
288 @c1 = Issue.generate!(:status_id => 1, :subject => "child c1", :tracker_id => 1, :project_id => 1, :parent_issue_id => 1) | |
289 @c2 = Issue.generate!(:status_id => 1, :subject => "child c2", :tracker_id => 1, :project_id => 1, :parent_issue_id => 1) | |
290 @c3 = Issue.generate!(:status_id => 1, :subject => "child c3", :tracker_id => 1, :project_id => 1, :parent_issue_id => @c1.id) | |
291 end | |
292 | |
293 context ".xml" do | |
294 should "display children" do | |
295 get '/issues/1.xml?include=children' | |
296 | |
297 assert_tag :tag => 'issue', | |
298 :child => { | |
299 :tag => 'children', | |
300 :children => {:count => 2}, | |
301 :child => { | |
302 :tag => 'issue', | |
303 :attributes => {:id => @c1.id.to_s}, | |
304 :child => { | |
305 :tag => 'subject', | |
306 :content => 'child c1', | |
307 :sibling => { | |
308 :tag => 'children', | |
309 :children => {:count => 1}, | |
310 :child => { | |
311 :tag => 'issue', | |
312 :attributes => {:id => @c3.id.to_s} | |
313 } | |
314 } | |
315 } | |
316 } | |
317 } | |
318 end | |
319 | |
320 context ".json" do | |
321 should "display children" do | |
322 get '/issues/1.json?include=children' | |
323 | |
324 json = ActiveSupport::JSON.decode(response.body) | |
325 assert_equal([ | |
326 { | |
327 'id' => @c1.id, 'subject' => 'child c1', 'tracker' => {'id' => 1, 'name' => 'Bug'}, | |
328 'children' => [{ 'id' => @c3.id, 'subject' => 'child c3', 'tracker' => {'id' => 1, 'name' => 'Bug'} }] | |
329 }, | |
330 { 'id' => @c2.id, 'subject' => 'child c2', 'tracker' => {'id' => 1, 'name' => 'Bug'} } | |
331 ], | |
332 json['issue']['children']) | |
333 end | |
334 end | |
335 end | |
336 end | |
337 end | |
338 | |
339 context "POST /issues.xml" do | |
340 should_allow_api_authentication(:post, | |
341 '/issues.xml', | |
342 {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}}, | |
343 {:success_code => :created}) | |
344 | |
345 should "create an issue with the attributes" do | |
346 assert_difference('Issue.count') do | |
347 post '/issues.xml', {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}}, :authorization => credentials('jsmith') | |
348 end | |
349 | |
350 issue = Issue.first(:order => 'id DESC') | |
351 assert_equal 1, issue.project_id | |
352 assert_equal 2, issue.tracker_id | |
353 assert_equal 3, issue.status_id | |
354 assert_equal 'API test', issue.subject | |
355 | |
356 assert_response :created | |
357 assert_equal 'application/xml', @response.content_type | |
358 assert_tag 'issue', :child => {:tag => 'id', :content => issue.id.to_s} | |
359 end | |
360 end | |
361 | |
362 context "POST /issues.xml with failure" do | |
363 should "have an errors tag" do | |
364 assert_no_difference('Issue.count') do | |
365 post '/issues.xml', {:issue => {:project_id => 1}}, :authorization => credentials('jsmith') | |
366 end | |
367 | |
368 assert_tag :errors, :child => {:tag => 'error', :content => "Subject can't be blank"} | |
369 end | |
370 end | |
371 | |
372 context "POST /issues.json" do | |
373 should_allow_api_authentication(:post, | |
374 '/issues.json', | |
375 {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}}, | |
376 {:success_code => :created}) | |
377 | |
378 should "create an issue with the attributes" do | |
379 assert_difference('Issue.count') do | |
380 post '/issues.json', {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}}, :authorization => credentials('jsmith') | |
381 end | |
382 | |
383 issue = Issue.first(:order => 'id DESC') | |
384 assert_equal 1, issue.project_id | |
385 assert_equal 2, issue.tracker_id | |
386 assert_equal 3, issue.status_id | |
387 assert_equal 'API test', issue.subject | |
388 end | |
389 | |
390 end | |
391 | |
392 context "POST /issues.json with failure" do | |
393 should "have an errors element" do | |
394 assert_no_difference('Issue.count') do | |
395 post '/issues.json', {:issue => {:project_id => 1}}, :authorization => credentials('jsmith') | |
396 end | |
397 | |
398 json = ActiveSupport::JSON.decode(response.body) | |
399 assert json['errors'].include?(['subject', "can't be blank"]) | |
400 end | |
401 end | |
402 | |
403 # Issue 6 is on a private project | |
404 context "PUT /issues/6.xml" do | |
405 setup do | |
406 @parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}} | |
407 @headers = { :authorization => credentials('jsmith') } | |
408 end | |
409 | |
410 should_allow_api_authentication(:put, | |
411 '/issues/6.xml', | |
412 {:issue => {:subject => 'API update', :notes => 'A new note'}}, | |
413 {:success_code => :ok}) | |
414 | |
415 should "not create a new issue" do | |
416 assert_no_difference('Issue.count') do | |
417 put '/issues/6.xml', @parameters, @headers | |
418 end | |
419 end | |
420 | |
421 should "create a new journal" do | |
422 assert_difference('Journal.count') do | |
423 put '/issues/6.xml', @parameters, @headers | |
424 end | |
425 end | |
426 | |
427 should "add the note to the journal" do | |
428 put '/issues/6.xml', @parameters, @headers | |
429 | |
430 journal = Journal.last | |
431 assert_equal "A new note", journal.notes | |
432 end | |
433 | |
434 should "update the issue" do | |
435 put '/issues/6.xml', @parameters, @headers | |
436 | |
437 issue = Issue.find(6) | |
438 assert_equal "API update", issue.subject | |
439 end | |
440 | |
441 end | |
442 | |
443 context "PUT /issues/3.xml with custom fields" do | |
444 setup do | |
445 @parameters = {:issue => {:custom_fields => [{'id' => '1', 'value' => 'PostgreSQL' }, {'id' => '2', 'value' => '150'}]}} | |
446 @headers = { :authorization => credentials('jsmith') } | |
447 end | |
448 | |
449 should "update custom fields" do | |
450 assert_no_difference('Issue.count') do | |
451 put '/issues/3.xml', @parameters, @headers | |
452 end | |
453 | |
454 issue = Issue.find(3) | |
455 assert_equal '150', issue.custom_value_for(2).value | |
456 assert_equal 'PostgreSQL', issue.custom_value_for(1).value | |
457 end | |
458 end | |
459 | |
460 context "PUT /issues/6.xml with failed update" do | |
461 setup do | |
462 @parameters = {:issue => {:subject => ''}} | |
463 @headers = { :authorization => credentials('jsmith') } | |
464 end | |
465 | |
466 should "not create a new issue" do | |
467 assert_no_difference('Issue.count') do | |
468 put '/issues/6.xml', @parameters, @headers | |
469 end | |
470 end | |
471 | |
472 should "not create a new journal" do | |
473 assert_no_difference('Journal.count') do | |
474 put '/issues/6.xml', @parameters, @headers | |
475 end | |
476 end | |
477 | |
478 should "have an errors tag" do | |
479 put '/issues/6.xml', @parameters, @headers | |
480 | |
481 assert_tag :errors, :child => {:tag => 'error', :content => "Subject can't be blank"} | |
482 end | |
483 end | |
484 | |
485 context "PUT /issues/6.json" do | |
486 setup do | |
487 @parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}} | |
488 @headers = { :authorization => credentials('jsmith') } | |
489 end | |
490 | |
491 should_allow_api_authentication(:put, | |
492 '/issues/6.json', | |
493 {:issue => {:subject => 'API update', :notes => 'A new note'}}, | |
494 {:success_code => :ok}) | |
495 | |
496 should "not create a new issue" do | |
497 assert_no_difference('Issue.count') do | |
498 put '/issues/6.json', @parameters, @headers | |
499 end | |
500 end | |
501 | |
502 should "create a new journal" do | |
503 assert_difference('Journal.count') do | |
504 put '/issues/6.json', @parameters, @headers | |
505 end | |
506 end | |
507 | |
508 should "add the note to the journal" do | |
509 put '/issues/6.json', @parameters, @headers | |
510 | |
511 journal = Journal.last | |
512 assert_equal "A new note", journal.notes | |
513 end | |
514 | |
515 should "update the issue" do | |
516 put '/issues/6.json', @parameters, @headers | |
517 | |
518 issue = Issue.find(6) | |
519 assert_equal "API update", issue.subject | |
520 end | |
521 | |
522 end | |
523 | |
524 context "PUT /issues/6.json with failed update" do | |
525 setup do | |
526 @parameters = {:issue => {:subject => ''}} | |
527 @headers = { :authorization => credentials('jsmith') } | |
528 end | |
529 | |
530 should "not create a new issue" do | |
531 assert_no_difference('Issue.count') do | |
532 put '/issues/6.json', @parameters, @headers | |
533 end | |
534 end | |
535 | |
536 should "not create a new journal" do | |
537 assert_no_difference('Journal.count') do | |
538 put '/issues/6.json', @parameters, @headers | |
539 end | |
540 end | |
541 | |
542 should "have an errors attribute" do | |
543 put '/issues/6.json', @parameters, @headers | |
544 | |
545 json = ActiveSupport::JSON.decode(response.body) | |
546 assert json['errors'].include?(['subject', "can't be blank"]) | |
547 end | |
548 end | |
549 | |
550 context "DELETE /issues/1.xml" do | |
551 should_allow_api_authentication(:delete, | |
552 '/issues/6.xml', | |
553 {}, | |
554 {:success_code => :ok}) | |
555 | |
556 should "delete the issue" do | |
557 assert_difference('Issue.count',-1) do | |
558 delete '/issues/6.xml', {}, :authorization => credentials('jsmith') | |
559 end | |
560 | |
561 assert_nil Issue.find_by_id(6) | |
562 end | |
563 end | |
564 | |
565 context "DELETE /issues/1.json" do | |
566 should_allow_api_authentication(:delete, | |
567 '/issues/6.json', | |
568 {}, | |
569 {:success_code => :ok}) | |
570 | |
571 should "delete the issue" do | |
572 assert_difference('Issue.count',-1) do | |
573 delete '/issues/6.json', {}, :authorization => credentials('jsmith') | |
574 end | |
575 | |
576 assert_nil Issue.find_by_id(6) | |
577 end | |
578 end | |
579 | |
580 def credentials(user, password=nil) | |
581 ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user) | |
582 end | |
583 end |