Add the has_many_polymorphs plugin
[cs356-p2-videostore.git] / vendor / plugins / has_many_polymorphs / test / unit / polymorph_test.rb
diff --git a/vendor/plugins/has_many_polymorphs/test/unit/polymorph_test.rb b/vendor/plugins/has_many_polymorphs/test/unit/polymorph_test.rb
new file mode 100644 (file)
index 0000000..0ca5d1a
--- /dev/null
@@ -0,0 +1,714 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+require 'dog'
+require 'wild_boar'
+require 'frog'
+require 'cat'
+require 'kitten'
+require 'aquatic/whale'
+require 'aquatic/fish'
+require 'aquatic/pupils_whale'
+require 'beautiful_fight_relationship' 
+
+class PolymorphTest < Test::Unit::TestCase
+  
+  set_fixture_class :bow_wows => Dog
+  set_fixture_class :keep_your_enemies_close => BeautifulFightRelationship
+  set_fixture_class :whales => Aquatic::Whale
+  set_fixture_class :fish => Aquatic::Fish
+  set_fixture_class :little_whale_pupils => Aquatic::PupilsWhale
+  
+  fixtures :cats, :bow_wows, :frogs, :wild_boars, :eaters_foodstuffs, :petfoods,
+              :fish, :whales, :little_whale_pupils, :keep_your_enemies_close, :people   
+        
+  def setup
+   @association_error = ActiveRecord::Associations::PolymorphicError
+   @kibbles = Petfood.find(1)
+   @bits = Petfood.find(2) 
+   @shamu = Aquatic::Whale.find(1)
+   @swimmy = Aquatic::Fish.find(1)
+   @rover = Dog.find(1)
+   @spot = Dog.find(2)
+   @puma  = WildBoar.find(1)
+   @chloe = Kitten.find(1)
+   @alice = Kitten.find(2)
+   @toby = Tabby.find(3)
+   @froggy = Frog.find(1)
+
+   @join_count = EatersFoodstuff.count    
+   @kibbles_eaters_count = @kibbles.eaters.size
+   @bits_eaters_count = @bits.eaters.size
+
+   @double_join_count = BeautifulFightRelationship.count
+   @alice_enemies_count = @alice.enemies.size
+  end  
+  
+  def test_all_relationship_validities
+    # q = []
+    # ObjectSpace.each_object(Class){|c| q << c if c.ancestors.include? ActiveRecord::Base }
+    # q.each{|c| puts "#{c.name}.reflect_on_all_associations.map &:check_validity! "}
+    Petfood.reflect_on_all_associations.map &:check_validity! 
+    Tabby.reflect_on_all_associations.map &:check_validity! 
+    Kitten.reflect_on_all_associations.map &:check_validity! 
+    Dog.reflect_on_all_associations.map &:check_validity! 
+    Canine.reflect_on_all_associations.map &:check_validity! 
+    Aquatic::Fish.reflect_on_all_associations.map &:check_validity! 
+    EatersFoodstuff.reflect_on_all_associations.map &:check_validity! 
+    WildBoar.reflect_on_all_associations.map &:check_validity! 
+    Frog.reflect_on_all_associations.map &:check_validity! 
+    Cat.reflect_on_all_associations.map &:check_validity! 
+    BeautifulFightRelationship.reflect_on_all_associations.map &:check_validity! 
+    Person.reflect_on_all_associations.map &:check_validity! 
+    Parentship.reflect_on_all_associations.map &:check_validity! 
+    Aquatic::Whale.reflect_on_all_associations.map &:check_validity! 
+    Aquatic::PupilsWhale.reflect_on_all_associations.map &:check_validity! 
+  end
+  
+  def test_assignment     
+    assert @kibbles.eaters.blank?
+    assert @kibbles.eaters.push(Cat.find_by_name('Chloe'))
+    assert_equal @kibbles_eaters_count += 1, @kibbles.eaters.count
+
+    @kibbles.reload
+    assert_equal @kibbles_eaters_count, @kibbles.eaters.count    
+  end
+  
+  def test_duplicate_assignment
+    # try to add a duplicate item when :ignore_duplicates is false
+    @kibbles.eaters.push(@alice)
+    assert @kibbles.eaters.include?(@alice)
+    @kibbles.eaters.push(@alice)
+    assert_equal @kibbles_eaters_count + 2, @kibbles.eaters.count
+    assert_equal @join_count + 2, EatersFoodstuff.count
+  end
+  
+  def test_create_and_push
+    assert @kibbles.eaters.push(@spot)  
+    assert_equal @kibbles_eaters_count += 1, @kibbles.eaters.count
+    assert @kibbles.eaters << @rover
+    assert @kibbles.eaters << Kitten.create(:name => "Miranda")
+    assert_equal @kibbles_eaters_count += 2, @kibbles.eaters.length
+
+    @kibbles.reload
+    assert_equal @kibbles_eaters_count, @kibbles.eaters.length   
+    
+    # test that ids and new flags were set appropriately
+    assert_not_nil @kibbles.eaters[0].id
+    assert !@kibbles.eaters[1].new_record?
+  end
+  def test_reload
+    assert @kibbles.reload
+    assert @kibbles.eaters.reload
+  end
+  def test_add_join_record
+    assert_equal Kitten, @chloe.class
+    assert join = EatersFoodstuff.new(:foodstuff_id => @bits.id, :eater_id => @chloe.id, :eater_type => @chloe.class.name ) 
+    assert join.save!
+    assert join.id
+    assert_equal @join_count + 1, EatersFoodstuff.count
+
+    #assert_equal @bits_eaters_count, @bits.eaters.size # Doesn't behave this way on latest edge anymore
+    assert_equal @bits_eaters_count + 1, @bits.eaters.count # SQL
+
+    # reload; is the new association there?
+    assert @bits.eaters.reload
+    assert @bits.eaters.include?(@chloe)
+  end
+
+  def test_build_join_record_on_association
+    assert_equal Kitten, @chloe.class
+    assert join = @chloe.eaters_foodstuffs.build(:foodstuff => @bits)
+    # assert_equal join.eater_type, @chloe.class.name # will be STI parent type
+    assert join.save!
+    assert join.id
+    assert_equal @join_count + 1, EatersFoodstuff.count
+
+    assert @bits.eaters.reload
+    assert @bits.eaters.include?(@chloe)
+  end
+
+#  not supporting this, since has_many :through doesn't support it either  
+#  def test_add_unsaved   
+#    # add an unsaved item
+#    assert @bits.eaters << Kitten.new(:name => "Bridget")
+#    assert_nil Kitten.find_by_name("Bridget")
+#    assert_equal @bits_eaters_count + 1, @bits.eaters.count
+#
+#    assert @bits.save
+#    @bits.reload
+#    assert_equal @bits_eaters_count + 1, @bits.eaters.count
+#    
+#  end
+  
+  def test_self_reference
+    assert @kibbles.eaters << @bits
+    assert_equal @kibbles_eaters_count += 1, @kibbles.eaters.count
+    assert @kibbles.eaters.include?(@bits)
+    @kibbles.reload
+    assert @kibbles.foodstuffs_of_eaters.blank?
+    
+    @bits.reload
+    assert @bits.foodstuffs_of_eaters.include?(@kibbles)
+    assert_equal [@kibbles], @bits.foodstuffs_of_eaters
+  end
+
+  def test_remove
+    assert @kibbles.eaters << @chloe
+    @kibbles.reload
+    assert @kibbles.eaters.delete(@kibbles.eaters[0])
+    assert_equal @kibbles_eaters_count, @kibbles.eaters.count
+  end
+  
+  def test_destroy
+    assert @kibbles.eaters.push(@chloe)
+    @kibbles.reload
+    assert @kibbles.eaters.length > 0
+    assert @kibbles.eaters[0].destroy
+    @kibbles.reload
+    assert_equal @kibbles_eaters_count, @kibbles.eaters.count
+  end
+
+  def test_clear
+    @kibbles.eaters << [@chloe, @spot, @rover]
+    @kibbles.reload
+    assert @kibbles.eaters.clear.blank?    
+    assert @kibbles.eaters.blank?    
+    @kibbles.reload    
+    assert @kibbles.eaters.blank?    
+  end
+    
+  def test_individual_collections
+    assert @kibbles.eaters.push(@chloe)
+    # check if individual collections work
+    assert_equal @kibbles.eater_kittens.length, 1
+    assert @kibbles.eater_dogs 
+    assert 1, @rover.eaters_foodstuffs.count
+  end
+  
+  def test_individual_collections_push
+    assert_equal [@chloe], (@kibbles.eater_kittens << @chloe)
+    @kibbles.reload
+    assert @kibbles.eaters.include?(@chloe)
+    assert @kibbles.eater_kittens.include?(@chloe)
+    assert !@kibbles.eater_dogs.include?(@chloe)
+  end
+
+  def test_individual_collections_delete
+    @kibbles.eaters << [@chloe, @spot, @rover]
+    @kibbles.reload
+    assert_equal [@chloe], @kibbles.eater_kittens.delete(@chloe)
+    assert @kibbles.eater_kittens.empty?
+    @kibbles.eater_kittens.delete(@chloe) # what should this return?
+    
+    @kibbles.reload    
+    assert @kibbles.eater_kittens.empty?
+    assert @kibbles.eater_dogs.include?(@spot)
+  end
+  
+  def test_individual_collections_clear
+    @kibbles.eaters << [@chloe, @spot, @rover]
+    @kibbles.reload
+
+    assert_equal [], @kibbles.eater_kittens.clear
+    assert @kibbles.eater_kittens.empty?    
+    assert_equal 2, @kibbles.eaters.size
+
+    assert @kibbles.eater_kittens.empty?    
+    assert_equal 2, @kibbles.eaters.size
+    assert !@kibbles.eater_kittens.include?(@chloe)
+    assert !@kibbles.eaters.include?(@chloe)
+
+    @kibbles.reload    
+    assert @kibbles.eater_kittens.empty?    
+    assert_equal 2, @kibbles.eaters.size
+    assert !@kibbles.eater_kittens.include?(@chloe)
+    assert !@kibbles.eaters.include?(@chloe)
+  end
+  
+  def test_childrens_individual_collections
+    assert Cat.find_by_name('Chloe').eaters_foodstuffs
+    assert @kibbles.eaters_foodstuffs
+  end
+  
+  def test_self_referential_join_tables
+    # check that the self-reference join tables go the right ways
+    assert_equal @kibbles_eaters_count, @kibbles.eaters_foodstuffs.count
+    assert_equal @kibbles.eaters_foodstuffs.count, @kibbles.eaters_foodstuffs_as_child.count
+  end
+
+  def test_dependent
+    assert @kibbles.eaters << @chloe
+    @kibbles.reload
+    # delete ourself and see if :dependent was obeyed
+    dependent_rows = @kibbles.eaters_foodstuffs
+    assert_equal dependent_rows.length, @kibbles.eaters.count
+    @join_count = EatersFoodstuff.count
+    
+    @kibbles.destroy
+    assert_equal @join_count - dependent_rows.length, EatersFoodstuff.count
+    assert_equal 0, EatersFoodstuff.find(:all, :conditions => ['foodstuff_id = ?', 1] ).length
+  end
+  
+  def test_normal_callbacks
+    assert @rover.respond_to?(:after_initialize)
+    assert @rover.respond_to?(:after_find)    
+    assert @rover.after_initialize_test
+    assert @rover.after_find_test
+  end    
+  
+  def test_model_callbacks_not_overridden_by_plugin_callbacks
+    assert 0, @bits.eaters.count
+    assert @bits.eaters.push(@rover)
+    @bits.save
+    @bits2 = Petfood.find_by_name("Bits")
+    @bits.reload
+    assert rover = @bits2.eaters.select { |x| x.name == "Rover" }[0]
+    assert rover.after_initialize_test
+    assert rover.after_find_test
+  end
+
+  def test_number_of_join_records
+    assert EatersFoodstuff.create(:foodstuff_id => 1, :eater_id => 1, :eater_type => "Cat")
+    @join_count = EatersFoodstuff.count    
+    assert @join_count > 0
+  end
+  
+  def test_number_of_regular_records
+    dogs = Dog.count
+    assert Dog.new(:name => "Auggie").save!
+    assert dogs + 1, Dog.count
+  end
+
+  def test_attributes_come_through_when_child_has_underscore_in_table_name
+    join = EatersFoodstuff.new(:foodstuff_id => @bits.id, :eater_id =>  @puma.id, :eater_type => @puma.class.name) 
+    join.save!
+    
+    @bits.eaters.reload
+
+    assert_equal "Puma", @puma.name
+    assert_equal "Puma", @bits.eaters.first.name
+  end
+  
+  
+  def test_before_save_on_join_table_is_not_clobbered_by_sti_base_class_fix
+    assert @kibbles.eaters << @chloe
+    assert_equal 3, @kibbles.eaters_foodstuffs.first.some_attribute
+  end
+  
+  def test_sti_type_counts_are_correct
+    @kibbles.eaters << [@chloe, @alice, @toby]
+    assert_equal 2, @kibbles.eater_kittens.count
+    assert_equal 1, @kibbles.eater_tabbies.count
+    assert !@kibbles.respond_to?(:eater_cats)
+  end
+  
+    
+  def test_creating_namespaced_relationship
+    assert @shamu.aquatic_pupils.empty?
+    @shamu.aquatic_pupils << @swimmy
+    assert_equal 1, @shamu.aquatic_pupils.length
+    @shamu.reload
+    assert_equal 1, @shamu.aquatic_pupils.length
+  end  
+
+  def test_namespaced_polymorphic_collection
+    @shamu.aquatic_pupils << @swimmy
+    assert @shamu.aquatic_pupils.include?(@swimmy)
+    @shamu.reload
+    assert @shamu.aquatic_pupils.include?(@swimmy)
+
+    @shamu.aquatic_pupils << @spot
+    assert @shamu.dogs.include?(@spot)
+    assert @shamu.aquatic_pupils.include?(@swimmy)
+    assert_equal @swimmy, @shamu.aquatic_fish.first
+    assert_equal 10, @shamu.aquatic_fish.first.speed
+  end
+  
+  def test_deleting_namespaced_relationship    
+    @shamu.aquatic_pupils << @swimmy
+    @shamu.aquatic_pupils << @spot
+    
+    @shamu.reload
+    @shamu.aquatic_pupils.delete @spot
+    assert !@shamu.dogs.include?(@spot)
+    assert !@shamu.aquatic_pupils.include?(@spot)
+    assert_equal 1, @shamu.aquatic_pupils.length
+  end
+  
+  def test_unrenamed_parent_of_namespaced_child
+    @shamu.aquatic_pupils << @swimmy
+    assert_equal [@shamu], @swimmy.whales
+  end
+  
+  def test_empty_double_collections
+    assert @puma.enemies.empty?
+    assert @froggy.protectors.empty?
+    assert @alice.enemies.empty?
+    assert @spot.protectors.empty?
+    assert @alice.beautiful_fight_relationships_as_enemy.empty?
+    assert @alice.beautiful_fight_relationships_as_protector.empty?
+    assert @alice.beautiful_fight_relationships.empty?    
+  end
+  
+  def test_double_collection_assignment
+    @alice.enemies << @spot
+    @alice.reload
+    @spot.reload
+    assert @spot.protectors.include?(@alice)
+    assert @alice.enemies.include?(@spot)
+    assert !@alice.protectors.include?(@alice)
+    assert_equal 1, @alice.beautiful_fight_relationships_as_protector.size
+    assert_equal 0, @alice.beautiful_fight_relationships_as_enemy.size
+    assert_equal 1, @alice.beautiful_fight_relationships.size
+    
+    # self reference
+    assert_equal 1, @alice.enemies.length
+    @alice.enemies.push @alice
+    assert @alice.enemies.include?(@alice)
+    assert_equal 2, @alice.enemies.length    
+    @alice.reload
+    assert_equal 2, @alice.beautiful_fight_relationships_as_protector.size
+    assert_equal 1, @alice.beautiful_fight_relationships_as_enemy.size
+    assert_equal 3, @alice.beautiful_fight_relationships.size
+  end
+  
+  def test_double_collection_build_join_record_on_association
+    
+    join = @alice.beautiful_fight_relationships_as_protector.build(:enemy => @spot)
+    
+    assert_equal @alice.class.base_class.name, join.protector_type
+    assert_nothing_raised { join.save! }
+
+    assert join.id
+    assert_equal @double_join_count + 1, BeautifulFightRelationship.count
+
+    assert @alice.enemies.reload
+    assert @alice.enemies.include?(@spot)
+  end
+  
+  def test_double_dependency_injection
+#    breakpoint
+  end
+  
+  def test_double_collection_deletion
+    @alice.enemies << @spot
+    @alice.reload
+    assert @alice.enemies.include?(@spot)
+    @alice.enemies.delete(@spot)
+    assert !@alice.enemies.include?(@spot)
+    assert @alice.enemies.empty?
+    @alice.reload
+    assert !@alice.enemies.include?(@spot)
+    assert @alice.enemies.empty?
+    assert_equal 0, @alice.beautiful_fight_relationships.size
+  end
+  def test_double_collection_deletion_from_opposite_side
+    @alice.protectors << @puma
+    @alice.reload
+    assert @alice.protectors.include?(@puma)
+    @alice.protectors.delete(@puma)
+    assert !@alice.protectors.include?(@puma)
+    assert @alice.protectors.empty?
+    @alice.reload
+    assert !@alice.protectors.include?(@puma)
+    assert @alice.protectors.empty?
+    assert_equal 0, @alice.beautiful_fight_relationships.size
+  end
+  def test_individual_collections_created_for_double_relationship
+    assert @alice.dogs.empty?
+    @alice.enemies << @spot
+
+    assert @alice.enemies.include?(@spot)
+    assert !@alice.kittens.include?(@alice)    
+
+    assert !@alice.dogs.include?(@spot)    
+    @alice.reload
+    assert @alice.dogs.include?(@spot)    
+    assert !WildBoar.find(@alice.id).dogs.include?(@spot) # make sure the parent type is checked
+  end
+
+  def test_individual_collections_created_for_double_relationship_from_opposite_side
+    assert @alice.wild_boars.empty?
+    @alice.protectors << @puma
+
+    assert @alice.protectors.include?(@puma)
+    assert !@alice.wild_boars.include?(@puma)    
+    @alice.reload
+    assert @alice.wild_boars.include?(@puma)    
+    
+    assert !Dog.find(@alice.id).wild_boars.include?(@puma) # make sure the parent type is checked
+  end
+  
+  def test_self_referential_individual_collections_created_for_double_relationship
+    @alice.enemies << @alice
+    @alice.reload
+    assert @alice.enemy_kittens.include?(@alice)
+    assert @alice.protector_kittens.include?(@alice)
+    assert @alice.kittens.include?(@alice)
+    assert_equal 2, @alice.kittens.size
+
+    @alice.enemies << (@chloe =  Kitten.find_by_name('Chloe'))
+    @alice.reload
+    assert @alice.enemy_kittens.include?(@chloe)
+    assert !@alice.protector_kittens.include?(@chloe)
+    assert @alice.kittens.include?(@chloe)
+    assert_equal 3, @alice.kittens.size    
+  end
+    
+  def test_child_of_polymorphic_join_can_reach_parent
+    @alice.enemies << @spot    
+    @alice.reload
+    assert @spot.protectors.include?(@alice)
+  end
+  
+  def test_double_collection_deletion_from_child_polymorphic_join
+    @alice.enemies << @spot
+    @spot.protectors.delete(@alice)
+    assert !@spot.protectors.include?(@alice)
+    @alice.reload
+    assert !@alice.enemies.include?(@spot)
+    BeautifulFightRelationship.create(:protector_id => 2, :protector_type => "Dog", :enemy_id => @spot.id, :enemy_type => @spot.class.name)
+    @alice.enemies << @spot
+    @spot.protectors.delete(@alice)
+    assert !@spot.protectors.include?(@alice)
+  end
+
+  def test_collection_query_on_unsaved_record
+    assert Dog.new.enemies.empty?
+    assert Dog.new.foodstuffs_of_eaters.empty?
+  end
+  def test_double_individual_collections_push
+    assert_equal [@chloe], (@spot.protector_kittens << @chloe)
+    @spot.reload
+    assert @spot.protectors.include?(@chloe)
+    assert @spot.protector_kittens.include?(@chloe)
+    assert !@spot.protector_dogs.include?(@chloe)
+    assert_equal [@froggy], (@spot.frogs << @froggy)
+    @spot.reload
+    assert @spot.enemies.include?(@froggy)
+    assert @spot.frogs.include?(@froggy)
+    assert !@spot.enemy_dogs.include?(@froggy)
+  end
+
+  def test_double_individual_collections_delete
+    @spot.protectors << [@chloe, @puma]
+    @spot.reload
+    assert_equal [@chloe], @spot.protector_kittens.delete(@chloe)
+    assert @spot.protector_kittens.empty?
+    @spot.protector_kittens.delete(@chloe) # again, unclear what .delete should return
+    
+    @spot.reload    
+    assert @spot.protector_kittens.empty?
+    assert @spot.wild_boars.include?(@puma)
+  end
+  
+  def test_double_individual_collections_clear
+    @spot.protectors << [@chloe, @puma, @alice]
+    @spot.reload
+    assert_equal [], @spot.protector_kittens.clear
+    assert @spot.protector_kittens.empty?    
+    assert_equal 1, @spot.protectors.size
+    @spot.reload    
+    assert @spot.protector_kittens.empty?    
+    assert_equal 1, @spot.protectors.size
+    assert !@spot.protector_kittens.include?(@chloe)
+    assert !@spot.protectors.include?(@chloe)
+    assert !@spot.protector_kittens.include?(@alice)
+    assert !@spot.protectors.include?(@alice)
+    assert @spot.protectors.include?(@puma)
+    assert @spot.wild_boars.include?(@puma)
+  end 
+
+  def test_single_extensions
+    assert_equal :correct_block_result, @shamu.aquatic_pupils.a_method
+    @kibbles.eaters.push(@alice)
+    @kibbles.eaters.push(@spot)
+    assert_equal :correct_join_result, @kibbles.eaters_foodstuffs.a_method
+    assert_equal :correct_module_result, @kibbles.eaters.a_method
+    assert_equal :correct_other_module_result, @kibbles.eaters.another_method
+    @kibbles.eaters.each do |eater| 
+      assert_equal :correct_join_result, eater.eaters_foodstuffs.a_method
+    end
+    assert_equal :correct_parent_proc_result, @kibbles.foodstuffs_of_eaters.a_method
+    assert_equal :correct_parent_proc_result, @kibbles.eaters.first.foodstuffs_of_eaters.a_method
+  end
+
+  def test_double_extensions
+    assert_equal :correct_proc_result, @spot.protectors.a_method 
+    assert_equal :correct_module_result, @spot.enemies.a_method 
+    assert_equal :correct_join_result, @spot.beautiful_fight_relationships_as_enemy.a_method
+    assert_equal :correct_join_result, @spot.beautiful_fight_relationships_as_protector.a_method
+    assert_equal :correct_join_result, @froggy.beautiful_fight_relationships.a_method
+    assert_equal :correct_join_result, @froggy.beautiful_fight_relationships_as_enemy.a_method    
+    assert_raises(NoMethodError) {@froggy.beautiful_fight_relationships_as_protector.a_method}    
+  end
+  
+  def test_pluralization_checks    
+    assert_raises(@association_error) {
+      eval "class SomeModel < ActiveRecord::Base
+        has_many_polymorphs :polymorphs, :from => [:dog, :cats]
+      end" }
+    assert_raises(@association_error) {
+      eval "class SomeModel < ActiveRecord::Base
+        has_many_polymorphs :polymorph, :from => [:dogs, :cats]
+      end" }
+    assert_raises(@association_error) {
+      eval "class SomeModel < ActiveRecord::Base
+        acts_as_double_polymorphic_join :polymorph => [:dogs, :cats], :unimorphs => [:dogs, :cats]
+      end" }    
+  end
+  
+  def test_error_message_on_namespaced_targets
+    assert_raises(@association_error) {
+      eval "class SomeModel < ActiveRecord::Base
+        has_many_polymorphs :polymorphs, :from => [:fish]
+      end" }
+  end
+
+  def test_single_custom_finders
+    [@kibbles, @alice, @puma, @spot, @bits].each {|record| @kibbles.eaters << record; sleep 1} # XXX yeah i know
+    assert_equal @kibbles.eaters, @kibbles.eaters.find(:all, :order => "eaters_foodstuffs.created_at ASC") 
+    assert_equal @kibbles.eaters.reverse, @kibbles.eaters.find(:all, :order => "eaters_foodstuffs.created_at DESC") 
+    if (ActiveRecord::Base.connection.is_a? ActiveRecord::ConnectionAdapters::MysqlAdapter rescue false)
+      assert_equal @kibbles.eaters.sort_by(&:created_at), @kibbles.eaters.find(:all, :order => "IFNULL(bow_wows.created_at,(IFNULL(petfoods.created_at,(IFNULL(wild_boars.created_at,(IFNULL(cats.created_at,fish.created_at))))))) ASC") 
+    end
+    assert_equal @kibbles.eaters.select{|x| x.is_a? Petfood}, @kibbles.eater_petfoods.find(:all, :order => "eaters_foodstuffs.created_at ASC") 
+  end
+  def test_double_custom_finders
+    @spot.protectors << [@chloe, @puma, @alice]
+    assert_equal [@chloe], @spot.protectors.find(:all, :conditions => ["cats.name = ?", @chloe.name], :limit => 1)
+    assert_equal [], @spot.protectors.find(:all, :conditions => ["cats.name = ?", @chloe.name], :limit => 1, :offset => 1)
+    assert_equal 2, @spot.protectors.find(:all, :limit => 100, :offset => 1).size
+  end
+  
+  def test_single_custom_finder_parameters_carry_to_individual_relationships
+   # XXX test nullout here
+  end
+
+  def test_double_custom_finder_parameters_carry_to_individual_relationships
+   # XXX test nullout here
+  end
+  
+  def test_include_doesnt_fail
+    assert_nothing_raised do
+      @spot.protectors.find(:all, :include => :wild_boars)
+    end
+  end
+
+  def test_abstract_method
+    assert_equal :correct_abstract_method_response, @spot.an_abstract_method
+  end
+  
+  def test_missing_target_should_raise
+    @kibbles.eaters << [@kibbles, @alice, @puma, @spot, @bits]
+    @spot.destroy_without_callbacks
+    assert_raises(@association_error) { @kibbles.eaters.reload }
+#    assert_raises(@association_error) { @kibbles.eater_dogs.reload }  # bah AR
+  end
+  
+  def test_lazy_loading_is_lazy
+    # XXX
+  end
+  
+  def test_push_with_skip_duplicates_false_doesnt_load_target
+    # Loading kibbles locally again because setup calls .size which loads target
+    kibbles = Petfood.find(1)
+    assert !kibbles.eaters.loaded?
+    assert !(kibbles.eater_dogs << Dog.create!(:name => "Mongy")).loaded?
+    assert !kibbles.eaters.loaded?
+  end
+  
+  def test_association_foreign_key_is_sane
+    assert_equal "eater_id", Petfood.reflect_on_association(:eaters).association_foreign_key
+  end
+
+  def test_reflection_instance_methods_are_sane
+    assert_equal EatersFoodstuff, Petfood.reflect_on_association(:eaters).klass
+    assert_equal EatersFoodstuff.name, Petfood.reflect_on_association(:eaters).class_name
+  end
+  
+  def test_parent_order
+    @alice.foodstuffs_of_eaters << Petfood.find(:all, :order => "the_petfood_primary_key ASC")
+    @alice.reload #not necessary
+    assert_equal [2,1], @alice.foodstuffs_of_eaters.map(&:id)  
+  end
+
+  def test_parent_conditions
+    @kibbles.eaters << @alice
+    assert_equal [@alice], @kibbles.eaters
+
+    @snausages = Petfood.create(:name => 'Snausages')
+    @snausages.eaters << @alice    
+    assert_equal [@alice], @snausages.eaters
+    
+    assert_equal [@kibbles], @alice.foodstuffs_of_eaters
+  end        
+  
+  def test_self_referential_hmp_with_conditions
+    p = Person.find(:first)
+    kid = Person.create(:name => "Tim", :age => 3)
+    p.kids << kid
+
+    kid.reload; p.reload
+
+  # assert_equal [p], kid.parents 
+  # assert Rails.has_one? Bug
+  # non-standard foreign_type key is not set properly when you are the polymorphic interface of a has_many going to a :through
+
+    assert_equal [kid], p.kids
+    assert_equal [kid], p.people
+  end
+
+#  def test_polymorphic_include
+#    @kibbles.eaters << [@kibbles, @alice, @puma, @spot, @bits]
+#    assert @kibbles.eaters.include?(@kibbles.eaters_foodstuffs.find(:all, :include => :eater).first.eater)
+#  end
+#
+#  def test_double_polymorphic_include
+#  end
+#
+#  def test_single_child_include  
+#  end
+#  
+#  def test_double_child_include  
+#  end
+#  
+#  def test_single_include_from_parent  
+#  end
+#
+#  def test_double_include_from_parent  
+#  end
+#
+#  def test_meta_referential_single_include  
+#  end
+#
+#  def test_meta_referential_double_include  
+#  end
+#  
+#  def test_meta_referential_single_include  
+#  end
+#
+#  def test_meta_referential_single_double_multi_include  
+#  end  
+#  
+#  def test_dont_ignore_duplicates  
+#  end
+#
+#  def test_ignore_duplicates  
+#  end
+#    
+#  def test_tagging_system_generator  
+#  end
+#
+#  def test_tagging_system_library  
+#  end
+
+end