fix the specs for the page model

This commit is contained in:
Didier Lafforgue 2012-02-16 22:07:00 +01:00
parent 73b559260e
commit 02e48f5c36
8 changed files with 195 additions and 60 deletions

2
.rspec
View File

@ -1,2 +1,2 @@
--drb
--colour --colour
--backtrace

View File

@ -9,6 +9,13 @@ module Locomotive
include ::Mongoid::Tree include ::Mongoid::Tree
include ::Mongoid::Tree::Ordering include ::Mongoid::Tree::Ordering
## fields ##
field :depth, :type => Integer, :default => 0
## callbacks ##
before_save :persist_depth
before_destroy :delete_descendants
## indexes ## ## indexes ##
index :position index :position
index [:depth.asc, :position.asc] index [:depth.asc, :position.asc]
@ -88,6 +95,16 @@ module Locomotive
end end
end end
def depth
self.parent_ids.count
end
protected
def persist_depth
self.attributes[:depth] = self.depth
end
end end
end end
end end

View File

@ -42,7 +42,7 @@ module Locomotive
validates_presence_of :site, :title, :slug validates_presence_of :site, :title, :slug
validates_uniqueness_of :slug, :scope => [:site_id, :parent_id] validates_uniqueness_of :slug, :scope => [:site_id, :parent_id]
validates_uniqueness_of :handle, :allow_blank => true validates_uniqueness_of :handle, :allow_blank => true
validates_exclusion_of :slug, :in => Locomotive.config.reserved_slugs, :if => Proc.new { |p| p.depth == 0 } validates_exclusion_of :slug, :in => Locomotive.config.reserved_slugs, :if => Proc.new { |p| p.depth <= 1 }
## named scopes ## ## named scopes ##
scope :latest_updated, :order_by => [[:updated_at, :desc]], :limit => Locomotive.config.ui.latest_entries_nb scope :latest_updated, :order_by => [[:updated_at, :desc]], :limit => Locomotive.config.ui.latest_entries_nb

View File

@ -67,8 +67,7 @@ module Locomotive
:slug => slug, :slug => slug,
:title => ::I18n.t("attributes.defaults.pages.#{slug}.title"), :title => ::I18n.t("attributes.defaults.pages.#{slug}.title"),
:raw_template => ::I18n.t("attributes.defaults.pages.#{slug}.body"), :raw_template => ::I18n.t("attributes.defaults.pages.#{slug}.body"),
:published => true, :published => true
:depth => 0
}) })
end end
end end

View File

@ -6,7 +6,7 @@ module Locomotive
:domain => 'example.com', :domain => 'example.com',
:reserved_subdomains => %w{www admin email blog webmail mail support help site sites}, :reserved_subdomains => %w{www admin email blog webmail mail support help site sites},
# :forbidden_paths => %w{layouts snippets stylesheets javascripts assets admin system api}, # :forbidden_paths => %w{layouts snippets stylesheets javascripts assets admin system api},
:reserved_slugs => %w{stylesheets javascripts assets admin images api pages edit}, :reserved_slugs => %w{stylesheets javascripts assets admin locomotive images api pages edit},
:locales => %w{en de fr pt-BR it nl no es ru}, :locales => %w{en de fr pt-BR it nl no es ru},
:site_locales => %w{en de fr pt-BR it nl no es ru}, :site_locales => %w{en de fr pt-BR it nl no es ru},
:cookie_key => '_locomotive_session', :cookie_key => '_locomotive_session',

View File

@ -31,4 +31,45 @@ module Mongoid#:nodoc:
end end
end end
end end
# make the validators work with localized field
module Validations #:nodoc:
def read_attribute_for_validation_with_localization(attr)
if fields[attr.to_s] && fields[attr.to_s].localized?
send(attr.to_sym)
else
read_attribute_for_validation_without_localization(attr)
end
end
alias_method_chain :read_attribute_for_validation, :localization
class PresenceValidator < ActiveModel::EachValidator
def validate_each(document, attribute, value)
document.errors.add(attribute, :blank, options) if value.blank?
end
end
end
#
# class UniquenessValidator < ActiveModel::EachValidator
#
# protected
#
# def criterion_with_localization(document, attribute, value)
# field = document.fields[attribute.to_s]
# if field && field.localized? && !value.blank?
# value = document.send(attribute.to_sym)
# end
#
# criterion_without_localization(document, attribute, value)
# end
#
# alias_method_chain :criterion, :localization
#
# end
#
# end
end end

View File

@ -15,7 +15,6 @@ describe Locomotive::GlobalActionsCell do
end end
it 'has a link to edit my account' do it 'has a link to edit my account' do
puts "last test"
menu.should have_link('Admin') menu.should have_link('Admin')
end end

View File

@ -13,29 +13,30 @@ describe Locomotive::Page do
FactoryGirl.build(:page).should be_valid FactoryGirl.build(:page).should be_valid
end end
# Validations ## describe 'validation' do
%w{site title}.each do |field| %w{site title}.each do |field|
it "should validate presence of #{field}" do it "requires the presence of the #{field}" do
page = FactoryGirl.build(:page, field.to_sym => nil) page = FactoryGirl.build(:page, field.to_sym => nil)
page.should_not be_valid page.should_not be_valid
page.errors[field.to_sym].should == ["can't be blank"] page.errors[field.to_sym].should == ["can't be blank"]
end end
end end
it 'should validate presence of slug' do it 'requires the presence of the slug' do
page = FactoryGirl.build(:page, :title => nil, :slug => nil) page = FactoryGirl.build(:page, :title => nil, :slug => nil)
page.should_not be_valid page.should_not be_valid
page.errors[:slug].should == ["can't be blank"] page.errors[:slug].should == ["can't be blank"]
end end
it 'should validate uniqueness of slug' do it 'requires the uniqueness of the slug' do
page = FactoryGirl.create(:page) page = FactoryGirl.create(:page)
(page = FactoryGirl.build(:page, :site => page.site)).should_not be_valid another_page = FactoryGirl.build(:page, :site => page.site)
page.errors[:slug].should == ["is already taken"] another_page.should_not be_valid
another_page.errors[:slug].should == ["is already taken"]
end end
it 'should validate uniqueness of slug within a "folder"' do it 'requires the uniqueness of the slug within a "folder"' do
site = FactoryGirl.create(:site) site = FactoryGirl.create(:site)
root = FactoryGirl.create(:page, :slug => 'index', :site => site) root = FactoryGirl.create(:page, :slug => 'index', :site => site)
child_1 = FactoryGirl.create(:page, :slug => 'first_child', :parent => root, :site => site) child_1 = FactoryGirl.create(:page, :slug => 'first_child', :parent => root, :site => site)
@ -46,14 +47,37 @@ describe Locomotive::Page do
page.valid?.should be_true page.valid?.should be_true
end end
%w{admin stylesheets images javascripts}.each do |slug| %w{admin locomotive stylesheets images javascripts}.each do |slug|
it "should consider '#{slug}' as invalid" do it "considers '#{slug}' as invalid" do
page = FactoryGirl.build(:page, :slug => slug) page = FactoryGirl.build(:page, :slug => slug)
page.stubs(:depth).returns(1)
page.should_not be_valid page.should_not be_valid
page.errors[:slug].should == ["is reserved"] page.errors[:slug].should == ["is reserved"]
end end
end end
context '#i18n' do
before(:each) do
::Mongoid::Fields::I18n.locale = 'en'
@page = FactoryGirl.build(:page, :title => 'Hello world')
::Mongoid::Fields::I18n.locale = 'fr'
end
after(:all) do
::Mongoid::Fields::I18n.locale = 'en'
end
it 'requires the presence of the title' do
@page.title = ''
@page.valid?.should be_false
@page.errors[:title].should == ["can't be blank"]
end
end
end
# Named scopes ## # Named scopes ##
# Associations ## # Associations ##
@ -64,7 +88,9 @@ describe Locomotive::Page do
it 'should tell if the page is the index one' do it 'should tell if the page is the index one' do
FactoryGirl.build(:page, :slug => 'index', :site => nil).index?.should be_true FactoryGirl.build(:page, :slug => 'index', :site => nil).index?.should be_true
FactoryGirl.build(:page, :slug => 'index', :depth => 1, :site => nil).index?.should be_false page = FactoryGirl.build(:page, :slug => 'index', :site => nil)
page.stubs(:depth).returns(1)
page.index?.should be_false
end end
it 'should have normalized slug' do it 'should have normalized slug' do
@ -108,44 +134,42 @@ describe Locomotive::Page do
end end
describe 'acts as tree' do describe 'tree organization' do
before(:each) do before(:each) do
@home = FactoryGirl.create(:page) @home = FactoryGirl.create(:page)
@child_1 = FactoryGirl.create(:page, :title => 'Subpage 1', :slug => 'foo', :parent_id => @home._id, :site => @home.site) @child_1 = FactoryGirl.create(:page, :title => 'Subpage 1', :slug => 'foo', :parent_id => @home._id, :site => @home.site)
end end
it 'should add root elements' do it 'adds root elements' do
page_404 = FactoryGirl.create(:page, :title => 'Page not found', :slug => '404', :site => @home.site) page_404 = FactoryGirl.create(:page, :title => 'Page not found', :slug => '404', :site => @home.site)
Locomotive::Page.roots.count.should == 2 Locomotive::Page.roots.count.should == 2
Locomotive::Page.roots.should == [@home, page_404] Locomotive::Page.roots.should == [@home, page_404]
end end
it 'should add sub pages' do it 'adds sub pages' do
child_2 = FactoryGirl.create(:page, :title => 'Subpage 2', :slug => 'bar', :parent => @home, :site => @home.site) child_2 = FactoryGirl.create(:page, :title => 'Subpage 2', :slug => 'bar', :parent => @home, :site => @home.site)
@home = Locomotive::Page.find(@home.id) @home = Locomotive::Page.find(@home.id)
@home.children.count.should == 2 @home.children.count.should == 2
@home.children.should == [@child_1, child_2] @home.children.should == [@child_1, child_2]
end end
it 'should move its children accordingly' do it 'moves its children accordingly' do
sub_child_1 = FactoryGirl.create(:page, :title => 'Sub Subpage 1', :slug => 'bar', :parent => @child_1, :site => @home.site) sub_child_1 = FactoryGirl.create(:page, :title => 'Sub Subpage 1', :slug => 'bar', :parent => @child_1, :site => @home.site)
archives = FactoryGirl.create(:page, :title => 'archives', :slug => 'archives', :parent => @home, :site => @home.site) archives = FactoryGirl.create(:page, :title => 'archives', :slug => 'archives', :parent => @home, :site => @home.site)
posts = FactoryGirl.create(:page, :title => 'posts', :slug => 'posts', :parent => archives, :site => @home.site) posts = FactoryGirl.create(:page, :title => 'posts', :slug => 'posts', :parent => archives, :site => @home.site)
@child_1.parent_id = archives._id @child_1.parent = archives
@child_1.save @child_1.save
@child_1.position.should == 2
@home.reload.children.count.should == 1 @home.reload.children.count.should == 1
archives.reload.children.count.should == 2 archives.reload.children.count.should == 2
archives.children.last.depth.should == 2 archives.children.last.depth.should == 2
archives.children.last.position.should == 2
archives.children.last.children.first.depth.should == 3 archives.children.last.children.first.depth.should == 3
end end
it 'should destroy descendants as well' do it 'destroys descendants as well' do
FactoryGirl.create(:page, :title => 'Sub Subpage 1', :slug => 'bar', :parent_id => @child_1._id, :site => @home.site) FactoryGirl.create(:page, :title => 'Sub Subpage 1', :slug => 'bar', :parent_id => @child_1._id, :site => @home.site)
@child_1.destroy @child_1.destroy
Locomotive::Page.where(:slug => 'bar').first.should be_nil Locomotive::Page.where(:slug => 'bar').first.should be_nil
@ -163,12 +187,12 @@ describe Locomotive::Page do
end end
it 'should be at the bottom of the folder once created' do it 'should be at the bottom of the folder once created' do
[@child_1, @child_2, @child_3].each_with_index { |c, i| c.position.should == i + 1 } [@child_1, @child_2, @child_3].each_with_index { |c, i| c.position.should == i }
end end
it 'should have its position updated if a sibling is removed' do it 'should have its position updated if a sibling is removed' do
@child_2.destroy @child_2.destroy
[@child_1, @child_3.reload].each_with_index { |c, i| c.position.should == i + 1 } [@child_1, @child_3.reload].each_with_index { |c, i| c.position.should == i }
end end
end end
@ -176,8 +200,9 @@ describe Locomotive::Page do
describe 'templatized extension' do describe 'templatized extension' do
before(:each) do before(:each) do
@page = FactoryGirl.build(:page, :site => nil, :templatized => true, :content_type_id => 42) @page = FactoryGirl.build(:page, :templatized => true, :target_klass_name => 'Foo')
Locomotive::ContentType.stubs(:find).returns(FactoryGirl.build(:content_type, :site => nil)) # @page.stubs(:target_klass)
# Locomotive::ContentType.stubs(:find).returns(FactoryGirl.build(:content_type, :site => nil))
end end
it 'is considered as a templatized page' do it 'is considered as a templatized page' do
@ -189,8 +214,52 @@ describe Locomotive::Page do
@page.slug.should == 'content_type_template' @page.slug.should == 'content_type_template'
end end
it 'does forget to set the content type id' do it 'returns the target klass' do
@page.content_type_id.should == 42 @page.target_klass.should == Foo
end
it 'has a name for the target entry' do
@page.target_entry_name.should == 'foo'
end
it 'uses the find_by_permalink method when fetching the entry' do
Foo.expects(:find_by_permalink)
@page.fetch_target_entry('foo')
end
context 'using a content type' do
before(:each) do
@site = FactoryGirl.build(:site)
@content_type = FactoryGirl.build(:content_type, :slug => 'posts', :site => @site)
@page.site = @site
@page.target_klass_name = 'Locomotive::Entry42'
end
it 'has a name for the target entry' do
@site.stubs(:content_types).returns(mock(:find => @content_type))
@page.target_entry_name.should == 'post'
end
context '#security' do
before(:each) do
Locomotive::ContentType.stubs(:find).returns(@content_type)
end
it 'is valid if the content type belongs to the site' do
@page.send(:ensure_target_klass_name_security)
@page.errors.should be_empty
end
it 'does not valid the page if the content type does not belong to the site' do
@content_type.site = FactoryGirl.build(:site)
@page.send(:ensure_target_klass_name_security)
@page.errors[:target_klass_name].should == ['presents a security problem']
end
end
end end
end end
@ -198,12 +267,12 @@ describe Locomotive::Page do
describe 'listed extension' do describe 'listed extension' do
it 'is considered as a visible page' do it 'is considered as a visible page' do
@page = FactoryGirl.build(:page, :site => nil, :content_type_id => 42) @page = FactoryGirl.build(:page, :site => nil)
@page.listed?.should be_true @page.listed?.should be_true
end end
it 'is not considered as a visible page' do it 'is not considered as a visible page' do
@page = FactoryGirl.build(:page, :site => nil, :listed => false, :content_type_id => 42) @page = FactoryGirl.build(:page, :site => nil, :listed => false)
@page.listed?.should be_false @page.listed?.should be_false
end end
@ -231,4 +300,14 @@ describe Locomotive::Page do
@page.errors[:redirect_url].should == ["is invalid"] @page.errors[:redirect_url].should == ["is invalid"]
end end
end end
class Foo
end
class Locomotive::Entry42
end
def fake_bson_id(id)
BSON::ObjectId(id.to_s.rjust(24, '0'))
end
end end