chris@37
|
1 # Redmine - project management software
|
chris@37
|
2 # Copyright (C) 2006-2010 Jean-Philippe Lang
|
chris@37
|
3 #
|
chris@37
|
4 # This program is free software; you can redistribute it and/or
|
chris@37
|
5 # modify it under the terms of the GNU General Public License
|
chris@37
|
6 # as published by the Free Software Foundation; either version 2
|
chris@37
|
7 # of the License, or (at your option) any later version.
|
chris@37
|
8 #
|
chris@37
|
9 # This program is distributed in the hope that it will be useful,
|
chris@37
|
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
|
chris@37
|
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
chris@37
|
12 # GNU General Public License for more details.
|
chris@37
|
13 #
|
chris@37
|
14 # You should have received a copy of the GNU General Public License
|
chris@37
|
15 # along with this program; if not, write to the Free Software
|
chris@37
|
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
chris@37
|
17
|
chris@37
|
18 require "#{File.dirname(__FILE__)}/../../test_helper"
|
chris@37
|
19
|
chris@37
|
20 class ApiTest::IssuesTest < ActionController::IntegrationTest
|
chris@37
|
21 fixtures :projects,
|
chris@37
|
22 :users,
|
chris@37
|
23 :roles,
|
chris@37
|
24 :members,
|
chris@37
|
25 :member_roles,
|
chris@37
|
26 :issues,
|
chris@37
|
27 :issue_statuses,
|
chris@37
|
28 :versions,
|
chris@37
|
29 :trackers,
|
chris@37
|
30 :projects_trackers,
|
chris@37
|
31 :issue_categories,
|
chris@37
|
32 :enabled_modules,
|
chris@37
|
33 :enumerations,
|
chris@37
|
34 :attachments,
|
chris@37
|
35 :workflows,
|
chris@37
|
36 :custom_fields,
|
chris@37
|
37 :custom_values,
|
chris@37
|
38 :custom_fields_projects,
|
chris@37
|
39 :custom_fields_trackers,
|
chris@37
|
40 :time_entries,
|
chris@37
|
41 :journals,
|
chris@37
|
42 :journal_details,
|
chris@37
|
43 :queries
|
chris@37
|
44
|
chris@37
|
45 def setup
|
chris@37
|
46 Setting.rest_api_enabled = '1'
|
chris@37
|
47 end
|
chris@37
|
48
|
chris@37
|
49 # Use a private project to make sure auth is really working and not just
|
chris@37
|
50 # only showing public issues.
|
chris@37
|
51 context "/index.xml" do
|
chris@37
|
52 should_allow_api_authentication(:get, "/projects/private-child/issues.xml")
|
chris@37
|
53 end
|
chris@37
|
54
|
chris@37
|
55 context "/index.json" do
|
chris@37
|
56 should_allow_api_authentication(:get, "/projects/private-child/issues.json")
|
chris@37
|
57 end
|
chris@37
|
58
|
chris@37
|
59 context "/index.xml with filter" do
|
chris@37
|
60 should_allow_api_authentication(:get, "/projects/private-child/issues.xml?status_id=5")
|
chris@37
|
61
|
chris@37
|
62 should "show only issues with the status_id" do
|
chris@37
|
63 get '/issues.xml?status_id=5'
|
chris@37
|
64 assert_tag :tag => 'issues',
|
chris@37
|
65 :children => { :count => Issue.visible.count(:conditions => {:status_id => 5}),
|
chris@37
|
66 :only => { :tag => 'issue' } }
|
chris@37
|
67 end
|
chris@37
|
68 end
|
chris@37
|
69
|
chris@37
|
70 context "/index.json with filter" do
|
chris@37
|
71 should_allow_api_authentication(:get, "/projects/private-child/issues.json?status_id=5")
|
chris@37
|
72
|
chris@37
|
73 should "show only issues with the status_id" do
|
chris@37
|
74 get '/issues.json?status_id=5'
|
chris@37
|
75
|
chris@37
|
76 json = ActiveSupport::JSON.decode(response.body)
|
chris@37
|
77 status_ids_used = json.collect {|j| j['status_id'] }
|
chris@37
|
78 assert_equal 3, status_ids_used.length
|
chris@37
|
79 assert status_ids_used.all? {|id| id == 5 }
|
chris@37
|
80 end
|
chris@37
|
81
|
chris@37
|
82 end
|
chris@37
|
83
|
chris@37
|
84 # Issue 6 is on a private project
|
chris@37
|
85 context "/issues/6.xml" do
|
chris@37
|
86 should_allow_api_authentication(:get, "/issues/6.xml")
|
chris@37
|
87 end
|
chris@37
|
88
|
chris@37
|
89 context "/issues/6.json" do
|
chris@37
|
90 should_allow_api_authentication(:get, "/issues/6.json")
|
chris@37
|
91 end
|
chris@37
|
92
|
chris@37
|
93 context "POST /issues.xml" do
|
chris@37
|
94 should_allow_api_authentication(:post,
|
chris@37
|
95 '/issues.xml',
|
chris@37
|
96 {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}},
|
chris@37
|
97 {:success_code => :created})
|
chris@37
|
98
|
chris@37
|
99 should "create an issue with the attributes" do
|
chris@37
|
100 assert_difference('Issue.count') do
|
chris@37
|
101 post '/issues.xml', {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}}, :authorization => credentials('jsmith')
|
chris@37
|
102 end
|
chris@37
|
103
|
chris@37
|
104 issue = Issue.first(:order => 'id DESC')
|
chris@37
|
105 assert_equal 1, issue.project_id
|
chris@37
|
106 assert_equal 2, issue.tracker_id
|
chris@37
|
107 assert_equal 3, issue.status_id
|
chris@37
|
108 assert_equal 'API test', issue.subject
|
chris@37
|
109
|
chris@37
|
110 assert_response :created
|
chris@37
|
111 assert_equal 'application/xml', @response.content_type
|
chris@37
|
112 assert_tag 'issue', :child => {:tag => 'id', :content => issue.id.to_s}
|
chris@37
|
113 end
|
chris@37
|
114 end
|
chris@37
|
115
|
chris@37
|
116 context "POST /issues.xml with failure" do
|
chris@37
|
117 should_allow_api_authentication(:post,
|
chris@37
|
118 '/issues.xml',
|
chris@37
|
119 {:issue => {:project_id => 1}},
|
chris@37
|
120 {:success_code => :unprocessable_entity})
|
chris@37
|
121
|
chris@37
|
122 should "have an errors tag" do
|
chris@37
|
123 assert_no_difference('Issue.count') do
|
chris@37
|
124 post '/issues.xml', {:issue => {:project_id => 1}}, :authorization => credentials('jsmith')
|
chris@37
|
125 end
|
chris@37
|
126
|
chris@37
|
127 assert_tag :errors, :child => {:tag => 'error', :content => "Subject can't be blank"}
|
chris@37
|
128 end
|
chris@37
|
129 end
|
chris@37
|
130
|
chris@37
|
131 context "POST /issues.json" do
|
chris@37
|
132 should_allow_api_authentication(:post,
|
chris@37
|
133 '/issues.json',
|
chris@37
|
134 {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}},
|
chris@37
|
135 {:success_code => :created})
|
chris@37
|
136
|
chris@37
|
137 should "create an issue with the attributes" do
|
chris@37
|
138 assert_difference('Issue.count') do
|
chris@37
|
139 post '/issues.json', {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}}, :authorization => credentials('jsmith')
|
chris@37
|
140 end
|
chris@37
|
141
|
chris@37
|
142 issue = Issue.first(:order => 'id DESC')
|
chris@37
|
143 assert_equal 1, issue.project_id
|
chris@37
|
144 assert_equal 2, issue.tracker_id
|
chris@37
|
145 assert_equal 3, issue.status_id
|
chris@37
|
146 assert_equal 'API test', issue.subject
|
chris@37
|
147 end
|
chris@37
|
148
|
chris@37
|
149 end
|
chris@37
|
150
|
chris@37
|
151 context "POST /issues.json with failure" do
|
chris@37
|
152 should_allow_api_authentication(:post,
|
chris@37
|
153 '/issues.json',
|
chris@37
|
154 {:issue => {:project_id => 1}},
|
chris@37
|
155 {:success_code => :unprocessable_entity})
|
chris@37
|
156
|
chris@37
|
157 should "have an errors element" do
|
chris@37
|
158 assert_no_difference('Issue.count') do
|
chris@37
|
159 post '/issues.json', {:issue => {:project_id => 1}}, :authorization => credentials('jsmith')
|
chris@37
|
160 end
|
chris@37
|
161
|
chris@37
|
162 json = ActiveSupport::JSON.decode(response.body)
|
chris@37
|
163 assert_equal "can't be blank", json.first['subject']
|
chris@37
|
164 end
|
chris@37
|
165 end
|
chris@37
|
166
|
chris@37
|
167 # Issue 6 is on a private project
|
chris@37
|
168 context "PUT /issues/6.xml" do
|
chris@37
|
169 setup do
|
chris@37
|
170 @parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}}
|
chris@37
|
171 @headers = { :authorization => credentials('jsmith') }
|
chris@37
|
172 end
|
chris@37
|
173
|
chris@37
|
174 should_allow_api_authentication(:put,
|
chris@37
|
175 '/issues/6.xml',
|
chris@37
|
176 {:issue => {:subject => 'API update', :notes => 'A new note'}},
|
chris@37
|
177 {:success_code => :ok})
|
chris@37
|
178
|
chris@37
|
179 should "not create a new issue" do
|
chris@37
|
180 assert_no_difference('Issue.count') do
|
chris@37
|
181 put '/issues/6.xml', @parameters, @headers
|
chris@37
|
182 end
|
chris@37
|
183 end
|
chris@37
|
184
|
chris@37
|
185 should "create a new journal" do
|
chris@37
|
186 assert_difference('Journal.count') do
|
chris@37
|
187 put '/issues/6.xml', @parameters, @headers
|
chris@37
|
188 end
|
chris@37
|
189 end
|
chris@37
|
190
|
chris@37
|
191 should "add the note to the journal" do
|
chris@37
|
192 put '/issues/6.xml', @parameters, @headers
|
chris@37
|
193
|
chris@37
|
194 journal = Journal.last
|
chris@37
|
195 assert_equal "A new note", journal.notes
|
chris@37
|
196 end
|
chris@37
|
197
|
chris@37
|
198 should "update the issue" do
|
chris@37
|
199 put '/issues/6.xml', @parameters, @headers
|
chris@37
|
200
|
chris@37
|
201 issue = Issue.find(6)
|
chris@37
|
202 assert_equal "API update", issue.subject
|
chris@37
|
203 end
|
chris@37
|
204
|
chris@37
|
205 end
|
chris@37
|
206
|
chris@37
|
207 context "PUT /issues/6.xml with failed update" do
|
chris@37
|
208 setup do
|
chris@37
|
209 @parameters = {:issue => {:subject => ''}}
|
chris@37
|
210 @headers = { :authorization => credentials('jsmith') }
|
chris@37
|
211 end
|
chris@37
|
212
|
chris@37
|
213 should_allow_api_authentication(:put,
|
chris@37
|
214 '/issues/6.xml',
|
chris@37
|
215 {:issue => {:subject => ''}}, # Missing subject should fail
|
chris@37
|
216 {:success_code => :unprocessable_entity})
|
chris@37
|
217
|
chris@37
|
218 should "not create a new issue" do
|
chris@37
|
219 assert_no_difference('Issue.count') do
|
chris@37
|
220 put '/issues/6.xml', @parameters, @headers
|
chris@37
|
221 end
|
chris@37
|
222 end
|
chris@37
|
223
|
chris@37
|
224 should "not create a new journal" do
|
chris@37
|
225 assert_no_difference('Journal.count') do
|
chris@37
|
226 put '/issues/6.xml', @parameters, @headers
|
chris@37
|
227 end
|
chris@37
|
228 end
|
chris@37
|
229
|
chris@37
|
230 should "have an errors tag" do
|
chris@37
|
231 put '/issues/6.xml', @parameters, @headers
|
chris@37
|
232
|
chris@37
|
233 assert_tag :errors, :child => {:tag => 'error', :content => "Subject can't be blank"}
|
chris@37
|
234 end
|
chris@37
|
235 end
|
chris@37
|
236
|
chris@37
|
237 context "PUT /issues/6.json" do
|
chris@37
|
238 setup do
|
chris@37
|
239 @parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}}
|
chris@37
|
240 @headers = { :authorization => credentials('jsmith') }
|
chris@37
|
241 end
|
chris@37
|
242
|
chris@37
|
243 should_allow_api_authentication(:put,
|
chris@37
|
244 '/issues/6.json',
|
chris@37
|
245 {:issue => {:subject => 'API update', :notes => 'A new note'}},
|
chris@37
|
246 {:success_code => :ok})
|
chris@37
|
247
|
chris@37
|
248 should "not create a new issue" do
|
chris@37
|
249 assert_no_difference('Issue.count') do
|
chris@37
|
250 put '/issues/6.json', @parameters, @headers
|
chris@37
|
251 end
|
chris@37
|
252 end
|
chris@37
|
253
|
chris@37
|
254 should "create a new journal" do
|
chris@37
|
255 assert_difference('Journal.count') do
|
chris@37
|
256 put '/issues/6.json', @parameters, @headers
|
chris@37
|
257 end
|
chris@37
|
258 end
|
chris@37
|
259
|
chris@37
|
260 should "add the note to the journal" do
|
chris@37
|
261 put '/issues/6.json', @parameters, @headers
|
chris@37
|
262
|
chris@37
|
263 journal = Journal.last
|
chris@37
|
264 assert_equal "A new note", journal.notes
|
chris@37
|
265 end
|
chris@37
|
266
|
chris@37
|
267 should "update the issue" do
|
chris@37
|
268 put '/issues/6.json', @parameters, @headers
|
chris@37
|
269
|
chris@37
|
270 issue = Issue.find(6)
|
chris@37
|
271 assert_equal "API update", issue.subject
|
chris@37
|
272 end
|
chris@37
|
273
|
chris@37
|
274 end
|
chris@37
|
275
|
chris@37
|
276 context "PUT /issues/6.json with failed update" do
|
chris@37
|
277 setup do
|
chris@37
|
278 @parameters = {:issue => {:subject => ''}}
|
chris@37
|
279 @headers = { :authorization => credentials('jsmith') }
|
chris@37
|
280 end
|
chris@37
|
281
|
chris@37
|
282 should_allow_api_authentication(:put,
|
chris@37
|
283 '/issues/6.json',
|
chris@37
|
284 {:issue => {:subject => ''}}, # Missing subject should fail
|
chris@37
|
285 {:success_code => :unprocessable_entity})
|
chris@37
|
286
|
chris@37
|
287 should "not create a new issue" do
|
chris@37
|
288 assert_no_difference('Issue.count') do
|
chris@37
|
289 put '/issues/6.json', @parameters, @headers
|
chris@37
|
290 end
|
chris@37
|
291 end
|
chris@37
|
292
|
chris@37
|
293 should "not create a new journal" do
|
chris@37
|
294 assert_no_difference('Journal.count') do
|
chris@37
|
295 put '/issues/6.json', @parameters, @headers
|
chris@37
|
296 end
|
chris@37
|
297 end
|
chris@37
|
298
|
chris@37
|
299 should "have an errors attribute" do
|
chris@37
|
300 put '/issues/6.json', @parameters, @headers
|
chris@37
|
301
|
chris@37
|
302 json = ActiveSupport::JSON.decode(response.body)
|
chris@37
|
303 assert_equal "can't be blank", json.first['subject']
|
chris@37
|
304 end
|
chris@37
|
305 end
|
chris@37
|
306
|
chris@37
|
307 context "DELETE /issues/1.xml" do
|
chris@37
|
308 should_allow_api_authentication(:delete,
|
chris@37
|
309 '/issues/6.xml',
|
chris@37
|
310 {},
|
chris@37
|
311 {:success_code => :ok})
|
chris@37
|
312
|
chris@37
|
313 should "delete the issue" do
|
chris@37
|
314 assert_difference('Issue.count',-1) do
|
chris@37
|
315 delete '/issues/6.xml', {}, :authorization => credentials('jsmith')
|
chris@37
|
316 end
|
chris@37
|
317
|
chris@37
|
318 assert_nil Issue.find_by_id(6)
|
chris@37
|
319 end
|
chris@37
|
320 end
|
chris@37
|
321
|
chris@37
|
322 context "DELETE /issues/1.json" do
|
chris@37
|
323 should_allow_api_authentication(:delete,
|
chris@37
|
324 '/issues/6.json',
|
chris@37
|
325 {},
|
chris@37
|
326 {:success_code => :ok})
|
chris@37
|
327
|
chris@37
|
328 should "delete the issue" do
|
chris@37
|
329 assert_difference('Issue.count',-1) do
|
chris@37
|
330 delete '/issues/6.json', {}, :authorization => credentials('jsmith')
|
chris@37
|
331 end
|
chris@37
|
332
|
chris@37
|
333 assert_nil Issue.find_by_id(6)
|
chris@37
|
334 end
|
chris@37
|
335 end
|
chris@37
|
336
|
chris@37
|
337 def credentials(user, password=nil)
|
chris@37
|
338 ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)
|
chris@37
|
339 end
|
chris@37
|
340 end
|