alchemy_cms 2.6.3 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.simplecov +14 -0
- data/.travis.yml +1 -1
- data/Gemfile +7 -6
- data/README.md +15 -5
- data/alchemy_cms.gemspec +3 -2
- data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +9 -17
- data/app/assets/javascripts/alchemy/alchemy.dirty.js.coffee +70 -0
- data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee +80 -0
- data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +43 -19
- data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +3 -1
- data/app/assets/javascripts/alchemy/alchemy.js +4 -2
- data/app/assets/javascripts/alchemy/alchemy.onload.js.coffee +1 -1
- data/app/assets/javascripts/alchemy/alchemy.spinner.js.coffee +14 -0
- data/app/assets/javascripts/alchemy/alchemy.tinymce.js.coffee.erb +96 -0
- data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +22 -0
- data/app/assets/javascripts/alchemy/alchemy.windows.js.coffee +28 -17
- data/app/assets/stylesheets/alchemy/base.scss +6 -0
- data/app/assets/stylesheets/alchemy/elements.scss +2 -28
- data/app/assets/stylesheets/alchemy/errors.scss +1 -1
- data/app/assets/stylesheets/alchemy/menubar.css.scss +2 -0
- data/app/assets/stylesheets/alchemy/sitemap.scss +21 -34
- data/app/assets/stylesheets/alchemy/tables.scss +13 -3
- data/app/controllers/alchemy/admin/attachments_controller.rb +10 -5
- data/app/controllers/alchemy/admin/base_controller.rb +19 -0
- data/app/controllers/alchemy/admin/contents_controller.rb +1 -4
- data/app/controllers/alchemy/admin/dashboard_controller.rb +2 -1
- data/app/controllers/alchemy/admin/elements_controller.rb +1 -1
- data/app/controllers/alchemy/admin/essence_files_controller.rb +1 -1
- data/app/controllers/alchemy/admin/essence_pictures_controller.rb +70 -56
- data/app/controllers/alchemy/admin/pages_controller.rb +37 -114
- data/app/controllers/alchemy/admin/pictures_controller.rb +5 -12
- data/app/controllers/alchemy/admin/resources_controller.rb +3 -1
- data/app/controllers/alchemy/admin/trash_controller.rb +1 -1
- data/app/controllers/alchemy/attachments_controller.rb +1 -1
- data/app/controllers/alchemy/base_controller.rb +3 -15
- data/app/controllers/alchemy/messages_controller.rb +4 -10
- data/app/controllers/alchemy/pages_controller.rb +6 -6
- data/app/controllers/alchemy/passwords_controller.rb +1 -1
- data/app/controllers/alchemy/user_sessions_controller.rb +1 -1
- data/app/helpers/alchemy/admin/base_helper.rb +49 -230
- data/app/helpers/alchemy/admin/contents_helper.rb +5 -1
- data/app/helpers/alchemy/admin/elements_helper.rb +19 -47
- data/app/helpers/alchemy/admin/essences_helper.rb +59 -17
- data/app/helpers/alchemy/admin/navigation_helper.rb +204 -0
- data/app/helpers/alchemy/admin/pages_helper.rb +22 -79
- data/app/helpers/alchemy/admin/pictures_helper.rb +1 -1
- data/app/helpers/alchemy/admin/tags_helper.rb +42 -0
- data/app/helpers/alchemy/base_helper.rb +0 -11
- data/app/helpers/alchemy/elements_helper.rb +48 -25
- data/app/helpers/alchemy/essences_helper.rb +0 -20
- data/app/helpers/alchemy/pages_helper.rb +18 -14
- data/app/helpers/alchemy/url_helper.rb +1 -0
- data/app/mailers/alchemy/messages.rb +4 -6
- data/app/models/alchemy/attachment.rb +3 -0
- data/app/models/alchemy/cell.rb +33 -35
- data/app/models/alchemy/content.rb +20 -111
- data/app/models/alchemy/content/factory.rb +188 -0
- data/app/models/alchemy/element.rb +51 -200
- data/app/models/alchemy/element/definitions.rb +52 -0
- data/app/models/alchemy/element/presenters.rb +87 -0
- data/app/models/alchemy/essence_date.rb +1 -1
- data/app/models/alchemy/essence_file.rb +6 -7
- data/app/models/alchemy/essence_picture.rb +19 -4
- data/app/models/alchemy/message.rb +18 -14
- data/app/models/alchemy/page.rb +120 -214
- data/app/models/alchemy/page/elements.rb +145 -36
- data/app/models/alchemy/page/natures.rb +90 -0
- data/app/models/alchemy/page/scopes.rb +93 -0
- data/app/models/alchemy/page/users.rb +25 -0
- data/app/models/alchemy/picture.rb +15 -0
- data/app/models/alchemy/site.rb +15 -1
- data/app/models/alchemy/site/layout.rb +38 -0
- data/app/models/alchemy/user.rb +13 -3
- data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +7 -7
- data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +8 -8
- data/app/views/alchemy/admin/attachments/_tag_list.html.erb +1 -16
- data/app/views/alchemy/admin/attachments/destroy.js.erb +1 -4
- data/app/views/alchemy/admin/contents/create.js.erb +1 -1
- data/app/views/alchemy/admin/dashboard/index.html.erb +14 -13
- data/app/views/alchemy/admin/elements/_element_head.html.erb +7 -7
- data/app/views/alchemy/admin/elements/_refresh_editor.js.erb +10 -0
- data/app/views/alchemy/admin/elements/create.js.erb +44 -44
- data/app/views/alchemy/admin/elements/fold.js.erb +22 -26
- data/app/views/alchemy/admin/elements/trash.js.erb +1 -1
- data/app/views/alchemy/admin/elements/update.js.erb +22 -25
- data/app/views/alchemy/admin/essence_files/assign.js.erb +8 -3
- data/app/views/alchemy/admin/essence_pictures/crop.html.erb +14 -12
- data/app/views/alchemy/admin/essence_pictures/edit.html.erb +22 -39
- data/app/views/alchemy/admin/pages/_page.html.erb +73 -80
- data/app/views/alchemy/admin/pages/destroy.js.erb +2 -2
- data/app/views/alchemy/admin/pages/edit.html.erb +21 -18
- data/app/views/alchemy/admin/pages/fold.js.erb +1 -0
- data/app/views/alchemy/admin/pages/info.html.erb +32 -0
- data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +11 -13
- data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +20 -20
- data/app/views/alchemy/admin/partials/_sub_navigation.html.erb +8 -0
- data/app/views/alchemy/admin/partials/_toolbar_button.html.erb +25 -0
- data/app/views/alchemy/admin/partials/_upload_form.html.erb +15 -15
- data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +39 -39
- data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +10 -10
- data/app/views/alchemy/admin/pictures/_tag_list.html.erb +1 -16
- data/app/views/alchemy/admin/resources/destroy.js.erb +1 -1
- data/app/views/alchemy/base/500.html.erb +1 -1
- data/app/views/alchemy/base/permission_denied.js.erb +1 -1
- data/app/views/alchemy/base/redirect.js.erb +1 -1
- data/app/views/alchemy/essences/_essence_link_editor.html.erb +1 -1
- data/app/views/alchemy/essences/_essence_picture_editor.html.erb +1 -1
- data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +1 -1
- data/app/views/alchemy/essences/_essence_text_editor.html.erb +1 -1
- data/app/views/alchemy/essences/{_essence_picture_tools.html.erb → shared/_essence_picture_tools.html.erb} +5 -5
- data/app/views/alchemy/essences/{_linkable_essence_tools.html.erb → shared/_linkable_essence_tools.html.erb} +0 -0
- data/app/views/alchemy/messages/contact_form_mail.de.text.erb +12 -0
- data/app/views/alchemy/messages/contact_form_mail.en.text.erb +12 -0
- data/app/views/alchemy/notifications/reset_password_instructions.de.text.erb +1 -1
- data/app/views/alchemy/notifications/reset_password_instructions.en.text.erb +2 -2
- data/app/views/alchemy/pages/sitemap.xml.erb +3 -5
- data/app/views/alchemy/user_sessions/leave.html.erb +1 -1
- data/app/views/layouts/alchemy/admin.html.erb +4 -2
- data/app/views/layouts/alchemy/sitemap.xml.erb +1 -1
- data/bin/alchemy +7 -13
- data/config/alchemy/config.yml +1 -0
- data/config/authorization_rules.rb +2 -3
- data/config/initializers/dragonfly.rb +2 -0
- data/config/locales/alchemy.de.yml +8 -9
- data/config/locales/alchemy.en.yml +7 -4
- data/config/routes.rb +3 -0
- data/db/migrate/{20130214233001_alchemy_two_point_five.rb → 20130827094554_alchemy_two_point_six.rb} +29 -6
- data/lib/alchemy/auth/engine.rb +9 -0
- data/lib/alchemy/capistrano.rb +37 -12
- data/lib/alchemy/config.rb +48 -35
- data/lib/alchemy/engine.rb +35 -6
- data/lib/alchemy/essence.rb +25 -29
- data/lib/alchemy/ferret/search.rb +86 -0
- data/lib/alchemy/{scoped_pagination_url_helper.rb → kaminari/scoped_pagination_url_helper.rb} +0 -0
- data/lib/alchemy/logger.rb +3 -4
- data/lib/alchemy/page_layout.rb +124 -55
- data/lib/alchemy/resource.rb +0 -10
- data/lib/alchemy/resources_helper.rb +0 -5
- data/lib/alchemy/seeder.rb +1 -32
- data/lib/alchemy/shell.rb +6 -1
- data/lib/alchemy/tinymce.rb +41 -32
- data/lib/alchemy/upgrader.rb +3 -1
- data/lib/alchemy/upgrader/two_point_five.rb +15 -8
- data/lib/alchemy/upgrader/two_point_one.rb +10 -10
- data/lib/alchemy/upgrader/two_point_two.rb +96 -51
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy_cms.rb +5 -46
- data/lib/rails/generators/alchemy/deploy_script/templates/deploy.rb.tt +1 -1
- data/lib/rails/generators/alchemy/devise/devise_generator.rb +9 -4
- data/lib/rails/generators/alchemy/essence/essence_generator.rb +7 -6
- data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +1 -1
- data/lib/rails/generators/alchemy/scaffold/files/_standard.html.erb +1 -0
- data/lib/rails/generators/alchemy/scaffold/scaffold_generator.rb +1 -0
- data/lib/rails/generators/alchemy/site_layouts/site_layouts_generator.rb +23 -0
- data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.erb +1 -0
- data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.haml +1 -0
- data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.slim +1 -0
- data/lib/rails/templates/alchemy.rb +2 -2
- data/lib/tasks/alchemy/db.rake +3 -1
- data/lib/tasks/alchemy/tidy.rake +82 -0
- data/lib/tasks/alchemy/upgrade.rake +2 -1
- data/spec/controllers/admin/attachments_controller_spec.rb +124 -0
- data/spec/controllers/admin/base_controller_spec.rb +35 -0
- data/spec/controllers/admin/clipboard_controller_spec.rb +1 -1
- data/spec/controllers/admin/contents_controller_spec.rb +17 -26
- data/spec/controllers/admin/dashboard_controller_spec.rb +121 -0
- data/spec/controllers/admin/elements_controller_spec.rb +1 -1
- data/spec/controllers/admin/essence_files_controller_spec.rb +67 -0
- data/spec/controllers/admin/essence_pictures_controller_spec.rb +161 -0
- data/spec/controllers/admin/languages_controller_spec.rb +1 -1
- data/spec/controllers/admin/layoutpages_controller_spec.rb +28 -0
- data/spec/controllers/admin/pages_controller_spec.rb +164 -118
- data/spec/controllers/admin/pictures_controller_spec.rb +89 -0
- data/spec/controllers/admin/trash_controller_spec.rb +21 -31
- data/spec/controllers/admin/users_controller_spec.rb +114 -85
- data/spec/controllers/attachments_controller_spec.rb +6 -2
- data/spec/controllers/base_controller_spec.rb +22 -0
- data/spec/controllers/elements_controller_spec.rb +1 -1
- data/spec/controllers/messages_controller_spec.rb +200 -0
- data/spec/controllers/pictures_controller_spec.rb +1 -1
- data/spec/controllers/user_sessions_controller_spec.rb +7 -6
- data/spec/controllers/users_controller_spec.rb +2 -2
- data/spec/dummy/config/alchemy/cells.yml +2 -0
- data/spec/dummy/config/application.rb +19 -8
- data/spec/dummy/db/migrate/{20130214233001_alchemy_two_point_five.rb → 20130827094554_alchemy_two_point_six.rb} +29 -6
- data/spec/dummy/db/schema.rb +1 -1
- data/spec/fast_specs.rb +15 -0
- data/spec/helpers/admin/base_helper_spec.rb +53 -34
- data/spec/helpers/admin/contents_helper_spec.rb +15 -7
- data/spec/helpers/admin/elements_helper_spec.rb +79 -34
- data/spec/helpers/admin/essences_helper_spec.rb +45 -31
- data/spec/helpers/admin/navigation_helper_spec.rb +204 -0
- data/spec/helpers/admin/pages_helper_spec.rb +25 -15
- data/spec/helpers/admin/tags_helper_spec.rb +62 -2
- data/spec/helpers/elements_helper_spec.rb +202 -138
- data/spec/helpers/pages_helper_spec.rb +48 -0
- data/spec/helpers/url_helper_spec.rb +7 -0
- data/spec/libraries/config_spec.rb +110 -3
- data/spec/libraries/essence_spec.rb +29 -9
- data/spec/libraries/page_layout_spec.rb +134 -0
- data/spec/libraries/resource_spec.rb +3 -16
- data/spec/libraries/resources_helper_spec.rb +4 -8
- data/spec/libraries/shell_spec.rb +1 -0
- data/spec/libraries/tinymce_spec.rb +61 -0
- data/spec/mailers/messages_spec.rb +23 -0
- data/spec/models/attachment_spec.rb +45 -0
- data/spec/models/cell_spec.rb +62 -9
- data/spec/models/content_spec.rb +110 -28
- data/spec/models/element_spec.rb +275 -253
- data/spec/models/essence_date_spec.rb +25 -0
- data/spec/models/essence_file_spec.rb +23 -0
- data/spec/models/essence_html_spec.rb +13 -0
- data/spec/models/essence_picture_spec.rb +16 -0
- data/spec/models/essence_text_spec.rb +29 -0
- data/spec/models/language_spec.rb +34 -0
- data/spec/models/message_spec.rb +43 -0
- data/spec/models/page_spec.rb +726 -567
- data/spec/models/picture_spec.rb +98 -0
- data/spec/models/site_spec.rb +60 -2
- data/spec/models/tag_spec.rb +31 -0
- data/spec/models/user_spec.rb +4 -4
- data/spec/spec_helper.rb +49 -58
- data/spec/support/alchemy/controller_helpers.rb +35 -0
- data/spec/support/alchemy/{specs_helpers.rb → integration_helpers.rb} +4 -8
- data/spec/{factories.rb → support/factories.rb} +11 -1
- data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +2 -8
- metadata +166 -106
- data/Guardfile +0 -16
- data/app/assets/javascripts/alchemy/alchemy.dirty.js +0 -93
- data/app/assets/javascripts/alchemy/alchemy.dragndrop.js +0 -122
- data/app/models/alchemy/tree_node.rb +0 -4
- data/app/views/alchemy/admin/pages/_page_infos.html.erb +0 -3
- data/app/views/alchemy/admin/partials/_sub_navigation_tab.html.erb +0 -8
- data/app/views/alchemy/messages/contact_form_mail.text.erb +0 -12
- data/config/initializers/kaminari_config.rb +0 -9
- data/db/migrate/20130221200514_migrate_attachments_to_dragonfly.rb +0 -21
- data/db/migrate/20130312205327_change_alchemy_users_role_to_roles.rb +0 -11
- data/lib/alchemy/auth_engine.rb +0 -7
- data/lib/alchemy/authentication_helpers.rb +0 -9
- data/lib/alchemy/ferret_search.rb +0 -84
- data/lib/extensions/array.rb +0 -25
- data/lib/extensions/hash.rb +0 -34
- data/spec/dummy/db/migrate/20130221200514_migrate_attachments_to_dragonfly.rb +0 -21
- data/spec/dummy/db/migrate/20130312205327_change_alchemy_users_role_to_roles.rb +0 -11
- data/spec/models/page_layout_spec.rb +0 -60
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Alchemy
|
|
4
|
+
describe EssenceDate do
|
|
5
|
+
let(:essence_date) { EssenceDate.new }
|
|
6
|
+
|
|
7
|
+
describe '#preview_text' do
|
|
8
|
+
|
|
9
|
+
context "if no date set" do
|
|
10
|
+
it "should return an empty string" do
|
|
11
|
+
expect(essence_date.preview_text).to eq("")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
context "if date set" do
|
|
16
|
+
it "should format the date by i18n" do
|
|
17
|
+
essence_date.date = Date.today
|
|
18
|
+
::I18n.should_receive(:l).with(essence_date.date, format: :date)
|
|
19
|
+
essence_date.preview_text
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Alchemy
|
|
4
|
+
describe EssenceFile do
|
|
5
|
+
|
|
6
|
+
describe '#preview_text' do
|
|
7
|
+
let(:attachment) { mock_model(Attachment, name: 'File') }
|
|
8
|
+
let(:essence) { EssenceFile.new }
|
|
9
|
+
|
|
10
|
+
it "returns the attachment's name as preview text" do
|
|
11
|
+
essence.stub(:attachment).and_return(attachment)
|
|
12
|
+
essence.preview_text.should == 'File'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
context "with no attachment assigned" do
|
|
16
|
+
it "returns empty string" do
|
|
17
|
+
essence.preview_text.should == ''
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Alchemy
|
|
4
|
+
describe EssenceHtml do
|
|
5
|
+
describe '#preview_text' do
|
|
6
|
+
let (:essence_html) { EssenceHtml.new(source: '<p>hello!</p>') }
|
|
7
|
+
|
|
8
|
+
it "should return html escaped source code" do
|
|
9
|
+
expect(essence_html.preview_text).to eq('<p>hello!</p>')
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -23,5 +23,21 @@ module Alchemy
|
|
|
23
23
|
essence.caption.should == "hello<br/>kitty"
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
describe '#preview_text' do
|
|
27
|
+
let(:picture) { mock_model(Picture, name: 'Cute Cat Kittens')}
|
|
28
|
+
let(:essence) { EssencePicture.new }
|
|
29
|
+
|
|
30
|
+
it "should return the pictures name as preview text" do
|
|
31
|
+
essence.stub(:picture).and_return(picture)
|
|
32
|
+
essence.preview_text.should == 'Cute Cat Kittens'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context "with no picture assigned" do
|
|
36
|
+
it "returns empty string" do
|
|
37
|
+
essence.preview_text.should == ''
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
26
42
|
end
|
|
27
43
|
end
|
|
@@ -37,5 +37,34 @@ module Alchemy
|
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
+
context "acts_as_essence methods" do
|
|
41
|
+
|
|
42
|
+
describe '#preview_text' do
|
|
43
|
+
let(:essence) { EssenceText.new(body: 'Lorem ipsum') }
|
|
44
|
+
|
|
45
|
+
it "should return a preview text" do
|
|
46
|
+
essence.preview_text.should == 'Lorem ipsum'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
context "with maxlength of 2" do
|
|
50
|
+
it "should return very short preview text" do
|
|
51
|
+
essence.preview_text(2).should == 'Lo'
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context "with another preview_text_column defined" do
|
|
56
|
+
before {
|
|
57
|
+
essence.stub(:title).and_return('Title column')
|
|
58
|
+
essence.stub(:preview_text_column).and_return(:title)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
it "should use this column as preview text method" do
|
|
62
|
+
essence.preview_text.should == 'Title column'
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
68
|
+
|
|
40
69
|
end
|
|
41
70
|
end
|
|
@@ -117,5 +117,39 @@ module Alchemy
|
|
|
117
117
|
|
|
118
118
|
end
|
|
119
119
|
|
|
120
|
+
describe '.all_codes_for_published' do
|
|
121
|
+
it "should return all codes of published languages" do
|
|
122
|
+
Language.stub!(:published).and_return([mock_model('Language', code: 'de'), mock_model('Language', code: 'en')])
|
|
123
|
+
expect(Language.all_codes_for_published).to eq(['de', 'en'])
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
context 'validations' do
|
|
128
|
+
let(:language) { Language.new(default: true, public: false) }
|
|
129
|
+
|
|
130
|
+
describe 'publicity_of_default_language' do
|
|
131
|
+
context 'if language is not published' do
|
|
132
|
+
it "should add an error to the object" do
|
|
133
|
+
expect(language.valid?).to eq(false)
|
|
134
|
+
expect(language.errors.messages).to have_key(:base)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
describe 'presence_of_default_language' do
|
|
140
|
+
context 'if no default language would exist anymore' do
|
|
141
|
+
before do
|
|
142
|
+
Language.stub!(:get_default).and_return(language)
|
|
143
|
+
language.stub!(:default_changed?).and_return(true)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it "should add an error to the object" do
|
|
147
|
+
expect(language.valid?).to eq(false)
|
|
148
|
+
expect(language.errors.messages).to have_key(:base)
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
120
154
|
end
|
|
121
155
|
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Alchemy
|
|
4
|
+
describe Message do
|
|
5
|
+
let(:message) { Message.new }
|
|
6
|
+
|
|
7
|
+
describe '.config' do
|
|
8
|
+
it "should return the mailer config" do
|
|
9
|
+
Config.should_receive(:get).with(:mailer)
|
|
10
|
+
Message.config
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe '#persisted?' do
|
|
15
|
+
it "should return false" do
|
|
16
|
+
expect(message.persisted?).to eq(false)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe '#attributes' do
|
|
21
|
+
it "should call .attributes" do
|
|
22
|
+
Message.should_receive(:attributes)
|
|
23
|
+
message.attributes
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe '#email_is_filled' do
|
|
28
|
+
context 'if email attribute is filled' do
|
|
29
|
+
it "should return true" do
|
|
30
|
+
message.stub!(:email).and_return('me@you.com')
|
|
31
|
+
expect(message.send(:email_is_filled)).to eq(true)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context 'if email attribute is not filled' do
|
|
36
|
+
it "should return false" do
|
|
37
|
+
message.stub!(:email).and_return('')
|
|
38
|
+
expect(message.send(:email_is_filled)).to eq(false)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
data/spec/models/page_spec.rb
CHANGED
|
@@ -13,141 +13,91 @@ module Alchemy
|
|
|
13
13
|
let(:public_page) { FactoryGirl.create(:public_page) }
|
|
14
14
|
let(:news_page) { FactoryGirl.create(:public_page, :page_layout => 'news', :do_not_autogenerate => false) }
|
|
15
15
|
|
|
16
|
-
describe ".layout_description" do
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
it "should return the page layout description as hash" do
|
|
21
|
-
language_root.layout_description['name'].should == 'intro'
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
it "should return an empty hash for root page" do
|
|
25
|
-
rootpage.layout_description.should == {}
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
it "should raise Exception if the page_layout could not be found in the definition file" do
|
|
31
|
-
expect { page.layout_description }.to raise_error
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
it "should contain one rootpage" do
|
|
37
|
-
Page.rootpage.should be_instance_of(Page)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
it "should return all rss feed elements" do
|
|
41
|
-
news_page.feed_elements.should_not be_empty
|
|
42
|
-
news_page.feed_elements.should == Element.find_all_by_name('news')
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
context "finding elements" do
|
|
46
|
-
|
|
47
|
-
before do
|
|
48
|
-
FactoryGirl.create(:element, :public => false, :page => public_page)
|
|
49
|
-
FactoryGirl.create(:element, :public => false, :page => public_page)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it "should return the collection of elements if passed an array into options[:collection]" do
|
|
53
|
-
options = {:collection => public_page.elements}
|
|
54
|
-
public_page.find_elements(options).all.should == public_page.elements.all
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
context "with show_non_public argument TRUE" do
|
|
58
|
-
|
|
59
|
-
it "should return all elements from empty options" do
|
|
60
|
-
public_page.find_elements({}, true).all.should == public_page.elements.all
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
it "should only return the elements passed as options[:only]" do
|
|
64
|
-
public_page.find_elements({:only => ['article']}, true).all.should == public_page.elements.named('article').all
|
|
65
|
-
end
|
|
17
|
+
# Validations
|
|
66
18
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
19
|
+
context 'validations' do
|
|
20
|
+
context "Creating a normal content page" do
|
|
21
|
+
let(:contentpage) { FactoryGirl.build(:page) }
|
|
70
22
|
|
|
71
|
-
|
|
72
|
-
|
|
23
|
+
context "when its urlname exists as global page" do
|
|
24
|
+
it "it should be possible to save." do
|
|
25
|
+
contentpage.urlname = "existing_twice"
|
|
26
|
+
global_with_same_urlname = FactoryGirl.create(:page, :urlname => "existing_twice", :layoutpage => true)
|
|
27
|
+
contentpage.should be_valid
|
|
28
|
+
end
|
|
73
29
|
end
|
|
74
30
|
|
|
75
|
-
it "should
|
|
76
|
-
|
|
31
|
+
it "should validate the page_layout" do
|
|
32
|
+
contentpage.page_layout = nil
|
|
33
|
+
contentpage.save
|
|
34
|
+
contentpage.should have(1).error_on(:page_layout)
|
|
77
35
|
end
|
|
78
36
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
it "should return all elements from empty arguments" do
|
|
84
|
-
public_page.find_elements().all.should == public_page.elements.published.all
|
|
37
|
+
it "should validate the parent_id" do
|
|
38
|
+
contentpage.parent_id = nil
|
|
39
|
+
contentpage.save
|
|
40
|
+
contentpage.should have(1).error_on(:parent_id)
|
|
85
41
|
end
|
|
86
42
|
|
|
87
|
-
it "should
|
|
88
|
-
|
|
43
|
+
it "should validate the uniqueness of urlname" do
|
|
44
|
+
with_same_urlname = FactoryGirl.create(:page, :urlname => "existing_twice")
|
|
45
|
+
contentpage.urlname = 'existing_twice'
|
|
46
|
+
contentpage.should_not be_valid
|
|
89
47
|
end
|
|
90
48
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
end
|
|
49
|
+
context "with url_nesting set to true" do
|
|
50
|
+
before { Config.stub!(:get).and_return(true) }
|
|
94
51
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
52
|
+
it "should only validate urlname dependent of parent" do
|
|
53
|
+
other_parent = FactoryGirl.create(:page, parent_id: Page.root.id)
|
|
54
|
+
with_same_urlname = FactoryGirl.create(:page, :urlname => "existing_twice")
|
|
55
|
+
contentpage.urlname = 'existing_twice'
|
|
56
|
+
contentpage.parent_id = other_parent.id
|
|
57
|
+
contentpage.should be_valid
|
|
58
|
+
end
|
|
98
59
|
|
|
99
|
-
|
|
100
|
-
|
|
60
|
+
it "should validate urlname dependent of parent" do
|
|
61
|
+
with_same_urlname = FactoryGirl.create(:page, :urlname => "existing_twice")
|
|
62
|
+
contentpage.urlname = 'existing_twice'
|
|
63
|
+
contentpage.should_not be_valid
|
|
64
|
+
end
|
|
101
65
|
end
|
|
102
|
-
|
|
103
66
|
end
|
|
104
67
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
context "before/after filter" do
|
|
110
|
-
|
|
111
|
-
it "should automatically set the title from its name" do
|
|
112
|
-
page = FactoryGirl.create(:page, :name => 'My Testpage', :language => language, :parent_id => language_root.id)
|
|
113
|
-
page.title.should == 'My Testpage'
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
it "should get a webfriendly urlname" do
|
|
117
|
-
page = FactoryGirl.create(:page, :name => 'klingon$&stößel ', :language => language, :parent_id => language_root.id)
|
|
118
|
-
page.urlname.should == 'klingon-stoessel'
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
it "should generate a three letter urlname from two letter name" do
|
|
122
|
-
page = FactoryGirl.create(:page, :name => 'Au', :language => language, :parent_id => language_root.id)
|
|
123
|
-
page.urlname.should == '-au'
|
|
68
|
+
context "creating the rootpage without parent_id and page_layout" do
|
|
69
|
+
before do
|
|
70
|
+
Page.delete_all
|
|
71
|
+
@rootpage = FactoryGirl.build(:page, :parent_id => nil, :page_layout => nil, :name => 'Rootpage')
|
|
124
72
|
end
|
|
125
73
|
|
|
126
|
-
it "should
|
|
127
|
-
|
|
128
|
-
|
|
74
|
+
it "should be valid" do
|
|
75
|
+
@rootpage.save
|
|
76
|
+
@rootpage.should be_valid
|
|
129
77
|
end
|
|
78
|
+
end
|
|
130
79
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
80
|
+
context "saving a systempage" do
|
|
81
|
+
before do
|
|
82
|
+
@systempage = FactoryGirl.build(:systempage)
|
|
134
83
|
end
|
|
135
84
|
|
|
136
|
-
it "should
|
|
137
|
-
|
|
138
|
-
|
|
85
|
+
it "should not validate the page_layout" do
|
|
86
|
+
@systempage.save
|
|
87
|
+
@systempage.should be_valid
|
|
139
88
|
end
|
|
140
|
-
|
|
141
89
|
end
|
|
142
|
-
|
|
143
90
|
end
|
|
144
91
|
|
|
145
|
-
describe '#update' do
|
|
146
92
|
|
|
147
|
-
|
|
93
|
+
# Callbacks
|
|
148
94
|
|
|
149
|
-
|
|
95
|
+
context 'callbacks' do
|
|
96
|
+
let(:page) do
|
|
97
|
+
FactoryGirl.create(:page, :name => 'My Testpage', :language => language, :parent_id => language_root.id)
|
|
98
|
+
end
|
|
150
99
|
|
|
100
|
+
context 'before_save' do
|
|
151
101
|
it "should not set the title automatically if the name changed but title is not blank" do
|
|
152
102
|
page.name = "My Renaming Test"
|
|
153
103
|
page.save; page.reload
|
|
@@ -159,9 +109,10 @@ module Alchemy
|
|
|
159
109
|
page.save; page.reload
|
|
160
110
|
page.title.should == "I like SEO"
|
|
161
111
|
end
|
|
112
|
+
end
|
|
162
113
|
|
|
114
|
+
context 'after_update' do
|
|
163
115
|
context "urlname has changed" do
|
|
164
|
-
|
|
165
116
|
it "should store legacy url if page is not redirect to external page" do
|
|
166
117
|
page.urlname = 'new-urlname'
|
|
167
118
|
page.save!
|
|
@@ -185,178 +136,174 @@ module Alchemy
|
|
|
185
136
|
page.save!
|
|
186
137
|
page.legacy_urls.select { |u| u.urlname == 'my-testpage' }.size.should == 1
|
|
187
138
|
end
|
|
188
|
-
|
|
189
139
|
end
|
|
190
140
|
|
|
191
141
|
context "urlname has not changed" do
|
|
192
|
-
|
|
193
142
|
it "should not store a legacy url" do
|
|
194
143
|
page.urlname = 'my-testpage'
|
|
195
144
|
page.save!
|
|
196
145
|
page.legacy_urls.should be_empty
|
|
197
146
|
end
|
|
198
|
-
|
|
199
147
|
end
|
|
200
|
-
|
|
201
148
|
end
|
|
202
149
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
let(:original_url) { "sample-url" }
|
|
208
|
-
let(:page) { FactoryGirl.create(:page, :language => language, :parent_id => language_root.id, :urlname => original_url, restricted: false) }
|
|
209
|
-
let(:node) { TreeNode.new(10, 11, 12, 13, "another-url", true) }
|
|
150
|
+
context "a normal page" do
|
|
151
|
+
before do
|
|
152
|
+
@page = FactoryGirl.build(:page, :language_code => nil, :language => klingonian, :do_not_autogenerate => false)
|
|
153
|
+
end
|
|
210
154
|
|
|
211
|
-
|
|
212
|
-
|
|
155
|
+
it "should set the language code" do
|
|
156
|
+
@page.save
|
|
157
|
+
@page.language_code.should == "kl"
|
|
158
|
+
end
|
|
213
159
|
|
|
214
|
-
|
|
160
|
+
it "should autogenerate the elements" do
|
|
161
|
+
@page.save
|
|
162
|
+
@page.elements.should_not be_empty
|
|
163
|
+
end
|
|
215
164
|
|
|
216
|
-
|
|
165
|
+
it "should not autogenerate elements that are already on the page" do
|
|
166
|
+
@page.elements << FactoryGirl.create(:element, :name => 'header')
|
|
167
|
+
@page.save
|
|
168
|
+
@page.elements.select { |e| e.name == 'header' }.length.should == 1
|
|
169
|
+
end
|
|
217
170
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
page.
|
|
221
|
-
expect(page.lft).to eq(node.left)
|
|
222
|
-
expect(page.rgt).to eq(node.right)
|
|
223
|
-
expect(page.parent_id).to eq(node.parent)
|
|
224
|
-
expect(page.depth).to eq(node.depth)
|
|
225
|
-
expect(page.urlname).to eq(node.url)
|
|
226
|
-
expect(page.restricted).to eq(node.restricted)
|
|
171
|
+
context "with cells" do
|
|
172
|
+
before do
|
|
173
|
+
@page.stub!(:definition).and_return({'name' => 'with_cells', 'cells' => ['header', 'main']})
|
|
227
174
|
end
|
|
228
175
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
page.update_node!(node)
|
|
234
|
-
page.reload
|
|
235
|
-
expect(page.legacy_urls.size).to eq(0)
|
|
236
|
-
end
|
|
176
|
+
it "should have the generated elements in their cells" do
|
|
177
|
+
@page.stub!(:cell_definitions).and_return([{'name' => 'header', 'elements' => ['article']}])
|
|
178
|
+
@page.save
|
|
179
|
+
@page.cells.where(:name => 'header').first.elements.should_not be_empty
|
|
237
180
|
end
|
|
238
181
|
|
|
239
|
-
context "
|
|
240
|
-
it "should
|
|
241
|
-
page.
|
|
242
|
-
page.
|
|
243
|
-
|
|
182
|
+
context "and no elements in cell definitions" do
|
|
183
|
+
it "should have the elements in the nil cell" do
|
|
184
|
+
@page.stub!(:cell_definitions).and_return([{'name' => 'header', 'elements' => []}])
|
|
185
|
+
@page.save
|
|
186
|
+
@page.cells.collect(&:elements).flatten.should be_empty
|
|
244
187
|
end
|
|
245
188
|
end
|
|
246
189
|
end
|
|
247
190
|
|
|
248
|
-
context "
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
page.
|
|
254
|
-
page.
|
|
255
|
-
expect(page.lft).to eq(node.left)
|
|
256
|
-
expect(page.rgt).to eq(node.right)
|
|
257
|
-
expect(page.parent_id).to eq(node.parent)
|
|
258
|
-
expect(page.depth).to eq(node.depth)
|
|
259
|
-
expect(page.urlname).to eq(original_url)
|
|
260
|
-
expect(page.restricted).to eq(node.restricted)
|
|
191
|
+
context "with children getting restricted set to true" do
|
|
192
|
+
before do
|
|
193
|
+
@page.save
|
|
194
|
+
@child1 = FactoryGirl.create(:page, :name => 'Child 1', :parent_id => @page.id)
|
|
195
|
+
@page.reload
|
|
196
|
+
@page.restricted = true
|
|
197
|
+
@page.save
|
|
261
198
|
end
|
|
262
199
|
|
|
263
|
-
it "should
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
expect(page.legacy_urls.size).to eq(0)
|
|
200
|
+
it "should restrict all its children" do
|
|
201
|
+
@child1.reload
|
|
202
|
+
@child1.restricted?.should be_true
|
|
267
203
|
end
|
|
268
204
|
end
|
|
269
|
-
end
|
|
270
205
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
before { page.stub(redirects_to_external?: false)}
|
|
277
|
-
|
|
278
|
-
it "should update all attributes except url" do
|
|
279
|
-
page.update_node!(node)
|
|
280
|
-
page.reload
|
|
281
|
-
expect(page.lft).to eq(node.left)
|
|
282
|
-
expect(page.rgt).to eq(node.right)
|
|
283
|
-
expect(page.parent_id).to eq(node.parent)
|
|
284
|
-
expect(page.depth).to eq(node.depth)
|
|
285
|
-
expect(page.urlname).to eq(original_url)
|
|
286
|
-
expect(page.restricted).to eq(node.restricted)
|
|
206
|
+
context "with restricted parent gets created" do
|
|
207
|
+
before do
|
|
208
|
+
@page.save
|
|
209
|
+
@page.parent.update_attributes(:restricted => true)
|
|
210
|
+
@new_page = FactoryGirl.create(:page, :name => 'New Page', :parent_id => @page.id)
|
|
287
211
|
end
|
|
288
212
|
|
|
289
|
-
it "should
|
|
290
|
-
|
|
291
|
-
page.reload
|
|
292
|
-
expect(page.legacy_urls.size).to eq(0)
|
|
213
|
+
it "should also be restricted" do
|
|
214
|
+
@new_page.restricted?.should be_true
|
|
293
215
|
end
|
|
294
|
-
|
|
295
216
|
end
|
|
296
217
|
|
|
297
|
-
context "
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
before { Alchemy::Config.stub(get: true) }
|
|
302
|
-
|
|
303
|
-
it "should update all attributes except url" do
|
|
304
|
-
page.update_node!(node)
|
|
305
|
-
page.reload
|
|
306
|
-
expect(page.lft).to eq(node.left)
|
|
307
|
-
expect(page.rgt).to eq(node.right)
|
|
308
|
-
expect(page.parent_id).to eq(node.parent)
|
|
309
|
-
expect(page.depth).to eq(node.depth)
|
|
310
|
-
expect(page.urlname).to eq(original_url)
|
|
311
|
-
expect(page.restricted).to eq(node.restricted)
|
|
218
|
+
context "with do_not_autogenerate set to true" do
|
|
219
|
+
before do
|
|
220
|
+
@page.do_not_autogenerate = true
|
|
312
221
|
end
|
|
313
222
|
|
|
314
|
-
it "should not
|
|
315
|
-
page.
|
|
316
|
-
page.
|
|
317
|
-
expect(page.legacy_urls.size).to eq(0)
|
|
223
|
+
it "should not autogenerate the elements" do
|
|
224
|
+
@page.save
|
|
225
|
+
@page.elements.should be_empty
|
|
318
226
|
end
|
|
319
227
|
end
|
|
320
228
|
end
|
|
321
|
-
end
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
describe "#destroy" do
|
|
325
|
-
|
|
326
|
-
context "with trashed but still assigned elements" do
|
|
327
229
|
|
|
230
|
+
context "a systempage" do
|
|
328
231
|
before do
|
|
329
|
-
|
|
232
|
+
@page = FactoryGirl.create(:systempage)
|
|
330
233
|
end
|
|
331
234
|
|
|
332
|
-
it "should not
|
|
333
|
-
|
|
334
|
-
Element.trashed.should_not be_empty
|
|
235
|
+
it "should not get the language code for language" do
|
|
236
|
+
@page.language_code.should be_nil
|
|
335
237
|
end
|
|
336
238
|
|
|
239
|
+
it "should not autogenerate the elements" do
|
|
240
|
+
@page.elements.should be_empty
|
|
241
|
+
end
|
|
337
242
|
end
|
|
338
243
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
describe '#first_public_child' do
|
|
342
|
-
|
|
343
|
-
before do
|
|
344
|
-
FactoryGirl.create(:page, :name => "First child", :language => language, :public => false, :parent_id => language_root.id)
|
|
345
|
-
end
|
|
244
|
+
context "after changing the page layout" do
|
|
245
|
+
let(:news_element) { FactoryGirl.create(:element, :name => 'news') }
|
|
346
246
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
247
|
+
it "all elements not allowed on this page should be trashed" do
|
|
248
|
+
news_page.elements << news_element
|
|
249
|
+
news_page.update_attributes :page_layout => 'standard'
|
|
250
|
+
news_page.elements.trashed.should include(news_element)
|
|
251
|
+
end
|
|
351
252
|
|
|
352
|
-
|
|
353
|
-
|
|
253
|
+
it "should autogenerate elements" do
|
|
254
|
+
news_page.update_attributes :page_layout => 'standard'
|
|
255
|
+
news_page.elements.available.collect(&:name).should include('header')
|
|
256
|
+
end
|
|
354
257
|
end
|
|
355
|
-
|
|
356
258
|
end
|
|
357
259
|
|
|
358
|
-
context ".contentpages" do
|
|
359
260
|
|
|
261
|
+
# ClassMethods (a-z)
|
|
262
|
+
|
|
263
|
+
describe '.all_from_clipboard_for_select' do
|
|
264
|
+
context "with clipboard holding pages having non unique page layout" do
|
|
265
|
+
it "should return the pages" do
|
|
266
|
+
page_1 = FactoryGirl.create(:page, :language => language)
|
|
267
|
+
page_2 = FactoryGirl.create(:page, :language => language, :name => 'Another page')
|
|
268
|
+
clipboard = [
|
|
269
|
+
{:id => page_1.id, :action => "copy"},
|
|
270
|
+
{:id => page_2.id, :action => "copy"}
|
|
271
|
+
]
|
|
272
|
+
Page.all_from_clipboard_for_select(clipboard, language.id).should include(page_1, page_2)
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
context "with clipboard holding a page having unique page layout" do
|
|
277
|
+
it "should not return any pages" do
|
|
278
|
+
page_1 = FactoryGirl.create(:page, :language => language, :page_layout => 'contact')
|
|
279
|
+
clipboard = [
|
|
280
|
+
{:id => page_1.id, :action => "copy"}
|
|
281
|
+
]
|
|
282
|
+
Page.all_from_clipboard_for_select(clipboard, language.id).should == []
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
context "with clipboard holding two pages. One having a unique page layout." do
|
|
287
|
+
it "should return one page" do
|
|
288
|
+
page_1 = FactoryGirl.create(:page, :language => language, :page_layout => 'standard')
|
|
289
|
+
page_2 = FactoryGirl.create(:page, :name => 'Another page', :language => language, :page_layout => 'contact')
|
|
290
|
+
clipboard = [
|
|
291
|
+
{:id => page_1.id, :action => "copy"},
|
|
292
|
+
{:id => page_2.id, :action => "copy"}
|
|
293
|
+
]
|
|
294
|
+
Page.all_from_clipboard_for_select(clipboard, language.id).should == [page_1]
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
describe '.all_locked' do
|
|
300
|
+
it "should return 1 page that is blocked by a user at the moment" do
|
|
301
|
+
FactoryGirl.create(:public_page, :locked => true, :name => 'First Public Child', :parent_id => language_root.id, :language => language)
|
|
302
|
+
Page.all_locked.should have(1).pages
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
describe '.contentpages' do
|
|
360
307
|
before do
|
|
361
308
|
layoutroot = Page.find_or_create_layout_root_for(klingonian.id)
|
|
362
309
|
@layoutpage = FactoryGirl.create(:public_page, :name => 'layoutpage', :layoutpage => true, :parent_id => layoutroot.id, :language => klingonian)
|
|
@@ -375,460 +322,693 @@ module Alchemy
|
|
|
375
322
|
it "should contain pages with attribute :layoutpage set to nil" do
|
|
376
323
|
Page.contentpages.to_a.select { |p| p.layoutpage == nil }.should include(@klingonian_lang_root)
|
|
377
324
|
end
|
|
378
|
-
|
|
379
325
|
end
|
|
380
326
|
|
|
381
|
-
|
|
327
|
+
describe '.copy' do
|
|
328
|
+
let(:page) { FactoryGirl.create(:page, :name => 'Source') }
|
|
329
|
+
subject { Page.copy(page) }
|
|
382
330
|
|
|
383
|
-
it "should
|
|
384
|
-
|
|
385
|
-
FactoryGirl.create(:public_page, :name => 'Second Public Child', :parent_id => language_root.id, :language => language)
|
|
386
|
-
Page.published.should have(3).pages
|
|
331
|
+
it "the copy should have added (copy) to name" do
|
|
332
|
+
subject.name.should == "#{page.name} (Copy)"
|
|
387
333
|
end
|
|
388
334
|
|
|
389
|
-
|
|
335
|
+
context "page with tags" do
|
|
336
|
+
before { page.tag_list = 'red, yellow'; page.save }
|
|
337
|
+
|
|
338
|
+
it "the copy should have source tag_list" do
|
|
339
|
+
# The order of tags varies between postgresql and sqlite/mysql
|
|
340
|
+
# This is related to acts-as-taggable-on v.2.4.1
|
|
341
|
+
# To fix the spec we sort the tags until the issue is solved (https://github.com/mbleigh/acts-as-taggable-on/issues/363)
|
|
342
|
+
subject.tag_list.should_not be_empty
|
|
343
|
+
subject.tag_list.sort.should == page.tag_list.sort
|
|
344
|
+
end
|
|
345
|
+
end
|
|
390
346
|
|
|
391
|
-
|
|
347
|
+
context "page with elements" do
|
|
348
|
+
before { page.elements << FactoryGirl.create(:element) }
|
|
392
349
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
350
|
+
it "the copy should have source elements" do
|
|
351
|
+
subject.elements.should_not be_empty
|
|
352
|
+
subject.elements.count.should == page.elements.count
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
context "page with trashed elements" do
|
|
357
|
+
before do
|
|
358
|
+
page.elements << FactoryGirl.create(:element)
|
|
359
|
+
page.elements.first.trash
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
it "the copy should not hold a copy of the trashed elements" do
|
|
363
|
+
subject.elements.should be_empty
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
context "page with cells" do
|
|
368
|
+
before { page.cells << FactoryGirl.create(:cell) }
|
|
369
|
+
|
|
370
|
+
it "the copy should have source cells" do
|
|
371
|
+
subject.cells.should_not be_empty
|
|
372
|
+
subject.cells.count.should == page.cells.length # It must be length, because!
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
context "page with autogenerate elements" do
|
|
377
|
+
before do
|
|
378
|
+
page = FactoryGirl.create(:page)
|
|
379
|
+
page.stub!(:definition).and_return({'name' => 'standard', 'elements' => ['headline'], 'autogenerate' => ['headline']})
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
it "the copy should not autogenerate elements" do
|
|
383
|
+
subject.elements.should be_empty
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
context "with different page name given" do
|
|
388
|
+
subject { Page.copy(page, {:name => 'Different name'}) }
|
|
389
|
+
it "should take this name" do
|
|
390
|
+
subject.name.should == 'Different name'
|
|
391
|
+
end
|
|
397
392
|
end
|
|
398
393
|
end
|
|
399
394
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
395
|
+
describe '.create' do
|
|
396
|
+
context "before/after filter" do
|
|
397
|
+
it "should automatically set the title from its name" do
|
|
398
|
+
page = FactoryGirl.create(:page, :name => 'My Testpage', :language => language, :parent_id => language_root.id)
|
|
399
|
+
page.title.should == 'My Testpage'
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
it "should get a webfriendly urlname" do
|
|
403
|
+
page = FactoryGirl.create(:page, :name => 'klingon$&stößel ', :language => language, :parent_id => language_root.id)
|
|
404
|
+
page.urlname.should == 'klingon-stoessel'
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
it "should generate a three letter urlname from two letter name" do
|
|
408
|
+
page = FactoryGirl.create(:page, :name => 'Au', :language => language, :parent_id => language_root.id)
|
|
409
|
+
page.urlname.should == '-au'
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
it "should generate a three letter urlname from two letter name with umlaut" do
|
|
413
|
+
page = FactoryGirl.create(:page, :name => 'Aü', :language => language, :parent_id => language_root.id)
|
|
414
|
+
page.urlname.should == 'aue'
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
it "should generate a three letter urlname from one letter name" do
|
|
418
|
+
page = FactoryGirl.create(:page, :name => 'A', :language => language, :parent_id => language_root.id)
|
|
419
|
+
page.urlname.should == '--a'
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
it "should add a user stamper" do
|
|
423
|
+
page = FactoryGirl.create(:page, :name => 'A', :language => language, :parent_id => language_root.id)
|
|
424
|
+
page.class.stamper_class.to_s.should == 'Alchemy::User'
|
|
425
|
+
end
|
|
404
426
|
end
|
|
405
427
|
end
|
|
406
428
|
|
|
407
|
-
|
|
429
|
+
describe '.language_roots' do
|
|
408
430
|
it "should return 1 language_root" do
|
|
409
431
|
FactoryGirl.create(:public_page, :name => 'First Public Child', :parent_id => language_root.id, :language => language)
|
|
410
432
|
Page.language_roots.should have(1).pages
|
|
411
433
|
end
|
|
412
434
|
end
|
|
413
435
|
|
|
436
|
+
describe '.layout_description' do
|
|
437
|
+
it "should raise Exception if the page_layout could not be found in the definition file" do
|
|
438
|
+
expect { page.layout_description }.to raise_error
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
context "for a language root page" do
|
|
442
|
+
it "should return the page layout description as hash" do
|
|
443
|
+
language_root.layout_description['name'].should == 'intro'
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
it "should return an empty hash for root page" do
|
|
447
|
+
rootpage.layout_description.should == {}
|
|
448
|
+
end
|
|
449
|
+
end
|
|
450
|
+
end
|
|
414
451
|
|
|
415
|
-
|
|
452
|
+
describe '.layoutpages' do
|
|
416
453
|
it "should return 1 layoutpage" do
|
|
417
454
|
FactoryGirl.create(:public_page, :layoutpage => true, :name => 'Layoutpage', :parent_id => rootpage.id, :language => language)
|
|
418
455
|
Page.layoutpages.should have(1).pages
|
|
419
456
|
end
|
|
420
457
|
end
|
|
421
458
|
|
|
422
|
-
|
|
423
|
-
it "should return
|
|
424
|
-
FactoryGirl.create(:public_page, :name => 'First Public Child', :
|
|
425
|
-
|
|
459
|
+
describe '.not_locked' do
|
|
460
|
+
it "should return pages that are not blocked by a user at the moment" do
|
|
461
|
+
FactoryGirl.create(:public_page, :locked => true, :name => 'First Public Child', :parent_id => language_root.id, :language => language)
|
|
462
|
+
FactoryGirl.create(:public_page, :name => 'Second Public Child', :parent_id => language_root.id, :language => language)
|
|
463
|
+
Page.not_locked.should have(3).pages
|
|
426
464
|
end
|
|
427
465
|
end
|
|
428
466
|
|
|
429
|
-
|
|
467
|
+
describe '.not_restricted' do
|
|
430
468
|
it "should return 2 accessible pages" do
|
|
431
469
|
FactoryGirl.create(:public_page, :name => 'First Public Child', :restricted => true, :parent_id => language_root.id, :language => language)
|
|
432
470
|
Page.not_restricted.should have(2).pages
|
|
433
471
|
end
|
|
434
472
|
end
|
|
435
473
|
|
|
436
|
-
|
|
474
|
+
describe '.public' do
|
|
475
|
+
it "should return pages that are public" do
|
|
476
|
+
FactoryGirl.create(:public_page, :name => 'First Public Child', :parent_id => language_root.id, :language => language)
|
|
477
|
+
FactoryGirl.create(:public_page, :name => 'Second Public Child', :parent_id => language_root.id, :language => language)
|
|
478
|
+
Page.published.should have(3).pages
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
describe '.restricted' do
|
|
437
483
|
it "should return 1 restricted page" do
|
|
438
484
|
FactoryGirl.create(:public_page, :name => 'First Public Child', :restricted => true, :parent_id => language_root.id, :language => language)
|
|
439
485
|
Page.restricted.should have(1).pages
|
|
440
486
|
end
|
|
441
487
|
end
|
|
442
488
|
|
|
443
|
-
|
|
444
|
-
it "should
|
|
445
|
-
|
|
446
|
-
page.unlock
|
|
447
|
-
page.locked.should == false
|
|
489
|
+
describe '.rootpage' do
|
|
490
|
+
it "should contain one rootpage" do
|
|
491
|
+
Page.rootpage.should be_instance_of(Page)
|
|
448
492
|
end
|
|
449
493
|
end
|
|
450
494
|
|
|
451
|
-
describe
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
@page.stub!(:layout_description).and_return({'name' => "foo", 'cells' => ["foo_cell"]})
|
|
456
|
-
@cell_descriptions = [{'name' => "foo_cell", 'elements' => ["1", "2"]}]
|
|
457
|
-
Cell.stub!(:definitions).and_return(@cell_descriptions)
|
|
458
|
-
end
|
|
459
|
-
|
|
460
|
-
it "should return all cell definitions for its page_layout" do
|
|
461
|
-
@page.cell_definitions.should == @cell_descriptions
|
|
462
|
-
end
|
|
463
|
-
|
|
464
|
-
it "should return empty array if no cells defined in page layout" do
|
|
465
|
-
@page.stub!(:layout_description).and_return({'name' => "foo"})
|
|
466
|
-
@page.cell_definitions.should == []
|
|
495
|
+
describe '.visible' do
|
|
496
|
+
it "should return 1 visible page" do
|
|
497
|
+
FactoryGirl.create(:public_page, :name => 'First Public Child', :visible => true, :parent_id => language_root.id, :language => language)
|
|
498
|
+
Page.visible.should have(1).pages
|
|
467
499
|
end
|
|
468
|
-
|
|
469
500
|
end
|
|
470
501
|
|
|
471
|
-
describe "#elements_grouped_by_cells" do
|
|
472
|
-
let(:page) { FactoryGirl.create(:public_page, :do_not_autogenerate => false) }
|
|
473
502
|
|
|
474
|
-
|
|
475
|
-
PageLayout.stub(:get).and_return({
|
|
476
|
-
'name' => 'standard',
|
|
477
|
-
'cells' => ['header'],
|
|
478
|
-
'elements' => ['header', 'text'],
|
|
479
|
-
'autogenerate' => ['header', 'text']
|
|
480
|
-
})
|
|
481
|
-
Cell.stub!(:definitions).and_return([{
|
|
482
|
-
'name' => "header",
|
|
483
|
-
'elements' => ["header"]
|
|
484
|
-
}])
|
|
485
|
-
end
|
|
503
|
+
# InstanceMethods (a-z)
|
|
486
504
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
elements.keys.first.should be_instance_of(Cell)
|
|
490
|
-
elements.values.first.first.should be_instance_of(Element)
|
|
491
|
-
end
|
|
505
|
+
describe '#available_element_definitions' do
|
|
506
|
+
let(:page) { FactoryGirl.build_stubbed(:public_page) }
|
|
492
507
|
|
|
493
|
-
it "
|
|
494
|
-
page.
|
|
508
|
+
it "returns all element definitions of available elements" do
|
|
509
|
+
page.available_element_definitions.should be_an(Array)
|
|
510
|
+
page.available_element_definitions.collect { |e| e['name'] }.should include('header')
|
|
495
511
|
end
|
|
496
512
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
context "with clipboard holding pages having non unique page layout" do
|
|
513
|
+
context "with unique elements already on page" do
|
|
514
|
+
let(:element) { FactoryGirl.build_stubbed(:unique_element) }
|
|
515
|
+
before { page.stub_chain(:elements, :not_trashed, :pluck).and_return([element.name]) }
|
|
502
516
|
|
|
503
|
-
it "
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
clipboard = [
|
|
507
|
-
{:id => page_1.id, :action => "copy"},
|
|
508
|
-
{:id => page_2.id, :action => "copy"}
|
|
509
|
-
]
|
|
510
|
-
Page.all_from_clipboard_for_select(clipboard, language.id).should include(page_1, page_2)
|
|
517
|
+
it "does not return unique element definitions" do
|
|
518
|
+
page.available_element_definitions.collect { |e| e['name'] }.should include('article')
|
|
519
|
+
page.available_element_definitions.collect { |e| e['name'] }.should_not include('header')
|
|
511
520
|
end
|
|
512
|
-
|
|
513
521
|
end
|
|
514
522
|
|
|
515
|
-
context "
|
|
523
|
+
context "for page_layout not existing" do
|
|
524
|
+
let(:page) { FactoryGirl.build_stubbed(:page, page_layout: 'not_existing_one') }
|
|
516
525
|
|
|
517
|
-
it "should
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
]
|
|
522
|
-
Page.all_from_clipboard_for_select(clipboard, language.id).should == []
|
|
526
|
+
it "should raise error" do
|
|
527
|
+
expect {
|
|
528
|
+
page.available_element_definitions
|
|
529
|
+
}.to raise_error(Alchemy::PageLayoutDefinitionError)
|
|
523
530
|
end
|
|
524
|
-
|
|
525
531
|
end
|
|
526
532
|
|
|
527
|
-
context
|
|
533
|
+
context 'limited amount' do
|
|
534
|
+
let(:page) { FactoryGirl.build_stubbed(:page, page_layout: 'columns') }
|
|
535
|
+
let(:unique_element) { FactoryGirl.build_stubbed(:unique_element, name: 'unique_headline') }
|
|
536
|
+
let(:element_1) { FactoryGirl.build_stubbed(:element, name: 'column_headline') }
|
|
537
|
+
let(:element_2) { FactoryGirl.build_stubbed(:element, name: 'column_headline') }
|
|
538
|
+
let(:element_3) { FactoryGirl.build_stubbed(:element, name: 'column_headline') }
|
|
528
539
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
540
|
+
before {
|
|
541
|
+
Element.stub(:definitions).and_return([
|
|
542
|
+
{
|
|
543
|
+
'name' => 'column_headline',
|
|
544
|
+
'amount' => 3,
|
|
545
|
+
'contents' => [{'name' => 'headline', 'type' => 'EssenceText'}]
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
'name' => 'unique_headline',
|
|
549
|
+
'unique' => true,
|
|
550
|
+
'amount' => 3,
|
|
551
|
+
'contents' => [{'name' => 'headline', 'type' => 'EssenceText'}]
|
|
552
|
+
}
|
|
553
|
+
])
|
|
554
|
+
PageLayout.stub(:get).and_return({
|
|
555
|
+
'name' => 'columns',
|
|
556
|
+
'elements' => ['column_headline', 'unique_headline'],
|
|
557
|
+
'autogenerate' => ['unique_headline', 'column_headline', 'column_headline', 'column_headline']
|
|
558
|
+
})
|
|
559
|
+
page.stub_chain(:elements, :not_trashed, :pluck).and_return([unique_element.name, element_1.name, element_2.name, element_3.name])
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
it "should be readable" do
|
|
563
|
+
element = page.element_definitions_by_name('column_headline').first
|
|
564
|
+
element['amount'].should be 3
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
it "should limit elements" do
|
|
568
|
+
page.available_element_definitions.collect { |e| e['name'] }.should_not include('column_headline')
|
|
537
569
|
end
|
|
538
570
|
|
|
571
|
+
it "should be ignored if unique" do
|
|
572
|
+
page.available_element_definitions.collect { |e| e['name'] }.should_not include('unique_headline')
|
|
573
|
+
end
|
|
539
574
|
end
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
describe '#available_element_names' do
|
|
578
|
+
let(:page) { FactoryGirl.build_stubbed(:page) }
|
|
540
579
|
|
|
580
|
+
it "returns all names of elements that could be placed on current page" do
|
|
581
|
+
page.available_element_names == %w(header article)
|
|
582
|
+
end
|
|
541
583
|
end
|
|
542
584
|
|
|
543
|
-
describe
|
|
585
|
+
describe '#cache_key' do
|
|
586
|
+
let(:page) { stub_model(Page) }
|
|
587
|
+
subject { page }
|
|
588
|
+
its(:cache_key) { should match(page.id.to_s) }
|
|
589
|
+
end
|
|
544
590
|
|
|
545
|
-
|
|
591
|
+
describe '#cell_definitions' do
|
|
592
|
+
before do
|
|
593
|
+
@page = FactoryGirl.build(:page, :page_layout => 'foo')
|
|
594
|
+
@page.stub!(:layout_description).and_return({'name' => "foo", 'cells' => ["foo_cell"]})
|
|
595
|
+
@cell_descriptions = [{'name' => "foo_cell", 'elements' => ["1", "2"]}]
|
|
596
|
+
Cell.stub!(:definitions).and_return(@cell_descriptions)
|
|
597
|
+
end
|
|
546
598
|
|
|
547
|
-
|
|
599
|
+
it "should return all cell definitions for its page_layout" do
|
|
600
|
+
@page.cell_definitions.should == @cell_descriptions
|
|
601
|
+
end
|
|
548
602
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
end
|
|
555
|
-
end
|
|
603
|
+
it "should return empty array if no cells defined in page layout" do
|
|
604
|
+
@page.stub!(:layout_description).and_return({'name' => "foo"})
|
|
605
|
+
@page.cell_definitions.should == []
|
|
606
|
+
end
|
|
607
|
+
end
|
|
556
608
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
contentpage.save
|
|
560
|
-
contentpage.should have(1).error_on(:page_layout)
|
|
561
|
-
end
|
|
609
|
+
describe '#destroy' do
|
|
610
|
+
context "with trashed but still assigned elements" do
|
|
562
611
|
|
|
563
|
-
|
|
564
|
-
contentpage.parent_id = nil
|
|
565
|
-
contentpage.save
|
|
566
|
-
contentpage.should have(1).error_on(:parent_id)
|
|
567
|
-
end
|
|
612
|
+
before { news_page.elements.map(&:trash) }
|
|
568
613
|
|
|
569
|
-
it "should
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
contentpage.should_not be_valid
|
|
614
|
+
it "should not delete the trashed elements" do
|
|
615
|
+
news_page.destroy
|
|
616
|
+
Element.trashed.should_not be_empty
|
|
573
617
|
end
|
|
574
618
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
it "should only validate urlname dependent of parent" do
|
|
579
|
-
other_parent = FactoryGirl.create(:page, parent_id: Page.root.id)
|
|
580
|
-
with_same_urlname = FactoryGirl.create(:page, :urlname => "existing_twice")
|
|
581
|
-
contentpage.urlname = 'existing_twice'
|
|
582
|
-
contentpage.parent_id = other_parent.id
|
|
583
|
-
contentpage.should be_valid
|
|
584
|
-
end
|
|
619
|
+
end
|
|
620
|
+
end
|
|
585
621
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
end
|
|
591
|
-
end
|
|
622
|
+
describe '#element_definitions' do
|
|
623
|
+
let(:page) { FactoryGirl.build_stubbed(:page) }
|
|
624
|
+
subject { page.element_definitions }
|
|
625
|
+
before { Element.should_receive(:definitions).and_return([{'name' => 'article'}, {'name' => 'header'}]) }
|
|
592
626
|
|
|
627
|
+
it "returns all element definitions that could be placed on current page" do
|
|
628
|
+
should include({'name' => 'article'})
|
|
629
|
+
should include({'name' => 'header'})
|
|
593
630
|
end
|
|
631
|
+
end
|
|
594
632
|
|
|
595
|
-
|
|
633
|
+
describe '#element_definitions_by_name' do
|
|
634
|
+
let(:page) { FactoryGirl.build_stubbed(:public_page) }
|
|
596
635
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
636
|
+
context "with no name given" do
|
|
637
|
+
it "returns empty array" do
|
|
638
|
+
page.element_definitions_by_name(nil).should == []
|
|
600
639
|
end
|
|
640
|
+
end
|
|
601
641
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
642
|
+
context "with 'all' passed as name" do
|
|
643
|
+
it "returns all element definitions" do
|
|
644
|
+
Element.should_receive(:definitions)
|
|
645
|
+
page.element_definitions_by_name('all')
|
|
605
646
|
end
|
|
606
|
-
|
|
607
647
|
end
|
|
608
648
|
|
|
609
|
-
context "
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
649
|
+
context "with :all passed as name" do
|
|
650
|
+
it "returns all element definitions" do
|
|
651
|
+
Element.should_receive(:definitions)
|
|
652
|
+
page.element_definitions_by_name(:all)
|
|
613
653
|
end
|
|
654
|
+
end
|
|
655
|
+
end
|
|
614
656
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
@systempage.should be_valid
|
|
618
|
-
end
|
|
657
|
+
describe '#element_definition_names' do
|
|
658
|
+
let(:page) { FactoryGirl.build_stubbed(:public_page) }
|
|
619
659
|
|
|
660
|
+
it "returns all element names defined in page layout" do
|
|
661
|
+
page.element_definition_names.should == %w(article header)
|
|
620
662
|
end
|
|
621
663
|
|
|
664
|
+
it "returns always an array" do
|
|
665
|
+
page.stub(:definition).and_return({})
|
|
666
|
+
page.element_definition_names.should be_an(Array)
|
|
667
|
+
end
|
|
622
668
|
end
|
|
623
669
|
|
|
624
|
-
describe '
|
|
625
|
-
|
|
626
|
-
context "a normal page" do
|
|
627
|
-
|
|
628
|
-
before do
|
|
629
|
-
@page = FactoryGirl.build(:page, :language_code => nil, :language => klingonian, :do_not_autogenerate => false)
|
|
630
|
-
end
|
|
670
|
+
describe '#elements_grouped_by_cells' do
|
|
671
|
+
let(:page) { FactoryGirl.create(:public_page, :do_not_autogenerate => false) }
|
|
631
672
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
673
|
+
before do
|
|
674
|
+
PageLayout.stub(:get).and_return({
|
|
675
|
+
'name' => 'standard',
|
|
676
|
+
'cells' => ['header'],
|
|
677
|
+
'elements' => ['header', 'text'],
|
|
678
|
+
'autogenerate' => ['header', 'text']
|
|
679
|
+
})
|
|
680
|
+
Cell.stub!(:definitions).and_return([{
|
|
681
|
+
'name' => "header",
|
|
682
|
+
'elements' => ["header"]
|
|
683
|
+
}])
|
|
684
|
+
end
|
|
636
685
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
686
|
+
it "should return elements grouped by cell" do
|
|
687
|
+
elements = page.elements_grouped_by_cells
|
|
688
|
+
elements.keys.first.should be_instance_of(Cell)
|
|
689
|
+
elements.values.first.first.should be_instance_of(Element)
|
|
690
|
+
end
|
|
641
691
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
end
|
|
692
|
+
it "should only include elements beeing in a cell " do
|
|
693
|
+
page.elements_grouped_by_cells.keys.should_not include(nil)
|
|
694
|
+
end
|
|
695
|
+
end
|
|
647
696
|
|
|
648
|
-
|
|
697
|
+
describe '#feed_elements' do
|
|
698
|
+
it "should return all rss feed elements" do
|
|
699
|
+
news_page.feed_elements.should_not be_empty
|
|
700
|
+
news_page.feed_elements.should == Element.find_all_by_name('news')
|
|
701
|
+
end
|
|
702
|
+
end
|
|
649
703
|
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
704
|
+
describe '#find_elements' do
|
|
705
|
+
before do
|
|
706
|
+
FactoryGirl.create(:element, :public => false, :page => public_page)
|
|
707
|
+
FactoryGirl.create(:element, :public => false, :page => public_page)
|
|
708
|
+
end
|
|
653
709
|
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
end
|
|
710
|
+
context "with show_non_public argument TRUE" do
|
|
711
|
+
it "should return all elements from empty options" do
|
|
712
|
+
public_page.find_elements({}, true).all.should == public_page.elements.all
|
|
713
|
+
end
|
|
659
714
|
|
|
660
|
-
|
|
715
|
+
it "should only return the elements passed as options[:only]" do
|
|
716
|
+
public_page.find_elements({:only => ['article']}, true).all.should == public_page.elements.named('article').all
|
|
717
|
+
end
|
|
661
718
|
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
@page.cells.collect(&:elements).flatten.should be_empty
|
|
666
|
-
end
|
|
719
|
+
it "should not return the elements passed as options[:except]" do
|
|
720
|
+
public_page.find_elements({:except => ['article']}, true).all.should == public_page.elements - public_page.elements.named('article').all
|
|
721
|
+
end
|
|
667
722
|
|
|
668
|
-
|
|
723
|
+
it "should return elements offsetted" do
|
|
724
|
+
public_page.find_elements({:offset => 2}, true).all.should == public_page.elements.offset(2)
|
|
725
|
+
end
|
|
669
726
|
|
|
727
|
+
it "should return elements limitted in count" do
|
|
728
|
+
public_page.find_elements({:count => 1}, true).all.should == public_page.elements.limit(1)
|
|
670
729
|
end
|
|
730
|
+
end
|
|
671
731
|
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
@page.save
|
|
675
|
-
@child1 = FactoryGirl.create(:page, :name => 'Child 1', :parent_id => @page.id)
|
|
676
|
-
@page.reload
|
|
677
|
-
}
|
|
732
|
+
context "with options[:from_cell]" do
|
|
733
|
+
let(:element) { FactoryGirl.build_stubbed(:element) }
|
|
678
734
|
|
|
679
|
-
|
|
735
|
+
context "given as String" do
|
|
736
|
+
context '' do
|
|
680
737
|
before {
|
|
681
|
-
|
|
682
|
-
@page.save
|
|
738
|
+
public_page.cells.stub_chain(:find_by_name, :elements, :offset, :limit, :published).and_return([element])
|
|
683
739
|
}
|
|
684
740
|
|
|
685
|
-
it "
|
|
686
|
-
|
|
687
|
-
@child1.restricted?.should be_true
|
|
741
|
+
it "returns only the elements from given cell" do
|
|
742
|
+
public_page.find_elements(from_cell: 'A Cell').to_a.should == [element]
|
|
688
743
|
end
|
|
689
744
|
end
|
|
690
745
|
|
|
691
|
-
context "
|
|
746
|
+
context "that can not be found" do
|
|
747
|
+
let(:elements) {[]}
|
|
692
748
|
before {
|
|
693
|
-
|
|
694
|
-
@page.save
|
|
749
|
+
elements.stub_chain(:offset, :limit, :published).and_return([])
|
|
695
750
|
}
|
|
696
751
|
|
|
697
|
-
it "
|
|
698
|
-
|
|
699
|
-
|
|
752
|
+
it "returns empty set" do
|
|
753
|
+
public_page.elements.should_receive(:where).with('1 = 0').and_return(elements)
|
|
754
|
+
public_page.find_elements(from_cell: 'Lolo').to_a.should == []
|
|
755
|
+
end
|
|
756
|
+
|
|
757
|
+
it "loggs a warning" do
|
|
758
|
+
Rails.logger.should_receive(:debug)
|
|
759
|
+
public_page.find_elements(from_cell: 'Lolo')
|
|
700
760
|
end
|
|
701
761
|
end
|
|
702
762
|
end
|
|
703
763
|
|
|
704
|
-
context "
|
|
705
|
-
|
|
706
|
-
before do
|
|
707
|
-
@page.save
|
|
708
|
-
@page.parent.update_attributes(:restricted => true)
|
|
709
|
-
@new_page = FactoryGirl.create(:page, :name => 'New Page', :parent_id => @page.id)
|
|
710
|
-
end
|
|
764
|
+
context "given as cell object" do
|
|
765
|
+
let(:cell) { FactoryGirl.build_stubbed(:cell, page: public_page) }
|
|
711
766
|
|
|
712
|
-
it "
|
|
713
|
-
|
|
767
|
+
it "returns only the elements from given cell" do
|
|
768
|
+
cell.stub_chain(:elements, :offset, :limit, :published).and_return([element])
|
|
769
|
+
public_page.find_elements(from_cell: cell).to_a.should == [element]
|
|
714
770
|
end
|
|
771
|
+
end
|
|
772
|
+
end
|
|
715
773
|
|
|
774
|
+
context "with show_non_public argument FALSE" do
|
|
775
|
+
it "should return all elements from empty arguments" do
|
|
776
|
+
public_page.find_elements().all.should == public_page.elements.published.all
|
|
716
777
|
end
|
|
717
778
|
|
|
718
|
-
|
|
779
|
+
it "should only return the public elements passed as options[:only]" do
|
|
780
|
+
public_page.find_elements(:only => ['article']).all.should == public_page.elements.published.named('article').all
|
|
781
|
+
end
|
|
719
782
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
783
|
+
it "should return all public elements except the ones passed as options[:except]" do
|
|
784
|
+
public_page.find_elements(:except => ['article']).all.should == public_page.elements.published.all - public_page.elements.published.named('article').all
|
|
785
|
+
end
|
|
723
786
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
end
|
|
787
|
+
it "should return elements offsetted" do
|
|
788
|
+
public_page.find_elements({:offset => 2}).all.should == public_page.elements.published.offset(2)
|
|
789
|
+
end
|
|
728
790
|
|
|
791
|
+
it "should return elements limitted in count" do
|
|
792
|
+
public_page.find_elements({:count => 1}).all.should == public_page.elements.published.limit(1)
|
|
729
793
|
end
|
|
794
|
+
end
|
|
795
|
+
end
|
|
730
796
|
|
|
797
|
+
describe '#first_public_child' do
|
|
798
|
+
before do
|
|
799
|
+
FactoryGirl.create(:page, :name => "First child", :language => language, :public => false, :parent_id => language_root.id)
|
|
731
800
|
end
|
|
732
801
|
|
|
733
|
-
|
|
802
|
+
it "should return first_public_child" do
|
|
803
|
+
first_public_child = FactoryGirl.create(:public_page, :name => "First public child", :language => language, :parent_id => language_root.id)
|
|
804
|
+
language_root.first_public_child.should == first_public_child
|
|
805
|
+
end
|
|
734
806
|
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
807
|
+
it "should return nil if no public child exists" do
|
|
808
|
+
language_root.first_public_child.should == nil
|
|
809
|
+
end
|
|
810
|
+
end
|
|
738
811
|
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
end
|
|
812
|
+
context 'folding' do
|
|
813
|
+
let(:user) { mock_model('User') }
|
|
742
814
|
|
|
743
|
-
|
|
744
|
-
|
|
815
|
+
describe '#fold!' do
|
|
816
|
+
context "with folded status set to true" do
|
|
817
|
+
it "should create a folded page for user" do
|
|
818
|
+
public_page.fold!(user.id, true)
|
|
819
|
+
expect(public_page.folded_pages.first.user_id).to eq(user.id)
|
|
820
|
+
end
|
|
745
821
|
end
|
|
746
|
-
|
|
747
822
|
end
|
|
748
823
|
|
|
749
|
-
|
|
824
|
+
describe '#folded?' do
|
|
825
|
+
let(:page) { Page.new }
|
|
750
826
|
|
|
751
|
-
|
|
827
|
+
context 'if page is folded' do
|
|
828
|
+
before do
|
|
829
|
+
page.stub_chain(:folded_pages, :find_by_user_id).and_return(mock_model('FoldedPage', folded: true))
|
|
830
|
+
end
|
|
752
831
|
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
news_page.elements.trashed.should include(news_element)
|
|
832
|
+
it "should return true" do
|
|
833
|
+
expect(page.folded?(user.id)).to eq(true)
|
|
834
|
+
end
|
|
757
835
|
end
|
|
758
836
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
837
|
+
context 'if page is not folded' do
|
|
838
|
+
it "should return false" do
|
|
839
|
+
expect(page.folded?(101093)).to eq(false)
|
|
840
|
+
end
|
|
762
841
|
end
|
|
842
|
+
end
|
|
843
|
+
end
|
|
844
|
+
|
|
845
|
+
describe '#lock!' do
|
|
846
|
+
let(:page) { FactoryGirl.create(:page) }
|
|
847
|
+
let(:user) { mock_model('User') }
|
|
763
848
|
|
|
849
|
+
it "should set locked to true" do
|
|
850
|
+
page.lock!(user)
|
|
851
|
+
page.reload
|
|
852
|
+
page.locked.should == true
|
|
764
853
|
end
|
|
765
854
|
|
|
855
|
+
it "should not update the timestamps " do
|
|
856
|
+
expect { page.lock!(user) }.to_not change(page, :updated_at)
|
|
857
|
+
end
|
|
858
|
+
|
|
859
|
+
it "should set locked_by to the users id" do
|
|
860
|
+
page.lock!(user)
|
|
861
|
+
page.reload
|
|
862
|
+
page.locked_by.should == user.id
|
|
863
|
+
end
|
|
766
864
|
end
|
|
767
865
|
|
|
768
|
-
describe '#
|
|
866
|
+
describe '#paste_from_clipboard' do
|
|
867
|
+
let(:source) { FactoryGirl.build_stubbed(:page) }
|
|
868
|
+
let(:new_parent) { FactoryGirl.build_stubbed(:page) }
|
|
869
|
+
let(:page_name) { "Pagename (pasted)" }
|
|
870
|
+
let(:copied_page) { mock_model('Page') }
|
|
769
871
|
|
|
770
|
-
|
|
771
|
-
|
|
872
|
+
subject { Page.paste_from_clipboard(source, new_parent, page_name) }
|
|
873
|
+
|
|
874
|
+
it "should copy the source page with the given name to the new parent" do
|
|
875
|
+
Page.should_receive(:copy).with(source, {
|
|
876
|
+
parent_id: new_parent.id,
|
|
877
|
+
language: new_parent.language,
|
|
878
|
+
name: page_name,
|
|
879
|
+
title: page_name
|
|
880
|
+
})
|
|
881
|
+
subject
|
|
772
882
|
end
|
|
773
883
|
|
|
774
|
-
|
|
884
|
+
it "should return the copied page" do
|
|
885
|
+
Page.stub!(:copy).and_return(copied_page)
|
|
886
|
+
expect(subject).to be_a(copied_page.class)
|
|
887
|
+
end
|
|
775
888
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
889
|
+
context "if source page has children" do
|
|
890
|
+
it "should also copy and paste the children" do
|
|
891
|
+
Page.stub!(:copy).and_return(copied_page)
|
|
892
|
+
source.stub!(:children).and_return([mock_model('Page')])
|
|
893
|
+
source.should_receive(:copy_children_to).with(copied_page)
|
|
894
|
+
subject
|
|
779
895
|
end
|
|
780
|
-
|
|
781
896
|
end
|
|
782
|
-
|
|
783
897
|
end
|
|
784
898
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
let(:
|
|
788
|
-
let(:
|
|
899
|
+
context 'previous and next.' do
|
|
900
|
+
let(:center_page) { FactoryGirl.create(:public_page, name: 'Center Page') }
|
|
901
|
+
let(:next_page) { FactoryGirl.create(:public_page, name: 'Next Page') }
|
|
902
|
+
let(:non_public_page) { FactoryGirl.create(:page, name: 'Not public Page') }
|
|
903
|
+
let(:restricted_page) { FactoryGirl.create(:restricted_page, public: true) }
|
|
789
904
|
|
|
790
905
|
before do
|
|
791
906
|
public_page
|
|
907
|
+
restricted_page
|
|
908
|
+
non_public_page
|
|
792
909
|
center_page
|
|
793
910
|
next_page
|
|
794
911
|
end
|
|
795
912
|
|
|
796
913
|
describe '#previous' do
|
|
797
|
-
|
|
798
914
|
it "should return the previous page on the same level" do
|
|
799
915
|
center_page.previous.should == public_page
|
|
800
916
|
end
|
|
801
917
|
|
|
802
918
|
context "no previous page on same level present" do
|
|
803
|
-
|
|
804
919
|
it "should return nil" do
|
|
805
920
|
public_page.previous.should be_nil
|
|
806
921
|
end
|
|
922
|
+
end
|
|
923
|
+
|
|
924
|
+
context "with options restricted" do
|
|
925
|
+
context "set to true" do
|
|
926
|
+
it "returns previous restricted page" do
|
|
927
|
+
center_page.previous(restricted: true).should == restricted_page
|
|
928
|
+
end
|
|
929
|
+
end
|
|
807
930
|
|
|
931
|
+
context "set to false" do
|
|
932
|
+
it "skips restricted page" do
|
|
933
|
+
center_page.previous(restricted: false).should == public_page
|
|
934
|
+
end
|
|
935
|
+
end
|
|
808
936
|
end
|
|
809
937
|
|
|
938
|
+
context "with options public" do
|
|
939
|
+
context "set to true" do
|
|
940
|
+
it "returns previous public page" do
|
|
941
|
+
center_page.previous(public: true).should == public_page
|
|
942
|
+
end
|
|
943
|
+
end
|
|
944
|
+
|
|
945
|
+
context "set to false" do
|
|
946
|
+
it "skips public page" do
|
|
947
|
+
center_page.previous(public: false).should == non_public_page
|
|
948
|
+
end
|
|
949
|
+
end
|
|
950
|
+
end
|
|
810
951
|
end
|
|
811
952
|
|
|
812
953
|
describe '#next' do
|
|
813
|
-
|
|
814
954
|
it "should return the next page on the same level" do
|
|
815
955
|
center_page.next.should == next_page
|
|
816
956
|
end
|
|
817
957
|
|
|
818
958
|
context "no next page on same level present" do
|
|
819
|
-
|
|
820
959
|
it "should return nil" do
|
|
821
960
|
next_page.next.should be_nil
|
|
822
961
|
end
|
|
962
|
+
end
|
|
963
|
+
end
|
|
964
|
+
end
|
|
965
|
+
|
|
966
|
+
describe '#publish!' do
|
|
967
|
+
let(:page) { FactoryGirl.build_stubbed(:page, public: false) }
|
|
968
|
+
|
|
969
|
+
before do
|
|
970
|
+
page.stub!(:save).and_return(true)
|
|
971
|
+
page.publish!
|
|
972
|
+
end
|
|
823
973
|
|
|
974
|
+
it "sets public attribute to true" do
|
|
975
|
+
page.public.should == true
|
|
976
|
+
end
|
|
977
|
+
end
|
|
978
|
+
|
|
979
|
+
describe '#set_language_from_parent_or_default_language' do
|
|
980
|
+
let(:default_language) { mock_model('Language', code: 'es') }
|
|
981
|
+
let(:page) { Page.new }
|
|
982
|
+
|
|
983
|
+
before { page.stub!(:parent).and_return(parent) }
|
|
984
|
+
|
|
985
|
+
subject { page }
|
|
986
|
+
|
|
987
|
+
context "parent has a language" do
|
|
988
|
+
let(:parent) { mock_model('Page', language: default_language, language_id: default_language.id, language_code: default_language.code) }
|
|
989
|
+
|
|
990
|
+
before do
|
|
991
|
+
page.set_language_from_parent_or_default_language
|
|
824
992
|
end
|
|
825
993
|
|
|
994
|
+
its(:language_id) { should eq(parent.language_id) }
|
|
995
|
+
its(:language_code) { should eq(parent.language_code) }
|
|
826
996
|
end
|
|
827
997
|
|
|
998
|
+
context "parent has no language" do
|
|
999
|
+
let(:parent) { mock_model('Page', language: nil, language_id: nil, language_code: nil) }
|
|
1000
|
+
|
|
1001
|
+
before do
|
|
1002
|
+
Language.stub!(:get_default).and_return(default_language)
|
|
1003
|
+
page.set_language_from_parent_or_default_language
|
|
1004
|
+
end
|
|
1005
|
+
|
|
1006
|
+
its(:language_id) { should eq(default_language.id) }
|
|
1007
|
+
its(:language_code) { should eq(default_language.code) }
|
|
1008
|
+
end
|
|
828
1009
|
end
|
|
829
1010
|
|
|
830
1011
|
describe '#taggable?' do
|
|
831
|
-
|
|
832
1012
|
context "definition has 'taggable' key with true value" do
|
|
833
1013
|
it "should return true" do
|
|
834
1014
|
page = FactoryGirl.build(:page)
|
|
@@ -852,93 +1032,29 @@ module Alchemy
|
|
|
852
1032
|
page.taggable?.should be_false
|
|
853
1033
|
end
|
|
854
1034
|
end
|
|
855
|
-
|
|
856
1035
|
end
|
|
857
1036
|
|
|
858
|
-
describe '
|
|
859
|
-
let(:page) { FactoryGirl.create(:page, :
|
|
860
|
-
subject { Page.copy(page) }
|
|
861
|
-
|
|
862
|
-
it "the copy should have added (copy) to name" do
|
|
863
|
-
subject.name.should == "#{page.name} (Copy)"
|
|
864
|
-
end
|
|
865
|
-
|
|
866
|
-
context "page with tags" do
|
|
867
|
-
before { page.tag_list = 'red, yellow'; page.save }
|
|
868
|
-
|
|
869
|
-
it "the copy should have source tag_list" do
|
|
870
|
-
# The order of tags varies between postgresql and sqlite/mysql
|
|
871
|
-
# This is related to acts-as-taggable-on v.2.4.1
|
|
872
|
-
# To fix the spec we sort the tags until the issue is solved (https://github.com/mbleigh/acts-as-taggable-on/issues/363)
|
|
873
|
-
subject.tag_list.should_not be_empty
|
|
874
|
-
subject.tag_list.sort.should == page.tag_list.sort
|
|
875
|
-
end
|
|
876
|
-
end
|
|
877
|
-
|
|
878
|
-
context "page with elements" do
|
|
879
|
-
before { page.elements << FactoryGirl.create(:element) }
|
|
880
|
-
|
|
881
|
-
it "the copy should have source elements" do
|
|
882
|
-
subject.elements.should_not be_empty
|
|
883
|
-
subject.elements.count.should == page.elements.count
|
|
884
|
-
end
|
|
885
|
-
end
|
|
886
|
-
|
|
887
|
-
context "page with trashed elements" do
|
|
888
|
-
before do
|
|
889
|
-
page.elements << FactoryGirl.create(:element)
|
|
890
|
-
page.elements.first.trash
|
|
891
|
-
end
|
|
892
|
-
|
|
893
|
-
it "the copy should not hold a copy of the trashed elements" do
|
|
894
|
-
subject.elements.should be_empty
|
|
895
|
-
end
|
|
896
|
-
end
|
|
897
|
-
|
|
898
|
-
context "page with cells" do
|
|
899
|
-
before { page.cells << FactoryGirl.create(:cell) }
|
|
900
|
-
|
|
901
|
-
it "the copy should have source cells" do
|
|
902
|
-
subject.cells.should_not be_empty
|
|
903
|
-
subject.cells.count.should == page.cells.length # It must be length, because!
|
|
904
|
-
end
|
|
905
|
-
end
|
|
906
|
-
|
|
907
|
-
context "page with autogenerate elements" do
|
|
908
|
-
before do
|
|
909
|
-
page = FactoryGirl.create(:page)
|
|
910
|
-
page.stub!(:definition).and_return({'name' => 'standard', 'elements' => ['headline'], 'autogenerate' => ['headline']})
|
|
911
|
-
end
|
|
1037
|
+
describe '#unlock!' do
|
|
1038
|
+
let(:page) { FactoryGirl.create(:page, locked: true, locked_by: 1) }
|
|
912
1039
|
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
1040
|
+
its "should set the locked status to false" do
|
|
1041
|
+
page.unlock!
|
|
1042
|
+
page.reload
|
|
1043
|
+
page.locked.should == false
|
|
916
1044
|
end
|
|
917
1045
|
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
it "should take this name" do
|
|
921
|
-
subject.name.should == 'Different name'
|
|
922
|
-
end
|
|
1046
|
+
it "should not update the timestamps " do
|
|
1047
|
+
expect { page.unlock! }.to_not change(page, :updated_at)
|
|
923
1048
|
end
|
|
924
|
-
end
|
|
925
|
-
|
|
926
|
-
describe "#cache_key" do
|
|
927
|
-
let(:page) { stub_model(Page) }
|
|
928
|
-
subject { page }
|
|
929
|
-
its(:cache_key) { should match(page.id.to_s) }
|
|
930
|
-
end
|
|
931
|
-
|
|
932
|
-
describe "#publish!" do
|
|
933
|
-
let(:page) { FactoryGirl.create(:page) }
|
|
934
|
-
before { page.publish! }
|
|
935
1049
|
|
|
936
|
-
it "
|
|
937
|
-
page.
|
|
1050
|
+
it "should set locked_by to nil" do
|
|
1051
|
+
page.unlock!
|
|
1052
|
+
page.reload
|
|
1053
|
+
page.locked_by.should == nil
|
|
938
1054
|
end
|
|
939
1055
|
end
|
|
940
1056
|
|
|
941
|
-
|
|
1057
|
+
context 'urlname updating' do
|
|
942
1058
|
let(:parentparent) { FactoryGirl.create(:page, name: 'parentparent', visible: true) }
|
|
943
1059
|
let(:parent) { FactoryGirl.create(:page, parent_id: parentparent.id, name: 'parent', visible: true) }
|
|
944
1060
|
let(:page) { FactoryGirl.create(:page, parent_id: parent.id, name: 'page', visible: true) }
|
|
@@ -1027,7 +1143,7 @@ module Alchemy
|
|
|
1027
1143
|
end
|
|
1028
1144
|
end
|
|
1029
1145
|
|
|
1030
|
-
|
|
1146
|
+
context 'page status methods' do
|
|
1031
1147
|
let(:page) { FactoryGirl.build(:page, public: true, visible: true, restricted: false, locked: false)}
|
|
1032
1148
|
|
|
1033
1149
|
describe '#status' do
|
|
@@ -1053,7 +1169,50 @@ module Alchemy
|
|
|
1053
1169
|
page.status_title(:restricted).should == 'Page is not restricted.'
|
|
1054
1170
|
end
|
|
1055
1171
|
end
|
|
1172
|
+
end
|
|
1173
|
+
|
|
1174
|
+
context 'indicate page editors' do
|
|
1175
|
+
let(:page) { Page.new }
|
|
1176
|
+
let(:user) { User.new(firstname: 'Paul', lastname: 'Page') }
|
|
1177
|
+
|
|
1178
|
+
describe '#creator_name' do
|
|
1179
|
+
before { page.stub(:creator).and_return(user) }
|
|
1180
|
+
|
|
1181
|
+
it "should return the name of the creator" do
|
|
1182
|
+
expect(page.creator_name).to eq('Paul Page')
|
|
1183
|
+
end
|
|
1184
|
+
end
|
|
1185
|
+
|
|
1186
|
+
describe '#updater_name' do
|
|
1187
|
+
before { page.stub(:updater).and_return(user) }
|
|
1188
|
+
|
|
1189
|
+
it "should return the name of the updater" do
|
|
1190
|
+
expect(page.updater_name).to eq('Paul Page')
|
|
1191
|
+
end
|
|
1192
|
+
end
|
|
1193
|
+
|
|
1194
|
+
describe '#locker_name' do
|
|
1195
|
+
before { page.stub(:locker).and_return(user) }
|
|
1196
|
+
|
|
1197
|
+
it "should return the name of the current page editor" do
|
|
1198
|
+
expect(page.locker_name).to eq('Paul Page')
|
|
1199
|
+
end
|
|
1200
|
+
end
|
|
1201
|
+
|
|
1202
|
+
end
|
|
1203
|
+
|
|
1204
|
+
describe '#controller_and_action' do
|
|
1205
|
+
let(:page) { Page.new }
|
|
1056
1206
|
|
|
1207
|
+
context 'if the page has a custom controller defined in its description' do
|
|
1208
|
+
before do
|
|
1209
|
+
page.stub!(:has_controller?).and_return(true)
|
|
1210
|
+
page.stub!(:layout_description).and_return({'controller' => 'comments', 'action' => 'index'})
|
|
1211
|
+
end
|
|
1212
|
+
it "should return a Hash with controller and action key-value pairs" do
|
|
1213
|
+
expect(page.controller_and_action).to eq({controller: '/comments', action: 'index'})
|
|
1214
|
+
end
|
|
1215
|
+
end
|
|
1057
1216
|
end
|
|
1058
1217
|
|
|
1059
1218
|
end
|