Chris@0: require 'test/unit' Chris@0: Chris@0: require 'rubygems' Chris@0: require 'active_record' Chris@0: Chris@0: $:.unshift File.dirname(__FILE__) + '/../lib' Chris@0: require File.dirname(__FILE__) + '/../init' Chris@0: Chris@0: class Test::Unit::TestCase Chris@0: def assert_queries(num = 1) Chris@0: $query_count = 0 Chris@0: yield Chris@0: ensure Chris@0: assert_equal num, $query_count, "#{$query_count} instead of #{num} queries were executed." Chris@0: end Chris@0: Chris@0: def assert_no_queries(&block) Chris@0: assert_queries(0, &block) Chris@0: end Chris@0: end Chris@0: Chris@0: ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:") Chris@0: Chris@0: # AR keeps printing annoying schema statements Chris@0: $stdout = StringIO.new Chris@0: Chris@0: def setup_db Chris@0: ActiveRecord::Base.logger Chris@0: ActiveRecord::Schema.define(:version => 1) do Chris@0: create_table :mixins do |t| Chris@0: t.column :type, :string Chris@0: t.column :parent_id, :integer Chris@0: end Chris@0: end Chris@0: end Chris@0: Chris@0: def teardown_db Chris@0: ActiveRecord::Base.connection.tables.each do |table| Chris@0: ActiveRecord::Base.connection.drop_table(table) Chris@0: end Chris@0: end Chris@0: Chris@0: class Mixin < ActiveRecord::Base Chris@0: end Chris@0: Chris@0: class TreeMixin < Mixin Chris@0: acts_as_tree :foreign_key => "parent_id", :order => "id" Chris@0: end Chris@0: Chris@0: class TreeMixinWithoutOrder < Mixin Chris@0: acts_as_tree :foreign_key => "parent_id" Chris@0: end Chris@0: Chris@0: class RecursivelyCascadedTreeMixin < Mixin Chris@0: acts_as_tree :foreign_key => "parent_id" Chris@0: has_one :first_child, :class_name => 'RecursivelyCascadedTreeMixin', :foreign_key => :parent_id Chris@0: end Chris@0: Chris@0: class TreeTest < Test::Unit::TestCase Chris@0: Chris@0: def setup Chris@0: setup_db Chris@0: @root1 = TreeMixin.create! Chris@0: @root_child1 = TreeMixin.create! :parent_id => @root1.id Chris@0: @child1_child = TreeMixin.create! :parent_id => @root_child1.id Chris@0: @root_child2 = TreeMixin.create! :parent_id => @root1.id Chris@0: @root2 = TreeMixin.create! Chris@0: @root3 = TreeMixin.create! Chris@0: end Chris@0: Chris@0: def teardown Chris@0: teardown_db Chris@0: end Chris@0: Chris@0: def test_children Chris@0: assert_equal @root1.children, [@root_child1, @root_child2] Chris@0: assert_equal @root_child1.children, [@child1_child] Chris@0: assert_equal @child1_child.children, [] Chris@0: assert_equal @root_child2.children, [] Chris@0: end Chris@0: Chris@0: def test_parent Chris@0: assert_equal @root_child1.parent, @root1 Chris@0: assert_equal @root_child1.parent, @root_child2.parent Chris@0: assert_nil @root1.parent Chris@0: end Chris@0: Chris@0: def test_delete Chris@0: assert_equal 6, TreeMixin.count Chris@0: @root1.destroy Chris@0: assert_equal 2, TreeMixin.count Chris@0: @root2.destroy Chris@0: @root3.destroy Chris@0: assert_equal 0, TreeMixin.count Chris@0: end Chris@0: Chris@0: def test_insert Chris@0: @extra = @root1.children.create Chris@0: Chris@0: assert @extra Chris@0: Chris@0: assert_equal @extra.parent, @root1 Chris@0: Chris@0: assert_equal 3, @root1.children.size Chris@0: assert @root1.children.include?(@extra) Chris@0: assert @root1.children.include?(@root_child1) Chris@0: assert @root1.children.include?(@root_child2) Chris@0: end Chris@0: Chris@0: def test_ancestors Chris@0: assert_equal [], @root1.ancestors Chris@0: assert_equal [@root1], @root_child1.ancestors Chris@0: assert_equal [@root_child1, @root1], @child1_child.ancestors Chris@0: assert_equal [@root1], @root_child2.ancestors Chris@0: assert_equal [], @root2.ancestors Chris@0: assert_equal [], @root3.ancestors Chris@0: end Chris@0: Chris@0: def test_root Chris@0: assert_equal @root1, TreeMixin.root Chris@0: assert_equal @root1, @root1.root Chris@0: assert_equal @root1, @root_child1.root Chris@0: assert_equal @root1, @child1_child.root Chris@0: assert_equal @root1, @root_child2.root Chris@0: assert_equal @root2, @root2.root Chris@0: assert_equal @root3, @root3.root Chris@0: end Chris@0: Chris@0: def test_roots Chris@0: assert_equal [@root1, @root2, @root3], TreeMixin.roots Chris@0: end Chris@0: Chris@0: def test_siblings Chris@0: assert_equal [@root2, @root3], @root1.siblings Chris@0: assert_equal [@root_child2], @root_child1.siblings Chris@0: assert_equal [], @child1_child.siblings Chris@0: assert_equal [@root_child1], @root_child2.siblings Chris@0: assert_equal [@root1, @root3], @root2.siblings Chris@0: assert_equal [@root1, @root2], @root3.siblings Chris@0: end Chris@0: Chris@0: def test_self_and_siblings Chris@0: assert_equal [@root1, @root2, @root3], @root1.self_and_siblings Chris@0: assert_equal [@root_child1, @root_child2], @root_child1.self_and_siblings Chris@0: assert_equal [@child1_child], @child1_child.self_and_siblings Chris@0: assert_equal [@root_child1, @root_child2], @root_child2.self_and_siblings Chris@0: assert_equal [@root1, @root2, @root3], @root2.self_and_siblings Chris@0: assert_equal [@root1, @root2, @root3], @root3.self_and_siblings Chris@0: end Chris@0: end Chris@0: Chris@0: class TreeTestWithEagerLoading < Test::Unit::TestCase Chris@0: Chris@0: def setup Chris@0: teardown_db Chris@0: setup_db Chris@0: @root1 = TreeMixin.create! Chris@0: @root_child1 = TreeMixin.create! :parent_id => @root1.id Chris@0: @child1_child = TreeMixin.create! :parent_id => @root_child1.id Chris@0: @root_child2 = TreeMixin.create! :parent_id => @root1.id Chris@0: @root2 = TreeMixin.create! Chris@0: @root3 = TreeMixin.create! Chris@0: Chris@0: @rc1 = RecursivelyCascadedTreeMixin.create! Chris@0: @rc2 = RecursivelyCascadedTreeMixin.create! :parent_id => @rc1.id Chris@0: @rc3 = RecursivelyCascadedTreeMixin.create! :parent_id => @rc2.id Chris@0: @rc4 = RecursivelyCascadedTreeMixin.create! :parent_id => @rc3.id Chris@0: end Chris@0: Chris@0: def teardown Chris@0: teardown_db Chris@0: end Chris@0: Chris@0: def test_eager_association_loading Chris@0: roots = TreeMixin.find(:all, :include => :children, :conditions => "mixins.parent_id IS NULL", :order => "mixins.id") Chris@0: assert_equal [@root1, @root2, @root3], roots Chris@0: assert_no_queries do Chris@0: assert_equal 2, roots[0].children.size Chris@0: assert_equal 0, roots[1].children.size Chris@0: assert_equal 0, roots[2].children.size Chris@0: end Chris@0: end Chris@0: Chris@0: def test_eager_association_loading_with_recursive_cascading_three_levels_has_many Chris@0: root_node = RecursivelyCascadedTreeMixin.find(:first, :include => { :children => { :children => :children } }, :order => 'mixins.id') Chris@0: assert_equal @rc4, assert_no_queries { root_node.children.first.children.first.children.first } Chris@0: end Chris@0: Chris@0: def test_eager_association_loading_with_recursive_cascading_three_levels_has_one Chris@0: root_node = RecursivelyCascadedTreeMixin.find(:first, :include => { :first_child => { :first_child => :first_child } }, :order => 'mixins.id') Chris@0: assert_equal @rc4, assert_no_queries { root_node.first_child.first_child.first_child } Chris@0: end Chris@0: Chris@0: def test_eager_association_loading_with_recursive_cascading_three_levels_belongs_to Chris@0: leaf_node = RecursivelyCascadedTreeMixin.find(:first, :include => { :parent => { :parent => :parent } }, :order => 'mixins.id DESC') Chris@0: assert_equal @rc1, assert_no_queries { leaf_node.parent.parent.parent } Chris@0: end Chris@0: end Chris@0: Chris@0: class TreeTestWithoutOrder < Test::Unit::TestCase Chris@0: Chris@0: def setup Chris@0: setup_db Chris@0: @root1 = TreeMixinWithoutOrder.create! Chris@0: @root2 = TreeMixinWithoutOrder.create! Chris@0: end Chris@0: Chris@0: def teardown Chris@0: teardown_db Chris@0: end Chris@0: Chris@0: def test_root Chris@0: assert [@root1, @root2].include?(TreeMixinWithoutOrder.root) Chris@0: end Chris@0: Chris@0: def test_roots Chris@0: assert_equal [], [@root1, @root2] - TreeMixinWithoutOrder.roots Chris@0: end Chris@0: end