base_test.rb 14.7 KB
Newer Older
1 2
require "#{File.dirname(__FILE__)}/abstract_unit"
require "fixtures/person"
3
require "fixtures/street_address"
4
require "fixtures/beast"
5 6 7

class BaseTest < Test::Unit::TestCase
  def setup
8 9 10
    @matz  = { :id => 1, :name => 'Matz' }.to_xml(:root => 'person')
    @david = { :id => 2, :name => 'David' }.to_xml(:root => 'person')
    @addy  = { :id => 1, :street => '12345 Street' }.to_xml(:root => 'address')
11
    @default_request_headers = { 'Content-Type' => 'application/xml' }
12 13 14 15
    @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')
16
    
17
    ActiveResource::HttpMock.respond_to do |mock|
18 19
      mock.get    "/people/1.xml",             {}, @matz
      mock.get    "/people/2.xml",             {}, @david
20
      mock.get    "/people/3.xml",             {'key' => 'value'}, nil, 404
21 22 23 24
      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
25 26 27
      mock.post   "/people.xml",               {}, @rick, 201, 'Location' => '/people/5.xml'
      mock.get    "/people.xml",               {}, @people
      mock.get    "/people/1/addresses.xml",   {}, @addresses
28
      mock.get    "/people/1/addresses/1.xml", {}, @addy
29 30
      mock.get    "/people/1/addresses/2.xml", {}, nil, 404
      mock.get    "/people/2/addresses/1.xml", {}, nil, 404
31 32 33 34 35 36 37 38
      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
39
    end
40 41
  end

J
Jeremy Kemper 已提交
42 43 44 45 46 47 48 49 50 51 52

  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

53 54 55 56 57
  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

58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
  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?
  end
J
Jeremy Kemper 已提交
88

89 90 91 92
  def test_collection_name
    assert_equal "people", Person.collection_name
  end

93 94 95 96
  def test_collection_path
    assert_equal '/people.xml', Person.collection_path
  end

97 98 99 100 101 102
  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')
103 104 105 106 107
    
    # 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')
108

109 110 111
    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])
    
    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'})
112 113
  end

114 115
  def test_custom_element_path
    assert_equal '/people/1/addresses/1.xml', StreetAddress.element_path(1, :person_id => 1)
116
    assert_equal '/people/1/addresses/1.xml', StreetAddress.element_path(1, 'person_id' => 1)
117 118
  end

119 120
  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')
121
    assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, 'person_id' => 1, :type => 'work')
122 123
    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'])
124 125
  end

126 127 128 129
  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

130 131
  def test_custom_collection_path
    assert_equal '/people/1/addresses.xml', StreetAddress.collection_path(:person_id => 1)
132
    assert_equal '/people/1/addresses.xml', StreetAddress.collection_path('person_id' => 1)
133 134
  end

135 136
  def test_custom_collection_path_with_parameters
    assert_equal '/people/1/addresses.xml?type=work', StreetAddress.collection_path(:person_id => 1, :type => 'work')
137
    assert_equal '/people/1/addresses.xml?type=work', StreetAddress.collection_path('person_id' => 1, :type => 'work')
138 139
  end

140 141 142 143
  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

144 145 146 147 148 149 150 151 152 153
  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
154
    assert_equal Set.new, Person.send(:prefix_parameters)
155
  end
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
  
  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
  
  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
  
  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
177 178 179 180

  def test_custom_prefix
    assert_equal '/people//', StreetAddress.prefix
    assert_equal '/people/1/', StreetAddress.prefix(:person_id => 1)
181
    assert_equal [:person_id].to_set, StreetAddress.send(:prefix_parameters)
182 183
  end

184 185 186 187
  def test_find_by_id
    matz = Person.find(1)
    assert_kind_of Person, matz
    assert_equal "Matz", matz.name
T
 
Tobias Lütke 已提交
188
    assert matz.name?
189
  end
190 191 192 193 194 195 196 197
  
  def test_respond_to
    matz = Person.find(1)
    assert matz.respond_to?(:name)
    assert matz.respond_to?(:name=)
    assert matz.respond_to?(:name?)
    assert !matz.respond_to?(:java)
  end
198

199
  def test_find_by_id_with_custom_prefix
200
    addy = StreetAddress.find(1, :params => { :person_id => 1 })
201 202 203 204
    assert_kind_of StreetAddress, addy
    assert_equal '12345 Street', addy.street
  end

205 206 207 208 209 210 211 212 213 214 215 216 217 218
  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

219
  def test_custom_header
220
    Person.headers['key'] = 'value'
221 222
    assert_raises(ActiveResource::ResourceNotFound) { Person.find(3) }
  ensure
223
    Person.headers.delete('key')
224 225
  end

226 227
  def test_find_by_id_not_found
    assert_raises(ActiveResource::ResourceNotFound) { Person.find(99) }
228 229 230
    assert_raises(ActiveResource::ResourceNotFound) { StreetAddress.find(1) }
  end

231
  def test_find_all_by_from
232
    ActiveResource::HttpMock.respond_to { |m| m.get "/companies/1/people.xml", {}, @people_david }
233 234 235 236 237 238
  
    people = Person.find(:all, :from => "/companies/1/people.xml")
    assert_equal 1, people.size
    assert_equal "David", people.first.name
  end

239
  def test_find_all_by_from_with_options
240
    ActiveResource::HttpMock.respond_to { |m| m.get "/companies/1/people.xml", {}, @people_david }
241 242 243 244 245 246 247
  
    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
248
    ActiveResource::HttpMock.respond_to { |m| m.get "/people/managers.xml", {}, @people_david }
249 250 251 252 253 254
  
    people = Person.find(:all, :from => :managers)
    assert_equal 1, people.size
    assert_equal "David", people.first.name
  end

255 256 257
  def test_find_single_by_from
    ActiveResource::HttpMock.respond_to { |m| m.get "/companies/1/manager.xml", {}, @david }

258 259 260 261 262 263 264 265
    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)
266 267 268
    assert_equal "David", david.name
  end

269
  def test_save
270
    rick = Person.new
271
    assert_equal true, rick.save
272 273 274
    assert_equal '5', rick.id
  end

275 276 277 278 279 280 281 282 283
  def test_id_from_response
    p = Person.new
    resp = {'Location' => '/foo/bar/1'}
    assert_equal '1', p.send(:id_from_response, resp)
    
    resp['Location'] << '.xml'
    assert_equal '1', p.send(:id_from_response, resp)
  end

284
  def test_create_with_custom_prefix
285
    matzs_house = StreetAddress.new(:person_id => 1)
286 287
    matzs_house.save
    assert_equal '5', matzs_house.id
288
  end
289

290 291
  # Test that loading a resource preserves its prefix_options.
  def test_load_preserves_prefix_options
292
    address = StreetAddress.find(1, :params => { :person_id => 1 })
293 294 295
    ryan = Person.new(:id => 1, :name => 'Ryan', :address => address)
    assert_equal address.prefix_options, ryan.address.prefix_options
  end
296 297 298 299 300 301 302 303 304 305 306
  
  def test_reload_works_with_prefix_options
    address = StreetAddress.find(1, :params => { :person_id => 1 })
    assert_equal address, address.reload
  end
  
  def test_reload_works_without_prefix_options    
    person = Person.find(:first)
    assert_equal person, person.reload
  end
    
307

308 309 310 311 312
  def test_create
    rick = Person.create(:name => 'Rick')
    assert rick.valid?
    assert !rick.new?
    assert_equal '5', rick.id
313 314 315

    # test additional attribute returned on create
    assert_equal 25, rick.age
316 317 318 319 320 321 322 323
    
    # Test that save exceptions get bubbled up too
    ActiveResource::HttpMock.respond_to do |mock|
      mock.post   "/people.xml", {}, nil, 409
    end    
    assert_raises(ActiveResource::ResourceConflict) { Person.create(:name => 'Rick') }
  end

324 325 326 327 328
  def test_update
    matz = Person.find(:first)
    matz.name = "David"
    assert_kind_of Person, matz
    assert_equal "David", matz.name
329
    assert_equal true, matz.save
330
  end
331

332
  def test_update_with_custom_prefix_with_specific_id
333
    addy = StreetAddress.find(1, :params => { :person_id => 1 })
334 335 336 337 338 339
    addy.street = "54321 Street"
    assert_kind_of StreetAddress, addy
    assert_equal "54321 Street", addy.street
    addy.save
  end

340 341 342 343 344 345 346 347
  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
  
348 349
  def test_update_conflict
    ActiveResource::HttpMock.respond_to do |mock|
350 351
      mock.get "/people/2.xml", {}, @david
      mock.put "/people/2.xml", @default_request_headers, nil, 409
352 353 354 355
    end
    assert_raises(ActiveResource::ResourceConflict) { Person.find(2).save }
  end

356 357
  def test_destroy
    assert Person.find(1).destroy
358
    ActiveResource::HttpMock.respond_to do |mock|
359
      mock.get "/people/1.xml", {}, nil, 404
360 361 362 363 364
    end
    assert_raises(ActiveResource::ResourceNotFound) { Person.find(1).destroy }
  end

  def test_destroy_with_custom_prefix
365
    assert StreetAddress.find(1, :params => { :person_id => 1 }).destroy
366
    ActiveResource::HttpMock.respond_to do |mock|
367
      mock.get "/people/1/addresses/1.xml", {}, nil, 404
368
    end
369
    assert_raises(ActiveResource::ResourceNotFound) { StreetAddress.find(1, :params => { :person_id => 1 }) }
370
  end
371 372 373

  def test_delete
    assert Person.delete(1)
374 375 376 377 378 379 380 381 382 383 384
    ActiveResource::HttpMock.respond_to do |mock|
      mock.get "/people/1.xml", {}, nil, 404
    end
    assert_raises(ActiveResource::ResourceNotFound) { Person.find(1) }
  end
  
  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
385
    assert_raises(ActiveResource::ResourceNotFound) { StreetAddress.find(1, :params => { :person_id => 1 }) }
386
  end
387 388 389 390 391 392 393 394 395 396 397 398 399

  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.
400 401 402
    assert StreetAddress.exists?(1,  :params => { :person_id => 1 })
    assert !StreetAddress.exists?(1, :params => { :person_id => 2 })
    assert !StreetAddress.exists?(2, :params => { :person_id => 1 })
403 404

    # Nested instance method.
405
    assert StreetAddress.find(1, :params => { :person_id => 1 }).exists?
406 407
    assert !StreetAddress.new({:id => 1, :person_id => 2}).exists?
    assert !StreetAddress.new({:id => 2, :person_id => 1}).exists?
408
  end
409 410 411 412 413
  
  def test_to_xml
    matz = Person.find(1)
    assert_equal "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<person>\n  <name>Matz</name>\n  <id type=\"integer\">1</id>\n</person>\n", matz.to_xml
  end
J
Jeremy Kemper 已提交
414
end