##// END OF EJS Templates
Changes the representation of journal details in issue API....
Jean-Philippe Lang -
r4369:ab6a93b029b2
parent child
Show More
@@ -1,59 +1,62
1 api.issue do
1 api.issue do
2 api.id @issue.id
2 api.id @issue.id
3 api.project(:id => @issue.project_id, :name => @issue.project.name) unless @issue.project.nil?
3 api.project(:id => @issue.project_id, :name => @issue.project.name) unless @issue.project.nil?
4 api.tracker(:id => @issue.tracker_id, :name => @issue.tracker.name) unless @issue.tracker.nil?
4 api.tracker(:id => @issue.tracker_id, :name => @issue.tracker.name) unless @issue.tracker.nil?
5 api.status(:id => @issue.status_id, :name => @issue.status.name) unless @issue.status.nil?
5 api.status(:id => @issue.status_id, :name => @issue.status.name) unless @issue.status.nil?
6 api.priority(:id => @issue.priority_id, :name => @issue.priority.name) unless @issue.priority.nil?
6 api.priority(:id => @issue.priority_id, :name => @issue.priority.name) unless @issue.priority.nil?
7 api.author(:id => @issue.author_id, :name => @issue.author.name) unless @issue.author.nil?
7 api.author(:id => @issue.author_id, :name => @issue.author.name) unless @issue.author.nil?
8 api.assigned_to(:id => @issue.assigned_to_id, :name => @issue.assigned_to.name) unless @issue.assigned_to.nil?
8 api.assigned_to(:id => @issue.assigned_to_id, :name => @issue.assigned_to.name) unless @issue.assigned_to.nil?
9 api.category(:id => @issue.category_id, :name => @issue.category.name) unless @issue.category.nil?
9 api.category(:id => @issue.category_id, :name => @issue.category.name) unless @issue.category.nil?
10 api.fixed_version(:id => @issue.fixed_version_id, :name => @issue.fixed_version.name) unless @issue.fixed_version.nil?
10 api.fixed_version(:id => @issue.fixed_version_id, :name => @issue.fixed_version.name) unless @issue.fixed_version.nil?
11 api.parent(:id => @issue.parent_id) unless @issue.parent.nil?
11 api.parent(:id => @issue.parent_id) unless @issue.parent.nil?
12
12
13 api.subject @issue.subject
13 api.subject @issue.subject
14 api.description @issue.description
14 api.description @issue.description
15 api.start_date @issue.start_date
15 api.start_date @issue.start_date
16 api.due_date @issue.due_date
16 api.due_date @issue.due_date
17 api.done_ratio @issue.done_ratio
17 api.done_ratio @issue.done_ratio
18 api.estimated_hours @issue.estimated_hours
18 api.estimated_hours @issue.estimated_hours
19 if User.current.allowed_to?(:view_time_entries, @project)
19 if User.current.allowed_to?(:view_time_entries, @project)
20 api.spent_hours @issue.spent_hours
20 api.spent_hours @issue.spent_hours
21 end
21 end
22
22
23 render_api_custom_values @issue.custom_field_values, api
23 render_api_custom_values @issue.custom_field_values, api
24
24
25 api.created_on @issue.created_on
25 api.created_on @issue.created_on
26 api.updated_on @issue.updated_on
26 api.updated_on @issue.updated_on
27
27
28 render_api_issue_children(@issue, api)
28 render_api_issue_children(@issue, api)
29
29
30 api.array :relations do
30 api.array :relations do
31 @issue.relations.select {|r| r.other_issue(@issue).visible? }.each do |relation|
31 @issue.relations.select {|r| r.other_issue(@issue).visible? }.each do |relation|
32 api.relation(:id => relation.id, :issue_id => relation.other_issue(@issue).id, :relation_type => relation.relation_type_for(@issue), :delay => relation.delay)
32 api.relation(:id => relation.id, :issue_id => relation.other_issue(@issue).id, :relation_type => relation.relation_type_for(@issue), :delay => relation.delay)
33 end
33 end
34 end
34 end
35
35
36 api.array :changesets do
36 api.array :changesets do
37 @issue.changesets.each do |changeset|
37 @issue.changesets.each do |changeset|
38 api.changeset :revision => changeset.revision do
38 api.changeset :revision => changeset.revision do
39 api.user(:id => changeset.user_id, :name => changeset.user.name) unless changeset.user.nil?
39 api.user(:id => changeset.user_id, :name => changeset.user.name) unless changeset.user.nil?
40 api.comments changeset.comments
40 api.comments changeset.comments
41 api.committed_on changeset.committed_on
41 api.committed_on changeset.committed_on
42 end
42 end
43 end
43 end
44 end if User.current.allowed_to?(:view_changesets, @project) && @issue.changesets.any?
44 end if User.current.allowed_to?(:view_changesets, @project) && @issue.changesets.any?
45
45
46 api.array :journals do
46 api.array :journals do
47 @issue.journals.each do |journal|
47 @issue.journals.each do |journal|
48 api.journal :id => journal.id do
48 api.journal :id => journal.id do
49 api.user(:id => journal.user_id, :name => journal.user.name) unless journal.user.nil?
49 api.user(:id => journal.user_id, :name => journal.user.name) unless journal.user.nil?
50 api.notes journal.notes
50 api.notes journal.notes
51 api.array :details do
51 api.array :details do
52 journal.details.each do |detail|
52 journal.details.each do |detail|
53 api.detail :property => detail.property, :name => detail.prop_key, :old => detail.old_value, :new => detail.value
53 api.detail :property => detail.property, :name => detail.prop_key do
54 api.old_value detail.old_value
55 api.new_value detail.value
56 end
54 end
57 end
55 end
58 end
56 end
59 end
57 end
60 end
58 end unless @issue.journals.empty?
61 end unless @issue.journals.empty?
59 end
62 end
@@ -1,437 +1,471
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2010 Jean-Philippe Lang
2 # Copyright (C) 2006-2010 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
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
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.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require "#{File.dirname(__FILE__)}/../../test_helper"
18 require "#{File.dirname(__FILE__)}/../../test_helper"
19
19
20 class ApiTest::IssuesTest < ActionController::IntegrationTest
20 class ApiTest::IssuesTest < ActionController::IntegrationTest
21 fixtures :projects,
21 fixtures :projects,
22 :users,
22 :users,
23 :roles,
23 :roles,
24 :members,
24 :members,
25 :member_roles,
25 :member_roles,
26 :issues,
26 :issues,
27 :issue_statuses,
27 :issue_statuses,
28 :versions,
28 :versions,
29 :trackers,
29 :trackers,
30 :projects_trackers,
30 :projects_trackers,
31 :issue_categories,
31 :issue_categories,
32 :enabled_modules,
32 :enabled_modules,
33 :enumerations,
33 :enumerations,
34 :attachments,
34 :attachments,
35 :workflows,
35 :workflows,
36 :custom_fields,
36 :custom_fields,
37 :custom_values,
37 :custom_values,
38 :custom_fields_projects,
38 :custom_fields_projects,
39 :custom_fields_trackers,
39 :custom_fields_trackers,
40 :time_entries,
40 :time_entries,
41 :journals,
41 :journals,
42 :journal_details,
42 :journal_details,
43 :queries
43 :queries
44
44
45 def setup
45 def setup
46 Setting.rest_api_enabled = '1'
46 Setting.rest_api_enabled = '1'
47 end
47 end
48
48
49 # Use a private project to make sure auth is really working and not just
49 # Use a private project to make sure auth is really working and not just
50 # only showing public issues.
50 # only showing public issues.
51 context "/index.xml" do
51 context "/index.xml" do
52 should_allow_api_authentication(:get, "/projects/private-child/issues.xml")
52 should_allow_api_authentication(:get, "/projects/private-child/issues.xml")
53 end
53 end
54
54
55 context "/index.json" do
55 context "/index.json" do
56 should_allow_api_authentication(:get, "/projects/private-child/issues.json")
56 should_allow_api_authentication(:get, "/projects/private-child/issues.json")
57 end
57 end
58
58
59 context "/index.xml with filter" do
59 context "/index.xml with filter" do
60 should_allow_api_authentication(:get, "/projects/private-child/issues.xml?status_id=5")
60 should_allow_api_authentication(:get, "/projects/private-child/issues.xml?status_id=5")
61
61
62 should "show only issues with the status_id" do
62 should "show only issues with the status_id" do
63 get '/issues.xml?status_id=5'
63 get '/issues.xml?status_id=5'
64 assert_tag :tag => 'issues',
64 assert_tag :tag => 'issues',
65 :children => { :count => Issue.visible.count(:conditions => {:status_id => 5}),
65 :children => { :count => Issue.visible.count(:conditions => {:status_id => 5}),
66 :only => { :tag => 'issue' } }
66 :only => { :tag => 'issue' } }
67 end
67 end
68 end
68 end
69
69
70 context "/index.json with filter" do
70 context "/index.json with filter" do
71 should_allow_api_authentication(:get, "/projects/private-child/issues.json?status_id=5")
71 should_allow_api_authentication(:get, "/projects/private-child/issues.json?status_id=5")
72
72
73 should "show only issues with the status_id" do
73 should "show only issues with the status_id" do
74 get '/issues.json?status_id=5'
74 get '/issues.json?status_id=5'
75
75
76 json = ActiveSupport::JSON.decode(response.body)
76 json = ActiveSupport::JSON.decode(response.body)
77 status_ids_used = json['issues'].collect {|j| j['status']['id'] }
77 status_ids_used = json['issues'].collect {|j| j['status']['id'] }
78 assert_equal 3, status_ids_used.length
78 assert_equal 3, status_ids_used.length
79 assert status_ids_used.all? {|id| id == 5 }
79 assert status_ids_used.all? {|id| id == 5 }
80 end
80 end
81
81
82 end
82 end
83
83
84 # Issue 6 is on a private project
84 # Issue 6 is on a private project
85 context "/issues/6.xml" do
85 context "/issues/6.xml" do
86 should_allow_api_authentication(:get, "/issues/6.xml")
86 should_allow_api_authentication(:get, "/issues/6.xml")
87 end
87 end
88
88
89 context "/issues/6.json" do
89 context "/issues/6.json" do
90 should_allow_api_authentication(:get, "/issues/6.json")
90 should_allow_api_authentication(:get, "/issues/6.json")
91 end
91 end
92
92
93 context "GET /issues/:id" do
93 context "GET /issues/:id" do
94 context "with journals" do
95 context ".xml" do
96 should "display journals" do
97 get '/issues/1.xml'
98
99 assert_tag :tag => 'issue',
100 :child => {
101 :tag => 'journals',
102 :attributes => { :type => 'array' },
103 :child => {
104 :tag => 'journal',
105 :attributes => { :id => '1'},
106 :child => {
107 :tag => 'details',
108 :attributes => { :type => 'array' },
109 :child => {
110 :tag => 'detail',
111 :attributes => { :name => 'status_id' },
112 :child => {
113 :tag => 'old_value',
114 :content => '1',
115 :sibling => {
116 :tag => 'new_value',
117 :content => '2'
118 }
119 }
120 }
121 }
122 }
123 }
124 end
125 end
126 end
127
94 context "with custom fields" do
128 context "with custom fields" do
95 context ".xml" do
129 context ".xml" do
96 should "display custom fields" do
130 should "display custom fields" do
97 get '/issues/3.xml'
131 get '/issues/3.xml'
98
132
99 assert_tag :tag => 'issue',
133 assert_tag :tag => 'issue',
100 :child => {
134 :child => {
101 :tag => 'custom_fields',
135 :tag => 'custom_fields',
102 :attributes => { :type => 'array' },
136 :attributes => { :type => 'array' },
103 :child => {
137 :child => {
104 :tag => 'custom_field',
138 :tag => 'custom_field',
105 :attributes => { :id => '1'},
139 :attributes => { :id => '1'},
106 :child => {
140 :child => {
107 :tag => 'value',
141 :tag => 'value',
108 :content => 'MySQL'
142 :content => 'MySQL'
109 }
143 }
110 }
144 }
111 }
145 }
112
146
113 assert_nothing_raised do
147 assert_nothing_raised do
114 Hash.from_xml(response.body).to_xml
148 Hash.from_xml(response.body).to_xml
115 end
149 end
116 end
150 end
117 end
151 end
118 end
152 end
119
153
120 context "with subtasks" do
154 context "with subtasks" do
121 setup do
155 setup do
122 @c1 = Issue.generate!(:status_id => 1, :subject => "child c1", :tracker_id => 1, :project_id => 1, :parent_issue_id => 1)
156 @c1 = Issue.generate!(:status_id => 1, :subject => "child c1", :tracker_id => 1, :project_id => 1, :parent_issue_id => 1)
123 @c2 = Issue.generate!(:status_id => 1, :subject => "child c2", :tracker_id => 1, :project_id => 1, :parent_issue_id => 1)
157 @c2 = Issue.generate!(:status_id => 1, :subject => "child c2", :tracker_id => 1, :project_id => 1, :parent_issue_id => 1)
124 @c3 = Issue.generate!(:status_id => 1, :subject => "child c3", :tracker_id => 1, :project_id => 1, :parent_issue_id => @c1.id)
158 @c3 = Issue.generate!(:status_id => 1, :subject => "child c3", :tracker_id => 1, :project_id => 1, :parent_issue_id => @c1.id)
125 end
159 end
126
160
127 context ".xml" do
161 context ".xml" do
128 should "display children" do
162 should "display children" do
129 get '/issues/1.xml'
163 get '/issues/1.xml'
130
164
131 assert_tag :tag => 'issue',
165 assert_tag :tag => 'issue',
132 :child => {
166 :child => {
133 :tag => 'children',
167 :tag => 'children',
134 :children => {:count => 2},
168 :children => {:count => 2},
135 :child => {
169 :child => {
136 :tag => 'issue',
170 :tag => 'issue',
137 :attributes => {:id => @c1.id.to_s},
171 :attributes => {:id => @c1.id.to_s},
138 :child => {
172 :child => {
139 :tag => 'subject',
173 :tag => 'subject',
140 :content => 'child c1',
174 :content => 'child c1',
141 :sibling => {
175 :sibling => {
142 :tag => 'children',
176 :tag => 'children',
143 :children => {:count => 1},
177 :children => {:count => 1},
144 :child => {
178 :child => {
145 :tag => 'issue',
179 :tag => 'issue',
146 :attributes => {:id => @c3.id.to_s}
180 :attributes => {:id => @c3.id.to_s}
147 }
181 }
148 }
182 }
149 }
183 }
150 }
184 }
151 }
185 }
152 end
186 end
153
187
154 context ".json" do
188 context ".json" do
155 should "display children" do
189 should "display children" do
156 get '/issues/1.json'
190 get '/issues/1.json'
157
191
158 json = ActiveSupport::JSON.decode(response.body)
192 json = ActiveSupport::JSON.decode(response.body)
159 assert_equal([
193 assert_equal([
160 {
194 {
161 'id' => @c1.id, 'subject' => 'child c1', 'tracker' => {'id' => 1, 'name' => 'Bug'},
195 'id' => @c1.id, 'subject' => 'child c1', 'tracker' => {'id' => 1, 'name' => 'Bug'},
162 'children' => [{ 'id' => @c3.id, 'subject' => 'child c3', 'tracker' => {'id' => 1, 'name' => 'Bug'} }]
196 'children' => [{ 'id' => @c3.id, 'subject' => 'child c3', 'tracker' => {'id' => 1, 'name' => 'Bug'} }]
163 },
197 },
164 { 'id' => @c2.id, 'subject' => 'child c2', 'tracker' => {'id' => 1, 'name' => 'Bug'} }
198 { 'id' => @c2.id, 'subject' => 'child c2', 'tracker' => {'id' => 1, 'name' => 'Bug'} }
165 ],
199 ],
166 json['issue']['children'])
200 json['issue']['children'])
167 end
201 end
168 end
202 end
169 end
203 end
170 end
204 end
171 end
205 end
172
206
173 context "POST /issues.xml" do
207 context "POST /issues.xml" do
174 should_allow_api_authentication(:post,
208 should_allow_api_authentication(:post,
175 '/issues.xml',
209 '/issues.xml',
176 {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}},
210 {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}},
177 {:success_code => :created})
211 {:success_code => :created})
178
212
179 should "create an issue with the attributes" do
213 should "create an issue with the attributes" do
180 assert_difference('Issue.count') do
214 assert_difference('Issue.count') do
181 post '/issues.xml', {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}}, :authorization => credentials('jsmith')
215 post '/issues.xml', {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}}, :authorization => credentials('jsmith')
182 end
216 end
183
217
184 issue = Issue.first(:order => 'id DESC')
218 issue = Issue.first(:order => 'id DESC')
185 assert_equal 1, issue.project_id
219 assert_equal 1, issue.project_id
186 assert_equal 2, issue.tracker_id
220 assert_equal 2, issue.tracker_id
187 assert_equal 3, issue.status_id
221 assert_equal 3, issue.status_id
188 assert_equal 'API test', issue.subject
222 assert_equal 'API test', issue.subject
189
223
190 assert_response :created
224 assert_response :created
191 assert_equal 'application/xml', @response.content_type
225 assert_equal 'application/xml', @response.content_type
192 assert_tag 'issue', :child => {:tag => 'id', :content => issue.id.to_s}
226 assert_tag 'issue', :child => {:tag => 'id', :content => issue.id.to_s}
193 end
227 end
194 end
228 end
195
229
196 context "POST /issues.xml with failure" do
230 context "POST /issues.xml with failure" do
197 should_allow_api_authentication(:post,
231 should_allow_api_authentication(:post,
198 '/issues.xml',
232 '/issues.xml',
199 {:issue => {:project_id => 1}},
233 {:issue => {:project_id => 1}},
200 {:success_code => :unprocessable_entity})
234 {:success_code => :unprocessable_entity})
201
235
202 should "have an errors tag" do
236 should "have an errors tag" do
203 assert_no_difference('Issue.count') do
237 assert_no_difference('Issue.count') do
204 post '/issues.xml', {:issue => {:project_id => 1}}, :authorization => credentials('jsmith')
238 post '/issues.xml', {:issue => {:project_id => 1}}, :authorization => credentials('jsmith')
205 end
239 end
206
240
207 assert_tag :errors, :child => {:tag => 'error', :content => "Subject can't be blank"}
241 assert_tag :errors, :child => {:tag => 'error', :content => "Subject can't be blank"}
208 end
242 end
209 end
243 end
210
244
211 context "POST /issues.json" do
245 context "POST /issues.json" do
212 should_allow_api_authentication(:post,
246 should_allow_api_authentication(:post,
213 '/issues.json',
247 '/issues.json',
214 {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}},
248 {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}},
215 {:success_code => :created})
249 {:success_code => :created})
216
250
217 should "create an issue with the attributes" do
251 should "create an issue with the attributes" do
218 assert_difference('Issue.count') do
252 assert_difference('Issue.count') do
219 post '/issues.json', {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}}, :authorization => credentials('jsmith')
253 post '/issues.json', {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}}, :authorization => credentials('jsmith')
220 end
254 end
221
255
222 issue = Issue.first(:order => 'id DESC')
256 issue = Issue.first(:order => 'id DESC')
223 assert_equal 1, issue.project_id
257 assert_equal 1, issue.project_id
224 assert_equal 2, issue.tracker_id
258 assert_equal 2, issue.tracker_id
225 assert_equal 3, issue.status_id
259 assert_equal 3, issue.status_id
226 assert_equal 'API test', issue.subject
260 assert_equal 'API test', issue.subject
227 end
261 end
228
262
229 end
263 end
230
264
231 context "POST /issues.json with failure" do
265 context "POST /issues.json with failure" do
232 should_allow_api_authentication(:post,
266 should_allow_api_authentication(:post,
233 '/issues.json',
267 '/issues.json',
234 {:issue => {:project_id => 1}},
268 {:issue => {:project_id => 1}},
235 {:success_code => :unprocessable_entity})
269 {:success_code => :unprocessable_entity})
236
270
237 should "have an errors element" do
271 should "have an errors element" do
238 assert_no_difference('Issue.count') do
272 assert_no_difference('Issue.count') do
239 post '/issues.json', {:issue => {:project_id => 1}}, :authorization => credentials('jsmith')
273 post '/issues.json', {:issue => {:project_id => 1}}, :authorization => credentials('jsmith')
240 end
274 end
241
275
242 json = ActiveSupport::JSON.decode(response.body)
276 json = ActiveSupport::JSON.decode(response.body)
243 assert json['errors'].include?(['subject', "can't be blank"])
277 assert json['errors'].include?(['subject', "can't be blank"])
244 end
278 end
245 end
279 end
246
280
247 # Issue 6 is on a private project
281 # Issue 6 is on a private project
248 context "PUT /issues/6.xml" do
282 context "PUT /issues/6.xml" do
249 setup do
283 setup do
250 @parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}}
284 @parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}}
251 @headers = { :authorization => credentials('jsmith') }
285 @headers = { :authorization => credentials('jsmith') }
252 end
286 end
253
287
254 should_allow_api_authentication(:put,
288 should_allow_api_authentication(:put,
255 '/issues/6.xml',
289 '/issues/6.xml',
256 {:issue => {:subject => 'API update', :notes => 'A new note'}},
290 {:issue => {:subject => 'API update', :notes => 'A new note'}},
257 {:success_code => :ok})
291 {:success_code => :ok})
258
292
259 should "not create a new issue" do
293 should "not create a new issue" do
260 assert_no_difference('Issue.count') do
294 assert_no_difference('Issue.count') do
261 put '/issues/6.xml', @parameters, @headers
295 put '/issues/6.xml', @parameters, @headers
262 end
296 end
263 end
297 end
264
298
265 should "create a new journal" do
299 should "create a new journal" do
266 assert_difference('Journal.count') do
300 assert_difference('Journal.count') do
267 put '/issues/6.xml', @parameters, @headers
301 put '/issues/6.xml', @parameters, @headers
268 end
302 end
269 end
303 end
270
304
271 should "add the note to the journal" do
305 should "add the note to the journal" do
272 put '/issues/6.xml', @parameters, @headers
306 put '/issues/6.xml', @parameters, @headers
273
307
274 journal = Journal.last
308 journal = Journal.last
275 assert_equal "A new note", journal.notes
309 assert_equal "A new note", journal.notes
276 end
310 end
277
311
278 should "update the issue" do
312 should "update the issue" do
279 put '/issues/6.xml', @parameters, @headers
313 put '/issues/6.xml', @parameters, @headers
280
314
281 issue = Issue.find(6)
315 issue = Issue.find(6)
282 assert_equal "API update", issue.subject
316 assert_equal "API update", issue.subject
283 end
317 end
284
318
285 end
319 end
286
320
287 context "PUT /issues/3.xml with custom fields" do
321 context "PUT /issues/3.xml with custom fields" do
288 setup do
322 setup do
289 @parameters = {:issue => {:custom_fields => [{'id' => '1', 'value' => 'PostgreSQL' }, {'id' => '2', 'value' => '150'}]}}
323 @parameters = {:issue => {:custom_fields => [{'id' => '1', 'value' => 'PostgreSQL' }, {'id' => '2', 'value' => '150'}]}}
290 @headers = { :authorization => credentials('jsmith') }
324 @headers = { :authorization => credentials('jsmith') }
291 end
325 end
292
326
293 should "update custom fields" do
327 should "update custom fields" do
294 assert_no_difference('Issue.count') do
328 assert_no_difference('Issue.count') do
295 put '/issues/3.xml', @parameters, @headers
329 put '/issues/3.xml', @parameters, @headers
296 end
330 end
297
331
298 issue = Issue.find(3)
332 issue = Issue.find(3)
299 assert_equal '150', issue.custom_value_for(2).value
333 assert_equal '150', issue.custom_value_for(2).value
300 assert_equal 'PostgreSQL', issue.custom_value_for(1).value
334 assert_equal 'PostgreSQL', issue.custom_value_for(1).value
301 end
335 end
302 end
336 end
303
337
304 context "PUT /issues/6.xml with failed update" do
338 context "PUT /issues/6.xml with failed update" do
305 setup do
339 setup do
306 @parameters = {:issue => {:subject => ''}}
340 @parameters = {:issue => {:subject => ''}}
307 @headers = { :authorization => credentials('jsmith') }
341 @headers = { :authorization => credentials('jsmith') }
308 end
342 end
309
343
310 should_allow_api_authentication(:put,
344 should_allow_api_authentication(:put,
311 '/issues/6.xml',
345 '/issues/6.xml',
312 {:issue => {:subject => ''}}, # Missing subject should fail
346 {:issue => {:subject => ''}}, # Missing subject should fail
313 {:success_code => :unprocessable_entity})
347 {:success_code => :unprocessable_entity})
314
348
315 should "not create a new issue" do
349 should "not create a new issue" do
316 assert_no_difference('Issue.count') do
350 assert_no_difference('Issue.count') do
317 put '/issues/6.xml', @parameters, @headers
351 put '/issues/6.xml', @parameters, @headers
318 end
352 end
319 end
353 end
320
354
321 should "not create a new journal" do
355 should "not create a new journal" do
322 assert_no_difference('Journal.count') do
356 assert_no_difference('Journal.count') do
323 put '/issues/6.xml', @parameters, @headers
357 put '/issues/6.xml', @parameters, @headers
324 end
358 end
325 end
359 end
326
360
327 should "have an errors tag" do
361 should "have an errors tag" do
328 put '/issues/6.xml', @parameters, @headers
362 put '/issues/6.xml', @parameters, @headers
329
363
330 assert_tag :errors, :child => {:tag => 'error', :content => "Subject can't be blank"}
364 assert_tag :errors, :child => {:tag => 'error', :content => "Subject can't be blank"}
331 end
365 end
332 end
366 end
333
367
334 context "PUT /issues/6.json" do
368 context "PUT /issues/6.json" do
335 setup do
369 setup do
336 @parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}}
370 @parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}}
337 @headers = { :authorization => credentials('jsmith') }
371 @headers = { :authorization => credentials('jsmith') }
338 end
372 end
339
373
340 should_allow_api_authentication(:put,
374 should_allow_api_authentication(:put,
341 '/issues/6.json',
375 '/issues/6.json',
342 {:issue => {:subject => 'API update', :notes => 'A new note'}},
376 {:issue => {:subject => 'API update', :notes => 'A new note'}},
343 {:success_code => :ok})
377 {:success_code => :ok})
344
378
345 should "not create a new issue" do
379 should "not create a new issue" do
346 assert_no_difference('Issue.count') do
380 assert_no_difference('Issue.count') do
347 put '/issues/6.json', @parameters, @headers
381 put '/issues/6.json', @parameters, @headers
348 end
382 end
349 end
383 end
350
384
351 should "create a new journal" do
385 should "create a new journal" do
352 assert_difference('Journal.count') do
386 assert_difference('Journal.count') do
353 put '/issues/6.json', @parameters, @headers
387 put '/issues/6.json', @parameters, @headers
354 end
388 end
355 end
389 end
356
390
357 should "add the note to the journal" do
391 should "add the note to the journal" do
358 put '/issues/6.json', @parameters, @headers
392 put '/issues/6.json', @parameters, @headers
359
393
360 journal = Journal.last
394 journal = Journal.last
361 assert_equal "A new note", journal.notes
395 assert_equal "A new note", journal.notes
362 end
396 end
363
397
364 should "update the issue" do
398 should "update the issue" do
365 put '/issues/6.json', @parameters, @headers
399 put '/issues/6.json', @parameters, @headers
366
400
367 issue = Issue.find(6)
401 issue = Issue.find(6)
368 assert_equal "API update", issue.subject
402 assert_equal "API update", issue.subject
369 end
403 end
370
404
371 end
405 end
372
406
373 context "PUT /issues/6.json with failed update" do
407 context "PUT /issues/6.json with failed update" do
374 setup do
408 setup do
375 @parameters = {:issue => {:subject => ''}}
409 @parameters = {:issue => {:subject => ''}}
376 @headers = { :authorization => credentials('jsmith') }
410 @headers = { :authorization => credentials('jsmith') }
377 end
411 end
378
412
379 should_allow_api_authentication(:put,
413 should_allow_api_authentication(:put,
380 '/issues/6.json',
414 '/issues/6.json',
381 {:issue => {:subject => ''}}, # Missing subject should fail
415 {:issue => {:subject => ''}}, # Missing subject should fail
382 {:success_code => :unprocessable_entity})
416 {:success_code => :unprocessable_entity})
383
417
384 should "not create a new issue" do
418 should "not create a new issue" do
385 assert_no_difference('Issue.count') do
419 assert_no_difference('Issue.count') do
386 put '/issues/6.json', @parameters, @headers
420 put '/issues/6.json', @parameters, @headers
387 end
421 end
388 end
422 end
389
423
390 should "not create a new journal" do
424 should "not create a new journal" do
391 assert_no_difference('Journal.count') do
425 assert_no_difference('Journal.count') do
392 put '/issues/6.json', @parameters, @headers
426 put '/issues/6.json', @parameters, @headers
393 end
427 end
394 end
428 end
395
429
396 should "have an errors attribute" do
430 should "have an errors attribute" do
397 put '/issues/6.json', @parameters, @headers
431 put '/issues/6.json', @parameters, @headers
398
432
399 json = ActiveSupport::JSON.decode(response.body)
433 json = ActiveSupport::JSON.decode(response.body)
400 assert json['errors'].include?(['subject', "can't be blank"])
434 assert json['errors'].include?(['subject', "can't be blank"])
401 end
435 end
402 end
436 end
403
437
404 context "DELETE /issues/1.xml" do
438 context "DELETE /issues/1.xml" do
405 should_allow_api_authentication(:delete,
439 should_allow_api_authentication(:delete,
406 '/issues/6.xml',
440 '/issues/6.xml',
407 {},
441 {},
408 {:success_code => :ok})
442 {:success_code => :ok})
409
443
410 should "delete the issue" do
444 should "delete the issue" do
411 assert_difference('Issue.count',-1) do
445 assert_difference('Issue.count',-1) do
412 delete '/issues/6.xml', {}, :authorization => credentials('jsmith')
446 delete '/issues/6.xml', {}, :authorization => credentials('jsmith')
413 end
447 end
414
448
415 assert_nil Issue.find_by_id(6)
449 assert_nil Issue.find_by_id(6)
416 end
450 end
417 end
451 end
418
452
419 context "DELETE /issues/1.json" do
453 context "DELETE /issues/1.json" do
420 should_allow_api_authentication(:delete,
454 should_allow_api_authentication(:delete,
421 '/issues/6.json',
455 '/issues/6.json',
422 {},
456 {},
423 {:success_code => :ok})
457 {:success_code => :ok})
424
458
425 should "delete the issue" do
459 should "delete the issue" do
426 assert_difference('Issue.count',-1) do
460 assert_difference('Issue.count',-1) do
427 delete '/issues/6.json', {}, :authorization => credentials('jsmith')
461 delete '/issues/6.json', {}, :authorization => credentials('jsmith')
428 end
462 end
429
463
430 assert_nil Issue.find_by_id(6)
464 assert_nil Issue.find_by_id(6)
431 end
465 end
432 end
466 end
433
467
434 def credentials(user, password=nil)
468 def credentials(user, password=nil)
435 ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)
469 ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)
436 end
470 end
437 end
471 end
General Comments 0
You need to be logged in to leave comments. Login now