Skip to content

Commit

Permalink
Added some macros to help setting up trees in specs
Browse files Browse the repository at this point in the history
  • Loading branch information
benedikt committed Jul 26, 2010
1 parent 155bf37 commit 97a3764
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 57 deletions.
113 changes: 62 additions & 51 deletions spec/mongoid/tree_spec.rb
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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

Expand Down
12 changes: 6 additions & 6 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
46 changes: 46 additions & 0 deletions spec/support/macros/tree_macros.rb
Original file line number Diff line number Diff line change
@@ -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
7 changes: 7 additions & 0 deletions spec/support/models/node.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Node
include Mongoid::Document
include Mongoid::Tree

field :name
end

0 comments on commit 97a3764

Please sign in to comment.