locomotivecms 3.0.0.pre.beta.1 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (175) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -3
  3. data/app/api/locomotive/api.rb +1 -0
  4. data/app/api/locomotive/api/entities/page_entity.rb +1 -1
  5. data/app/api/locomotive/api/entities/site_entity.rb +9 -1
  6. data/app/api/locomotive/api/exception_rescuers.rb +3 -5
  7. data/app/api/locomotive/api/forms/page_form.rb +1 -1
  8. data/app/api/locomotive/api/forms/site_form.rb +1 -2
  9. data/app/api/locomotive/api/helpers/authentication_helper.rb +6 -1
  10. data/app/api/locomotive/api/helpers/locales_helper.rb +15 -0
  11. data/app/api/locomotive/api/helpers/params_helper.rb +13 -0
  12. data/app/api/locomotive/api/middlewares/locale_middleware.rb +6 -1
  13. data/app/api/locomotive/api/resources/content_entry_resource.rb +2 -0
  14. data/app/api/locomotive/api/resources/content_type_resource.rb +2 -2
  15. data/app/api/locomotive/api/resources/current_site_resource.rb +2 -1
  16. data/app/api/locomotive/api/resources/membership_resource.rb +0 -4
  17. data/app/api/locomotive/api/resources/page_resource.rb +6 -1
  18. data/app/api/locomotive/api/resources/site_resource.rb +4 -2
  19. data/app/assets/javascripts/locomotive.js +1 -0
  20. data/app/assets/javascripts/locomotive/utils/nprogress.js.coffee +3 -1
  21. data/app/assets/javascripts/locomotive/views/editable_elements/index_view.js.coffee +10 -3
  22. data/app/assets/javascripts/locomotive/views/inputs/markdown_view.js.coffee +82 -0
  23. data/app/assets/javascripts/locomotive/views/inputs/rte/file_view.js.coffee +1 -1
  24. data/app/assets/javascripts/locomotive/views/inputs/rte/link_view.js.coffee +1 -1
  25. data/app/assets/javascripts/locomotive/views/inputs/rte_view.js.coffee.erb +1 -1
  26. data/app/assets/javascripts/locomotive/views/inputs/text_view.js.coffee +4 -1
  27. data/app/assets/javascripts/locomotive/views/pages/list_view.js.coffee +3 -0
  28. data/app/assets/javascripts/locomotive/views/shared/form_view.js.coffee +22 -1
  29. data/app/assets/javascripts/locomotive/views/shared/header_view.js.coffee +2 -2
  30. data/app/assets/stylesheets/locomotive/application.scss +2 -0
  31. data/app/assets/stylesheets/locomotive/base/_form.scss +2 -0
  32. data/app/assets/stylesheets/locomotive/base/form/_api_key.scss +0 -1
  33. data/app/assets/stylesheets/locomotive/base/form/_array_input.scss +2 -0
  34. data/app/assets/stylesheets/locomotive/base/form/_base.scss +13 -2
  35. data/app/assets/stylesheets/locomotive/base/form/_color_input.scss +12 -0
  36. data/app/assets/stylesheets/locomotive/base/form/_markdown.scss +292 -0
  37. data/app/assets/stylesheets/locomotive/base/form/_popover.scss +22 -0
  38. data/app/assets/stylesheets/locomotive/base/form/_rte.scss +2 -1
  39. data/app/assets/stylesheets/locomotive/components/_activity_feed.scss +1 -0
  40. data/app/assets/stylesheets/locomotive/components/_dashboard.scss +29 -0
  41. data/app/assets/stylesheets/locomotive/components/_live_editing.scss +13 -1
  42. data/app/assets/stylesheets/locomotive/components/_main.scss +1 -1
  43. data/app/assets/stylesheets/locomotive/components/_transitions.scss +24 -3
  44. data/app/assets/stylesheets/locomotive/components/sidebar/_base.scss +1 -0
  45. data/app/assets/stylesheets/locomotive/globals/_bootstrap.scss +2 -2
  46. data/app/assets/stylesheets/locomotive/globals/_variables.scss +4 -3
  47. data/app/assets/stylesheets/locomotive/layouts/_live_editing.scss +4 -0
  48. data/app/controllers/locomotive/concerns/locale_helpers_controller.rb +1 -0
  49. data/app/controllers/locomotive/content_entries_controller.rb +10 -2
  50. data/app/controllers/locomotive/pages_controller.rb +2 -1
  51. data/app/controllers/locomotive/passwords_controller.rb +17 -1
  52. data/app/helpers/locomotive/base_helper.rb +19 -0
  53. data/app/helpers/locomotive/content_types_helper.rb +2 -1
  54. data/app/helpers/locomotive/custom_fields_helper.rb +14 -1
  55. data/app/helpers/locomotive/dashboard_helper.rb +12 -0
  56. data/app/helpers/locomotive/editable_elements_helper.rb +9 -4
  57. data/app/helpers/locomotive/pages_helper.rb +1 -14
  58. data/app/helpers/locomotive/shared/pages_helper.rb +17 -0
  59. data/app/helpers/locomotive/translations_helper.rb +0 -14
  60. data/app/inputs/locomotive/color_input.rb +18 -0
  61. data/app/inputs/locomotive/markdown_input.rb +19 -0
  62. data/app/models/locomotive/account.rb +2 -1
  63. data/app/models/locomotive/concerns/content_entry/file_size.rb +27 -0
  64. data/app/models/locomotive/concerns/content_type/group_by.rb +3 -1
  65. data/app/models/locomotive/concerns/page/layout.rb +63 -19
  66. data/app/models/locomotive/concerns/shared/site_scope.rb +37 -0
  67. data/app/models/locomotive/concerns/site/cache.rb +32 -0
  68. data/app/models/locomotive/concerns/theme_asset/plain_text.rb +85 -0
  69. data/app/models/locomotive/content_entry.rb +7 -7
  70. data/app/models/locomotive/content_type.rb +12 -6
  71. data/app/models/locomotive/page.rb +12 -14
  72. data/app/models/locomotive/site.rb +9 -3
  73. data/app/models/locomotive/snippet.rb +6 -4
  74. data/app/models/locomotive/theme_asset.rb +8 -73
  75. data/app/models/locomotive/translation.rb +6 -5
  76. data/app/policies/locomotive/site_policy.rb +2 -2
  77. data/app/services/locomotive/content_entry_service.rb +7 -6
  78. data/app/services/locomotive/site_service.rb +1 -0
  79. data/app/views/locomotive/content_entries/_entry.html.slim +1 -0
  80. data/app/views/locomotive/content_entries/edit.html.slim +1 -1
  81. data/app/views/locomotive/content_entries/new.html.slim +1 -1
  82. data/app/views/locomotive/current_site/_membership.html.slim +1 -0
  83. data/app/views/locomotive/current_site/edit.html.slim +1 -1
  84. data/app/views/locomotive/current_site/form/_access_points.html.slim +1 -1
  85. data/app/views/locomotive/current_site/form/_advanced.html.slim +2 -0
  86. data/app/views/locomotive/dashboard/_activity.html.slim +26 -0
  87. data/app/views/locomotive/dashboard/_url.html.slim +9 -0
  88. data/app/views/locomotive/dashboard/show.html.slim +3 -21
  89. data/app/views/locomotive/devise_mailer/reset_password_instructions.html.slim +1 -1
  90. data/app/views/locomotive/editable_elements/_edit.html.slim +8 -1
  91. data/app/views/locomotive/editable_elements/_form.html.slim +1 -1
  92. data/app/views/locomotive/editable_elements/index_without_preview.html.slim +24 -17
  93. data/app/views/locomotive/layouts/application.html.slim +6 -4
  94. data/app/views/locomotive/layouts/live_editing.html.slim +9 -0
  95. data/app/views/locomotive/layouts/not_logged_in.html.slim +1 -1
  96. data/app/views/locomotive/layouts/without_site.html.slim +2 -0
  97. data/app/views/locomotive/memberships/edit.html.slim +1 -1
  98. data/app/views/locomotive/memberships/new.html.slim +1 -1
  99. data/app/views/locomotive/my_account/edit.html.slim +7 -5
  100. data/app/views/locomotive/pages/_header.html.slim +7 -0
  101. data/app/views/locomotive/pages/edit.html.slim +2 -4
  102. data/app/views/locomotive/pages/form/_main.html.slim +4 -1
  103. data/app/views/locomotive/pages/form/_tabs.html.slim +4 -3
  104. data/app/views/locomotive/public_submission_accounts/_account.html.slim +1 -1
  105. data/app/views/locomotive/public_submission_accounts/edit.html.slim +1 -1
  106. data/app/views/locomotive/shared/_header.html.slim +25 -22
  107. data/app/views/locomotive/shared/_locale_picker_link.html.slim +3 -0
  108. data/app/views/locomotive/shared/_main_app_header.html.slim +1 -1
  109. data/app/views/locomotive/shared/_sidebar.html.slim +15 -11
  110. data/app/views/locomotive/shared/rte/_markdown_toolbar.html.slim +42 -0
  111. data/config/locales/admin_ui.en.yml +9 -4
  112. data/config/locales/default.en.yml +4 -0
  113. data/config/locales/devise.en.yml +1 -0
  114. data/config/locales/simple_form.en.yml +6 -2
  115. data/lib/locomotive/action_controller/responder.rb +5 -0
  116. data/lib/locomotive/engine.rb +5 -0
  117. data/lib/locomotive/middlewares/site.rb +39 -21
  118. data/lib/locomotive/simple_form.rb +3 -31
  119. data/lib/locomotive/steam/middlewares/cache.rb +62 -0
  120. data/lib/locomotive/steam/middlewares/page_editing.rb +9 -3
  121. data/lib/locomotive/steam/services/api_entry_submission_service.rb +6 -3
  122. data/lib/locomotive/steam/services/liquid_parser_with_cache_service.rb +74 -0
  123. data/lib/locomotive/steam_adaptor.rb +7 -1
  124. data/lib/locomotive/version.rb +1 -1
  125. data/lib/tasks/development.rake +4 -0
  126. data/lib/tasks/locomotive.rake +14 -0
  127. data/spec/lib/locomotive/steam/services/api_entry_submission_service_spec.rb +10 -1
  128. data/spec/lib/locomotive/steam/services/liquid_parser_with_cache_service_spec.rb +53 -0
  129. data/spec/models/locomotive/concerns/content_entry/file_size_spec.rb +40 -0
  130. data/spec/models/locomotive/concerns/page/layout_spec.rb +122 -17
  131. data/spec/models/locomotive/concerns/site/cache_spec.rb +60 -0
  132. data/spec/models/locomotive/content_entry_spec.rb +7 -0
  133. data/spec/models/locomotive/content_type_spec.rb +18 -11
  134. data/spec/models/locomotive/page_spec.rb +32 -8
  135. data/spec/models/locomotive/snippet_spec.rb +13 -4
  136. data/spec/models/locomotive/theme_asset_spec.rb +10 -3
  137. data/spec/models/locomotive/translation_spec.rb +28 -0
  138. data/spec/requests/locomotive/steam/cache_spec.rb +83 -0
  139. data/spec/requests/site_spec.rb +24 -0
  140. data/spec/support/capybara.rb +5 -13
  141. data/spec/support/factories.rb +9 -0
  142. data/spec/support/features/session_helpers.rb +19 -3
  143. data/spec/support/features/site_helpers.rb +27 -0
  144. data/spec/support/shared_examples/site_scope_examples.rb +27 -0
  145. data/vendor/assets/images/locomotive/bootstrap-colorpicker/alpha-horizontal.png +0 -0
  146. data/vendor/assets/images/locomotive/bootstrap-colorpicker/alpha.png +0 -0
  147. data/vendor/assets/images/locomotive/bootstrap-colorpicker/hue-horizontal.png +0 -0
  148. data/vendor/assets/images/locomotive/bootstrap-colorpicker/hue.png +0 -0
  149. data/vendor/assets/images/locomotive/bootstrap-colorpicker/saturation.png +0 -0
  150. data/vendor/assets/javascripts/locomotive/bootstrap-colorpicker.js +1 -0
  151. data/vendor/assets/javascripts/locomotive/datepicker_i18n.js.erb +6 -6
  152. data/vendor/assets/javascripts/locomotive/kramed.min.js +11 -0
  153. data/vendor/assets/stylesheets/locomotive/bootstrap-colorpicker.scss +9 -0
  154. metadata +59 -44
  155. data/app/controllers/locomotive/api/accounts_controller.rb +0 -60
  156. data/app/controllers/locomotive/api/base_controller.rb +0 -35
  157. data/app/controllers/locomotive/api/content_assets_controller.rb +0 -51
  158. data/app/controllers/locomotive/api/content_entries_controller.rb +0 -71
  159. data/app/controllers/locomotive/api/content_types_controller.rb +0 -52
  160. data/app/controllers/locomotive/api/current_site_controller.rb +0 -34
  161. data/app/controllers/locomotive/api/memberships_controller.rb +0 -52
  162. data/app/controllers/locomotive/api/my_account_controller.rb +0 -46
  163. data/app/controllers/locomotive/api/pages_controller.rb +0 -53
  164. data/app/controllers/locomotive/api/sites_controller.rb +0 -58
  165. data/app/controllers/locomotive/api/snippets_controller.rb +0 -52
  166. data/app/controllers/locomotive/api/theme_assets_controller.rb +0 -51
  167. data/app/controllers/locomotive/api/tokens_controller.rb +0 -36
  168. data/app/controllers/locomotive/api/translations_controller.rb +0 -51
  169. data/app/controllers/locomotive/api/version_controller.rb +0 -11
  170. data/spec/models/locomotive/editable_control_spec.rb +0 -79
  171. data/spec/models/locomotive/editable_file_spec.rb +0 -94
  172. data/spec/models/locomotive/editable_text_spec.rb +0 -219
  173. data/vendor/assets/images/select2-spinner.gif +0 -0
  174. data/vendor/assets/images/select2.png +0 -0
  175. data/vendor/assets/images/select2x2.png +0 -0
@@ -4,8 +4,11 @@ module Locomotive
4
4
  class APIEntrySubmissionService < Struct.new(:site, :locale)
5
5
 
6
6
  def submit(slug, attributes = {})
7
- load_content_type(slug)
8
- create_entry(attributes)
7
+ if load_content_type(slug)
8
+ create_entry(attributes)
9
+ else
10
+ nil
11
+ end
9
12
  end
10
13
 
11
14
  def to_json(entry)
@@ -15,7 +18,7 @@ module Locomotive
15
18
  private
16
19
 
17
20
  def load_content_type(slug)
18
- @content_type = site.content_types.where(slug: slug).first
21
+ @content_type = site.content_types.where(slug: slug, public_submission_enabled: true).first
19
22
  end
20
23
 
21
24
  def create_entry(attributes)
@@ -0,0 +1,74 @@
1
+ module Locomotive
2
+ module Steam
3
+
4
+ class LiquidParserWithCacheService < LiquidParserService
5
+
6
+ UNMARSHALABLE_OPTIONS = %i(parser page parent_finder snippet_finder).freeze
7
+
8
+ attr_accessor_initialize :current_site, :parent_finder, :snippet_finder, :locale
9
+
10
+ def parse(page)
11
+ return super unless current_site.cache_enabled
12
+
13
+ read_template_from_cache(page) || write_template_in_cache(page, super)
14
+ end
15
+
16
+ def cache_key(page)
17
+ "#{Locomotive::VERSION}/site/#{current_site._id}/template/#{current_site.template_version.to_i}/page/#{page._id}/#{locale}"
18
+ end
19
+
20
+ private
21
+
22
+ def read_template_from_cache(page)
23
+ if marshaled = Rails.cache.read(cache_key(page))
24
+ Marshal.load(marshaled)
25
+ end
26
+ end
27
+
28
+ def write_template_in_cache(page, template)
29
+ begin
30
+ Rails.cache.write(cache_key(page), marshal(template))
31
+ rescue Exception => e
32
+ Rails.logger.warn "Could not marshal #{cache_key(page)}, error: #{e.message}"
33
+ end
34
+
35
+ template
36
+ end
37
+
38
+ def marshal(template)
39
+ _template = template.dup
40
+
41
+ # get rid of options in any tags/blocks of the document
42
+ # because options can not be marshaled
43
+ remove_unmarshalable_options(_template)
44
+
45
+ clean_template!(_template.root)
46
+
47
+ Marshal.dump(_template)
48
+ end
49
+
50
+ def clean_template!(node)
51
+ remove_unmarshalable_options(node)
52
+
53
+ # special case
54
+ clean_template!(node.descendant) if node.respond_to?(:descendant) && node.descendant
55
+
56
+ if node.respond_to?(:nodelist) && node.nodelist
57
+ node.nodelist.each do |_node|
58
+ clean_template!(_node)
59
+ end
60
+ end
61
+ end
62
+
63
+ def remove_unmarshalable_options(node)
64
+ options = node.instance_variable_get(:@options)
65
+
66
+ return if options.blank?
67
+
68
+ options.delete_if { |name, _| UNMARSHALABLE_OPTIONS.include?(name) }
69
+ end
70
+
71
+ end
72
+
73
+ end
74
+ end
@@ -26,17 +26,23 @@ Locomotive::Steam.configure do |config|
26
26
 
27
27
  require_relative 'steam/middlewares/missing_translations'
28
28
  require_relative 'steam/middlewares/page_editing'
29
+ require_relative 'steam/middlewares/cache'
29
30
 
31
+ config.middleware.insert_after Locomotive::Steam::Middlewares::Page, Locomotive::Steam::Middlewares::Cache
30
32
  config.middleware.insert_after Locomotive::Steam::Middlewares::Page, Locomotive::Steam::Middlewares::PageEditing
31
33
  config.middleware.insert_after Locomotive::Steam::Middlewares::Page, Locomotive::Steam::Middlewares::MissingTranslations
32
34
 
33
35
  require_relative 'steam/services/api_entry_submission_service'
36
+ require_relative 'steam/services/liquid_parser_with_cache_service'
34
37
 
35
38
  # let the Rails engine handle the "no site" error
36
39
  config.render_404_if_no_site = false
37
40
 
38
41
  config.services_hook = -> (services) {
39
- services.entry_submission = Locomotive::Steam::APIEntrySubmissionService.new(services.current_site, services.locale) if services.request
42
+ if services.request
43
+ services.entry_submission = Locomotive::Steam::APIEntrySubmissionService.new(services.current_site, services.locale)
44
+ services.defer(:liquid_parser) { Locomotive::Steam::LiquidParserWithCacheService.new(services.current_site, services.parent_finder, services.snippet_finder, services.locale) }
45
+ end
40
46
  }
41
47
  end
42
48
 
@@ -2,5 +2,5 @@
2
2
  # MAJOR.MINOR.PATCH format.
3
3
  # 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0
4
4
  module Locomotive #:nodoc
5
- VERSION = '3.0.0-beta.1'
5
+ VERSION = '3.0.0.rc1'
6
6
  end
@@ -31,10 +31,14 @@ namespace :development do
31
31
  site.memberships.build account: account, role: 'admin'
32
32
  site.save!
33
33
 
34
+ puts "\"LocomotiveCMS\" created: #{site._id}"
35
+
34
36
  site = Locomotive::Site.create! name: "Sample site", handle: "sample", domains: ["sample.example.com"]
35
37
  site.memberships.build account: account, role: 'admin'
36
38
  site.save!
37
39
 
40
+ puts "\"Sample site\" created: #{site._id}"
41
+
38
42
  puts "Now you have a www.example.com site"
39
43
  puts "and a sample.example.com site as well. (add them to your /etc/hosts)"
40
44
  puts "You can login with admin@locomotivecms.com and \"locomotive\" password."
@@ -31,6 +31,20 @@ namespace :locomotive do
31
31
  task v3: :environment do
32
32
  puts '...'
33
33
 
34
+ # subdomain to handle
35
+ Locomotive::Site.all.each_by(10) do |site|
36
+ if subdomain = site.attributes['subdomain']
37
+ site.set handle: subdomain
38
+ end
39
+ end
40
+ puts '[x] set the handle attribute for all the sites'
41
+
42
+ # number_of_entries by content type
43
+ Locomotive::ContentType.all.each_by(10) do |content_type|
44
+ content_type.set number_of_entries: content_type.entries.count
45
+ end
46
+ puts '[x] set the number of entries by content type'
47
+
34
48
  # content asset checksums
35
49
  Locomotive::ContentAsset.all.each do |asset|
36
50
  asset.send(:calculate_checksum)
@@ -4,7 +4,8 @@ describe Locomotive::Steam::APIEntrySubmissionService do
4
4
 
5
5
  let(:site) { create(:site) }
6
6
  let(:locale) { :en }
7
- let!(:content_type) { create('message content type', site: site).reload }
7
+ let(:enabled) { true }
8
+ let!(:content_type) { create('message content type', site: site, public_submission_enabled: enabled).reload }
8
9
  let(:service) { described_class.new(site, locale) }
9
10
 
10
11
  describe '#submit' do
@@ -20,6 +21,14 @@ describe Locomotive::Steam::APIEntrySubmissionService do
20
21
  expect(subject.message).to eq 'Hello'
21
22
  end
22
23
 
24
+ context 'no public submission allowed' do
25
+
26
+ let(:enabled) { false }
27
+
28
+ it { expect(subject).to eq nil }
29
+
30
+ end
31
+
23
32
  end #
24
33
 
25
34
  describe '#to_json' do
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe Locomotive::Steam::LiquidParserWithCacheService do
4
+
5
+ let(:cache) { false }
6
+ let(:site) { build(:site, cache_enabled: cache, template_version: DateTime.parse('2009/09/10 00:00:00')).to_steam }
7
+ let(:parent_finder) { nil}
8
+ let(:service) { described_class.new(site, parent_finder, nil, 'en') }
9
+
10
+ describe '#cache_key' do
11
+
12
+ let(:page) { instance_double('ParsedPage', _id: '0001') }
13
+
14
+ subject { service.cache_key(page) }
15
+
16
+ it { expect(subject).to match %r{\A#{Locomotive::VERSION}/site\/[a-z0-9]+\/template\/1252540800\/page\/0001\/en\Z} }
17
+
18
+ end
19
+
20
+ describe '#parse' do
21
+
22
+ let(:parent) { instance_double('ParsedPage', liquid_source: 'Hello {% block content %}!{% endblock %}') }
23
+ let(:page) { instance_double('ParsedPage', _id: '0001', liquid_source: '{% extends parent %}{% block content %}world{{ block.super}}{% endblock %}') }
24
+ let(:parent_finder) { instance_double('ParentFinder', find: parent) }
25
+
26
+ subject { service.parse(page) }
27
+
28
+ it { expect(subject).not_to eq nil }
29
+ it { expect(subject.render).to eq 'Hello world!' }
30
+
31
+ it 'does not cache the template' do
32
+ service.parse(page) # warm up the cache
33
+ expect(service).to receive(:_parse)
34
+ subject
35
+ end
36
+
37
+ context 'cache enabled' do
38
+
39
+ before(:each) { Rails.cache.clear }
40
+
41
+ let(:cache) { true }
42
+
43
+ it 'does not parse the template twice' do
44
+ service.parse(page) # warm up the cache
45
+ expect(service).not_to receive(:_parse)
46
+ expect(subject.render).to eq 'Hello world!'
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe Locomotive::Concerns::ContentEntry::FileSize do
4
+
5
+ let(:content_type) { create_content_type }
6
+ let(:content_entry) { build_content_entry }
7
+
8
+ subject { content_entry._file_size }
9
+
10
+ context 'entry not persisted' do
11
+
12
+ it { expect(subject).to eq 0 }
13
+
14
+ end
15
+
16
+ context 'entry persisted' do
17
+
18
+ before { content_entry.save! }
19
+
20
+ it { expect(subject).to eq 1309 }
21
+
22
+ end
23
+
24
+ def create_content_type
25
+ allow_any_instance_of(Locomotive::Site).to receive(:create_default_pages!).and_return(true)
26
+ FactoryGirl.build(:content_type).tap do |content_type|
27
+ content_type.entries_custom_fields.build label: 'Title', type: 'string'
28
+ content_type.entries_custom_fields.build label: 'File 1', type: 'file'
29
+ content_type.entries_custom_fields.build label: 'File 2', type: 'file'
30
+ content_type.valid?
31
+ content_type.send(:set_label_field)
32
+ content_type.save!
33
+ end
34
+ end
35
+
36
+ def build_content_entry
37
+ content_type.entries.build(title: 'LocomotiveCMS', file_1: FixturedAsset.open('5k.png'), file_2: FixturedAsset.open('main.css'))
38
+ end
39
+
40
+ end
@@ -2,46 +2,84 @@ require 'spec_helper'
2
2
 
3
3
  describe Locomotive::Concerns::Page::Layout do
4
4
 
5
- let(:site) { FactoryGirl.build(:site) }
5
+ let(:site) { build(:site) }
6
6
  let(:allow_layout) { true }
7
- let(:layout) { Locomotive::Page.new(is_layout: true, fullpath: 'awesome-layout') }
8
- let(:page) { Locomotive::Page.new(layout: layout, allow_layout: allow_layout, site: site) }
7
+ let(:template) { nil }
8
+ let(:layout) { Locomotive::Page.new(_id: 42, is_layout: true, fullpath: 'awesome-layout') }
9
+ let(:page) { Locomotive::Page.new(layout: layout, allow_layout: allow_layout, site: site, raw_template: template) }
9
10
 
10
- describe 'allow_layout default value' do
11
+ describe '#find_layout' do
11
12
 
12
- let(:page) { Locomotive::Page.new }
13
+ subject { page.find_layout; page.layout_id }
13
14
 
14
- subject { page.allow_layout }
15
+ it { is_expected.to eq 42 }
15
16
 
16
- describe 'true for a new page' do
17
+ context 'from the raw_template' do
17
18
 
18
- it { is_expected.to eq true }
19
+ let(:page) { build(:page, raw_template: ' {% extends foo/bar %} ', site: site) }
20
+
21
+ it 'looks for the layout based on the extends liquid tag' do
22
+ expect(page.site.pages).to receive(:fullpath).with('foo/bar').and_return([layout])
23
+ is_expected.to eq 42
24
+ end
25
+
26
+ it 'switches to the default locale' do
27
+ allow(page.site).to receive(:is_default_locale?).and_return(false)
28
+ expect(page.site).to receive(:with_default_locale).and_return(layout)
29
+ is_expected.to eq 42
30
+ end
19
31
 
20
32
  end
21
33
 
22
- describe 'false for an existing page without the allow_layout attribute' do
34
+ end
23
35
 
24
- let(:page) { p = Locomotive::Page.new(site: site); p.save(validate: false); p.unset(:allow_layout); Locomotive::Page.find(p._id) }
36
+ describe '#valid_allow_layout_consistency' do
37
+
38
+ before { page.valid? }
39
+ subject { page.allow_layout? }
40
+
41
+ it { is_expected.to eq true }
42
+
43
+ context 'allow_layout was false at first' do
25
44
 
45
+ let(:allow_layout) { false }
26
46
  it { is_expected.to eq false }
27
47
 
48
+ context "the template doesn't include the extend liquid tag" do
49
+ let(:template) { '{% extends parent %}' }
50
+ it { is_expected.to eq false }
51
+ end
52
+ end
53
+
54
+ context 'the template includes the extend liquid tag' do
55
+ let(:template) { '{% extends parent %} Bla bla' }
56
+ it { is_expected.to eq true }
57
+ end
58
+
59
+ context 'the template includes the extend liquid tag but also blocks' do
60
+ let(:template) { '{% extends layouts/simple %} {% block content %}Hello world{% endblock %}' }
61
+ it { is_expected.to eq false }
28
62
  end
29
63
 
30
64
  end
31
65
 
32
- describe 'use a layout' do
66
+ describe 'allow_layout default value' do
33
67
 
34
- before { page.valid? }
68
+ let(:page) { Locomotive::Page.new }
35
69
 
36
- subject { page.raw_template }
70
+ subject { page.allow_layout }
37
71
 
38
- it { is_expected.to eq '{% extends "awesome-layout" %}' }
72
+ describe 'true for a new page' do
39
73
 
40
- context 'but changing the layout is not allowed' do
74
+ it { is_expected.to eq true }
41
75
 
42
- let(:allow_layout) { false }
76
+ end
77
+
78
+ describe 'false for an existing page without the allow_layout attribute' do
79
+
80
+ let(:page) { p = Locomotive::Page.new(site: site); p.save(validate: false); p.unset(:allow_layout); Locomotive::Page.find(p._id) }
43
81
 
44
- it { is_expected.to eq "{% extends 'parent' %}" }
82
+ it { is_expected.to eq false }
45
83
 
46
84
  end
47
85
 
@@ -73,4 +111,71 @@ describe Locomotive::Concerns::Page::Layout do
73
111
 
74
112
  end
75
113
 
114
+ describe 'use a layout' do
115
+
116
+ subject { page.raw_template }
117
+
118
+ context 'on create' do
119
+
120
+ before { page.valid? }
121
+ it { is_expected.to eq '{% extends "awesome-layout" %}' }
122
+
123
+ context 'select the parent layout' do
124
+
125
+ let(:page) { build(:page, layout_id: 'parent', allow_layout: allow_layout, site: site, raw_template: nil) }
126
+ it { is_expected.to eq '{% extends parent %}' }
127
+
128
+ end
129
+
130
+ context 'no selected layout' do
131
+
132
+ let(:page) { build(:page, slug: 'new-page', allow_layout: allow_layout, site: site, raw_template: nil) }
133
+ it { is_expected.to eq '{% extends parent %}' }
134
+
135
+ context 'the page is the home page' do
136
+
137
+ let(:page) { build(:page, slug: 'index', site: site, layout_id: 'parent') }
138
+ it { is_expected.to eq '{% extends parent %}' }
139
+
140
+ it 'also adds an error to the layout attribute' do
141
+ expect(page.valid?).to eq false
142
+ expect(page.errors[:layout_id].first).to eq "The index page can't have its parent page as a layout"
143
+ end
144
+
145
+ end
146
+
147
+ end
148
+
149
+ end
150
+
151
+ context 'on update' do
152
+
153
+ let(:site) { create(:site) }
154
+ let!(:page) { create(:page, slug: 'sub_page', allow_layout: allow_layout, raw_template: '{% extends parent %}') }
155
+
156
+ before { page.layout = layout; page.valid? }
157
+
158
+ subject { page.raw_template }
159
+
160
+ it { is_expected.to eq '{% extends "awesome-layout" %}' }
161
+
162
+ context 'no layout allowed' do
163
+
164
+ let(:allow_layout) { false }
165
+ it { is_expected.to eq '{% extends parent %}' }
166
+
167
+ end
168
+
169
+ context 'parent selected' do
170
+
171
+ before { page.layout_id = 'parent'; page.valid? }
172
+
173
+ it { is_expected.to eq '{% extends parent %}' }
174
+
175
+ end
176
+
177
+ end
178
+
179
+ end
180
+
76
181
  end