base_test.rb 30.8 KB
Newer Older
1
require 'abstract_unit'
2
require "fixtures/person"
3
require "fixtures/customer"
4
require "fixtures/street_address"
5
require "fixtures/beast"
6 7 8

class BaseTest < Test::Unit::TestCase
  def setup
9 10
    @matz  = { :id => 1, :name => 'Matz' }.to_xml(:root => 'person')
    @david = { :id => 2, :name => 'David' }.to_xml(:root => 'person')
11
    @greg  = { :id => 3, :name => 'Greg' }.to_xml(:root => 'person')
12
    @addy  = { :id => 1, :street => '12345 Street' }.to_xml(:root => 'address')
13
    @default_request_headers = { 'Content-Type' => 'application/xml' }
14 15 16 17
    @rick = { :name => "Rick", :age => 25 }.to_xml(:root => "person")
    @people = [{ :id => 1, :name => 'Matz' }, { :id => 2, :name => 'David' }].to_xml(:root => 'people')
    @people_david = [{ :id => 2, :name => 'David' }].to_xml(:root => 'people')
    @addresses = [{ :id => 1, :street => '12345 Street' }].to_xml(:root => 'addresses')
18

19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
    # - deep nested resource -
    # - Luis (Customer)
    #   - JK (Customer::Friend)
    #     - Mateo (Customer::Friend::Brother)
    #       - Edith (Customer::Friend::Brother::Child)
    #       - Martha (Customer::Friend::Brother::Child)
    #     - Felipe (Customer::Friend::Brother)
    #       - Bryan (Customer::Friend::Brother::Child)
    #       - Luke (Customer::Friend::Brother::Child)
    #   - Eduardo (Customer::Friend)
    #     - Sebas (Customer::Friend::Brother)
    #       - Andres (Customer::Friend::Brother::Child)
    #       - Jorge (Customer::Friend::Brother::Child)
    #     - Elsa (Customer::Friend::Brother)
    #       - Natacha (Customer::Friend::Brother::Child)
    #     - Milena (Customer::Friend::Brother)
    #
    @luis = {:id => 1, :name => 'Luis',
              :friends => [{:name => 'JK',
                            :brothers => [{:name => 'Mateo',
                                           :children => [{:name => 'Edith'},{:name => 'Martha'}]},
                                          {:name => 'Felipe',
                                           :children => [{:name => 'Bryan'},{:name => 'Luke'}]}]},
                           {:name => 'Eduardo',
                            :brothers => [{:name => 'Sebas',
                                           :children => [{:name => 'Andres'},{:name => 'Jorge'}]},
                                          {:name => 'Elsa',
                                           :children => [{:name => 'Natacha'}]},
                                          {:name => 'Milena',
                                           :children => []}]}]}.to_xml(:root => 'customer')
49
    # - resource with yaml array of strings; for ActiveRecords using serialize :bar, Array
50
    @marty = <<-eof.strip
51 52 53 54 55 56 57 58 59 60 61
      <?xml version=\"1.0\" encoding=\"UTF-8\"?>
      <person>
        <id type=\"integer\">5</id>
        <name>Marty</name>
        <colors type=\"yaml\">---
      - \"red\"
      - \"green\"
      - \"blue\"
      </colors>
      </person>
    eof
62

63
    ActiveResource::HttpMock.respond_to do |mock|
64 65
      mock.get    "/people/1.xml",                {}, @matz
      mock.get    "/people/2.xml",                {}, @david
66
      mock.get    "/people/5.xml",                {}, @marty
67
      mock.get    "/people/Greg.xml",             {}, @greg
68 69 70 71 72 73 74 75 76 77 78
      mock.get    "/people/4.xml",                {'key' => 'value'}, nil, 404
      mock.put    "/people/1.xml",                {}, nil, 204
      mock.delete "/people/1.xml",                {}, nil, 200
      mock.delete "/people/2.xml",                {}, nil, 400
      mock.get    "/people/99.xml",               {}, nil, 404
      mock.post   "/people.xml",                  {}, @rick, 201, 'Location' => '/people/5.xml'
      mock.get    "/people.xml",                  {}, @people
      mock.get    "/people/1/addresses.xml",      {}, @addresses
      mock.get    "/people/1/addresses/1.xml",    {}, @addy
      mock.get    "/people/1/addresses/2.xml",    {}, nil, 404
      mock.get    "/people/2/addresses/1.xml",    {}, nil, 404
79
      mock.get    "/people/Greg/addresses/1.xml", {}, @addy
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
      mock.put    "/people/1/addresses/1.xml",    {}, nil, 204
      mock.delete "/people/1/addresses/1.xml",    {}, nil, 200
      mock.post   "/people/1/addresses.xml",      {}, nil, 201, 'Location' => '/people/1/addresses/5'
      mock.get    "/people//addresses.xml",       {}, nil, 404
      mock.get    "/people//addresses/1.xml",     {}, nil, 404
      mock.put    "/people//addresses/1.xml",     {}, nil, 404
      mock.delete "/people//addresses/1.xml",     {}, nil, 404
      mock.post   "/people//addresses.xml",       {}, nil, 404
      mock.head   "/people/1.xml",                {}, nil, 200
      mock.head   "/people/Greg.xml",             {}, nil, 200
      mock.head   "/people/99.xml",               {}, nil, 404
      mock.head   "/people/1/addresses/1.xml",    {}, nil, 200
      mock.head   "/people/1/addresses/2.xml",    {}, nil, 404
      mock.head   "/people/2/addresses/1.xml",    {}, nil, 404
      mock.head   "/people/Greg/addresses/1.xml", {}, nil, 200
95 96
      # customer
      mock.get    "/customers/1.xml",             {}, @luis
97
    end
98 99 100

    Person.user = nil
    Person.password = nil
101 102
  end

J
Jeremy Kemper 已提交
103 104 105 106 107 108 109 110 111 112 113

  def test_site_accessor_accepts_uri_or_string_argument
    site = URI.parse('http://localhost')

    assert_nothing_raised { Person.site = 'http://localhost' }
    assert_equal site, Person.site

    assert_nothing_raised { Person.site = site }
    assert_equal site, Person.site
  end

114 115 116 117
  def test_should_use_site_prefix_and_credentials
    assert_equal 'http://foo:bar@beast.caboo.se', Forum.site.to_s
    assert_equal 'http://foo:bar@beast.caboo.se/forums/:forum_id', Topic.site.to_s
  end
118

119
  def test_site_variable_can_be_reset
120
    actor = Class.new(ActiveResource::Base)
121 122 123
    assert_nil actor.site
    actor.site = 'http://localhost:31337'
    actor.site = nil
124
    assert_nil actor.site
125
  end
126

127 128 129 130 131 132 133 134 135 136 137 138
  def test_should_accept_setting_user
    Forum.user = 'david'
    assert_equal('david', Forum.user)
    assert_equal('david', Forum.connection.user)
  end

  def test_should_accept_setting_password
    Forum.password = 'test123'
    assert_equal('test123', Forum.password)
    assert_equal('test123', Forum.connection.password)
  end

139 140 141 142 143 144
  def test_should_accept_setting_timeout
    Forum.timeout = 5
    assert_equal(5, Forum.timeout)
    assert_equal(5, Forum.connection.timeout)
  end

145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
  def test_user_variable_can_be_reset
    actor = Class.new(ActiveResource::Base)
    actor.site = 'http://cinema'
    assert_nil actor.user
    actor.user = 'username'
    actor.user = nil
    assert_nil actor.user
    assert_nil actor.connection.user
  end

  def test_password_variable_can_be_reset
    actor = Class.new(ActiveResource::Base)
    actor.site = 'http://cinema'
    assert_nil actor.password
    actor.password = 'username'
    actor.password = nil
    assert_nil actor.password
    assert_nil actor.connection.password
  end

165 166 167 168 169 170 171 172 173 174
  def test_timeout_variable_can_be_reset
    actor = Class.new(ActiveResource::Base)
    actor.site = 'http://cinema'
    assert_nil actor.timeout
    actor.timeout = 5
    actor.timeout = nil
    assert_nil actor.timeout
    assert_nil actor.connection.timeout
  end

175 176 177 178 179 180 181
  def test_credentials_from_site_are_decoded
    actor = Class.new(ActiveResource::Base)
    actor.site = 'http://my%40email.com:%31%32%33@cinema'
    assert_equal("my@email.com", actor.user)
    assert_equal("123", actor.password)
  end

182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
  def test_site_reader_uses_superclass_site_until_written
    # Superclass is Object so returns nil.
    assert_nil ActiveResource::Base.site
    assert_nil Class.new(ActiveResource::Base).site

    # Subclass uses superclass site.
    actor = Class.new(Person)
    assert_equal Person.site, actor.site

    # Subclass returns frozen superclass copy.
    assert !Person.site.frozen?
    assert actor.site.frozen?

    # Changing subclass site doesn't change superclass site.
    actor.site = 'http://localhost:31337'
    assert_not_equal Person.site, actor.site

    # Changed subclass site is not frozen.
    assert !actor.site.frozen?

    # Changing superclass site doesn't overwrite subclass site.
    Person.site = 'http://somewhere.else'
    assert_not_equal Person.site, actor.site

    # Changing superclass site after subclassing changes subclass site.
    jester = Class.new(actor)
    actor.site = 'http://nomad'
    assert_equal actor.site, jester.site
    assert jester.site.frozen?
211 212

    # Subclasses are always equal to superclass site when not overridden
213 214
    fruit = Class.new(ActiveResource::Base)
    apple = Class.new(fruit)
215

216
    fruit.site = 'http://market'
217
    assert_equal fruit.site, apple.site, 'subclass did not adopt changes from parent class'
218

219
    fruit.site = 'http://supermarket'
220
    assert_equal fruit.site, apple.site, 'subclass did not adopt changes from parent class'
221
  end
222

223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
  def test_user_reader_uses_superclass_user_until_written
    # Superclass is Object so returns nil.
    assert_nil ActiveResource::Base.user
    assert_nil Class.new(ActiveResource::Base).user
    Person.user = 'anonymous'

    # Subclass uses superclass user.
    actor = Class.new(Person)
    assert_equal Person.user, actor.user

    # Subclass returns frozen superclass copy.
    assert !Person.user.frozen?
    assert actor.user.frozen?

    # Changing subclass user doesn't change superclass user.
    actor.user = 'david'
    assert_not_equal Person.user, actor.user

    # Changing superclass user doesn't overwrite subclass user.
    Person.user = 'john'
    assert_not_equal Person.user, actor.user

    # Changing superclass user after subclassing changes subclass user.
    jester = Class.new(actor)
    actor.user = 'john.doe'
    assert_equal actor.user, jester.user

    # Subclasses are always equal to superclass user when not overridden
    fruit = Class.new(ActiveResource::Base)
    apple = Class.new(fruit)

    fruit.user = 'manager'
    assert_equal fruit.user, apple.user, 'subclass did not adopt changes from parent class'

    fruit.user = 'client'
    assert_equal fruit.user, apple.user, 'subclass did not adopt changes from parent class'
  end

  def test_password_reader_uses_superclass_password_until_written
    # Superclass is Object so returns nil.
    assert_nil ActiveResource::Base.password
    assert_nil Class.new(ActiveResource::Base).password
    Person.password = 'my-password'

    # Subclass uses superclass password.
    actor = Class.new(Person)
    assert_equal Person.password, actor.password

    # Subclass returns frozen superclass copy.
    assert !Person.password.frozen?
    assert actor.password.frozen?

    # Changing subclass password doesn't change superclass password.
    actor.password = 'secret'
    assert_not_equal Person.password, actor.password

    # Changing superclass password doesn't overwrite subclass password.
    Person.password = 'super-secret'
    assert_not_equal Person.password, actor.password

    # Changing superclass password after subclassing changes subclass password.
    jester = Class.new(actor)
    actor.password = 'even-more-secret'
    assert_equal actor.password, jester.password

    # Subclasses are always equal to superclass password when not overridden
    fruit = Class.new(ActiveResource::Base)
    apple = Class.new(fruit)

    fruit.password = 'mega-secret'
    assert_equal fruit.password, apple.password, 'subclass did not adopt changes from parent class'

    fruit.password = 'ok-password'
    assert_equal fruit.password, apple.password, 'subclass did not adopt changes from parent class'
  end

299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
  def test_timeout_reader_uses_superclass_timeout_until_written
    # Superclass is Object so returns nil.
    assert_nil ActiveResource::Base.timeout
    assert_nil Class.new(ActiveResource::Base).timeout
    Person.timeout = 5

    # Subclass uses superclass timeout.
    actor = Class.new(Person)
    assert_equal Person.timeout, actor.timeout

    # Changing subclass timeout doesn't change superclass timeout.
    actor.timeout = 10
    assert_not_equal Person.timeout, actor.timeout

    # Changing superclass timeout doesn't overwrite subclass timeout.
    Person.timeout = 15
    assert_not_equal Person.timeout, actor.timeout

    # Changing superclass timeout after subclassing changes subclass timeout.
    jester = Class.new(actor)
    actor.timeout = 20
    assert_equal actor.timeout, jester.timeout

    # Subclasses are always equal to superclass timeout when not overridden.
    fruit = Class.new(ActiveResource::Base)
    apple = Class.new(fruit)

    fruit.timeout = 25
    assert_equal fruit.timeout, apple.timeout, 'subclass did not adopt changes from parent class'

    fruit.timeout = 30
    assert_equal fruit.timeout, apple.timeout, 'subclass did not adopt changes from parent class'
  end

333
  def test_updating_baseclass_site_object_wipes_descendent_cached_connection_objects
334
    # Subclasses are always equal to superclass site when not overridden
335 336
    fruit = Class.new(ActiveResource::Base)
    apple = Class.new(fruit)
337

338 339
    fruit.site = 'http://market'
    assert_equal fruit.connection.site, apple.connection.site
340
    first_connection = apple.connection.object_id
341

342
    fruit.site = 'http://supermarket'
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
    assert_equal fruit.connection.site, apple.connection.site
    second_connection = apple.connection.object_id
    assert_not_equal(first_connection, second_connection, 'Connection should be re-created')
  end

  def test_updating_baseclass_user_wipes_descendent_cached_connection_objects
    # Subclasses are always equal to superclass user when not overridden
    fruit = Class.new(ActiveResource::Base)
    apple = Class.new(fruit)
    fruit.site = 'http://market'

    fruit.user = 'david'
    assert_equal fruit.connection.user, apple.connection.user
    first_connection = apple.connection.object_id

    fruit.user = 'john'
    assert_equal fruit.connection.user, apple.connection.user
    second_connection = apple.connection.object_id
    assert_not_equal(first_connection, second_connection, 'Connection should be re-created')
  end

  def test_updating_baseclass_password_wipes_descendent_cached_connection_objects
    # Subclasses are always equal to superclass password when not overridden
    fruit = Class.new(ActiveResource::Base)
    apple = Class.new(fruit)
    fruit.site = 'http://market'

    fruit.password = 'secret'
    assert_equal fruit.connection.password, apple.connection.password
    first_connection = apple.connection.object_id

    fruit.password = 'supersecret'
    assert_equal fruit.connection.password, apple.connection.password
    second_connection = apple.connection.object_id
    assert_not_equal(first_connection, second_connection, 'Connection should be re-created')
378
  end
J
Jeremy Kemper 已提交
379

380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
  def test_updating_baseclass_timeout_wipes_descendent_cached_connection_objects
    # Subclasses are always equal to superclass timeout when not overridden
    fruit = Class.new(ActiveResource::Base)
    apple = Class.new(fruit)
    fruit.site = 'http://market'

    fruit.timeout = 5
    assert_equal fruit.connection.timeout, apple.connection.timeout
    first_connection = apple.connection.object_id

    fruit.timeout = 10
    assert_equal fruit.connection.timeout, apple.connection.timeout
    second_connection = apple.connection.object_id
    assert_not_equal(first_connection, second_connection, 'Connection should be re-created')
  end

396 397 398 399
  def test_collection_name
    assert_equal "people", Person.collection_name
  end

400 401 402 403
  def test_collection_path
    assert_equal '/people.xml', Person.collection_path
  end

404 405 406 407 408 409
  def test_collection_path_with_parameters
    assert_equal '/people.xml?gender=male', Person.collection_path(:gender => 'male')
    assert_equal '/people.xml?gender=false', Person.collection_path(:gender => false)
    assert_equal '/people.xml?gender=', Person.collection_path(:gender => nil)

    assert_equal '/people.xml?gender=male', Person.collection_path('gender' => 'male')
410

411 412 413 414
    # Use includes? because ordering of param hash is not guaranteed
    assert Person.collection_path(:gender => 'male', :student => true).include?('/people.xml?')
    assert Person.collection_path(:gender => 'male', :student => true).include?('gender=male')
    assert Person.collection_path(:gender => 'male', :student => true).include?('student=true')
415

416
    assert_equal '/people.xml?name%5B%5D=bob&name%5B%5D=your+uncle%2Bme&name%5B%5D=&name%5B%5D=false', Person.collection_path(:name => ['bob', 'your uncle+me', nil, false])
417

418
    assert_equal '/people.xml?struct%5Ba%5D%5B%5D=2&struct%5Ba%5D%5B%5D=1&struct%5Bb%5D=fred', Person.collection_path(:struct => {:a => [2,1], 'b' => 'fred'})
419 420
  end

421 422
  def test_custom_element_path
    assert_equal '/people/1/addresses/1.xml', StreetAddress.element_path(1, :person_id => 1)
423
    assert_equal '/people/1/addresses/1.xml', StreetAddress.element_path(1, 'person_id' => 1)
424
    assert_equal '/people/Greg/addresses/1.xml', StreetAddress.element_path(1, 'person_id' => 'Greg')
425
  end
426

427 428 429
  def test_custom_element_path_with_redefined_to_param
    Person.module_eval do
      alias_method :original_to_param_element_path, :to_param
430
       def to_param
431 432 433 434 435 436
         name
       end
    end

    # Class method.
    assert_equal '/people/Greg.xml', Person.element_path('Greg')
437

438 439 440 441 442 443 444 445 446 447
    # Protected Instance method.
    assert_equal '/people/Greg.xml', Person.find('Greg').send(:element_path)

    ensure
      # revert back to original
      Person.module_eval do
        # save the 'new' to_param so we don't get a warning about discarding the method
        alias_method :element_path_to_param, :to_param
        alias_method :to_param, :original_to_param_element_path
      end
448 449
  end

450 451
  def test_custom_element_path_with_parameters
    assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, :person_id => 1, :type => 'work')
452
    assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, 'person_id' => 1, :type => 'work')
453 454
    assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, :type => 'work', :person_id => 1)
    assert_equal '/people/1/addresses/1.xml?type%5B%5D=work&type%5B%5D=play+time', StreetAddress.element_path(1, :person_id => 1, :type => ['work', 'play time'])
455 456
  end

457 458 459 460
  def test_custom_element_path_with_prefix_and_parameters
    assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, {:person_id => 1}, {:type => 'work'})
  end

461 462
  def test_custom_collection_path
    assert_equal '/people/1/addresses.xml', StreetAddress.collection_path(:person_id => 1)
463
    assert_equal '/people/1/addresses.xml', StreetAddress.collection_path('person_id' => 1)
464 465
  end

466 467
  def test_custom_collection_path_with_parameters
    assert_equal '/people/1/addresses.xml?type=work', StreetAddress.collection_path(:person_id => 1, :type => 'work')
468
    assert_equal '/people/1/addresses.xml?type=work', StreetAddress.collection_path('person_id' => 1, :type => 'work')
469 470
  end

471 472 473 474
  def test_custom_collection_path_with_prefix_and_parameters
    assert_equal '/people/1/addresses.xml?type=work', StreetAddress.collection_path({:person_id => 1}, {:type => 'work'})
  end

475 476 477 478 479 480 481 482 483 484
  def test_custom_element_name
    assert_equal 'address', StreetAddress.element_name
  end

  def test_custom_collection_name
    assert_equal 'addresses', StreetAddress.collection_name
  end

  def test_prefix
    assert_equal "/", Person.prefix
485
    assert_equal Set.new, Person.__send__(:prefix_parameters)
486
  end
487

488 489 490 491 492 493
  def test_set_prefix
    SetterTrap.rollback_sets(Person) do |person_class|
      person_class.prefix = "the_prefix"
      assert_equal "the_prefix", person_class.prefix
    end
  end
494

495 496 497 498 499 500
  def test_set_prefix_with_inline_keys
    SetterTrap.rollback_sets(Person) do |person_class|
      person_class.prefix = "the_prefix:the_param"
      assert_equal "the_prefixthe_param_value", person_class.prefix(:the_param => "the_param_value")
    end
  end
501

502 503 504 505 506 507 508 509 510
  def test_set_prefix_twice_should_clear_params
    SetterTrap.rollback_sets(Person) do |person_class|
      person_class.prefix = "the_prefix/:the_param1"
      assert_equal Set.new([:the_param1]), person_class.prefix_parameters
      person_class.prefix = "the_prefix/:the_param2"
      assert_equal Set.new([:the_param2]), person_class.prefix_parameters
    end
  end

511 512 513 514 515 516
  def test_set_prefix_with_default_value
    SetterTrap.rollback_sets(Person) do |person_class|
      person_class.set_prefix
      assert_equal "/", person_class.prefix
    end
  end
517 518 519 520

  def test_custom_prefix
    assert_equal '/people//', StreetAddress.prefix
    assert_equal '/people/1/', StreetAddress.prefix(:person_id => 1)
521
    assert_equal [:person_id].to_set, StreetAddress.__send__(:prefix_parameters)
522 523
  end

524 525 526 527
  def test_find_by_id
    matz = Person.find(1)
    assert_kind_of Person, matz
    assert_equal "Matz", matz.name
T
 
Tobias Lütke 已提交
528
    assert matz.name?
529
  end
530

531 532 533 534 535
  def test_respond_to
    matz = Person.find(1)
    assert matz.respond_to?(:name)
    assert matz.respond_to?(:name=)
    assert matz.respond_to?(:name?)
536
    assert !matz.respond_to?(:super_scalable_stuff)
537
  end
538

539
  def test_find_by_id_with_custom_prefix
540
    addy = StreetAddress.find(1, :params => { :person_id => 1 })
541 542 543 544
    assert_kind_of StreetAddress, addy
    assert_equal '12345 Street', addy.street
  end

545 546 547 548 549 550 551 552 553 554 555 556 557 558
  def test_find_all
    all = Person.find(:all)
    assert_equal 2, all.size
    assert_kind_of Person, all.first
    assert_equal "Matz", all.first.name
    assert_equal "David", all.last.name
  end

  def test_find_first
    matz = Person.find(:first)
    assert_kind_of Person, matz
    assert_equal "Matz", matz.name
  end

559 560 561 562 563 564
  def test_find_last
    david = Person.find(:last)
    assert_kind_of Person, david
    assert_equal 'David', david.name
  end

565
  def test_custom_header
566
    Person.headers['key'] = 'value'
567
    assert_raise(ActiveResource::ResourceNotFound) { Person.find(4) }
568
  ensure
569
    Person.headers.delete('key')
570 571
  end

572
  def test_find_by_id_not_found
573 574
    assert_raise(ActiveResource::ResourceNotFound) { Person.find(99) }
    assert_raise(ActiveResource::ResourceNotFound) { StreetAddress.find(1) }
575 576
  end

577
  def test_find_all_by_from
578
    ActiveResource::HttpMock.respond_to { |m| m.get "/companies/1/people.xml", {}, @people_david }
579

580 581 582 583 584
    people = Person.find(:all, :from => "/companies/1/people.xml")
    assert_equal 1, people.size
    assert_equal "David", people.first.name
  end

585
  def test_find_all_by_from_with_options
586
    ActiveResource::HttpMock.respond_to { |m| m.get "/companies/1/people.xml", {}, @people_david }
587

588 589 590 591 592 593
    people = Person.find(:all, :from => "/companies/1/people.xml")
    assert_equal 1, people.size
    assert_equal "David", people.first.name
  end

  def test_find_all_by_symbol_from
594
    ActiveResource::HttpMock.respond_to { |m| m.get "/people/managers.xml", {}, @people_david }
595

596 597 598 599 600
    people = Person.find(:all, :from => :managers)
    assert_equal 1, people.size
    assert_equal "David", people.first.name
  end

601 602 603
  def test_find_single_by_from
    ActiveResource::HttpMock.respond_to { |m| m.get "/companies/1/manager.xml", {}, @david }

604 605 606 607 608 609 610 611
    david = Person.find(:one, :from => "/companies/1/manager.xml")
    assert_equal "David", david.name
  end

  def test_find_single_by_symbol_from
    ActiveResource::HttpMock.respond_to { |m| m.get "/people/leader.xml", {}, @david }

    david = Person.find(:one, :from => :leader)
612 613 614
    assert_equal "David", david.name
  end

615
  def test_save
616
    rick = Person.new
617
    assert_equal true, rick.save
618 619 620
    assert_equal '5', rick.id
  end

621 622 623
  def test_id_from_response
    p = Person.new
    resp = {'Location' => '/foo/bar/1'}
624
    assert_equal '1', p.__send__(:id_from_response, resp)
625

626
    resp['Location'] << '.xml'
627
    assert_equal '1', p.__send__(:id_from_response, resp)
628 629
  end

630 631 632 633 634 635
  def test_id_from_response_without_location
    p = Person.new
    resp = {}
    assert_equal nil, p.__send__(:id_from_response, resp)
  end

636
  def test_create_with_custom_prefix
637
    matzs_house = StreetAddress.new(:person_id => 1)
638 639
    matzs_house.save
    assert_equal '5', matzs_house.id
640
  end
641

642 643
  # Test that loading a resource preserves its prefix_options.
  def test_load_preserves_prefix_options
644
    address = StreetAddress.find(1, :params => { :person_id => 1 })
645 646 647
    ryan = Person.new(:id => 1, :name => 'Ryan', :address => address)
    assert_equal address.prefix_options, ryan.address.prefix_options
  end
648

649 650 651 652
  def test_reload_works_with_prefix_options
    address = StreetAddress.find(1, :params => { :person_id => 1 })
    assert_equal address, address.reload
  end
653

654 655 656
  def test_reload_with_redefined_to_param
    Person.module_eval do
      alias_method :original_to_param_reload, :to_param
657
       def to_param
658 659 660 661 662 663 664 665 666 667 668 669 670 671
         name
       end
    end

    person = Person.find('Greg')
    assert_equal person, person.reload

    ensure
      # revert back to original
      Person.module_eval do
        # save the 'new' to_param so we don't get a warning about discarding the method
        alias_method :reload_to_param, :to_param
        alias_method :to_param, :original_to_param_reload
      end
672 673 674
  end

  def test_reload_works_without_prefix_options
675 676 677
    person = Person.find(:first)
    assert_equal person, person.reload
  end
678

679 680 681 682 683
  def test_create
    rick = Person.create(:name => 'Rick')
    assert rick.valid?
    assert !rick.new?
    assert_equal '5', rick.id
684 685 686

    # test additional attribute returned on create
    assert_equal 25, rick.age
687

688 689 690
    # Test that save exceptions get bubbled up too
    ActiveResource::HttpMock.respond_to do |mock|
      mock.post   "/people.xml", {}, nil, 409
691
    end
692
    assert_raise(ActiveResource::ResourceConflict) { Person.create(:name => 'Rick') }
693 694
  end

695 696 697 698 699 700 701 702
  def test_create_without_location
    ActiveResource::HttpMock.respond_to do |mock|
      mock.post   "/people.xml", {}, nil, 201
    end
    person = Person.create(:name => 'Rick')
    assert_equal nil, person.id
  end

703
  def test_clone
J
Jeremy Kemper 已提交
704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
    matz = Person.find(1)
    matz_c = matz.clone
    assert matz_c.new?
    matz.attributes.each do |k, v|
      assert_equal v, matz_c.send(k) if k != Person.primary_key
    end
  end

  def test_nested_clone
    addy = StreetAddress.find(1, :params => {:person_id => 1})
    addy_c = addy.clone
    assert addy_c.new?
    addy.attributes.each do |k, v|
      assert_equal v, addy_c.send(k) if k != StreetAddress.primary_key
    end
    assert_equal addy.prefix_options, addy_c.prefix_options
  end

  def test_complex_clone
    matz = Person.find(1)
    matz.address = StreetAddress.find(1, :params => {:person_id => matz.id})
    matz.non_ar_hash = {:not => "an ARes instance"}
    matz.non_ar_arr = ["not", "ARes"]
    matz_c = matz.clone
    assert matz_c.new?
729
    assert_raise(NoMethodError) {matz_c.address}
J
Jeremy Kemper 已提交
730 731 732 733 734 735 736
    assert_equal matz.non_ar_hash, matz_c.non_ar_hash
    assert_equal matz.non_ar_arr, matz_c.non_ar_arr

    # Test that actual copy, not just reference copy
    matz.non_ar_hash[:not] = "changed"
    assert_not_equal matz.non_ar_hash, matz_c.non_ar_hash
  end
737

738 739 740 741 742
  def test_update
    matz = Person.find(:first)
    matz.name = "David"
    assert_kind_of Person, matz
    assert_equal "David", matz.name
743
    assert_equal true, matz.save
744
  end
745

746
  def test_update_with_custom_prefix_with_specific_id
747
    addy = StreetAddress.find(1, :params => { :person_id => 1 })
748 749 750 751 752 753
    addy.street = "54321 Street"
    assert_kind_of StreetAddress, addy
    assert_equal "54321 Street", addy.street
    addy.save
  end

754 755 756 757 758 759 760
  def test_update_with_custom_prefix_without_specific_id
    addy = StreetAddress.find(:first, :params => { :person_id => 1 })
    addy.street = "54321 Lane"
    assert_kind_of StreetAddress, addy
    assert_equal "54321 Lane", addy.street
    addy.save
  end
761

762 763
  def test_update_conflict
    ActiveResource::HttpMock.respond_to do |mock|
764 765
      mock.get "/people/2.xml", {}, @david
      mock.put "/people/2.xml", @default_request_headers, nil, 409
766
    end
767
    assert_raise(ActiveResource::ResourceConflict) { Person.find(2).save }
768 769
  end

770 771
  def test_destroy
    assert Person.find(1).destroy
772
    ActiveResource::HttpMock.respond_to do |mock|
773
      mock.get "/people/1.xml", {}, nil, 404
774
    end
775
    assert_raise(ActiveResource::ResourceNotFound) { Person.find(1).destroy }
776 777 778
  end

  def test_destroy_with_custom_prefix
779
    assert StreetAddress.find(1, :params => { :person_id => 1 }).destroy
780
    ActiveResource::HttpMock.respond_to do |mock|
781
      mock.get "/people/1/addresses/1.xml", {}, nil, 404
782
    end
783
    assert_raise(ActiveResource::ResourceNotFound) { StreetAddress.find(1, :params => { :person_id => 1 }) }
784
  end
785 786 787

  def test_delete
    assert Person.delete(1)
788 789 790
    ActiveResource::HttpMock.respond_to do |mock|
      mock.get "/people/1.xml", {}, nil, 404
    end
791
    assert_raise(ActiveResource::ResourceNotFound) { Person.find(1) }
792
  end
793

794 795 796 797 798
  def test_delete_with_custom_prefix
    assert StreetAddress.delete(1, :person_id => 1)
    ActiveResource::HttpMock.respond_to do |mock|
      mock.get "/people/1/addresses/1.xml", {}, nil, 404
    end
799
    assert_raise(ActiveResource::ResourceNotFound) { StreetAddress.find(1, :params => { :person_id => 1 }) }
800
  end
801 802 803 804 805 806 807 808 809 810 811 812 813

  def test_exists
    # Class method.
    assert !Person.exists?(nil)
    assert Person.exists?(1)
    assert !Person.exists?(99)

    # Instance method.
    assert !Person.new.exists?
    assert Person.find(1).exists?
    assert !Person.new(:id => 99).exists?

    # Nested class method.
814 815 816
    assert StreetAddress.exists?(1,  :params => { :person_id => 1 })
    assert !StreetAddress.exists?(1, :params => { :person_id => 2 })
    assert !StreetAddress.exists?(2, :params => { :person_id => 1 })
817 818

    # Nested instance method.
819
    assert StreetAddress.find(1, :params => { :person_id => 1 }).exists?
820 821
    assert !StreetAddress.new({:id => 1, :person_id => 2}).exists?
    assert !StreetAddress.new({:id => 2, :person_id => 1}).exists?
822
  end
823

824 825 826
  def test_exists_with_redefined_to_param
    Person.module_eval do
      alias_method :original_to_param_exists, :to_param
J
Jeremy Kemper 已提交
827 828 829
      def to_param
        name
      end
830 831 832
    end

    # Class method.
833
    assert Person.exists?('Greg')
834 835

    # Instance method.
836
    assert Person.find('Greg').exists?
837 838

    # Nested class method.
839
    assert StreetAddress.exists?(1,  :params => { :person_id => Person.find('Greg').to_param })
840 841 842 843

    # Nested instance method.
    assert StreetAddress.find(1, :params => { :person_id => Person.find('Greg').to_param }).exists?

J
Jeremy Kemper 已提交
844 845 846 847 848 849 850
  ensure
    # revert back to original
    Person.module_eval do
      # save the 'new' to_param so we don't get a warning about discarding the method
      alias_method :exists_to_param, :to_param
      alias_method :to_param, :original_to_param_exists
    end
851 852
  end

853 854
  def test_to_xml
    matz = Person.find(1)
855
    xml = matz.encode
856 857 858
    assert xml.starts_with?('<?xml version="1.0" encoding="UTF-8"?>')
    assert xml.include?('<name>Matz</name>')
    assert xml.include?('<id type="integer">1</id>')
859
  end
860 861 862 863 864 865 866

  def test_to_param_quacks_like_active_record
    new_person = Person.new
    assert_nil new_person.to_param
    matz = Person.find(1)
    assert_equal '1', matz.to_param
  end
867 868 869 870 871 872 873 874 875 876 877 878 879 880

  def test_parse_deep_nested_resources
    luis = Customer.find(1)
    assert_kind_of Customer, luis
    luis.friends.each do |friend|
      assert_kind_of Customer::Friend, friend
      friend.brothers.each do |brother|
        assert_kind_of Customer::Friend::Brother, brother
        brother.children.each do |child|
          assert_kind_of Customer::Friend::Brother::Child, child
        end
      end
    end
  end
881 882 883 884 885 886 887 888 889 890

  def test_load_yaml_array
    assert_nothing_raised do
      marty = Person.find(5)
      assert_equal 3, marty.colors.size
      marty.colors.each do |color|
        assert_kind_of String, color
      end
    end
  end
J
Jeremy Kemper 已提交
891
end