locomotivecms_steam 1.6.0.beta1 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -1
- data/Gemfile.lock +79 -39
- data/bin/steam.rb +1 -7
- data/docker-compose.yml +4 -0
- data/lib/locomotive/steam/configuration.rb +13 -0
- data/lib/locomotive/steam/entities/site.rb +1 -0
- data/lib/locomotive/steam/liquid/tags/concerns/attributes.rb +97 -10
- data/lib/locomotive/steam/liquid/tags/concerns/path.rb +23 -4
- data/lib/locomotive/steam/liquid/tags/consume.rb +2 -2
- data/lib/locomotive/steam/liquid/tags/editable/base.rb +4 -4
- data/lib/locomotive/steam/liquid/tags/global_section.rb +1 -1
- data/lib/locomotive/steam/liquid/tags/inherited_block.rb +2 -3
- data/lib/locomotive/steam/liquid/tags/section.rb +4 -4
- data/lib/locomotive/steam/liquid/tags/snippet.rb +10 -0
- data/lib/locomotive/steam/liquid/tags/with_scope.rb +16 -24
- data/lib/locomotive/steam/middlewares/auth.rb +9 -5
- data/lib/locomotive/steam/middlewares/concerns/auth_helpers.rb +1 -1
- data/lib/locomotive/steam/middlewares/concerns/helpers.rb +5 -1
- data/lib/locomotive/steam/middlewares/concerns/rendering.rb +1 -1
- data/lib/locomotive/steam/middlewares/locale.rb +5 -5
- data/lib/locomotive/steam/middlewares/logging.rb +2 -4
- data/lib/locomotive/steam/middlewares/page.rb +4 -4
- data/lib/locomotive/steam/middlewares/path.rb +7 -1
- data/lib/locomotive/steam/middlewares/private_access.rb +2 -2
- data/lib/locomotive/steam/middlewares/templatized_page.rb +1 -1
- data/lib/locomotive/steam/middlewares/timezone.rb +1 -1
- data/lib/locomotive/steam/models/i18n_field.rb +2 -2
- data/lib/locomotive/steam/models/mapper.rb +2 -1
- data/lib/locomotive/steam/services/content_entry_service.rb +12 -0
- data/lib/locomotive/steam/version.rb +1 -1
- data/lib/locomotive/steam.rb +7 -0
- data/locomotivecms_steam.gemspec +3 -1
- data/spec/fixtures/default/app/content_types/accounts.yml +3 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/support/helpers.rb +2 -4
- data/spec/unit/liquid/tags/paginate_spec.rb +1 -1
- data/spec/unit/liquid/tags/with_scope_spec.rb +59 -0
- data/spec/unit/middlewares/cache_spec.rb +4 -4
- data/spec/unit/middlewares/path_spec.rb +70 -0
- metadata +45 -9
@@ -33,28 +33,37 @@ module Locomotive
|
|
33
33
|
'x' => Regexp::EXTENDED
|
34
34
|
}.freeze
|
35
35
|
|
36
|
+
OPERATORS = %w(all exists gt gte in lt lte ne nin size near within)
|
37
|
+
|
38
|
+
SYMBOL_OPERATORS_REGEXP = /(\w+\.(#{OPERATORS.join('|')})){1}\s*\:/o
|
39
|
+
|
36
40
|
attr_reader :attributes, :attributes_var_name
|
37
41
|
|
38
42
|
def initialize(tag_name, markup, options)
|
39
43
|
super
|
40
44
|
|
45
|
+
# convert symbol operators into valid ruby code
|
46
|
+
markup.gsub!(SYMBOL_OPERATORS_REGEXP, ':"\1" =>')
|
47
|
+
|
41
48
|
# simple hash?
|
42
49
|
parse_attributes(markup) { |value| parse_attribute(value) }
|
43
50
|
|
44
|
-
if
|
51
|
+
if raw_attributes.empty? && markup =~ SingleVariable
|
45
52
|
# alright, maybe we'vot got a single variable built
|
46
53
|
# with the Action liquid tag instead?
|
47
54
|
@attributes_var_name = Regexp.last_match(1)
|
48
55
|
end
|
49
56
|
|
50
|
-
if
|
57
|
+
if raw_attributes.empty? && attributes_var_name.blank?
|
51
58
|
raise ::Liquid::SyntaxError.new("Syntax Error in 'with_scope' - Valid syntax: with_scope <name_1>: <value_1>, ..., <name_n>: <value_n>")
|
52
59
|
end
|
53
60
|
end
|
54
61
|
|
55
62
|
def render(context)
|
56
63
|
context.stack do
|
57
|
-
context[
|
64
|
+
@raw_attributes = context[attributes_var_name] || {} if attributes_var_name.present?
|
65
|
+
@raw_attributes.transform_keys! { |key| key.to_s == '_permalink' ? '_slug' : key.to_s }
|
66
|
+
context['with_scope'] = evaluate_attributes(context)
|
58
67
|
|
59
68
|
# for now, no content type is assigned to this with_scope
|
60
69
|
context['with_scope_content_type'] = false
|
@@ -68,7 +77,7 @@ module Locomotive
|
|
68
77
|
def parse_attribute(value)
|
69
78
|
case value
|
70
79
|
when StrictRegexpFragment
|
71
|
-
# let the
|
80
|
+
# let the evaluate_value attribute create the Regexp (done during the rendering phase)
|
72
81
|
value
|
73
82
|
when ArrayFragment
|
74
83
|
$1.split(',').map { |_value| parse_attribute(_value) }
|
@@ -77,28 +86,11 @@ module Locomotive
|
|
77
86
|
end
|
78
87
|
end
|
79
88
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
HashWithIndifferentAccess.new.tap do |hash|
|
84
|
-
attributes.each do |key, value|
|
85
|
-
# _slug instead of _permalink
|
86
|
-
_key = key.to_s == '_permalink' ? '_slug' : key.to_s
|
87
|
-
|
88
|
-
# evaluate the value if possible before casting it
|
89
|
-
_value = value.is_a?(::Liquid::VariableLookup) ? context.evaluate(value) : value
|
90
|
-
|
91
|
-
hash[_key] = cast_value(context, _value)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def cast_value(context, value)
|
97
|
-
case value
|
98
|
-
when Array then value.map { |_value| cast_value(context, _value) }
|
89
|
+
def evaluate_value(context, value, lax: false)
|
90
|
+
_value = super
|
91
|
+
case _value
|
99
92
|
when StrictRegexpFragment then create_regexp($1, $2)
|
100
93
|
else
|
101
|
-
_value = context.evaluate(value)
|
102
94
|
_value.respond_to?(:_id) ? _value.send(:_source) : _value
|
103
95
|
end
|
104
96
|
end
|
@@ -30,7 +30,12 @@ module Locomotive::Steam
|
|
30
30
|
private
|
31
31
|
|
32
32
|
def sign_up(options)
|
33
|
-
return if authenticated?
|
33
|
+
return if authenticated?
|
34
|
+
|
35
|
+
if !is_recaptcha_valid?(options.type, options.recaptcha_response)
|
36
|
+
append_message(:invalid_recaptcha_code)
|
37
|
+
return
|
38
|
+
end
|
34
39
|
|
35
40
|
status, entry = services.auth.sign_up(options, default_liquid_context, request)
|
36
41
|
|
@@ -101,7 +106,7 @@ module Locomotive::Steam
|
|
101
106
|
end
|
102
107
|
|
103
108
|
def append_message(message)
|
104
|
-
|
109
|
+
debug_log "[Auth] status message = #{message.inspect}"
|
105
110
|
|
106
111
|
message ||= 'error'
|
107
112
|
liquid_assigns["auth_#{message}"] = "auth_#{message}"
|
@@ -158,7 +163,7 @@ module Locomotive::Steam
|
|
158
163
|
end
|
159
164
|
|
160
165
|
def from
|
161
|
-
smtp_config['sender'] || 'support@locomotivecms.com'
|
166
|
+
smtp_config['sender'] || smtp_config['from'] || 'support@locomotivecms.com'
|
162
167
|
end
|
163
168
|
|
164
169
|
def subject
|
@@ -182,7 +187,7 @@ module Locomotive::Steam
|
|
182
187
|
end
|
183
188
|
|
184
189
|
def recaptcha_response
|
185
|
-
params[
|
190
|
+
params['g-recaptcha-response']
|
186
191
|
end
|
187
192
|
|
188
193
|
def smtp
|
@@ -213,7 +218,6 @@ module Locomotive::Steam
|
|
213
218
|
end
|
214
219
|
end
|
215
220
|
|
216
|
-
|
217
221
|
end
|
218
222
|
|
219
223
|
end
|
@@ -19,7 +19,7 @@ module Locomotive::Steam
|
|
19
19
|
|
20
20
|
env['steam.authenticated_entry'] = nil if entry.nil?
|
21
21
|
|
22
|
-
|
22
|
+
debug_log "[Auth] authenticated #{type.to_s.singularize} ##{entry&._id.to_s}"
|
23
23
|
|
24
24
|
liquid_assigns["current_#{type.singularize}"] = entry
|
25
25
|
end
|
@@ -40,7 +40,7 @@ module Locomotive::Steam
|
|
40
40
|
def redirect_to(location, type = 301)
|
41
41
|
_location = mounted_on && !location.starts_with?(mounted_on) && (location =~ Locomotive::Steam::IsHTTP).nil? ? "#{mounted_on}#{location}" : location
|
42
42
|
|
43
|
-
self.
|
43
|
+
self.debug_log "Redirected to #{_location}".blue
|
44
44
|
|
45
45
|
headers = { 'Content-Type' => HTML_CONTENT_TYPE, 'Location' => _location }
|
46
46
|
inject_cookies(headers)
|
@@ -83,6 +83,10 @@ module Locomotive::Steam
|
|
83
83
|
Locomotive::Common::Logger.info (' ' * offset) + msg
|
84
84
|
end
|
85
85
|
|
86
|
+
def debug_log(msg, offset = 2)
|
87
|
+
Locomotive::Common::Logger.debug (' ' * offset) + msg
|
88
|
+
end
|
89
|
+
|
86
90
|
end
|
87
91
|
end
|
88
92
|
end
|
@@ -23,7 +23,7 @@ module Locomotive::Steam
|
|
23
23
|
|
24
24
|
set_locale_cookie
|
25
25
|
|
26
|
-
|
26
|
+
debug_log "Locale used: #{locale.upcase}"
|
27
27
|
|
28
28
|
I18n.with_locale(locale) do
|
29
29
|
self.next
|
@@ -48,7 +48,7 @@ module Locomotive::Steam
|
|
48
48
|
|
49
49
|
def locale_from_params
|
50
50
|
params[:locale]&.to_sym.tap do |locale|
|
51
|
-
|
51
|
+
debug_log 'Locale extracted from the params' unless locale.blank?
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
@@ -62,7 +62,7 @@ module Locomotive::Steam
|
|
62
62
|
env['steam.path'] = path.gsub(/^\/#{$1 + $2}/, '/')
|
63
63
|
env['steam.locale_in_path'] = true
|
64
64
|
|
65
|
-
|
65
|
+
debug_log'Locale extracted from the path'
|
66
66
|
|
67
67
|
locale.to_sym
|
68
68
|
end
|
@@ -73,14 +73,14 @@ module Locomotive::Steam
|
|
73
73
|
.sort { |a, b| b[1] <=> a[1] }
|
74
74
|
.map { |lang, _| lang[0..1].to_sym }
|
75
75
|
.find { |lang| locales.include?(lang) }.tap do |locale|
|
76
|
-
|
76
|
+
debug_log 'Locale extracted from the header' unless locale.blank?
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
80
|
def locale_from_cookie
|
81
81
|
if locale = services.cookie.get(cookie_key_name)
|
82
82
|
|
83
|
-
|
83
|
+
debug_log 'Locale extracted from the cookie'
|
84
84
|
|
85
85
|
locale.to_sym
|
86
86
|
end
|
@@ -14,10 +14,8 @@ module Locomotive::Steam
|
|
14
14
|
|
15
15
|
log "Started #{env['REQUEST_METHOD'].upcase} \"#{env['PATH_INFO']}\" at #{now}".light_white, 0
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
end
|
20
|
-
|
17
|
+
debug_log "Params: #{env.fetch('steam.request').params.inspect}"
|
18
|
+
|
21
19
|
app.call(env).tap do |response|
|
22
20
|
done_in_ms = ((Time.now - now) * 10000).truncate / 10.0
|
23
21
|
log "Completed #{code_to_human(response.first)} in #{done_in_ms}ms\n\n".green
|
@@ -13,10 +13,10 @@ module Locomotive::Steam
|
|
13
13
|
|
14
14
|
if page = fetch_page
|
15
15
|
if !page.not_found?
|
16
|
-
|
16
|
+
debug_log "Found page \"#{page.title}\" [#{page.fullpath}]"
|
17
17
|
else
|
18
18
|
ActiveSupport::Notifications.instrument('steam.render.page_not_found', path: path, locale: locale, default_locale: default_locale)
|
19
|
-
|
19
|
+
debug_log "Page not found (#{path.inspect}), rendering the 404 page.".magenta
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -47,7 +47,7 @@ module Locomotive::Steam
|
|
47
47
|
regexp = Regexp.new(/^#{_route}$/i)
|
48
48
|
|
49
49
|
if (matches = path.match(regexp))
|
50
|
-
|
50
|
+
debug_log "Route found! #{route} (#{handle})"
|
51
51
|
|
52
52
|
# we want the named route parameters in the request params object
|
53
53
|
# because they will be needed in the liquid template.
|
@@ -63,7 +63,7 @@ module Locomotive::Steam
|
|
63
63
|
def fetch_page_from_paths
|
64
64
|
page_finder.match(path).tap do |pages|
|
65
65
|
if pages.size > 1
|
66
|
-
self.
|
66
|
+
self.debug_log "Found multiple pages: #{pages.map(&:title).join(', ')}"
|
67
67
|
end
|
68
68
|
end.first
|
69
69
|
end
|
@@ -16,9 +16,15 @@ module Locomotive::Steam
|
|
16
16
|
protected
|
17
17
|
|
18
18
|
def set_path!(env)
|
19
|
+
site = env['steam.site']
|
19
20
|
path = env['steam.path'].dup
|
20
21
|
|
21
|
-
|
22
|
+
if site.allow_dots_in_slugs
|
23
|
+
path.gsub!(/\.(html|htm)$/, '')
|
24
|
+
else
|
25
|
+
path.gsub!(/\.[a-zA-Z][a-zA-Z0-9]{2,}$/, '')
|
26
|
+
end
|
27
|
+
|
22
28
|
path.gsub!(/^\//, '')
|
23
29
|
path.gsub!(/^[A-Z]:\//, '')
|
24
30
|
|
@@ -14,7 +14,7 @@ module Locomotive::Steam
|
|
14
14
|
return if env['steam.private_access_disabled']
|
15
15
|
|
16
16
|
if site.private_access
|
17
|
-
|
17
|
+
debug_log "Site with private access"
|
18
18
|
|
19
19
|
if access_granted?
|
20
20
|
store_password
|
@@ -28,7 +28,7 @@ module Locomotive::Steam
|
|
28
28
|
|
29
29
|
def render_lock_screen
|
30
30
|
if page = services.page_finder.by_handle('lock_screen', false)
|
31
|
-
|
31
|
+
debug_log "Found custom lock screen: #{page.title}"
|
32
32
|
env['steam.page'] = page
|
33
33
|
else
|
34
34
|
render_response(lock_screen_html, 403)
|
@@ -26,7 +26,7 @@ module Locomotive::Steam
|
|
26
26
|
env['steam.content_entry'] = page.content_entry = entry
|
27
27
|
|
28
28
|
# log it
|
29
|
-
|
29
|
+
debug_log "Found content entry: #{entry._label}"
|
30
30
|
else
|
31
31
|
url = services.url_builder.url_for(page_not_found, locale)
|
32
32
|
redirect_to url, 302
|
@@ -76,7 +76,8 @@ module Locomotive::Steam
|
|
76
76
|
|
77
77
|
# localized fields
|
78
78
|
@localized_attributes.each do |name|
|
79
|
-
|
79
|
+
# hack: force the name for select type fields (content entries only)
|
80
|
+
entity.send(name).serialize(attributes, name)
|
80
81
|
end
|
81
82
|
|
82
83
|
# association name -> id (belongs_to) or ids (many_to_many)
|
@@ -73,6 +73,7 @@ module Locomotive
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
+
# Warning: do not work with localized and file fields
|
76
77
|
def update_decorated_entry(decorated_entry, attributes)
|
77
78
|
with_repository(decorated_entry.content_type) do |_repository|
|
78
79
|
entry = decorated_entry.__getobj__
|
@@ -80,6 +81,17 @@ module Locomotive
|
|
80
81
|
|
81
82
|
entry.change(_attributes)
|
82
83
|
|
84
|
+
# remove the proxy select fields because we don't need them at this point
|
85
|
+
# and MongoDB is going to complain when persisting it.
|
86
|
+
_repository.content_type.select_fields.each do |field|
|
87
|
+
entry.attributes.delete(field.name)
|
88
|
+
end
|
89
|
+
|
90
|
+
# remove any association field
|
91
|
+
_repository.content_type.association_fields.each do |field|
|
92
|
+
entry.attributes.delete(field.name)
|
93
|
+
end
|
94
|
+
|
83
95
|
_repository.update(entry)
|
84
96
|
|
85
97
|
logEntryOperation(decorated_entry.content_type.slug, decorated_entry)
|
data/lib/locomotive/steam.rb
CHANGED
@@ -48,6 +48,13 @@ module Locomotive
|
|
48
48
|
def self.configure
|
49
49
|
yield(configuration)
|
50
50
|
|
51
|
+
# configure the logger
|
52
|
+
Locomotive::Common.reset
|
53
|
+
Locomotive::Common.configure do |config|
|
54
|
+
config.notifier = Locomotive::Common::Logger.setup(configuration.log_file)
|
55
|
+
config.notifier.level = configuration.log_level
|
56
|
+
end
|
57
|
+
|
51
58
|
require_relative 'steam/initializers'
|
52
59
|
end
|
53
60
|
|
data/locomotivecms_steam.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.add_development_dependency 'mongo', '~> 2.13.1'
|
21
21
|
spec.add_development_dependency 'origin', '~> 2.3.1'
|
22
22
|
|
23
|
-
spec.add_dependency 'nokogiri', '
|
23
|
+
spec.add_dependency 'nokogiri', '>= 1.11', '< 1.14'
|
24
24
|
spec.add_dependency 'sanitize', '~> 5.2.1'
|
25
25
|
spec.add_dependency 'morphine', '~> 0.1.1'
|
26
26
|
spec.add_dependency 'httparty', '~> 0.16.0'
|
@@ -48,6 +48,8 @@ Gem::Specification.new do |spec|
|
|
48
48
|
spec.add_dependency 'mime-types', '~> 3.3.0'
|
49
49
|
spec.add_dependency 'duktape', '~> 2.0.1.1'
|
50
50
|
spec.add_dependency 'pony', '~> 1.12'
|
51
|
+
spec.add_dependency 'parser', '~> 2.7'
|
52
|
+
spec.add_dependency 'unparser', '~> 0.4'
|
51
53
|
|
52
54
|
spec.add_dependency 'locomotivecms_common', '~> 0.4.0'
|
53
55
|
|
@@ -22,6 +22,9 @@ order_by: manually
|
|
22
22
|
# Activate public 'create' API (e.g for a contact form)
|
23
23
|
# public_submission_enabled: false
|
24
24
|
|
25
|
+
# Enable Google Recaptcha to create new public entries
|
26
|
+
# recaptcha_required: true
|
27
|
+
|
25
28
|
# Array of emails to be notified of new entries made with the public API
|
26
29
|
# public_submission_accounts: ['john@example.com']
|
27
30
|
|
data/spec/spec_helper.rb
CHANGED
@@ -45,7 +45,7 @@ RSpec.configure do |config|
|
|
45
45
|
config.filter_run focused: true
|
46
46
|
config.run_all_when_everything_filtered = true
|
47
47
|
|
48
|
-
config.before(:all) { remove_logs;
|
48
|
+
config.before(:all) { remove_logs; reset_logger }
|
49
49
|
config.before { reset! }
|
50
50
|
config.after { reset! }
|
51
51
|
config.order = :random
|
data/spec/support/helpers.rb
CHANGED
@@ -19,7 +19,7 @@ module Spec
|
|
19
19
|
FileUtils.rm_rf(File.expand_path('../../fixtures/default/log', __FILE__))
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
22
|
+
def reset_logger(logger_output = nil)
|
23
23
|
Locomotive::Common.reset
|
24
24
|
Locomotive::Common.configure do |config|
|
25
25
|
logger_output ||= File.join(default_fixture_site_path, 'log/steam.log')
|
@@ -30,9 +30,6 @@ module Spec
|
|
30
30
|
def run_server
|
31
31
|
require 'haml'
|
32
32
|
|
33
|
-
output = ENV['STEAM_VERBOSE'] ? nil : File.join(default_fixture_site_path, 'log/steam.log')
|
34
|
-
setup_common(output)
|
35
|
-
|
36
33
|
Locomotive::Steam.configure do |config|
|
37
34
|
config.mode = :test
|
38
35
|
config.adapter = { name: :filesystem, path: default_fixture_site_path }
|
@@ -40,6 +37,7 @@ module Spec
|
|
40
37
|
config.asset_path = File.expand_path(File.join(default_fixture_site_path, 'public'))
|
41
38
|
config.serve_assets = true
|
42
39
|
config.minify_assets = true
|
40
|
+
config.log_file = ENV['STEAM_VERBOSE'] ? nil : File.join(default_fixture_site_path, 'log/steam.log')
|
43
41
|
end
|
44
42
|
|
45
43
|
Locomotive::Common::Logger.info 'Server started...'
|
@@ -31,7 +31,7 @@ EOF
|
|
31
31
|
|
32
32
|
let(:source) { '{% paginate projects by 2, window_size: 4 %}{% endpaginate %}' }
|
33
33
|
let(:block) { subject.root.nodelist.first }
|
34
|
-
it { expect(block.send(:window_size)
|
34
|
+
it { expect(block.send(:raw_attributes)[:window_size]).to eq 4 }
|
35
35
|
|
36
36
|
end
|
37
37
|
|
@@ -63,6 +63,56 @@ describe Locomotive::Steam::Liquid::Tags::WithScope do
|
|
63
63
|
|
64
64
|
end
|
65
65
|
|
66
|
+
describe 'decode advanced options' do
|
67
|
+
let(:options) { "" }
|
68
|
+
let(:source) { "{% with_scope key: #{options} %}{% assign conditions = with_scope %}{% endwith_scope %}" }
|
69
|
+
context "Array" do
|
70
|
+
context "of Integer" do
|
71
|
+
let(:options) { "[1, 2, 3]" }
|
72
|
+
it { expect(conditions['key']).to eq [1, 2, 3] }
|
73
|
+
end
|
74
|
+
|
75
|
+
context "of String" do
|
76
|
+
let(:options) { "['a', 'b', 'c']" }
|
77
|
+
it { expect(conditions['key']).to eq ['a', 'b', 'c'] }
|
78
|
+
end
|
79
|
+
|
80
|
+
context "With variable" do
|
81
|
+
let(:assigns) { {'a' => 1, 'c' => 3} }
|
82
|
+
let(:options) { "[a, 2, c, 'd']" }
|
83
|
+
it { expect(conditions['key']).to eq [1, 2, 3, 'd'] }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "Hash" do
|
88
|
+
context "With key value" do
|
89
|
+
let(:options) { "{a: 1, b: 2, c: 3, d: 'foo'}" }
|
90
|
+
it { expect(conditions['key'].keys).to eq(%w(a b c d)) }
|
91
|
+
it { expect(conditions['key']['a']).to eq 1 }
|
92
|
+
it { expect(conditions['key']['b']).to eq 2 }
|
93
|
+
it { expect(conditions['key']['c']).to eq 3 }
|
94
|
+
it { expect(conditions['key']['d']).to eq 'foo' }
|
95
|
+
end
|
96
|
+
|
97
|
+
context "With key variable" do
|
98
|
+
let(:assigns) { {'a' => 1, 'c' => 3} }
|
99
|
+
let(:options) { "{a: a, b: 2, c: c, d: 'foo'}" }
|
100
|
+
it { expect(conditions['key'].keys).to eq(%w(a b c d)) }
|
101
|
+
it { expect(conditions['key']['a']).to eq 1 }
|
102
|
+
it { expect(conditions['key']['b']).to eq 2 }
|
103
|
+
it { expect(conditions['key']['c']).to eq 3 }
|
104
|
+
it { expect(conditions['key']['d']).to eq 'foo' }
|
105
|
+
end
|
106
|
+
|
107
|
+
context "With params" do
|
108
|
+
let(:assigns) { { 'params' => Locomotive::Steam::Liquid::Drops::Params.new({ foo: 'bar' }) } }
|
109
|
+
let(:options) { "{'a': params.foo}" }
|
110
|
+
it { expect(conditions['key'].keys).to eq(%w(a)) }
|
111
|
+
it { expect(conditions['key']['a']).to eq 'bar' }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
66
116
|
describe 'decode regexps' do
|
67
117
|
|
68
118
|
let(:source) { "{% with_scope title: /Like this one|or this one/ %}{% assign conditions = with_scope %}{% endwith_scope %}" }
|
@@ -146,6 +196,15 @@ describe Locomotive::Steam::Liquid::Tags::WithScope do
|
|
146
196
|
|
147
197
|
end
|
148
198
|
|
199
|
+
describe 'In a loop context, each scope should be evaluated correctly' do
|
200
|
+
let(:assigns) { {'list' => ['A', 'B', 'C']} }
|
201
|
+
|
202
|
+
let(:source) { "{% for key in list %}{% with_scope foo: key %}{% assign conditions = with_scope %}{% endwith_scope %}{{ conditions }}{% endfor %}" }
|
203
|
+
|
204
|
+
it { expect(output).to eq '{"foo"=>"A"}{"foo"=>"B"}{"foo"=>"C"}' }
|
205
|
+
|
206
|
+
end
|
207
|
+
|
149
208
|
end
|
150
209
|
|
151
210
|
end
|
@@ -55,11 +55,11 @@ describe Locomotive::Steam::Middlewares::Cache do
|
|
55
55
|
|
56
56
|
let(:response) { nil }
|
57
57
|
|
58
|
-
before { expect(cache).to receive(:read).with('
|
58
|
+
before { expect(cache).to receive(:read).with('c34181a7a079edc9de373067bffc28f0').and_return(response) }
|
59
59
|
|
60
60
|
context 'the cache is empty' do
|
61
61
|
|
62
|
-
before { expect(cache).to receive(:write).with('
|
62
|
+
before { expect(cache).to receive(:write).with('c34181a7a079edc9de373067bffc28f0', Marshal.dump([200, {}, ["Hello world!"]])) }
|
63
63
|
|
64
64
|
it 'tells the CDN to cache the page and also cache it internally' do
|
65
65
|
is_expected.to eq ['max-age=0, s-maxage=3600, public, must-revalidate', 'Accept-Language']
|
@@ -69,7 +69,7 @@ describe Locomotive::Steam::Middlewares::Cache do
|
|
69
69
|
|
70
70
|
subject { send_request[:env]['steam.cache_etag'] }
|
71
71
|
|
72
|
-
it { is_expected.to eq '
|
72
|
+
it { is_expected.to eq 'c34181a7a079edc9de373067bffc28f0' }
|
73
73
|
|
74
74
|
end
|
75
75
|
|
@@ -104,7 +104,7 @@ describe Locomotive::Steam::Middlewares::Cache do
|
|
104
104
|
|
105
105
|
context 'based on the ETag' do
|
106
106
|
|
107
|
-
let(:etag) { '
|
107
|
+
let(:etag) { 'c34181a7a079edc9de373067bffc28f0' }
|
108
108
|
|
109
109
|
it 'returns a 304 (Not modified) without no cache headers' do
|
110
110
|
expect(subject.first).to eq 304
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require_relative '../../../lib/locomotive/steam/middlewares/path'
|
4
|
+
|
5
|
+
describe Locomotive::Steam::Middlewares::Path do
|
6
|
+
|
7
|
+
let(:allow_dots_in_slugs) { false }
|
8
|
+
let(:site) { instance_double('Site', allow_dots_in_slugs: allow_dots_in_slugs) }
|
9
|
+
let(:routes) { {} }
|
10
|
+
let(:url) { 'http://models.example.com' }
|
11
|
+
let(:path) { 'hello-world' }
|
12
|
+
let(:app) { ->(env) { [200, env, 'app'] } }
|
13
|
+
let(:middleware) { described_class.new(app) }
|
14
|
+
|
15
|
+
subject do
|
16
|
+
env = env_for(url, 'steam.site' => site)
|
17
|
+
env['steam.path'] = path
|
18
|
+
env['steam.locale'] = 'en'
|
19
|
+
env['steam.request'] = Rack::Request.new(env)
|
20
|
+
code, env = middleware.call(env)
|
21
|
+
env['steam.path']
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'allow_dots_in_slugs is off' do
|
25
|
+
context 'html extension' do
|
26
|
+
let(:path) { 'foo.html' }
|
27
|
+
it { is_expected.to eq 'foo' }
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'the path stores a version' do
|
31
|
+
let(:path) { 'foo-v1.0' }
|
32
|
+
it { is_expected.to eq 'foo-v1.0' }
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'prefixed by 3 letters word' do
|
36
|
+
let(:path) { 'foo.bar' }
|
37
|
+
it { is_expected.to eq 'foo' }
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'starting by a dot' do
|
41
|
+
let(:path) { '.well-known' }
|
42
|
+
it { is_expected.to eq '.well-known' }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'allow_dots_in_slugs is on' do
|
47
|
+
let(:allow_dots_in_slugs) { true }
|
48
|
+
|
49
|
+
context 'html extension' do
|
50
|
+
let(:path) { 'foo.html' }
|
51
|
+
it { is_expected.to eq 'foo' }
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'prefixed by a version' do
|
55
|
+
let(:path) { 'foo-v1.0' }
|
56
|
+
it { is_expected.to eq 'foo-v1.0' }
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'prefixed by 3 letters word' do
|
60
|
+
let(:path) { 'foo.bar' }
|
61
|
+
it { is_expected.to eq 'foo.bar' }
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'starting by a dot' do
|
65
|
+
let(:path) { '.well-known' }
|
66
|
+
it { is_expected.to eq '.well-known' }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|