annotate .svn/pristine/a7/a781bd953d0066a0cb212d6ea0e21fdfc9eb41c7.svn-base @ 1628:9c5f8e24dadc live tip

Quieten this cron script
author Chris Cannam
date Tue, 25 Aug 2020 11:38:49 +0100
parents e248c7af89ec
children
rev   line source
Chris@1494 1 # Redmine - project management software
Chris@1494 2 # Copyright (C) 2006-2014 Jean-Philippe Lang
Chris@1494 3 #
Chris@1494 4 # This program is free software; you can redistribute it and/or
Chris@1494 5 # modify it under the terms of the GNU General Public License
Chris@1494 6 # as published by the Free Software Foundation; either version 2
Chris@1494 7 # of the License, or (at your option) any later version.
Chris@1494 8 #
Chris@1494 9 # This program is distributed in the hope that it will be useful,
Chris@1494 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@1494 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@1494 12 # GNU General Public License for more details.
Chris@1494 13 #
Chris@1494 14 # You should have received a copy of the GNU General Public License
Chris@1494 15 # along with this program; if not, write to the Free Software
Chris@1494 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Chris@1494 17
Chris@1494 18 require File.expand_path('../../../test_helper', __FILE__)
Chris@1494 19
Chris@1494 20 class Redmine::ApiTest::IssuesTest < Redmine::ApiTest::Base
Chris@1494 21 fixtures :projects,
Chris@1494 22 :users,
Chris@1494 23 :roles,
Chris@1494 24 :members,
Chris@1494 25 :member_roles,
Chris@1494 26 :issues,
Chris@1494 27 :issue_statuses,
Chris@1494 28 :issue_relations,
Chris@1494 29 :versions,
Chris@1494 30 :trackers,
Chris@1494 31 :projects_trackers,
Chris@1494 32 :issue_categories,
Chris@1494 33 :enabled_modules,
Chris@1494 34 :enumerations,
Chris@1494 35 :attachments,
Chris@1494 36 :workflows,
Chris@1494 37 :custom_fields,
Chris@1494 38 :custom_values,
Chris@1494 39 :custom_fields_projects,
Chris@1494 40 :custom_fields_trackers,
Chris@1494 41 :time_entries,
Chris@1494 42 :journals,
Chris@1494 43 :journal_details,
Chris@1494 44 :queries,
Chris@1494 45 :attachments
Chris@1494 46
Chris@1494 47 def setup
Chris@1494 48 Setting.rest_api_enabled = '1'
Chris@1494 49 end
Chris@1494 50
Chris@1494 51 context "/issues" do
Chris@1494 52 # Use a private project to make sure auth is really working and not just
Chris@1494 53 # only showing public issues.
Chris@1494 54 should_allow_api_authentication(:get, "/projects/private-child/issues.xml")
Chris@1494 55
Chris@1494 56 should "contain metadata" do
Chris@1494 57 get '/issues.xml'
Chris@1494 58
Chris@1494 59 assert_tag :tag => 'issues',
Chris@1494 60 :attributes => {
Chris@1494 61 :type => 'array',
Chris@1494 62 :total_count => assigns(:issue_count),
Chris@1494 63 :limit => 25,
Chris@1494 64 :offset => 0
Chris@1494 65 }
Chris@1494 66 end
Chris@1494 67
Chris@1494 68 context "with offset and limit" do
Chris@1494 69 should "use the params" do
Chris@1494 70 get '/issues.xml?offset=2&limit=3'
Chris@1494 71
Chris@1494 72 assert_equal 3, assigns(:limit)
Chris@1494 73 assert_equal 2, assigns(:offset)
Chris@1494 74 assert_tag :tag => 'issues', :children => {:count => 3, :only => {:tag => 'issue'}}
Chris@1494 75 end
Chris@1494 76 end
Chris@1494 77
Chris@1494 78 context "with nometa param" do
Chris@1494 79 should "not contain metadata" do
Chris@1494 80 get '/issues.xml?nometa=1'
Chris@1494 81
Chris@1494 82 assert_tag :tag => 'issues',
Chris@1494 83 :attributes => {
Chris@1494 84 :type => 'array',
Chris@1494 85 :total_count => nil,
Chris@1494 86 :limit => nil,
Chris@1494 87 :offset => nil
Chris@1494 88 }
Chris@1494 89 end
Chris@1494 90 end
Chris@1494 91
Chris@1494 92 context "with nometa header" do
Chris@1494 93 should "not contain metadata" do
Chris@1494 94 get '/issues.xml', {}, {'X-Redmine-Nometa' => '1'}
Chris@1494 95
Chris@1494 96 assert_tag :tag => 'issues',
Chris@1494 97 :attributes => {
Chris@1494 98 :type => 'array',
Chris@1494 99 :total_count => nil,
Chris@1494 100 :limit => nil,
Chris@1494 101 :offset => nil
Chris@1494 102 }
Chris@1494 103 end
Chris@1494 104 end
Chris@1494 105
Chris@1494 106 context "with relations" do
Chris@1494 107 should "display relations" do
Chris@1494 108 get '/issues.xml?include=relations'
Chris@1494 109
Chris@1494 110 assert_response :success
Chris@1494 111 assert_equal 'application/xml', @response.content_type
Chris@1494 112 assert_tag 'relations',
Chris@1494 113 :parent => {:tag => 'issue', :child => {:tag => 'id', :content => '3'}},
Chris@1494 114 :children => {:count => 1},
Chris@1494 115 :child => {
Chris@1494 116 :tag => 'relation',
Chris@1494 117 :attributes => {:id => '2', :issue_id => '2', :issue_to_id => '3',
Chris@1494 118 :relation_type => 'relates'}
Chris@1494 119 }
Chris@1494 120 assert_tag 'relations',
Chris@1494 121 :parent => {:tag => 'issue', :child => {:tag => 'id', :content => '1'}},
Chris@1494 122 :children => {:count => 0}
Chris@1494 123 end
Chris@1494 124 end
Chris@1494 125
Chris@1494 126 context "with invalid query params" do
Chris@1494 127 should "return errors" do
Chris@1494 128 get '/issues.xml', {:f => ['start_date'], :op => {:start_date => '='}}
Chris@1494 129
Chris@1494 130 assert_response :unprocessable_entity
Chris@1494 131 assert_equal 'application/xml', @response.content_type
Chris@1494 132 assert_tag 'errors', :child => {:tag => 'error', :content => "Start date can't be blank"}
Chris@1494 133 end
Chris@1494 134 end
Chris@1494 135
Chris@1494 136 context "with custom field filter" do
Chris@1494 137 should "show only issues with the custom field value" do
Chris@1494 138 get '/issues.xml',
Chris@1494 139 {:set_filter => 1, :f => ['cf_1'], :op => {:cf_1 => '='},
Chris@1494 140 :v => {:cf_1 => ['MySQL']}}
Chris@1494 141 expected_ids = Issue.visible.
Chris@1494 142 joins(:custom_values).
Chris@1494 143 where(:custom_values => {:custom_field_id => 1, :value => 'MySQL'}).map(&:id)
Chris@1494 144 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
Chris@1494 145 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
Chris@1494 146 end
Chris@1494 147 end
Chris@1494 148 end
Chris@1494 149
Chris@1494 150 context "with custom field filter (shorthand method)" do
Chris@1494 151 should "show only issues with the custom field value" do
Chris@1494 152 get '/issues.xml', { :cf_1 => 'MySQL' }
Chris@1494 153
Chris@1494 154 expected_ids = Issue.visible.
Chris@1494 155 joins(:custom_values).
Chris@1494 156 where(:custom_values => {:custom_field_id => 1, :value => 'MySQL'}).map(&:id)
Chris@1494 157
Chris@1494 158 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
Chris@1494 159 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
Chris@1494 160 end
Chris@1494 161 end
Chris@1494 162 end
Chris@1494 163 end
Chris@1494 164
Chris@1494 165 context "/index.json" do
Chris@1494 166 should_allow_api_authentication(:get, "/projects/private-child/issues.json")
Chris@1494 167 end
Chris@1494 168
Chris@1494 169 context "/index.xml with filter" do
Chris@1494 170 should "show only issues with the status_id" do
Chris@1494 171 get '/issues.xml?status_id=5'
Chris@1494 172
Chris@1494 173 expected_ids = Issue.visible.where(:status_id => 5).map(&:id)
Chris@1494 174
Chris@1494 175 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
Chris@1494 176 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
Chris@1494 177 end
Chris@1494 178 end
Chris@1494 179 end
Chris@1494 180
Chris@1494 181 context "/index.json with filter" do
Chris@1494 182 should "show only issues with the status_id" do
Chris@1494 183 get '/issues.json?status_id=5'
Chris@1494 184
Chris@1494 185 json = ActiveSupport::JSON.decode(response.body)
Chris@1494 186 status_ids_used = json['issues'].collect {|j| j['status']['id'] }
Chris@1494 187 assert_equal 3, status_ids_used.length
Chris@1494 188 assert status_ids_used.all? {|id| id == 5 }
Chris@1494 189 end
Chris@1494 190
Chris@1494 191 end
Chris@1494 192
Chris@1494 193 # Issue 6 is on a private project
Chris@1494 194 context "/issues/6.xml" do
Chris@1494 195 should_allow_api_authentication(:get, "/issues/6.xml")
Chris@1494 196 end
Chris@1494 197
Chris@1494 198 context "/issues/6.json" do
Chris@1494 199 should_allow_api_authentication(:get, "/issues/6.json")
Chris@1494 200 end
Chris@1494 201
Chris@1494 202 context "GET /issues/:id" do
Chris@1494 203 context "with journals" do
Chris@1494 204 context ".xml" do
Chris@1494 205 should "display journals" do
Chris@1494 206 get '/issues/1.xml?include=journals'
Chris@1494 207
Chris@1494 208 assert_tag :tag => 'issue',
Chris@1494 209 :child => {
Chris@1494 210 :tag => 'journals',
Chris@1494 211 :attributes => { :type => 'array' },
Chris@1494 212 :child => {
Chris@1494 213 :tag => 'journal',
Chris@1494 214 :attributes => { :id => '1'},
Chris@1494 215 :child => {
Chris@1494 216 :tag => 'details',
Chris@1494 217 :attributes => { :type => 'array' },
Chris@1494 218 :child => {
Chris@1494 219 :tag => 'detail',
Chris@1494 220 :attributes => { :name => 'status_id' },
Chris@1494 221 :child => {
Chris@1494 222 :tag => 'old_value',
Chris@1494 223 :content => '1',
Chris@1494 224 :sibling => {
Chris@1494 225 :tag => 'new_value',
Chris@1494 226 :content => '2'
Chris@1494 227 }
Chris@1494 228 }
Chris@1494 229 }
Chris@1494 230 }
Chris@1494 231 }
Chris@1494 232 }
Chris@1494 233 end
Chris@1494 234 end
Chris@1494 235 end
Chris@1494 236
Chris@1494 237 context "with custom fields" do
Chris@1494 238 context ".xml" do
Chris@1494 239 should "display custom fields" do
Chris@1494 240 get '/issues/3.xml'
Chris@1494 241
Chris@1494 242 assert_tag :tag => 'issue',
Chris@1494 243 :child => {
Chris@1494 244 :tag => 'custom_fields',
Chris@1494 245 :attributes => { :type => 'array' },
Chris@1494 246 :child => {
Chris@1494 247 :tag => 'custom_field',
Chris@1494 248 :attributes => { :id => '1'},
Chris@1494 249 :child => {
Chris@1494 250 :tag => 'value',
Chris@1494 251 :content => 'MySQL'
Chris@1494 252 }
Chris@1494 253 }
Chris@1494 254 }
Chris@1494 255
Chris@1494 256 assert_nothing_raised do
Chris@1494 257 Hash.from_xml(response.body).to_xml
Chris@1494 258 end
Chris@1494 259 end
Chris@1494 260 end
Chris@1494 261 end
Chris@1494 262
Chris@1494 263 context "with multi custom fields" do
Chris@1494 264 setup do
Chris@1494 265 field = CustomField.find(1)
Chris@1494 266 field.update_attribute :multiple, true
Chris@1494 267 issue = Issue.find(3)
Chris@1494 268 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
Chris@1494 269 issue.save!
Chris@1494 270 end
Chris@1494 271
Chris@1494 272 context ".xml" do
Chris@1494 273 should "display custom fields" do
Chris@1494 274 get '/issues/3.xml'
Chris@1494 275 assert_response :success
Chris@1494 276 assert_tag :tag => 'issue',
Chris@1494 277 :child => {
Chris@1494 278 :tag => 'custom_fields',
Chris@1494 279 :attributes => { :type => 'array' },
Chris@1494 280 :child => {
Chris@1494 281 :tag => 'custom_field',
Chris@1494 282 :attributes => { :id => '1'},
Chris@1494 283 :child => {
Chris@1494 284 :tag => 'value',
Chris@1494 285 :attributes => { :type => 'array' },
Chris@1494 286 :children => { :count => 2 }
Chris@1494 287 }
Chris@1494 288 }
Chris@1494 289 }
Chris@1494 290
Chris@1494 291 xml = Hash.from_xml(response.body)
Chris@1494 292 custom_fields = xml['issue']['custom_fields']
Chris@1494 293 assert_kind_of Array, custom_fields
Chris@1494 294 field = custom_fields.detect {|f| f['id'] == '1'}
Chris@1494 295 assert_kind_of Hash, field
Chris@1494 296 assert_equal ['MySQL', 'Oracle'], field['value'].sort
Chris@1494 297 end
Chris@1494 298 end
Chris@1494 299
Chris@1494 300 context ".json" do
Chris@1494 301 should "display custom fields" do
Chris@1494 302 get '/issues/3.json'
Chris@1494 303 assert_response :success
Chris@1494 304 json = ActiveSupport::JSON.decode(response.body)
Chris@1494 305 custom_fields = json['issue']['custom_fields']
Chris@1494 306 assert_kind_of Array, custom_fields
Chris@1494 307 field = custom_fields.detect {|f| f['id'] == 1}
Chris@1494 308 assert_kind_of Hash, field
Chris@1494 309 assert_equal ['MySQL', 'Oracle'], field['value'].sort
Chris@1494 310 end
Chris@1494 311 end
Chris@1494 312 end
Chris@1494 313
Chris@1494 314 context "with empty value for multi custom field" do
Chris@1494 315 setup do
Chris@1494 316 field = CustomField.find(1)
Chris@1494 317 field.update_attribute :multiple, true
Chris@1494 318 issue = Issue.find(3)
Chris@1494 319 issue.custom_field_values = {1 => ['']}
Chris@1494 320 issue.save!
Chris@1494 321 end
Chris@1494 322
Chris@1494 323 context ".xml" do
Chris@1494 324 should "display custom fields" do
Chris@1494 325 get '/issues/3.xml'
Chris@1494 326 assert_response :success
Chris@1494 327 assert_tag :tag => 'issue',
Chris@1494 328 :child => {
Chris@1494 329 :tag => 'custom_fields',
Chris@1494 330 :attributes => { :type => 'array' },
Chris@1494 331 :child => {
Chris@1494 332 :tag => 'custom_field',
Chris@1494 333 :attributes => { :id => '1'},
Chris@1494 334 :child => {
Chris@1494 335 :tag => 'value',
Chris@1494 336 :attributes => { :type => 'array' },
Chris@1494 337 :children => { :count => 0 }
Chris@1494 338 }
Chris@1494 339 }
Chris@1494 340 }
Chris@1494 341
Chris@1494 342 xml = Hash.from_xml(response.body)
Chris@1494 343 custom_fields = xml['issue']['custom_fields']
Chris@1494 344 assert_kind_of Array, custom_fields
Chris@1494 345 field = custom_fields.detect {|f| f['id'] == '1'}
Chris@1494 346 assert_kind_of Hash, field
Chris@1494 347 assert_equal [], field['value']
Chris@1494 348 end
Chris@1494 349 end
Chris@1494 350
Chris@1494 351 context ".json" do
Chris@1494 352 should "display custom fields" do
Chris@1494 353 get '/issues/3.json'
Chris@1494 354 assert_response :success
Chris@1494 355 json = ActiveSupport::JSON.decode(response.body)
Chris@1494 356 custom_fields = json['issue']['custom_fields']
Chris@1494 357 assert_kind_of Array, custom_fields
Chris@1494 358 field = custom_fields.detect {|f| f['id'] == 1}
Chris@1494 359 assert_kind_of Hash, field
Chris@1494 360 assert_equal [], field['value'].sort
Chris@1494 361 end
Chris@1494 362 end
Chris@1494 363 end
Chris@1494 364
Chris@1494 365 context "with attachments" do
Chris@1494 366 context ".xml" do
Chris@1494 367 should "display attachments" do
Chris@1494 368 get '/issues/3.xml?include=attachments'
Chris@1494 369
Chris@1494 370 assert_tag :tag => 'issue',
Chris@1494 371 :child => {
Chris@1494 372 :tag => 'attachments',
Chris@1494 373 :children => {:count => 5},
Chris@1494 374 :child => {
Chris@1494 375 :tag => 'attachment',
Chris@1494 376 :child => {
Chris@1494 377 :tag => 'filename',
Chris@1494 378 :content => 'source.rb',
Chris@1494 379 :sibling => {
Chris@1494 380 :tag => 'content_url',
Chris@1494 381 :content => 'http://www.example.com/attachments/download/4/source.rb'
Chris@1494 382 }
Chris@1494 383 }
Chris@1494 384 }
Chris@1494 385 }
Chris@1494 386 end
Chris@1494 387 end
Chris@1494 388 end
Chris@1494 389
Chris@1494 390 context "with subtasks" do
Chris@1494 391 setup do
Chris@1494 392 @c1 = Issue.create!(
Chris@1494 393 :status_id => 1, :subject => "child c1",
Chris@1494 394 :tracker_id => 1, :project_id => 1, :author_id => 1,
Chris@1494 395 :parent_issue_id => 1
Chris@1494 396 )
Chris@1494 397 @c2 = Issue.create!(
Chris@1494 398 :status_id => 1, :subject => "child c2",
Chris@1494 399 :tracker_id => 1, :project_id => 1, :author_id => 1,
Chris@1494 400 :parent_issue_id => 1
Chris@1494 401 )
Chris@1494 402 @c3 = Issue.create!(
Chris@1494 403 :status_id => 1, :subject => "child c3",
Chris@1494 404 :tracker_id => 1, :project_id => 1, :author_id => 1,
Chris@1494 405 :parent_issue_id => @c1.id
Chris@1494 406 )
Chris@1494 407 end
Chris@1494 408
Chris@1494 409 context ".xml" do
Chris@1494 410 should "display children" do
Chris@1494 411 get '/issues/1.xml?include=children'
Chris@1494 412
Chris@1494 413 assert_tag :tag => 'issue',
Chris@1494 414 :child => {
Chris@1494 415 :tag => 'children',
Chris@1494 416 :children => {:count => 2},
Chris@1494 417 :child => {
Chris@1494 418 :tag => 'issue',
Chris@1494 419 :attributes => {:id => @c1.id.to_s},
Chris@1494 420 :child => {
Chris@1494 421 :tag => 'subject',
Chris@1494 422 :content => 'child c1',
Chris@1494 423 :sibling => {
Chris@1494 424 :tag => 'children',
Chris@1494 425 :children => {:count => 1},
Chris@1494 426 :child => {
Chris@1494 427 :tag => 'issue',
Chris@1494 428 :attributes => {:id => @c3.id.to_s}
Chris@1494 429 }
Chris@1494 430 }
Chris@1494 431 }
Chris@1494 432 }
Chris@1494 433 }
Chris@1494 434 end
Chris@1494 435
Chris@1494 436 context ".json" do
Chris@1494 437 should "display children" do
Chris@1494 438 get '/issues/1.json?include=children'
Chris@1494 439
Chris@1494 440 json = ActiveSupport::JSON.decode(response.body)
Chris@1494 441 assert_equal([
Chris@1494 442 {
Chris@1494 443 'id' => @c1.id, 'subject' => 'child c1', 'tracker' => {'id' => 1, 'name' => 'Bug'},
Chris@1494 444 'children' => [{'id' => @c3.id, 'subject' => 'child c3',
Chris@1494 445 'tracker' => {'id' => 1, 'name' => 'Bug'} }]
Chris@1494 446 },
Chris@1494 447 { 'id' => @c2.id, 'subject' => 'child c2', 'tracker' => {'id' => 1, 'name' => 'Bug'} }
Chris@1494 448 ],
Chris@1494 449 json['issue']['children'])
Chris@1494 450 end
Chris@1494 451 end
Chris@1494 452 end
Chris@1494 453 end
Chris@1494 454 end
Chris@1494 455
Chris@1494 456 test "GET /issues/:id.xml?include=watchers should include watchers" do
Chris@1494 457 Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
Chris@1494 458
Chris@1494 459 get '/issues/1.xml?include=watchers', {}, credentials('jsmith')
Chris@1494 460
Chris@1494 461 assert_response :ok
Chris@1494 462 assert_equal 'application/xml', response.content_type
Chris@1494 463 assert_select 'issue' do
Chris@1494 464 assert_select 'watchers', Issue.find(1).watchers.count
Chris@1494 465 assert_select 'watchers' do
Chris@1494 466 assert_select 'user[id=3]'
Chris@1494 467 end
Chris@1494 468 end
Chris@1494 469 end
Chris@1494 470
Chris@1494 471 context "POST /issues.xml" do
Chris@1494 472 should_allow_api_authentication(
Chris@1494 473 :post,
Chris@1494 474 '/issues.xml',
Chris@1494 475 {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}},
Chris@1494 476 {:success_code => :created}
Chris@1494 477 )
Chris@1494 478 should "create an issue with the attributes" do
Chris@1494 479 assert_difference('Issue.count') do
Chris@1494 480 post '/issues.xml',
Chris@1494 481 {:issue => {:project_id => 1, :subject => 'API test',
Chris@1494 482 :tracker_id => 2, :status_id => 3}}, credentials('jsmith')
Chris@1494 483 end
Chris@1494 484 issue = Issue.first(:order => 'id DESC')
Chris@1494 485 assert_equal 1, issue.project_id
Chris@1494 486 assert_equal 2, issue.tracker_id
Chris@1494 487 assert_equal 3, issue.status_id
Chris@1494 488 assert_equal 'API test', issue.subject
Chris@1494 489
Chris@1494 490 assert_response :created
Chris@1494 491 assert_equal 'application/xml', @response.content_type
Chris@1494 492 assert_tag 'issue', :child => {:tag => 'id', :content => issue.id.to_s}
Chris@1494 493 end
Chris@1494 494 end
Chris@1494 495
Chris@1494 496 test "POST /issues.xml with watcher_user_ids should create issue with watchers" do
Chris@1494 497 assert_difference('Issue.count') do
Chris@1494 498 post '/issues.xml',
Chris@1494 499 {:issue => {:project_id => 1, :subject => 'Watchers',
Chris@1494 500 :tracker_id => 2, :status_id => 3, :watcher_user_ids => [3, 1]}}, credentials('jsmith')
Chris@1494 501 assert_response :created
Chris@1494 502 end
Chris@1494 503 issue = Issue.order('id desc').first
Chris@1494 504 assert_equal 2, issue.watchers.size
Chris@1494 505 assert_equal [1, 3], issue.watcher_user_ids.sort
Chris@1494 506 end
Chris@1494 507
Chris@1494 508 context "POST /issues.xml with failure" do
Chris@1494 509 should "have an errors tag" do
Chris@1494 510 assert_no_difference('Issue.count') do
Chris@1494 511 post '/issues.xml', {:issue => {:project_id => 1}}, credentials('jsmith')
Chris@1494 512 end
Chris@1494 513
Chris@1494 514 assert_tag :errors, :child => {:tag => 'error', :content => "Subject can't be blank"}
Chris@1494 515 end
Chris@1494 516 end
Chris@1494 517
Chris@1494 518 context "POST /issues.json" do
Chris@1494 519 should_allow_api_authentication(:post,
Chris@1494 520 '/issues.json',
Chris@1494 521 {:issue => {:project_id => 1, :subject => 'API test',
Chris@1494 522 :tracker_id => 2, :status_id => 3}},
Chris@1494 523 {:success_code => :created})
Chris@1494 524
Chris@1494 525 should "create an issue with the attributes" do
Chris@1494 526 assert_difference('Issue.count') do
Chris@1494 527 post '/issues.json',
Chris@1494 528 {:issue => {:project_id => 1, :subject => 'API test',
Chris@1494 529 :tracker_id => 2, :status_id => 3}},
Chris@1494 530 credentials('jsmith')
Chris@1494 531 end
Chris@1494 532
Chris@1494 533 issue = Issue.first(:order => 'id DESC')
Chris@1494 534 assert_equal 1, issue.project_id
Chris@1494 535 assert_equal 2, issue.tracker_id
Chris@1494 536 assert_equal 3, issue.status_id
Chris@1494 537 assert_equal 'API test', issue.subject
Chris@1494 538 end
Chris@1494 539
Chris@1494 540 end
Chris@1494 541
Chris@1494 542 context "POST /issues.json with failure" do
Chris@1494 543 should "have an errors element" do
Chris@1494 544 assert_no_difference('Issue.count') do
Chris@1494 545 post '/issues.json', {:issue => {:project_id => 1}}, credentials('jsmith')
Chris@1494 546 end
Chris@1494 547
Chris@1494 548 json = ActiveSupport::JSON.decode(response.body)
Chris@1494 549 assert json['errors'].include?("Subject can't be blank")
Chris@1494 550 end
Chris@1494 551 end
Chris@1494 552
Chris@1494 553 # Issue 6 is on a private project
Chris@1494 554 context "PUT /issues/6.xml" do
Chris@1494 555 setup do
Chris@1494 556 @parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}}
Chris@1494 557 end
Chris@1494 558
Chris@1494 559 should_allow_api_authentication(:put,
Chris@1494 560 '/issues/6.xml',
Chris@1494 561 {:issue => {:subject => 'API update', :notes => 'A new note'}},
Chris@1494 562 {:success_code => :ok})
Chris@1494 563
Chris@1494 564 should "not create a new issue" do
Chris@1494 565 assert_no_difference('Issue.count') do
Chris@1494 566 put '/issues/6.xml', @parameters, credentials('jsmith')
Chris@1494 567 end
Chris@1494 568 end
Chris@1494 569
Chris@1494 570 should "create a new journal" do
Chris@1494 571 assert_difference('Journal.count') do
Chris@1494 572 put '/issues/6.xml', @parameters, credentials('jsmith')
Chris@1494 573 end
Chris@1494 574 end
Chris@1494 575
Chris@1494 576 should "add the note to the journal" do
Chris@1494 577 put '/issues/6.xml', @parameters, credentials('jsmith')
Chris@1494 578
Chris@1494 579 journal = Journal.last
Chris@1494 580 assert_equal "A new note", journal.notes
Chris@1494 581 end
Chris@1494 582
Chris@1494 583 should "update the issue" do
Chris@1494 584 put '/issues/6.xml', @parameters, credentials('jsmith')
Chris@1494 585
Chris@1494 586 issue = Issue.find(6)
Chris@1494 587 assert_equal "API update", issue.subject
Chris@1494 588 end
Chris@1494 589
Chris@1494 590 end
Chris@1494 591
Chris@1494 592 context "PUT /issues/3.xml with custom fields" do
Chris@1494 593 setup do
Chris@1494 594 @parameters = {
Chris@1494 595 :issue => {:custom_fields => [{'id' => '1', 'value' => 'PostgreSQL' },
Chris@1494 596 {'id' => '2', 'value' => '150'}]}
Chris@1494 597 }
Chris@1494 598 end
Chris@1494 599
Chris@1494 600 should "update custom fields" do
Chris@1494 601 assert_no_difference('Issue.count') do
Chris@1494 602 put '/issues/3.xml', @parameters, credentials('jsmith')
Chris@1494 603 end
Chris@1494 604
Chris@1494 605 issue = Issue.find(3)
Chris@1494 606 assert_equal '150', issue.custom_value_for(2).value
Chris@1494 607 assert_equal 'PostgreSQL', issue.custom_value_for(1).value
Chris@1494 608 end
Chris@1494 609 end
Chris@1494 610
Chris@1494 611 context "PUT /issues/3.xml with multi custom fields" do
Chris@1494 612 setup do
Chris@1494 613 field = CustomField.find(1)
Chris@1494 614 field.update_attribute :multiple, true
Chris@1494 615 @parameters = {
Chris@1494 616 :issue => {:custom_fields => [{'id' => '1', 'value' => ['MySQL', 'PostgreSQL'] },
Chris@1494 617 {'id' => '2', 'value' => '150'}]}
Chris@1494 618 }
Chris@1494 619 end
Chris@1494 620
Chris@1494 621 should "update custom fields" do
Chris@1494 622 assert_no_difference('Issue.count') do
Chris@1494 623 put '/issues/3.xml', @parameters, credentials('jsmith')
Chris@1494 624 end
Chris@1494 625
Chris@1494 626 issue = Issue.find(3)
Chris@1494 627 assert_equal '150', issue.custom_value_for(2).value
Chris@1494 628 assert_equal ['MySQL', 'PostgreSQL'], issue.custom_field_value(1).sort
Chris@1494 629 end
Chris@1494 630 end
Chris@1494 631
Chris@1494 632 context "PUT /issues/3.xml with project change" do
Chris@1494 633 setup do
Chris@1494 634 @parameters = {:issue => {:project_id => 2, :subject => 'Project changed'}}
Chris@1494 635 end
Chris@1494 636
Chris@1494 637 should "update project" do
Chris@1494 638 assert_no_difference('Issue.count') do
Chris@1494 639 put '/issues/3.xml', @parameters, credentials('jsmith')
Chris@1494 640 end
Chris@1494 641
Chris@1494 642 issue = Issue.find(3)
Chris@1494 643 assert_equal 2, issue.project_id
Chris@1494 644 assert_equal 'Project changed', issue.subject
Chris@1494 645 end
Chris@1494 646 end
Chris@1494 647
Chris@1494 648 context "PUT /issues/6.xml with failed update" do
Chris@1494 649 setup do
Chris@1494 650 @parameters = {:issue => {:subject => ''}}
Chris@1494 651 end
Chris@1494 652
Chris@1494 653 should "not create a new issue" do
Chris@1494 654 assert_no_difference('Issue.count') do
Chris@1494 655 put '/issues/6.xml', @parameters, credentials('jsmith')
Chris@1494 656 end
Chris@1494 657 end
Chris@1494 658
Chris@1494 659 should "not create a new journal" do
Chris@1494 660 assert_no_difference('Journal.count') do
Chris@1494 661 put '/issues/6.xml', @parameters, credentials('jsmith')
Chris@1494 662 end
Chris@1494 663 end
Chris@1494 664
Chris@1494 665 should "have an errors tag" do
Chris@1494 666 put '/issues/6.xml', @parameters, credentials('jsmith')
Chris@1494 667
Chris@1494 668 assert_tag :errors, :child => {:tag => 'error', :content => "Subject can't be blank"}
Chris@1494 669 end
Chris@1494 670 end
Chris@1494 671
Chris@1494 672 context "PUT /issues/6.json" do
Chris@1494 673 setup do
Chris@1494 674 @parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}}
Chris@1494 675 end
Chris@1494 676
Chris@1494 677 should_allow_api_authentication(:put,
Chris@1494 678 '/issues/6.json',
Chris@1494 679 {:issue => {:subject => 'API update', :notes => 'A new note'}},
Chris@1494 680 {:success_code => :ok})
Chris@1494 681
Chris@1494 682 should "update the issue" do
Chris@1494 683 assert_no_difference('Issue.count') do
Chris@1494 684 assert_difference('Journal.count') do
Chris@1494 685 put '/issues/6.json', @parameters, credentials('jsmith')
Chris@1494 686
Chris@1494 687 assert_response :ok
Chris@1494 688 assert_equal '', response.body
Chris@1494 689 end
Chris@1494 690 end
Chris@1494 691
Chris@1494 692 issue = Issue.find(6)
Chris@1494 693 assert_equal "API update", issue.subject
Chris@1494 694 journal = Journal.last
Chris@1494 695 assert_equal "A new note", journal.notes
Chris@1494 696 end
Chris@1494 697 end
Chris@1494 698
Chris@1494 699 context "PUT /issues/6.json with failed update" do
Chris@1494 700 should "return errors" do
Chris@1494 701 assert_no_difference('Issue.count') do
Chris@1494 702 assert_no_difference('Journal.count') do
Chris@1494 703 put '/issues/6.json', {:issue => {:subject => ''}}, credentials('jsmith')
Chris@1494 704
Chris@1494 705 assert_response :unprocessable_entity
Chris@1494 706 end
Chris@1494 707 end
Chris@1494 708
Chris@1494 709 json = ActiveSupport::JSON.decode(response.body)
Chris@1494 710 assert json['errors'].include?("Subject can't be blank")
Chris@1494 711 end
Chris@1494 712 end
Chris@1494 713
Chris@1494 714 context "DELETE /issues/1.xml" do
Chris@1494 715 should_allow_api_authentication(:delete,
Chris@1494 716 '/issues/6.xml',
Chris@1494 717 {},
Chris@1494 718 {:success_code => :ok})
Chris@1494 719
Chris@1494 720 should "delete the issue" do
Chris@1494 721 assert_difference('Issue.count', -1) do
Chris@1494 722 delete '/issues/6.xml', {}, credentials('jsmith')
Chris@1494 723
Chris@1494 724 assert_response :ok
Chris@1494 725 assert_equal '', response.body
Chris@1494 726 end
Chris@1494 727
Chris@1494 728 assert_nil Issue.find_by_id(6)
Chris@1494 729 end
Chris@1494 730 end
Chris@1494 731
Chris@1494 732 context "DELETE /issues/1.json" do
Chris@1494 733 should_allow_api_authentication(:delete,
Chris@1494 734 '/issues/6.json',
Chris@1494 735 {},
Chris@1494 736 {:success_code => :ok})
Chris@1494 737
Chris@1494 738 should "delete the issue" do
Chris@1494 739 assert_difference('Issue.count', -1) do
Chris@1494 740 delete '/issues/6.json', {}, credentials('jsmith')
Chris@1494 741
Chris@1494 742 assert_response :ok
Chris@1494 743 assert_equal '', response.body
Chris@1494 744 end
Chris@1494 745
Chris@1494 746 assert_nil Issue.find_by_id(6)
Chris@1494 747 end
Chris@1494 748 end
Chris@1494 749
Chris@1494 750 test "POST /issues/:id/watchers.xml should add watcher" do
Chris@1494 751 assert_difference 'Watcher.count' do
Chris@1494 752 post '/issues/1/watchers.xml', {:user_id => 3}, credentials('jsmith')
Chris@1494 753
Chris@1494 754 assert_response :ok
Chris@1494 755 assert_equal '', response.body
Chris@1494 756 end
Chris@1494 757 watcher = Watcher.order('id desc').first
Chris@1494 758 assert_equal Issue.find(1), watcher.watchable
Chris@1494 759 assert_equal User.find(3), watcher.user
Chris@1494 760 end
Chris@1494 761
Chris@1494 762 test "DELETE /issues/:id/watchers/:user_id.xml should remove watcher" do
Chris@1494 763 Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
Chris@1494 764
Chris@1494 765 assert_difference 'Watcher.count', -1 do
Chris@1494 766 delete '/issues/1/watchers/3.xml', {}, credentials('jsmith')
Chris@1494 767
Chris@1494 768 assert_response :ok
Chris@1494 769 assert_equal '', response.body
Chris@1494 770 end
Chris@1494 771 assert_equal false, Issue.find(1).watched_by?(User.find(3))
Chris@1494 772 end
Chris@1494 773
Chris@1494 774 def test_create_issue_with_uploaded_file
Chris@1494 775 set_tmp_attachments_directory
Chris@1494 776 # upload the file
Chris@1494 777 assert_difference 'Attachment.count' do
Chris@1494 778 post '/uploads.xml', 'test_create_with_upload',
Chris@1494 779 {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
Chris@1494 780 assert_response :created
Chris@1494 781 end
Chris@1494 782 xml = Hash.from_xml(response.body)
Chris@1494 783 token = xml['upload']['token']
Chris@1494 784 attachment = Attachment.first(:order => 'id DESC')
Chris@1494 785
Chris@1494 786 # create the issue with the upload's token
Chris@1494 787 assert_difference 'Issue.count' do
Chris@1494 788 post '/issues.xml',
Chris@1494 789 {:issue => {:project_id => 1, :subject => 'Uploaded file',
Chris@1494 790 :uploads => [{:token => token, :filename => 'test.txt',
Chris@1494 791 :content_type => 'text/plain'}]}},
Chris@1494 792 credentials('jsmith')
Chris@1494 793 assert_response :created
Chris@1494 794 end
Chris@1494 795 issue = Issue.first(:order => 'id DESC')
Chris@1494 796 assert_equal 1, issue.attachments.count
Chris@1494 797 assert_equal attachment, issue.attachments.first
Chris@1494 798
Chris@1494 799 attachment.reload
Chris@1494 800 assert_equal 'test.txt', attachment.filename
Chris@1494 801 assert_equal 'text/plain', attachment.content_type
Chris@1494 802 assert_equal 'test_create_with_upload'.size, attachment.filesize
Chris@1494 803 assert_equal 2, attachment.author_id
Chris@1494 804
Chris@1494 805 # get the issue with its attachments
Chris@1494 806 get "/issues/#{issue.id}.xml", :include => 'attachments'
Chris@1494 807 assert_response :success
Chris@1494 808 xml = Hash.from_xml(response.body)
Chris@1494 809 attachments = xml['issue']['attachments']
Chris@1494 810 assert_kind_of Array, attachments
Chris@1494 811 assert_equal 1, attachments.size
Chris@1494 812 url = attachments.first['content_url']
Chris@1494 813 assert_not_nil url
Chris@1494 814
Chris@1494 815 # download the attachment
Chris@1494 816 get url
Chris@1494 817 assert_response :success
Chris@1494 818 end
Chris@1494 819
Chris@1494 820 def test_update_issue_with_uploaded_file
Chris@1494 821 set_tmp_attachments_directory
Chris@1494 822 # upload the file
Chris@1494 823 assert_difference 'Attachment.count' do
Chris@1494 824 post '/uploads.xml', 'test_upload_with_upload',
Chris@1494 825 {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
Chris@1494 826 assert_response :created
Chris@1494 827 end
Chris@1494 828 xml = Hash.from_xml(response.body)
Chris@1494 829 token = xml['upload']['token']
Chris@1494 830 attachment = Attachment.first(:order => 'id DESC')
Chris@1494 831
Chris@1494 832 # update the issue with the upload's token
Chris@1494 833 assert_difference 'Journal.count' do
Chris@1494 834 put '/issues/1.xml',
Chris@1494 835 {:issue => {:notes => 'Attachment added',
Chris@1494 836 :uploads => [{:token => token, :filename => 'test.txt',
Chris@1494 837 :content_type => 'text/plain'}]}},
Chris@1494 838 credentials('jsmith')
Chris@1494 839 assert_response :ok
Chris@1494 840 assert_equal '', @response.body
Chris@1494 841 end
Chris@1494 842
Chris@1494 843 issue = Issue.find(1)
Chris@1494 844 assert_include attachment, issue.attachments
Chris@1494 845 end
Chris@1494 846 end