diff --git a/spec/mongoid/tree_spec.rb b/spec/mongoid/tree_spec.rb index fed4a69..eb083d8 100644 --- a/spec/mongoid/tree_spec.rb +++ b/spec/mongoid/tree_spec.rb @@ -1,10 +1,5 @@ require 'spec_helper' -class Node - include Mongoid::Document - include Mongoid::Tree -end - describe Mongoid::Tree do it "should reference many children as inverse of parent" do @@ -33,43 +28,53 @@ class Node describe 'when saved' do + before(:each) do + setup_tree <<-ENDTREE + - root: + - child: + - subchild: + - subsubchild + - other_root: + - other_child + ENDTREE + end + + it "should set the child's parent_id when added to parent's children" do + root = Node.create; child = Node.create + root.children << child + child.parent.should == root + child.parent_id.should == root.id + end + + it "should set the child's parent_id parent is set on child" do + root = Node.create; child = Node.create + child.parent = root + child.parent.should == root + child.parent_id.should == root.id + end + it "should rebuild its parent_ids" do - root = Node.create; child = Node.create; subchild = Node.create + root = Node.create; child = Node.create root.children << child - child.children << subchild # Mongoid implicitly saves - subchild.parent_ids.should == [root.id, child.id] + child.parent_ids.should == [root.id] end it "should rebuild its children's parent_ids when its own parent_ids changed" do - root = Node.create; child = Node.create; subchild = Node.create; new_root = Node.create - root.children << child - child.children << subchild - - new_root.children << child - - subchild.reload - subchild.parent_ids.should == [new_root.id, child.id] + other_root = node(:other_root); child = node(:child); subchild = node(:subchild); + other_root.children << child + subchild.reload # To get the updated version + subchild.parent_ids.should == [other_root.id, child.id] end it "should correctly rebuild its descendants' parent_ids when moved into an other subtree" do - root = Node.create; child = Node.create; subchild = Node.create; subsubchild = Node.create - new_root = Node.create; new_child = Node.create - - root.children << child - child.children << subchild - subchild.children << subsubchild - - subsubchild.parent_ids.should == [root.id, child.id, subchild.id] - - new_root.children << new_child - new_child.children << subchild + subchild = node(:subchild); subsubchild = node(:subsubchild); other_child = node(:other_child) + other_child.children << subchild subsubchild.reload - subsubchild.parent_ids.should == [new_root.id, new_child.id, subchild.id] + subsubchild.parent_ids.should == [node(:other_root).id, other_child.id, subchild.id] end it "should not rebuild its children's parent_ids when it's not required" do - root = Node.create; child = Node.create; - root.children << child + root = node(:root) root.should_not_receive(:rearrange_children) root.save end @@ -78,87 +83,93 @@ class Node describe 'utility methods' do - let!(:root) { Node.create } - let!(:child) { root.children << n = Node.create; n } - let!(:other_child) { root.children << n = Node.create; n } - let!(:subchild) { child.children << n = Node.create; n } + before(:each) do + setup_tree <<-ENDTREE + root: + - child: + - subchild + - other_child + ENDTREE + end describe '.root?' do it "should return true for root documents" do - root.should be_root + node(:root).should be_root end it "should return false for non-root documents" do - child.should_not be_root + node(:child).should_not be_root end end describe '.leaf?' do it "should return true for leaf documents" do - subchild.should be_leaf + node(:subchild).should be_leaf + node(:other_child).should be_leaf Node.new.should be_leaf end it "should return false for non-leaf documents" do - child.should_not be_leaf - root.should_not be_leaf + node(:child).should_not be_leaf + node(:root).should_not be_leaf end end describe '.root' do it "should return the root for this document" do - subchild.root.should == root + node(:subchild).root.should == node(:root) end end describe 'ancestors' do it ".ancestors should return the documents ancestors" do - subchild.ancestors.to_a.should == [root, child] + node(:subchild).ancestors.to_a.should == [node(:root), node(:child)] end it ".ancestors_and_self should return the documents ancestors and itself" do - subchild.ancestors_and_self.to_a.should == [root, child, subchild] + node(:subchild).ancestors_and_self.to_a.should == [node(:root), node(:child), node(:subchild)] end describe '.ancestor_of?' do it "should return true for ancestors" do - child.should be_ancestor_of(subchild) + node(:child).should be_ancestor_of(node(:subchild)) end it "should return false for non-ancestors" do - other_child.should_not be_ancestor_of(subchild) + node(:other_child).should_not be_ancestor_of(node(:subchild)) end end end describe 'descendants' do it ".descendants should return the documents descendants" do - root.descendants.to_a.should == [child, other_child, subchild] + node(:root).descendants.to_a.should =~ [node(:child), node(:other_child), node(:subchild)] end it ".descendants_and_self should return the documents descendants and itself" do - root.descendants_and_self.to_a.should == [root, child, other_child, subchild] + node(:root).descendants_and_self.to_a.should =~ [node(:root), node(:child), node(:other_child), node(:subchild)] end describe '.descendant_of?' do it "should return true for descendants" do - subchild.should be_descendant_of(child) - subchild.should be_descendant_of(root) + subchild = node(:subchild) + subchild.should be_descendant_of(node(:child)) + subchild.should be_descendant_of(node(:root)) end it "should return false for non-descendants" do - subchild.should_not be_descendant_of(other_child) + node(:subchild).should_not be_descendant_of(node(:other_child)) end end end describe 'siblings' do it ".siblings should return the documents siblings" do - child.siblings.to_a.should == [other_child] + node(:child).siblings.to_a.should == [node(:other_child)] end it ".siblings_and_self should return the documents siblings and itself" do - child.siblings_and_self.to_a.should == [child, other_child] + node(:child).siblings_and_self.to_a.should == [node(:child), node(:other_child)] end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 8ade456..9fe9bb8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -6,16 +6,16 @@ require 'rspec' -Dir['#{File.dirname(__FILE__)}/support/**/*.rb'].each { |f| require f } +Mongoid.configure do |config| + config.master = Mongo::Connection.new.db('mongoid_tree_test') + config.allow_dynamic_fields = false +end + +Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } RSpec.configure do |config| config.mock_with :rspec config.after :each do Mongoid.master.collections.reject { |c| c.name =~ /^system\./ }.each(&:drop) end -end - -Mongoid.configure do |config| - config.master = Mongo::Connection.new.db('mongoid_tree_test') - config.allow_dynamic_fields = false end \ No newline at end of file diff --git a/spec/support/macros/tree_macros.rb b/spec/support/macros/tree_macros.rb new file mode 100644 index 0000000..150442f --- /dev/null +++ b/spec/support/macros/tree_macros.rb @@ -0,0 +1,46 @@ +require 'yaml' + +module Mongoid::Tree::TreeMacros + + def setup_tree(tree) + create_tree(YAML.load(tree)) + end + + def node(name) + @nodes[name].reload + end + + def print_tree(node, print_ids = false, depth = 0) + print ' ' * depth + print '- ' unless depth == 0 + print node.name + print " (#{node.id})" if print_ids + print ':' if node.children.any? + print "\n" + node.children.each { |c| print_tree(c, print_ids, depth + 1) } + end + + private + + def create_tree(object) + case object + when String: return create_node(object) + when Array: object.each { |tree| create_tree(tree) } + when Hash: + name, children = object.first + node = create_node(name) + children.each { |c| node.children << create_tree(c) } + return node + end + end + + def create_node(name) + @nodes ||= HashWithIndifferentAccess.new + @nodes[name] = Node.create(:name => name) + end + +end + +RSpec.configure do |config| + config.include Mongoid::Tree::TreeMacros +end \ No newline at end of file diff --git a/spec/support/models/node.rb b/spec/support/models/node.rb new file mode 100644 index 0000000..bad96c3 --- /dev/null +++ b/spec/support/models/node.rb @@ -0,0 +1,7 @@ +class Node + include Mongoid::Document + include Mongoid::Tree + + field :name +end +