alchemy_cms 3.2.0.beta → 3.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +661 -863
  3. data/README.md +5 -63
  4. data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +11 -10
  5. data/app/assets/javascripts/alchemy/alchemy.initializer.js.coffee +6 -0
  6. data/app/assets/stylesheets/alchemy/_extends.scss +0 -6
  7. data/app/assets/stylesheets/alchemy/_mixins.scss +6 -0
  8. data/app/assets/stylesheets/alchemy/buttons.scss +1 -1
  9. data/app/assets/stylesheets/alchemy/elements.scss +1 -1
  10. data/app/assets/stylesheets/alchemy/menubar.scss +1 -1
  11. data/app/assets/stylesheets/alchemy/selects.scss +5 -1
  12. data/app/assets/stylesheets/alchemy/upload.scss +1 -1
  13. data/app/controllers/alchemy/admin/pages_controller.rb +1 -1
  14. data/app/controllers/alchemy/base_controller.rb +4 -57
  15. data/app/controllers/alchemy/messages_controller.rb +2 -2
  16. data/app/controllers/alchemy/pages_controller.rb +22 -31
  17. data/app/controllers/alchemy/pictures_controller.rb +2 -2
  18. data/app/helpers/alchemy/admin/base_helper.rb +7 -0
  19. data/app/helpers/alchemy/admin/elements_helper.rb +31 -15
  20. data/app/helpers/alchemy/admin/pages_helper.rb +17 -0
  21. data/app/helpers/alchemy/base_helper.rb +0 -28
  22. data/app/helpers/alchemy/pages_helper.rb +18 -12
  23. data/app/helpers/alchemy/url_helper.rb +2 -2
  24. data/app/models/alchemy/cell.rb +1 -1
  25. data/app/models/alchemy/content/factory.rb +12 -6
  26. data/app/models/alchemy/element.rb +3 -3
  27. data/app/models/alchemy/element/definitions.rb +1 -1
  28. data/app/models/alchemy/element_to_page.rb +7 -0
  29. data/app/models/alchemy/language.rb +1 -1
  30. data/app/models/alchemy/page.rb +8 -1
  31. data/app/models/alchemy/page/page_cells.rb +2 -2
  32. data/app/models/alchemy/page/page_elements.rb +23 -5
  33. data/app/models/alchemy/page/page_natures.rb +3 -3
  34. data/app/models/alchemy/page/page_scopes.rb +1 -1
  35. data/app/models/alchemy/picture.rb +1 -1
  36. data/app/views/alchemy/admin/pages/_create_language_form.html.erb +1 -1
  37. data/app/views/alchemy/admin/pages/_form.html.erb +1 -1
  38. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +1 -1
  39. data/app/views/alchemy/breadcrumb/_page.html.erb +3 -2
  40. data/app/views/alchemy/breadcrumb/_separator.html.erb +1 -0
  41. data/app/views/alchemy/breadcrumb/_wrapper.html.erb +13 -0
  42. data/app/views/alchemy/language_links/_language.html.erb +1 -1
  43. data/app/views/alchemy/navigation/_link.html.erb +1 -1
  44. data/app/views/alchemy/pages/show.rss.builder +5 -7
  45. data/app/views/layouts/alchemy/admin.html.erb +5 -0
  46. data/config/routes.rb +13 -10
  47. data/lib/alchemy/configuration_methods.rb +29 -0
  48. data/lib/alchemy/controller_actions.rb +12 -4
  49. data/lib/alchemy/engine.rb +3 -0
  50. data/lib/alchemy/errors.rb +1 -1
  51. data/lib/alchemy/essence.rb +14 -12
  52. data/lib/alchemy/on_page_layout.rb +58 -0
  53. data/lib/alchemy/page_layout.rb +1 -1
  54. data/lib/alchemy/permissions.rb +21 -16
  55. data/lib/alchemy/routing_constraints.rb +49 -0
  56. data/lib/alchemy/seeder.rb +4 -2
  57. data/lib/alchemy/ssl_protection.rb +30 -0
  58. data/lib/alchemy/test_support/essence_shared_examples.rb +118 -25
  59. data/lib/alchemy/test_support/factories.rb +5 -8
  60. data/lib/alchemy/test_support/integration_helpers.rb +16 -10
  61. data/lib/alchemy/upgrader/three_point_two.rb +34 -4
  62. data/lib/alchemy/version.rb +1 -1
  63. data/lib/rails/generators/alchemy/{scaffold → install}/files/_article_editor.html.erb +0 -0
  64. data/lib/rails/generators/alchemy/{scaffold → install}/files/_article_view.html.erb +0 -0
  65. data/lib/rails/generators/alchemy/{scaffold → install}/files/_standard.html.erb +0 -0
  66. data/lib/rails/generators/alchemy/{scaffold → install}/files/alchemy.de.yml +0 -0
  67. data/lib/rails/generators/alchemy/{scaffold → install}/files/alchemy.elements.css.scss +0 -0
  68. data/lib/rails/generators/alchemy/{scaffold → install}/files/alchemy.en.yml +0 -0
  69. data/lib/rails/generators/alchemy/{scaffold → install}/files/alchemy.es.yml +0 -0
  70. data/lib/rails/generators/alchemy/{scaffold → install}/files/application.html.erb +0 -0
  71. data/lib/rails/generators/alchemy/install/install_generator.rb +69 -0
  72. data/lib/rails/generators/alchemy/{scaffold/files/elements.yml → install/templates/elements.yml.tt} +2 -0
  73. data/lib/rails/generators/alchemy/{scaffold → install}/templates/page_layouts.yml.tt +2 -0
  74. data/lib/rails/generators/alchemy/views/views_generator.rb +41 -0
  75. data/lib/rails/templates/alchemy.rb +2 -2
  76. data/lib/tasks/alchemy/db.rake +0 -5
  77. data/lib/tasks/alchemy/install.rake +10 -5
  78. data/lib/tasks/alchemy/tidy.rake +2 -0
  79. data/spec/controllers/admin/attachments_controller_spec.rb +1 -1
  80. data/spec/controllers/admin/clipboard_controller_spec.rb +1 -1
  81. data/spec/controllers/admin/contents_controller_spec.rb +1 -1
  82. data/spec/controllers/admin/dashboard_controller_spec.rb +2 -2
  83. data/spec/controllers/admin/elements_controller_spec.rb +1 -1
  84. data/spec/controllers/admin/essence_files_controller_spec.rb +1 -1
  85. data/spec/controllers/admin/essence_pictures_controller_spec.rb +1 -1
  86. data/spec/controllers/admin/languages_controller_spec.rb +1 -1
  87. data/spec/controllers/admin/layoutpages_controller_spec.rb +1 -1
  88. data/spec/controllers/admin/pages_controller_spec.rb +4 -4
  89. data/spec/controllers/admin/pictures_controller_spec.rb +1 -1
  90. data/spec/controllers/admin/resources_controller_spec.rb +1 -1
  91. data/spec/controllers/admin/trash_controller_spec.rb +1 -1
  92. data/spec/controllers/alchemy/admin/tags_controller_spec.rb +1 -1
  93. data/spec/controllers/attachments_controller_spec.rb +1 -1
  94. data/spec/controllers/base_controller_spec.rb +22 -0
  95. data/spec/controllers/elements_controller_spec.rb +1 -1
  96. data/spec/controllers/pages_controller_spec.rb +15 -16
  97. data/spec/controllers/pictures_controller_spec.rb +212 -162
  98. data/spec/dummy/app/controllers/login_controller.rb +5 -0
  99. data/spec/dummy/app/models/dummy_model.rb +3 -0
  100. data/spec/dummy/config/alchemy/cells.yml +4 -1
  101. data/spec/dummy/config/alchemy/elements.yml +8 -0
  102. data/spec/dummy/config/alchemy/page_layouts.yml +5 -1
  103. data/spec/dummy/config/routes.rb +1 -2
  104. data/spec/dummy/db/migrate/20150412103152_create_dummy_model.rb +7 -0
  105. data/spec/dummy/db/schema.rb +30 -26
  106. data/spec/features/admin/dashboard_spec.rb +11 -9
  107. data/spec/features/admin/language_tree_feature_spec.rb +5 -6
  108. data/spec/features/admin/legacy_page_url_management_spec.rb +1 -1
  109. data/spec/features/admin/link_overlay_spec.rb +1 -1
  110. data/spec/features/admin/locale_select_feature_spec.rb +1 -1
  111. data/spec/features/admin/modules_integration_spec.rb +1 -1
  112. data/spec/features/admin/navigation_feature_spec.rb +1 -1
  113. data/spec/features/admin/page_creation_feature_spec.rb +1 -1
  114. data/spec/features/admin/page_editing_feature_spec.rb +3 -3
  115. data/spec/features/admin/picture_library_integration_spec.rb +1 -1
  116. data/spec/features/admin/resources_integration_spec.rb +1 -1
  117. data/spec/features/admin/site_select_feature_spec.rb +32 -0
  118. data/spec/features/admin/tinymce_feature_spec.rb +1 -3
  119. data/spec/features/page_feature_spec.rb +36 -27
  120. data/spec/features/security_spec.rb +1 -1
  121. data/spec/features/translation_integration_spec.rb +3 -3
  122. data/spec/helpers/admin/elements_helper_spec.rb +103 -26
  123. data/spec/helpers/admin/pages_helper_spec.rb +32 -1
  124. data/spec/helpers/base_helper_spec.rb +0 -45
  125. data/spec/helpers/pages_helper_spec.rb +18 -17
  126. data/spec/helpers/url_helper_spec.rb +8 -5
  127. data/spec/libraries/controller_actions_spec.rb +2 -2
  128. data/spec/libraries/on_page_layout_spec.rb +112 -0
  129. data/spec/libraries/page_layout_spec.rb +5 -1
  130. data/spec/libraries/permissions_spec.rb +13 -15
  131. data/spec/models/cell_spec.rb +4 -0
  132. data/spec/models/content_spec.rb +6 -0
  133. data/spec/models/dummy_model_spec.rb +11 -0
  134. data/spec/models/element_spec.rb +6 -1
  135. data/spec/models/element_to_page_spec.rb +14 -0
  136. data/spec/models/page_spec.rb +111 -19
  137. data/spec/routing/routing_spec.rb +120 -101
  138. data/spec/spec_helper.rb +3 -3
  139. metadata +36 -21
  140. data/app/views/alchemy/breadcrumb/_spacer.html.erb +0 -1
  141. data/lib/alchemy/capistrano.rb +0 -230
  142. data/lib/alchemy/test_support/auth_helpers.rb +0 -35
  143. data/lib/rails/generators/alchemy/deploy_script/deploy_script_generator.rb +0 -90
  144. data/lib/rails/generators/alchemy/deploy_script/templates/deploy.rb.tt +0 -113
  145. data/lib/rails/generators/alchemy/scaffold/scaffold_generator.rb +0 -63
  146. data/spec/dummy/app/controllers/errors_controller.rb +0 -5
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.feature "Picture Library" do
4
4
  before do
5
- authorize_as_admin
5
+ authorize_user(:as_admin)
6
6
  end
7
7
 
8
8
  describe "Tagging" do
@@ -4,7 +4,7 @@ describe "Resources" do
4
4
  let(:event) { FactoryGirl.create(:event) }
5
5
  let(:second_event) { FactoryGirl.create(:event, :name => 'My second Event', :entrance_fee => 12.32) }
6
6
 
7
- before { authorize_as_admin }
7
+ before { authorize_user(:as_admin) }
8
8
 
9
9
  describe "index view" do
10
10
 
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Site select' do
4
+
5
+ before do
6
+ authorize_user(:as_admin)
7
+ end
8
+
9
+ it "does not display the site change" do
10
+ visit admin_dashboard_path
11
+ expect(page).not_to have_select('change_site')
12
+ end
13
+
14
+ context "multiple sites" do
15
+ let!(:a_site) { FactoryGirl.create(:site) }
16
+
17
+ it "contains all sites in a selectbox" do
18
+ visit admin_dashboard_path
19
+ expect(page).to have_select('change_site', options: [Alchemy::Site.default.name, a_site.name], selected: Alchemy::Site.default.name)
20
+ end
21
+
22
+ context 'when requesting non-default site' do
23
+ it "provides the correct site" do
24
+ visit admin_pages_path(site_id: a_site.id)
25
+ expect(page).to have_select('change_site', selected: a_site.name)
26
+
27
+ visit admin_dashboard_path
28
+ expect(page).to have_select('change_site', selected: a_site.name)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,11 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'TinyMCE Editor' do
4
- let(:user) { DummyUser.new }
5
4
 
6
5
  before do
7
- user.update(alchemy_roles: %w(admin), name: "Joe User", id: 1)
8
- authorize_as_admin(user)
6
+ authorize_user(:as_admin)
9
7
  end
10
8
 
11
9
  it 'base path should be set to tinymce asset folder' do
@@ -3,14 +3,14 @@ require 'spec_helper'
3
3
  module Alchemy
4
4
  describe 'Page' do
5
5
  let(:default_language) { Language.default }
6
- let(:default_language_root) { FactoryGirl.create(:language_root_page, :language => default_language, :name => 'Home') }
7
- let(:public_page_1) { FactoryGirl.create(:public_page, :visible => true, :name => 'Page 1') }
8
- let(:public_child) { FactoryGirl.create(:public_page, :name => 'Public Child', :parent_id => public_page_1.id) }
6
+ let(:default_language_root) { create(:language_root_page, :language => default_language, :name => 'Home') }
7
+ let(:public_page_1) { create(:public_page, :visible => true, :name => 'Page 1') }
8
+ let(:public_child) { create(:public_page, :name => 'Public Child', :parent_id => public_page_1.id) }
9
9
 
10
10
  before { default_language_root }
11
11
 
12
12
  it "should include all its elements and contents" do
13
- p = FactoryGirl.create(:public_page, :do_not_autogenerate => false)
13
+ p = create(:public_page, :do_not_autogenerate => false)
14
14
  article = p.elements.find_by_name('article')
15
15
  article.content_by_name('intro').essence.update_attributes(:body => 'Welcome to Peters Petshop', :public => true)
16
16
  visit "/#{p.urlname}"
@@ -19,8 +19,8 @@ module Alchemy
19
19
 
20
20
  it "should show the navigation with all visible pages" do
21
21
  pages = [
22
- FactoryGirl.create(:public_page, :visible => true, :name => 'Page 1'),
23
- FactoryGirl.create(:public_page, :visible => true, :name => 'Page 2')
22
+ create(:public_page, :visible => true, :name => 'Page 1'),
23
+ create(:public_page, :visible => true, :name => 'Page 2')
24
24
  ]
25
25
  visit '/'
26
26
  within('div#navigation ul') { expect(page).to have_selector('li a[href="/page-1"], li a[href="/page-2"]') }
@@ -33,7 +33,7 @@ module Alchemy
33
33
  allow_any_instance_of(PagesController).to receive(:multi_language?).and_return(true)
34
34
  end
35
35
 
36
- let(:second_page) { FactoryGirl.create(:public_page, name: 'Second Page') }
36
+ let(:second_page) { create(:public_page, name: 'Second Page') }
37
37
  let(:legacy_url) { LegacyPageUrl.create(urlname: 'index.php?option=com_content&view=article&id=48&Itemid=69', page: second_page) }
38
38
 
39
39
  it "should redirect legacy url with unknown format & query string" do
@@ -100,16 +100,18 @@ module Alchemy
100
100
  before { allow(Alchemy.user_class).to receive(:admins).and_return([1, 2]) }
101
101
 
102
102
  it "should render 404 if urlname and lang parameter do not belong to same page" do
103
- FactoryGirl.create(:klingonian)
104
- visit "/kl/#{public_page_1.urlname}"
105
- expect(page.status_code).to eq(404)
103
+ create(:klingonian)
104
+ expect {
105
+ visit "/kl/#{public_page_1.urlname}"
106
+ }.to raise_error(ActionController::RoutingError)
106
107
  end
107
108
 
108
109
  it "should render 404 if requested language does not exist" do
109
110
  public_page_1
110
111
  LegacyPageUrl.delete_all
111
- visit "/fo/#{public_page_1.urlname}"
112
- expect(page.status_code).to eq(404)
112
+ expect {
113
+ visit "/fo/#{public_page_1.urlname}"
114
+ }.to raise_error(ActionController::RoutingError)
113
115
  end
114
116
  end
115
117
  end
@@ -120,7 +122,7 @@ module Alchemy
120
122
  allow(Config).to receive(:get) { |arg| arg == :url_nesting ? false : Config.parameter(arg) }
121
123
  end
122
124
 
123
- let(:second_page) { FactoryGirl.create(:public_page, name: 'Second Page') }
125
+ let(:second_page) { create(:public_page, name: 'Second Page') }
124
126
  let(:legacy_url) { LegacyPageUrl.create(urlname: 'index.php?option=com_content&view=article&id=48&Itemid=69', page: second_page) }
125
127
 
126
128
  it "should redirect legacy url with unknown format & query string" do
@@ -158,7 +160,7 @@ module Alchemy
158
160
  end
159
161
 
160
162
  it "should keep additional params" do
161
- visit "/de/#{public_page_1.urlname}?query=Peter"
163
+ visit "/en/#{public_page_1.urlname}?query=Peter"
162
164
  expect(page.current_url).to match(/\?query=Peter/)
163
165
  end
164
166
  end
@@ -166,12 +168,14 @@ module Alchemy
166
168
 
167
169
  describe "Handling of non-existing pages" do
168
170
  before do
169
- allow(Alchemy.user_class).to receive(:admins).and_return([1, 2]) # We need a admin user or the signup page will show up
170
- visit "/non-existing-page"
171
+ # We need a admin user or the signup page will show up
172
+ allow(Alchemy.user_class).to receive(:admins).and_return([1, 2])
171
173
  end
172
174
 
173
175
  it "should render public/404.html" do
174
- expect(page.status_code).to eq(404)
176
+ expect {
177
+ visit "/non-existing-page"
178
+ }.to raise_error(ActionController::RoutingError)
175
179
  end
176
180
  end
177
181
 
@@ -191,7 +195,7 @@ module Alchemy
191
195
 
192
196
  context "rendering for members" do
193
197
  it "is prohibited" do
194
- authorize_as_admin(mock_model('DummyUser', alchemy_roles: %w(member), language: 'en'))
198
+ authorize_user(build(:alchemy_dummy_user))
195
199
  visit "/#{public_page_1.urlname}"
196
200
  within('body') { expect(page).not_to have_selector('#alchemy_menubar') }
197
201
  end
@@ -199,7 +203,7 @@ module Alchemy
199
203
 
200
204
  context "rendering for authors" do
201
205
  it "is allowed" do
202
- authorize_as_admin(mock_model('DummyUser', alchemy_roles: %w(author), language: 'en', cache_key: 'aaa'))
206
+ authorize_user(:as_author)
203
207
  visit "/#{public_page_1.urlname}"
204
208
  within('body') { expect(page).to have_selector('#alchemy_menubar') }
205
209
  end
@@ -207,7 +211,7 @@ module Alchemy
207
211
 
208
212
  context "rendering for editors" do
209
213
  it "is allowed" do
210
- authorize_as_admin(mock_model('DummyUser', alchemy_roles: %w(editor), language: 'en', cache_key: 'aaa'))
214
+ authorize_user(:as_editor)
211
215
  visit "/#{public_page_1.urlname}"
212
216
  within('body') { expect(page).to have_selector('#alchemy_menubar') }
213
217
  end
@@ -215,7 +219,7 @@ module Alchemy
215
219
 
216
220
  context "rendering for admins" do
217
221
  it "is allowed" do
218
- authorize_as_admin(mock_model('DummyUser', alchemy_roles: %w(admin), language: 'en', cache_key: 'aaa'))
222
+ authorize_user(:as_admin)
219
223
  visit "/#{public_page_1.urlname}"
220
224
  within('body') { expect(page).to have_selector('#alchemy_menubar') }
221
225
  end
@@ -223,20 +227,26 @@ module Alchemy
223
227
 
224
228
  context "contains" do
225
229
  before do
226
- authorize_as_admin(mock_model('DummyUser', alchemy_roles: %w(admin), language: 'en', cache_key: 'aaa'))
230
+ authorize_user(:as_admin)
227
231
  visit "/#{public_page_1.urlname}"
228
232
  end
229
233
 
230
234
  it "a link to the admin area" do
231
- within('#alchemy_menubar') { expect(page).to have_selector("li a[href='#{alchemy.admin_dashboard_path}']") }
235
+ within('#alchemy_menubar') do
236
+ expect(page).to have_selector("li a[href='#{alchemy.admin_dashboard_path}']")
237
+ end
232
238
  end
233
239
 
234
240
  it "a link to edit the current page" do
235
- within('#alchemy_menubar') { expect(page).to have_selector("li a[href='#{alchemy.edit_admin_page_path(public_page_1)}']") }
241
+ within('#alchemy_menubar') do
242
+ expect(page).to have_selector("li a[href='#{alchemy.edit_admin_page_path(public_page_1)}']")
243
+ end
236
244
  end
237
245
 
238
246
  it "a form and button to logout of alchemy" do
239
- within('#alchemy_menubar') { expect(page).to have_selector("li form[action='#{Alchemy.logout_path}'], li button[type='submit']") }
247
+ within('#alchemy_menubar') do
248
+ expect(page).to have_selector("li form[action='#{Alchemy.logout_path}'], li button[type='submit']")
249
+ end
240
250
  end
241
251
  end
242
252
  end
@@ -265,7 +275,7 @@ module Alchemy
265
275
  end
266
276
 
267
277
  context 'as a member user' do
268
- before { authorize_as_admin(create(:member_user)) }
278
+ before { authorize_user(create(:alchemy_dummy_user)) }
269
279
 
270
280
  it "I am able to visit the page" do
271
281
  visit restricted_page.urlname
@@ -273,6 +283,5 @@ module Alchemy
273
283
  end
274
284
  end
275
285
  end
276
-
277
286
  end
278
287
  end
@@ -13,7 +13,7 @@ describe "Security." do
13
13
  allow_any_instance_of(Alchemy::BaseController)
14
14
  .to receive(:ssl_required?)
15
15
  .and_return(true)
16
- authorize_as_admin(DummyUser.new(alchemy_roles: %w(admin)))
16
+ authorize_user(:as_admin)
17
17
  end
18
18
 
19
19
  it "redirects every request to https." do
@@ -2,9 +2,9 @@ require 'spec_helper'
2
2
 
3
3
  describe "Translation integration" do
4
4
  context "in admin backend" do
5
- let(:dummy_user) { mock_model('DummyUser', alchemy_roles: %w(admin), language: 'de') }
5
+ let(:dummy_user) { mock_model(Alchemy.user_class, alchemy_roles: %w(admin), language: 'de') }
6
6
 
7
- before { authorize_as_admin(dummy_user) }
7
+ before { authorize_user(dummy_user) }
8
8
 
9
9
  it "should be possible to set the locale of the admin backend via params" do
10
10
  visit admin_dashboard_path(locale: 'nl')
@@ -38,7 +38,7 @@ describe "Translation integration" do
38
38
  end
39
39
 
40
40
  context "if user has no preferred locale" do
41
- let(:dummy_user) { mock_model('DummyUser', alchemy_roles: %w(admin), language: nil) }
41
+ let(:dummy_user) { mock_model(Alchemy.user_class, alchemy_roles: %w(admin), language: nil) }
42
42
 
43
43
  it "should use the browsers language setting" do
44
44
  page.driver.header 'ACCEPT-LANGUAGE', 'es-ES'
@@ -2,7 +2,6 @@ require 'spec_helper'
2
2
 
3
3
  module Alchemy
4
4
  describe Admin::ElementsHelper do
5
-
6
5
  let(:page) { build_stubbed(:public_page) }
7
6
  let(:element) { build_stubbed(:element, page: page) }
8
7
 
@@ -18,46 +17,124 @@ module Alchemy
18
17
  end
19
18
 
20
19
  describe "#grouped_elements_for_select" do
21
- let(:elements) {
20
+ let(:elements) do
22
21
  [
23
22
  mock_model('Element', name: '1', display_name: '1'),
24
23
  mock_model('Element', name: '2', display_name: '2')
25
24
  ]
26
- }
25
+ end
26
+ let(:element_definitions) { [{"name" => "1"}, {"name" => "2"}] }
27
+ let(:cell_definitions) { [] }
28
+ let(:page_definition) { {} }
27
29
 
28
30
  before do
29
- allow(page).to receive(:layout_description).and_return({
30
- 'name' => "foo",
31
- 'cells' => ["foo_cell"]
32
- })
33
- cell_descriptions = [{
34
- 'name' => "foo_cell",
35
- 'elements' => ["1", "2"]
36
- }]
37
- allow(Cell).to receive(:definitions).and_return(cell_descriptions)
31
+ allow(page).to receive(:definition).and_return(page_definition)
32
+ allow(Cell).to receive(:definitions).and_return(cell_definitions)
33
+ allow(Element).to receive(:definitions).and_return(element_definitions)
38
34
  helper.instance_variable_set('@page', page)
39
35
  end
40
36
 
41
- it "should return array of elements grouped by cell for select_tag helper" do
42
- expect(helper.grouped_elements_for_select(elements)).to include("Foo cell" => [["1", "1#foo_cell"], ["2", "2#foo_cell"]])
37
+ context "with empty elements array given" do
38
+ it "return an empty array" do
39
+ expect(helper.grouped_elements_for_select([])).to eq([])
40
+ end
43
41
  end
44
42
 
45
- context "with empty elements array" do
46
- it "should return an empty string" do
47
- expect(helper.grouped_elements_for_select([])).to eq("")
43
+ context "with an element collection given" do
44
+ let(:page_definition) do
45
+ {'name' => "foo", 'cells' => ["foo_cell"], 'elements' => []}
48
46
  end
49
- end
50
47
 
51
- context "with empty cell definitions" do
52
- it "should return an empty string" do
53
- allow(page).to receive(:layout_description).and_return({'name' => "foo"})
54
- expect(helper.grouped_elements_for_select(elements)).to eq("")
48
+ let(:cell_definitions) do
49
+ [{'name' => "foo_cell", 'elements' => ["1", "2"]}]
50
+ end
51
+
52
+ it "returns an array of elements grouped by cell for select_tag helper" do
53
+ expect(helper.grouped_elements_for_select(elements)).to eq("Foo cell" => [["1", "1#foo_cell"], ["2", "2#foo_cell"]])
54
+ end
55
+
56
+ context "without cells key in page definition" do
57
+ let(:page_definition) do
58
+ {'name' => "foo", "elements" => ["1", "2"]}
59
+ end
60
+
61
+ it "returns an empty array" do
62
+ expect(helper.grouped_elements_for_select(elements)).to eq([])
63
+ end
64
+ end
65
+
66
+ context "with empty cells in page definition" do
67
+ let(:page_definition) do
68
+ {"name" => "foo", "cells" => [], "elements" => ["1", "2"]}
69
+ end
70
+
71
+ it "returns an empty array" do
72
+ expect(helper.grouped_elements_for_select(elements)).to eq([])
73
+ end
74
+ end
75
+
76
+ context "with a cell containing no elements" do
77
+ let(:cell_definitions) do
78
+ [{"name" => "empty_cell", "elements" => []}]
79
+ end
80
+
81
+ let(:page_definition) do
82
+ {"name" => "foo", "cells" => ["empty_cell"], "elements" => ["1", "2"]}
83
+ end
84
+
85
+ it "does not include that cell" do
86
+ expect(helper.grouped_elements_for_select(elements)).to eq("Main content" => [["1", "1"], ["2", "2"]])
87
+ end
88
+ end
89
+
90
+ context "with an element in a cell only" do
91
+ let(:elements) do
92
+ [mock_model('Element', name: 'in_cell', display_name: 'In Cell')]
93
+ end
94
+
95
+ let(:page_definition) do
96
+ {'name' => "foo", 'cells' => ["foo_cell"], 'elements' => []}
97
+ end
98
+
99
+ let(:cell_definitions) do
100
+ [{'name' => "foo_cell", 'elements' => ["in_cell"]}]
101
+ end
102
+
103
+ it "returns an option for the element in the cell only" do
104
+ expect(helper.grouped_elements_for_select(elements)).to include("Foo cell" => [["In cell", "in_cell#foo_cell"]])
105
+ end
55
106
  end
56
- end
57
107
 
58
- context "with cell having no elements" do
59
- it "should remove that cell from hash" do
60
- expect(helper.grouped_elements_for_select(elements)['Empty cell']).to be_nil
108
+ context "with the same element in both cell and page" do
109
+ let(:element_definitions) do
110
+ [{"name" => "in_cell_and_page"}]
111
+ end
112
+
113
+ let(:elements) do
114
+ [mock_model('Element', name: 'in_cell_and_page', display_name: 'In Cell and Page')]
115
+ end
116
+
117
+ let(:page_definition) do
118
+ {
119
+ 'name' => "foo",
120
+ 'cells' => ["foo_cell"],
121
+ 'elements' => ["in_cell_and_page"]
122
+ }
123
+ end
124
+
125
+ let(:cell_definitions) do
126
+ [{
127
+ 'name' => "foo_cell",
128
+ 'elements' => ["in_cell_and_page"]
129
+ }]
130
+ end
131
+
132
+ it "returns two options of same element, one for the cell and one for the page" do
133
+ expect(helper.grouped_elements_for_select(elements)).to eq({
134
+ "Main content" => [["In cell and page", "in_cell_and_page"]],
135
+ "Foo cell" => [["In cell and page", "in_cell_and_page#foo_cell"]]
136
+ })
137
+ end
61
138
  end
62
139
  end
63
140
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Alchemy::Admin::PagesHelper do
4
4
 
5
5
  describe '#sitemap_folder_link' do
6
- let(:user) { admin_user }
6
+ let(:user) { build(:alchemy_dummy_user, :as_admin) }
7
7
 
8
8
  before { allow(helper).to receive(:current_alchemy_user).and_return(user) }
9
9
 
@@ -61,4 +61,35 @@ describe Alchemy::Admin::PagesHelper do
61
61
  end
62
62
  end
63
63
 
64
+ describe '#page_layout_label' do
65
+ let(:page) { build(:page) }
66
+
67
+ subject { helper.page_layout_label(page) }
68
+
69
+ context 'when page is not yet persisted' do
70
+ it 'displays text only' do
71
+ is_expected.to eq(Alchemy::I18n.t(:page_type))
72
+ end
73
+ end
74
+
75
+ context 'when page is persited' do
76
+ before { page.save! }
77
+
78
+ context 'with page layout existing' do
79
+ it 'displays text only' do
80
+ is_expected.to eq(Alchemy::I18n.t(:page_type))
81
+ end
82
+ end
83
+
84
+ context 'with page layout description missing' do
85
+ before do
86
+ expect(page).to receive(:layout_description).and_return([])
87
+ end
88
+
89
+ it 'displays icon with warning' do
90
+ is_expected.to match /warning icon/
91
+ end
92
+ end
93
+ end
94
+ end
64
95
  end