test/unit/test_page.rb in spontaneous-0.2.0.beta1 vs test/unit/test_page.rb in spontaneous-0.2.0.beta2

- old
+ new

@@ -1,376 +1,477 @@ # encoding: UTF-8 require File.expand_path('../../test_helper', __FILE__) -class PageTest < MiniTest::Spec - - def setup +describe "Page" do + before do @site = setup_site + Content.delete + class ::Page + field :title, :string + box :sub + end end - def teardown + after do + Object.send(:remove_const, :Page) + Object.send(:remove_const, :Piece) teardown_site end - context "Pages:" do - setup do - Content.delete - class Page < ::Page - field :title, :string - box :sub - end - class Piece < ::Piece; end + describe "Root page" do + it "be created by first page insert" do + p = Page.create + assert p.root? + p.path.must_equal "/" + p.slug.must_equal "" + p.parent.must_be_nil end - teardown do - PageTest.send(:remove_const, :Page) - PageTest.send(:remove_const, :Piece) + + it "be a singleton" do + p = Page.create + assert p.root? + q = Page.create + refute q.root? end - context "Root page" do - setup do - end - should "be created by first page insert" do - p = Page.create - p.root?.should be_true - p.path.should == "/" - p.slug.should == "" - p.parent.should be_nil - end + end - should "be a singleton" do - p = Page.create - p.root?.should be_true - q = Page.create - q.root?.should be_false - end + describe "invisible roots" do + before do + @root = Page.create + assert @root.root? + class ::ErrorPage < Page; end + ErrorPage.box :pages end - context "Slugs" do - setup do - end + after do + Object.send :remove_const, :ErrorPage rescue nil + end - should "be generated if missing" do - o = Page.create - p = Page.create - p.slug.should_not == "" - p.save - p.reload.slug.should_not == "" - end + it "is given a path starting with '#'" do + root = Page.create slug: "error" + root.path.must_equal "#error" + end - should "be made URL safe" do - o = Page.create - p = Page.create - p.slug = " something's illegal and ugly!!" - p.slug.should == "somethings-illegal-and-ugly" - p.save - p.reload.slug.should == "somethings-illegal-and-ugly" - end + it "re-calculates its path using '#'" do + root = ErrorPage.create slug: "error" + page = Page.new slug: "404" + root.pages << page + root.save + root.path.must_equal "#error" + root.slug = "changed" + root.save + root.path.must_equal "#changed" + page.reload.path.must_equal "#changed/404" + end - should "be set from title if using generated slug" do - r = Page.create - slug = Page.generate_default_slug - Page.stubs(:generate_default_slug).returns(slug) - o = Page.create(:title => "New Page") - p = Page.create(:title => "New Page") - o.slug.should == slug - r.sub << o - o.save - o = Page[o.id] - o.slug.should == slug - o.sub << p - o.save - o = Page[o.id] - o.slug.should == slug - o.title = "New Title" - o.save - o.reload - o.slug.should == "new-title" - o.title = "Another Title" - o.save - o.reload - o.slug.should == "new-title" - end + it "has paths that start with '#'" do + root = ErrorPage.create slug: "error" + page = Page.new slug: "404" + root.pages << page + root.save + page.path.must_equal "#error/404" + end - should "not be longer than 255 chars" do - o = Page.create - long_slug = (["bang"]*100) - o.slug = long_slug.join(' ') - o.slug.length.should == 255 - o.slug.should == long_slug.join('-')[0..254] - end + it "has a depth of 0" do + root = ErrorPage.create slug: "error" + root.depth.must_equal 0 end - context "Pages in tree" do - setup do - Content.delete - @p = Page.create - @p.root?.should be_true - @q = Page.new(:slug => 'q') - @r = Page.new(:slug => 'r') - @s = Page.new(:slug => 's') - @t = Page.new(:slug => 't') - @p.sub << @q - @q.sub << @r - @q.sub << @s - @s.sub << @t - @p.save - @q.save - @r.save - @s.save - @t.save - # doing this means that the == tests work below - @p = Page[@p.id] - @q = Page[@q.id] - @r = Page[@r.id] - @s = Page[@s.id] - @t = Page[@t.id] - end + it "raises an error if the alternate root doesn't have a slug" do + lambda { Page.create slug: "" }.must_raise Spontaneous::AnonymousRootException + end - should "be able to find a reference to their inline entry" do - @q.entry.class.should == Spontaneous::PagePiece - end + it "allows the creation of invisible roots without a visible root" do + Page.root.destroy + Page.root.must_equal nil + root = ErrorPage.create_root "error" + Page.root.must_equal nil + Site["#error"].must_equal root + end + end - should "have a reference to their parent" do - @p.parent.should be_nil - @q.parent.should === @p - @r.parent.should === @q - @s.parent.should === @q - @t.parent.should === @s - end - should "have a reference to their owner" do - @p.owner.should be_nil - @q.owner.should === @p - @r.owner.should === @q - @s.owner.should === @q - @t.owner.should === @s - end + describe "Slugs" do + it "be generated if missing" do + o = Page.create + p = Page.create + p.slug.wont_equal "" + p.save + p.reload.slug.wont_equal "" + end - should "know their container" do - @p.container.should be_nil - @q.container.should == @p.sub - @r.container.should == @q.sub - @s.container.should == @q.sub - @t.container.should == @s.sub - end + it "be made URL safe" do + o = Page.create + p = Page.create + p.slug = " something's illegal and ugly!!" + p.slug.must_equal "somethings-illegal-and-ugly" + p.save + p.reload.slug.must_equal "somethings-illegal-and-ugly" + end - should "know their containing box" do - @p.box.should be_nil - @q.box.should == @p.sub - @r.box.should == @q.sub - @s.box.should == @q.sub - @t.box.should == @s.sub - end + it "be set from title if using generated slug" do + r = Page.create + slug = Page.generate_default_slug + Page.stubs(:generate_default_slug).returns(slug) + o = Page.create(:title => "New Page") + p = Page.create(:title => "New Page") + o.slug.must_equal slug + r.sub << o + o.save + o = Page[o.id] + o.slug.must_equal slug + o.sub << p + o.save + o = Page[o.id] + o.slug.must_equal slug + o.title = "New Title" + o.save + o.reload + o.slug.must_equal "new-title" + o.title = "Another Title" + o.save + o.reload + o.slug.must_equal "new-title" + end - should "have a list of their children" do - @p.children.should == [@q] - @q.children.should == [@r, @s] - @r.children.should == [] - @s.children.should == [@t] - @t.children.should == [] - end + it "doesn't set a conflicting url on creation" do + r = Page.create + o = Page.create(:title => "New Page") + r.sub << o + o.save - should "have a reference to themselves as page" do - @p.page.should == @p - @q.page.should == @q - @r.page.should == @r - @s.page.should == @s - @t.page.should == @t - end + p = Page.create(:title => "New Page") + r.sub << p + p.save + slug_o = o.slug + slug_p = p.slug + o.slug.wont_equal p.slug + end - should "have a reference to themselves as content_instance" do - @p.content_instance.should == @p - end + it "fixes conflicting slugs automatically" do + r = Page.create + o = Page.create(:title => "New Page", :slug => "my-slug") + r.sub << o + o.save - should "keep track of their depth" do - @p.depth.should == 0 - @q.depth.should == 1 - @r.depth.should == 2 - @s.depth.should == 2 - @t.depth.should == 3 - end + p = Page.create(:title => "New Page") + r.sub << p + p.save + p.slug = "my-slug" + p.save + o.slug.wont_equal p.slug + p.path.must_equal "/my-slug-01" + end - should "have the correct page hierarchy" do - Page.box :things1 - Page.box :things2 - a = Page.new - c = Page.new - d = Page.new - e = Page.new - a.things1 << c - a.things2 << d - a.things2 << e - a.save - a.reload - c.reload - d.reload - e.reload - c.parent.should == a - d.parent.should == a - e.parent.should == a - c.content_ancestors.should == [a, a.things1] - d.content_ancestors.should == [a, a.things2] - e.content_ancestors.should == [a, a.things2] - # the zeroth box is 'sub' - c.page_order_string.should == "00001.00000" - d.page_order_string.should == "00002.00000" - e.page_order_string.should == "00002.00001" - end + it "fixes conflicting slugs created from titles automatically" do + r = Page.create + o = Page.create(:title => "New Page", :slug => "my-slug") + r.sub << o + o.save - should "have the correct page hierarchy for pages within pieces" do - Page.box :things - Piece.box :pages - a = Page.new - b = Piece.new - a.things << b - c = Page.new - d = Page.new - b.pages << c - b.pages << d - a.save - a.reload - b.reload - c.reload - d.reload - c.parent.should == a - c.content_ancestors.should == [a, a.things, b, b.pages] - c.page_order_string.should == "00001.00000.00000.00000" - d.page_order_string.should == "00001.00000.00000.00001" - end + p = Page.create(:title => "New Page") + r.sub << p + p.save + p.title = "My Slug" + p.save + p.slug.must_equal "my-slug-01" + o.slug.wont_equal p.slug + p.path.must_equal "/my-slug-01" + end - should "have correct paths" do - @p.path.should == "/" - @q.path.should == "/q" - @r.path.should == "/q/r" - @s.path.should == "/q/s" - @t.path.should == "/q/s/t" - end + it "not be longer than 64 chars" do + o = Page.create + long_slug = (["bang"]*100) + o.slug = long_slug.join(' ') + o.slug.length.must_equal 64 + o.slug.must_equal long_slug.join('-')[0..63] + end - should "update paths when being adopted" do - @p.sub.adopt(@s) - @s.reload - @t.reload - @s.path.should == "/s" - @t.path.should == "/s/t" - end + it "should crop titles at word boundaries" do + o = Page.create + long_slug = (["bangor"]*100) + expected = %w(bangor bangor bangor bangor bangor bangor bangor bangor bangor).join('-') + o.slug = long_slug.join(' ') + o.slug.length.must_equal expected.length + o.slug.must_equal expected + end - should "all have a reference to the root node" do - # @p.root?.should be_true - @p.root.should === @p - @q.root.should === @p - @r.root.should === @p - @s.root.should === @p - @t.root.should === @p - end + it "should just crop a very long word to the max length" do + o = Page.create + o.slug = "a"*100 + o.slug.length.must_equal 64 + end + end - should "have correct ancestor paths" do - @p.ancestor_path.should == [] - @q.ancestor_path.should == [@p.id] - @r.ancestor_path.should == [@p.id, @q.id] - @s.ancestor_path.should == [@p.id, @q.id] - @t.ancestor_path.should == [@p.id, @q.id, @s.id] - end - should "know their ancestors" do - # must be a better way to test these arrays - @p.ancestors.should === [] - @q.ancestors.should === [@p] - @r.ancestors.should == [@p, @q] - @s.ancestors.should == [@p, @q] - @t.ancestors.should === [@p, @q, @s] - end + describe "Pages in tree" do + before do + Content.delete + @p = Page.create + assert @p.root? + @q = Page.new(:slug => 'q') + @r = Page.new(:slug => 'r') + @s = Page.new(:slug => 's') + @t = Page.new(:slug => 't') + @p.sub << @q + @q.sub << @r + @q.sub << @s + @s.sub << @t + @p.save + @q.save + @r.save + @s.save + @t.save + # doing this means that the == tests work below + @p = Page[@p.id] + @q = Page[@q.id] + @r = Page[@r.id] + @s = Page[@s.id] + @t = Page[@t.id] + end - should "know their generation" do - @r.generation.should == [@r, @s] - @s.generation.should == [@r, @s] - end + it "be able to find a reference to their inline entry" do + @q.entry.class.must_equal Spontaneous::PagePiece + end - should "know their siblings" do - @r.siblings.should == [@s] - @s.siblings.should == [@r] - end + it "have a reference to their parent" do + @p.parent.must_be_nil + @q.parent.must_equal @p + @r.parent.must_equal @q + @s.parent.must_equal @q + @t.parent.must_equal @s + end + it "have a reference to their owner" do + @p.owner.must_be_nil + @q.owner.must_equal @p + @r.owner.must_equal @q + @s.owner.must_equal @q + @t.owner.must_equal @s + end - should "always have the right path" do - @q.slug = "changed" - @q.save - @p.reload.path.should == "/" - @q.reload.path.should == "/changed" - @r.reload.path.should == "/changed/#{@r.slug}" - @s.reload.path.should == "/changed/#{@s.slug}" - @t.reload.path.should == "/changed/#{@s.slug}/#{@t.slug}" - end + it "know their container" do + @p.container.must_be_nil + @q.container.must_equal @p.sub + @r.container.must_equal @q.sub + @s.container.must_equal @q.sub + @t.container.must_equal @s.sub + end - should "have direct access to ancestors at any depth" do - @q.ancestor(0).should == @p - @r.ancestor(0).should == @p - @r.ancestor(1).should == @q - @s.ancestor(1).should == @q - @t.ancestor(1).should == @q - @t.ancestor(2).should == @s - @t.ancestor(-1).should == @s - @t.ancestor(-2).should == @q - end + it "know their containing box" do + @p.box.must_be_nil + @q.box.must_equal @p.sub + @r.box.must_equal @q.sub + @s.box.must_equal @q.sub + @t.box.must_equal @s.sub + end - should "test for ancestry" do - @t.ancestor?(@s).should be_true - @t.ancestor?(@q).should be_true - @t.ancestor?(@p).should be_true - @q.ancestor?(@t).should be_false - end + it "have a list of their children" do + @p.children.must_equal [@q] + @q.children.must_equal [@r, @s] + @r.children.must_equal [] + @s.children.must_equal [@t] + @t.children.must_equal [] + end - should "know if it's in the current path" do - @t.active?(@s).should be_true - @t.active?(@t).should be_true - @t.active?(@q).should be_true - @t.active?(@p).should be_true - @q.active?(@t).should be_false - end + it "have a reference to themselves as page" do + @p.page.must_equal @p + @q.page.must_equal @q + @r.page.must_equal @r + @s.page.must_equal @s + @t.page.must_equal @t + end - should "provide a list of pages at any depth" do - @t.at_depth(2).should == [@r, @s] - @p.at_depth(1).should == [@q] - lambda { @p.at_depth(2) }.must_raise(ArgumentError) - end + it "have a reference to themselves as content_instance" do + @p.content_instance.must_equal @p end - context "page pieces" do - setup do - Page.box :things - Piece.box :things - @parent = Page.create - @piece = Piece.new - @child = Page.new - @parent.things << @piece - @piece.things << @child - @parent.save - @piece.save - @child.save - @page_piece = @parent.things.first.things.first - end + it "keep track of their depth" do + @p.depth.must_equal 0 + @q.depth.must_equal 1 + @r.depth.must_equal 2 + @s.depth.must_equal 2 + @t.depth.must_equal 3 + end - should "report their depth according to their position in the piece tree" do - @parent.depth.should == 0 - @parent.contents.first.depth.should == 1 - @parent.contents.first.contents.first.depth.should == 2 - end + it "have the correct page hierarchy" do + Page.box :things1 + Page.box :things2 + a = Page.new + c = Page.new + d = Page.new + e = Page.new + a.things1 << c + a.things2 << d + a.things2 << e + a.save + a.reload + c.reload + d.reload + e.reload + c.parent.must_equal a + d.parent.must_equal a + e.parent.must_equal a + c.content_ancestors.must_equal [a, a.things1] + d.content_ancestors.must_equal [a, a.things2] + e.content_ancestors.must_equal [a, a.things2] + # the zeroth box is 'sub' + c.page_order_string.must_equal "00001.00000" + d.page_order_string.must_equal "00002.00000" + e.page_order_string.must_equal "00002.00001" + end - should "know their page" do - @page_piece.page.should == @parent - end + it "have the correct page hierarchy for pages within pieces" do + Page.box :things + Piece.box :pages + a = Page.new + b = Piece.new + a.things << b + c = Page.new + d = Page.new + b.pages << c + b.pages << d + a.save + a.reload + b.reload + c.reload + d.reload + c.parent.must_equal a + c.content_ancestors.must_equal [a, a.things, b, b.pages] + c.page_order_string.must_equal "00001.00000.00000.00000" + d.page_order_string.must_equal "00001.00000.00000.00001" + end - should "know their container" do - @page_piece.container.should == @piece.things - end + it "have correct paths" do + @p.path.must_equal "/" + @q.path.must_equal "/q" + @r.path.must_equal "/q/r" + @s.path.must_equal "/q/s" + @t.path.must_equal "/q/s/t" + end - should "know their box" do - @page_piece.box.should == @piece.things - end + it "update paths when being adopted" do + @p.sub.adopt(@s) + @s.reload + @t.reload + @s.path.must_equal "/s" + @t.path.must_equal "/s/t" + end - should "know their parent" do - @page_piece.parent.should == @piece - end + it "all have a reference to the root node" do + @p.root.must_equal @p + @q.root.must_equal @p + @r.root.must_equal @p + @s.root.must_equal @p + @t.root.must_equal @p + end - should "know their owner" do - @page_piece.owner.should == @piece - end + it "have correct ancestor paths" do + @p.ancestor_path.must_equal [] + @q.ancestor_path.must_equal [@p.id] + @r.ancestor_path.must_equal [@p.id, @q.id] + @s.ancestor_path.must_equal [@p.id, @q.id] + @t.ancestor_path.must_equal [@p.id, @q.id, @s.id] + end + it "know their ancestors" do + # must be a better way to test these arrays + @p.ancestors.must_equal [] + @q.ancestors.must_equal [@p] + @r.ancestors.must_equal [@p, @q] + @s.ancestors.must_equal [@p, @q] + @t.ancestors.must_equal [@p, @q, @s] + end + + it "know their generation" do + @r.generation.must_equal [@r, @s] + @s.generation.must_equal [@r, @s] + end + + it "know their siblings" do + @r.siblings.must_equal [@s] + @s.siblings.must_equal [@r] + end + + it "always have the right path" do + @q.slug = "changed" + @q.save + @p.reload.path.must_equal "/" + @q.reload.path.must_equal "/changed" + @r.reload.path.must_equal "/changed/#{@r.slug}" + @s.reload.path.must_equal "/changed/#{@s.slug}" + @t.reload.path.must_equal "/changed/#{@s.slug}/#{@t.slug}" + end + + it "have direct access to ancestors at any depth" do + @q.ancestor(0).must_equal @p + @r.ancestor(0).must_equal @p + @r.ancestor(1).must_equal @q + @s.ancestor(1).must_equal @q + @t.ancestor(1).must_equal @q + @t.ancestor(2).must_equal @s + @t.ancestor(-1).must_equal @s + @t.ancestor(-2).must_equal @q + end + + it "test for ancestry" do + assert @t.ancestor?(@s) + assert @t.ancestor?(@q) + assert @t.ancestor?(@p) + refute @q.ancestor?(@t) + end + + it "know if it's in the current path" do + assert @t.active?(@s) + assert @t.active?(@t) + assert @t.active?(@q) + assert @t.active?(@p) + refute @q.active?(@t) + end + + it "provide a list of pages at any depth" do + @t.at_depth(2).must_equal [@r, @s] + @p.at_depth(1).must_equal [@q] + lambda { @p.at_depth(2) }.must_raise(ArgumentError) + end + end + + describe "page pieces" do + before do + Page.box :things + Piece.box :things + @parent = Page.create + @piece = Piece.new + @child = Page.new + @parent.things << @piece + @piece.things << @child + @parent.save + @piece.save + @child.save + @page_piece = @parent.things.first.things.first + end + + it "report their depth according to their position in the piece tree" do + @parent.depth.must_equal 0 + @parent.contents.first.depth.must_equal 1 + @parent.contents.first.contents.first.depth.must_equal 2 + end + + it "know their page" do + @page_piece.page.must_equal @parent + end + + it "know their container" do + @page_piece.container.must_equal @piece.things + end + + it "know their box" do + @page_piece.box.must_equal @piece.things + end + + it "know their parent" do + @page_piece.parent.must_equal @piece + end + + it "know their owner" do + @page_piece.owner.must_equal @piece end end end