diff --git a/.gitignore b/.gitignore index 8cc86459..20b63c58 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.swp *.gem *.rbc .bundle diff --git a/.test b/.test new file mode 100644 index 00000000..e69de29b diff --git a/lib/locomotive/steam/liquid/drops/i18n_base.rb b/lib/locomotive/steam/liquid/drops/i18n_base.rb index 1b99353c..91c1653b 100644 --- a/lib/locomotive/steam/liquid/drops/i18n_base.rb +++ b/lib/locomotive/steam/liquid/drops/i18n_base.rb @@ -16,6 +16,10 @@ def context=(context) @_source.__locale__ = locale end + if country = context.registers[:country] + @_source.__country__ = country + end + @_source.__default_locale__ = context.registers[:site].try(:default_locale) super diff --git a/lib/locomotive/steam/middlewares/auth.rb b/lib/locomotive/steam/middlewares/auth.rb index a2281672..0d560c3c 100644 --- a/lib/locomotive/steam/middlewares/auth.rb +++ b/lib/locomotive/steam/middlewares/auth.rb @@ -62,6 +62,8 @@ def sign_out(options) store_authenticated(nil) + redirect_to options.callback || path + append_message(:signed_out) end @@ -169,7 +171,7 @@ def reset_token end def from - params[:auth_email_from] || 'support@locomotivecms.com' + smtp_config['sender'] || 'support@locomotivecms.com' end def subject @@ -188,23 +190,39 @@ def entry params[:auth_entry] end + def smtp_config + @config ||= _read_smtp_config + end + def smtp - name = params[:auth_email_smtp_namespace] || 'smtp' - namespace = site.metafields.try(:[], name) + if smtp_config.blank? + {} + else + { + address: smtp_config['address'], + port: smtp_config['port'], + user_name: smtp_config['user_name'], + password: smtp_config['password'], + authentication: smtp_config['authentication'] || 'plain', + enable_starttls_auto: (smtp_config['enable_starttls_auto'] || "0").to_bool, + } + end + end - if namespace.blank? + private + + def _read_smtp_config + name = params[:auth_email_smtp_namespace] || 'smtp' + config = site.metafields.try(:[], name) + if config.blank? Locomotive::Common::Logger.error "[Auth] Missing SMTP settings in the Site metafields. Namespace: #{name}".light_red - return {} + {} + else + config end - - { - address: namespace[params[:auth_email_smtp_address_alias] || 'address'], - port: namespace[params[:auth_email_smtp_port_alias] || 'port'], - user_name: namespace[params[:auth_email_smtp_user_name_alias] || 'user_name'], - password: namespace[params[:auth_email_smtp_password_alias] || 'password'] - } end + end end diff --git a/lib/locomotive/steam/middlewares/default_env.rb b/lib/locomotive/steam/middlewares/default_env.rb index 62cd75c3..9ffc4a3d 100644 --- a/lib/locomotive/steam/middlewares/default_env.rb +++ b/lib/locomotive/steam/middlewares/default_env.rb @@ -11,6 +11,7 @@ def call(env) env['steam.request'] = request env['steam.services'] = build_services(request) env['steam.liquid_assigns'] = {} + env['steam.cookies'] = {} app.call(env) end diff --git a/lib/locomotive/steam/middlewares/helpers.rb b/lib/locomotive/steam/middlewares/helpers.rb index 7a9f9d8e..d636287f 100644 --- a/lib/locomotive/steam/middlewares/helpers.rb +++ b/lib/locomotive/steam/middlewares/helpers.rb @@ -45,6 +45,10 @@ def default_locale site.default_locale end + def session + env['rack.session'] + end + def live_editing? !!env['steam.live_editing'] end @@ -83,8 +87,12 @@ def json? #= Helper methods - def render_response(content, code = 200, type = nil) - @next_response = [code, { 'Content-Type' => type || 'text/html' }, [content]] + def render_response(content, code = 200, type = nil, no_cookies=false) + headers = { 'Content-Type' => type || 'text/html' } + unless no_cookies + inject_cookies(headers) + end + @next_response = [code, headers, [content]] end def redirect_to(location, type = 301) @@ -92,7 +100,16 @@ def redirect_to(location, type = 301) self.log "Redirected to #{_location}".blue - @next_response = [type, { 'Content-Type' => 'text/html', 'Location' => _location }, []] + headers = { 'Content-Type' => 'text/html', 'Location' => _location } + inject_cookies(headers) + + @next_response = [type, headers, []] + end + + def inject_cookies(headers) + request.env['steam.cookies'].each do |key, vals| + Rack::Utils.set_cookie_header!(headers, key, vals.symbolize_keys!) + end end def modify_path(path = nil, &block) diff --git a/lib/locomotive/steam/middlewares/locale.rb b/lib/locomotive/steam/middlewares/locale.rb index c5b2c20e..b694b788 100644 --- a/lib/locomotive/steam/middlewares/locale.rb +++ b/lib/locomotive/steam/middlewares/locale.rb @@ -1,3 +1,5 @@ +require 'maxmind/db' + module Locomotive::Steam module Middlewares @@ -9,16 +11,26 @@ module Middlewares # /fr/ => locale = :fr # /index => locale = :en (default one) # - # The + # /en/index?locale=fr => locale = :fr + # /index => redirection to /en if the locale in cookie is :en # class Locale < ThreadSafe include Helpers def _call - locale = extract_locale + env['steam.path'] = request.path_info + + env['steam.locale'] = services.locale = extract_locale + + country = extract_country + env['steam.country'] = country + + set_locale_cookie + set_country_cookie(country) - log "Detecting locale #{locale.upcase}" + log "Locale used: #{locale.upcase}" + log "Country used: #{country.upcase}" I18n.with_locale(locale) do self.next @@ -27,25 +39,134 @@ def _call protected - def extract_locale - _locale = locale_from_params || default_locale - _path = request.path_info + def extract_country + country = country_from_params || country_from_cookie || country_from_geoip(env) || country_from_default + country.to_s.downcase + end + + def country_from_params + params[:country]&.to_sym.tap do |country| + log 'Country extracted from the params' unless country.blank? + end + end - if _path =~ /^\/(#{site.locales.join('|')})+(\/|$)/ - _locale = $1 - _path = _path.gsub($1 + $2, '') + def country_from_cookie + if country = services.cookie.get(cookie_country_key_name) + log 'Country extracted from the cookie' + country.to_sym + end + end + + def country_from_geoip(remote_ip) + reader = MaxMind::DB.new('/home/akretion/GeoLite2-Country.mmdb', mode: MaxMind::DB::MODE_MEMORY) + remote_ip = env["action_dispatch.remote_ip"].to_s + record = reader.get(remote_ip) + if record.nil? + log "Country not found in database for: #{remote_ip}" + return nil + else + log "Country found in database for: #{remote_ip}" + return record['country']['iso_code'] + end + end - # let the other middlewares that the locale was - # extracted from the path. + def country_from_default + return "fr" + end + + def locale_from_path + path = request.path_info + + if path =~ /^\/(#{site.locales.join('|')})+(\/|$)/ + locale = $1 + + # no need to keep the locale in the path used to fetch the page + env['steam.path'] = path.gsub($1 + $2, '') env['steam.locale_in_path'] = true + + log 'Locale extracted from the path' + + locale.to_sym end + end - env['steam.path'] = _path - env['steam.locale'] = services.locale = _locale + + def extract_locale + # Regarding the index page (basically, "/"), we've to see if we could + # guess the locale from the headers the browser sends to us. + locale = if is_index_page? + locale_from_params || locale_from_cookie || locale_from_header + else + locale_from_path || locale_from_params + end + + # make sure, the locale is among the ones defined in the site, + # otherwise take the default one. + locale && locales.include?(locale) ? locale : default_locale end def locale_from_params - locales.include?(params[:locale]) ? params[:locale] : nil + params[:locale]&.to_sym.tap do |locale| + log 'Locale extracted from the params' unless locale.blank? + end + end + + def locale_from_path + path = request.path_info + + if path =~ /^\/(#{site.locales.join('|')})+(\/|$)/ + locale = $1 + + # no need to keep the locale in the path used to fetch the page + env['steam.path'] = path.gsub($1 + $2, '') + env['steam.locale_in_path'] = true + + log 'Locale extracted from the path' + + locale.to_sym + end + end + + def locale_from_header + request.accept_language.lazy + .sort { |a, b| b[1] <=> a[1] } + .map { |lang, _| lang[0..1].to_sym } + .find { |lang| locales.include?(lang) }.tap do |locale| + log 'Locale extracted from the header' unless locale.blank? + end + end + + def locale_from_cookie + if locale = services.cookie.get(cookie_key_name) + + log 'Locale extracted from the cookie' + + locale.to_sym + end + end + + def set_locale_cookie + services.cookie.set(cookie_key_name, {'value': locale, 'path': '/', 'max_age': 1.year}) + end + + + def set_country_cookie(country) + services.cookie.set(cookie_country_key_name, {'value': country, 'path': '/', 'max_age': 1.year}) + end + + # The preview urls for all the sites share the same domain, so cookie[:locale] + # would be the same for all the preview urls and this is not good. + # This is why we need to use a different key. + def cookie_key_name + live_editing? ? "steam-locale-#{site.handle}" : 'steam-locale' + end + + def cookie_country_key_name + live_editing? ? "steam-country-#{site.handle}" : 'steam-country' + end + + def is_index_page? + ['/', ''].include?(request.path_info) end end diff --git a/lib/locomotive/steam/middlewares/locale_redirection.rb b/lib/locomotive/steam/middlewares/locale_redirection.rb index ecab5207..6c24ba2c 100644 --- a/lib/locomotive/steam/middlewares/locale_redirection.rb +++ b/lib/locomotive/steam/middlewares/locale_redirection.rb @@ -11,8 +11,10 @@ class LocaleRedirection < ThreadSafe include Helpers def _call - if url = redirect_url - redirect_to url + if redirect_to_root_path_with_lang + redirect_to(path_with_locale, 302) + elsif url = redirect_url + redirect_to(url, redirect_type) end end @@ -21,13 +23,20 @@ def _call def redirect_url if apply_redirection? if site.prefix_default_locale - path_with_default_locale if locale_not_mentioned_in_path? + path_with_locale if locale_not_mentioned_in_path? else env['steam.path'] if default_locale? && locale_mentioned_in_path? end end end + # only applied if redirect_url is not nil + def redirect_type + # We don't want a permanent redirection for the index page in case + # the user wants to change the current locale from the index page. + self.path == '/' && self.locales.size > 1 ? 302 : 301 + end + def apply_redirection? site.locales.size > 1 && request.get? && env['PATH_INFO'] != '/sitemap.xml' end @@ -44,12 +53,15 @@ def locale_not_mentioned_in_path? !locale_mentioned_in_path? end - def path_with_default_locale + def path_with_locale modify_path do |segments| - segments.insert(1, site.default_locale) + segments.insert(1, locale) end end + def redirect_to_root_path_with_lang + locale_not_mentioned_in_path? && path.gsub(/^\//, '') == '' && !default_locale? + end end end diff --git a/lib/locomotive/steam/middlewares/path.rb b/lib/locomotive/steam/middlewares/path.rb index e8ea3fae..d710f48b 100644 --- a/lib/locomotive/steam/middlewares/path.rb +++ b/lib/locomotive/steam/middlewares/path.rb @@ -16,7 +16,7 @@ def call(env) protected def set_path!(env) - path = (env['steam.path'] || request.path_info).dup + path = env['steam.path'].dup path.gsub!(/\.[a-zA-Z][a-zA-Z0-9]{2,}$/, '') path.gsub!(/^\//, '') diff --git a/lib/locomotive/steam/middlewares/renderer.rb b/lib/locomotive/steam/middlewares/renderer.rb index bb4d6715..08e346bd 100644 --- a/lib/locomotive/steam/middlewares/renderer.rb +++ b/lib/locomotive/steam/middlewares/renderer.rb @@ -59,7 +59,8 @@ def liquid_registers repositories: services.repositories, logger: Locomotive::Common::Logger, live_editing: !!env['steam.live_editing'], - session: request.session + session: request.session, + cookies: request.cookies } end @@ -97,6 +98,7 @@ def _steam_liquid_assigns def _locale_liquid_assigns { 'locale' => locale.to_s, + 'country' => env['steam.country'], 'default_locale' => site.default_locale.to_s, 'locales' => site.locales.map(&:to_s) } diff --git a/lib/locomotive/steam/middlewares/robots.rb b/lib/locomotive/steam/middlewares/robots.rb index cfd7fa4a..110595b1 100644 --- a/lib/locomotive/steam/middlewares/robots.rb +++ b/lib/locomotive/steam/middlewares/robots.rb @@ -10,7 +10,7 @@ class Robots def call(env) if env['PATH_INFO'] == '/robots.txt' site = env['steam.site'] - render_response(site[:robots_txt] || '', 200, 'text/plain') + render_response(site[:robots_txt] || '', 200, 'text/plain', no_cookies=true) else app.call(env) end diff --git a/lib/locomotive/steam/services.rb b/lib/locomotive/steam/services.rb index 235882e5..5df84361 100644 --- a/lib/locomotive/steam/services.rb +++ b/lib/locomotive/steam/services.rb @@ -63,7 +63,7 @@ class Instance end register :action do - Steam::ActionService.new(current_site, email, content_entry: content_entry, api: external_api, redirection: page_redirection) + Steam::ActionService.new(current_site, email, content_entry: content_entry, api: external_api, redirection: page_redirection, cookie: cookie) end register :content_entry do @@ -130,6 +130,10 @@ class Instance Steam::NoCacheService.new end + register :cookie do + Steam::CookieService.new(request) + end + register :configuration do Locomotive::Steam.configuration end diff --git a/lib/locomotive/steam/services/action_service.rb b/lib/locomotive/steam/services/action_service.rb index 1cc97bb0..c3a08926 100644 --- a/lib/locomotive/steam/services/action_service.rb +++ b/lib/locomotive/steam/services/action_service.rb @@ -11,13 +11,15 @@ module Steam class ActionService - SERVICES = %w(content_entry api redirection) + SERVICES = %w(content_entry api redirection cookie) BUILT_IN_FUNCTIONS = %w( getProp setProp getSessionProp setSessionProp + getCookiesProp + setCookiesProp sendEmail allEntries findEntry @@ -81,6 +83,14 @@ def set_session_prop_lambda(liquid_context) -> (name, value) { liquid_context.registers[:session][name.to_sym] = value } end + def get_cookies_prop_lambda(liquid_context) + -> (name) { cookie_service.get(name.to_s) } + end + + def set_cookies_prop_lambda(liquid_context) + -> (name, values) { cookie_service.set(name.to_s, values) } + end + def all_entries_lambda(liquid_context) -> (type, conditions) { content_entry_service.all(type, conditions, true) } end diff --git a/lib/locomotive/steam/services/cookie_service.rb b/lib/locomotive/steam/services/cookie_service.rb new file mode 100644 index 00000000..9fe86cb6 --- /dev/null +++ b/lib/locomotive/steam/services/cookie_service.rb @@ -0,0 +1,25 @@ +module Locomotive + module Steam + + class CookieService + + def initialize(request) + @request = request + @cookies = request.env['steam.cookies'] + end + + def set(key, vals) + @cookies[key] = vals + end + + def get(key) + if @cookies.include?(key) + @cookies[key]['value'] + else + @request.cookies[key] + end + end + + end + end +end diff --git a/lib/locomotive/steam/services/url_builder_service.rb b/lib/locomotive/steam/services/url_builder_service.rb index 883622de..642b8e34 100644 --- a/lib/locomotive/steam/services/url_builder_service.rb +++ b/lib/locomotive/steam/services/url_builder_service.rb @@ -11,17 +11,33 @@ def url_for(page, locale = nil) def _url_for(page, locale = nil) [''].tap do |segments| - locale ||= current_locale - same_locale = locale.to_sym == site.default_locale.to_sym + locale = locale&.to_sym + _locale = (locale || current_locale).to_sym + default_locale = site.default_locale.to_sym + same_locale = _locale == default_locale - # if the prefix_default_locale is enabled, we need to - # add the locale no matter if the locale is the same as the default one + fullpath = sanitized_fullpath(page, same_locale) + + # To insert the locale in the path, 2 cases: + # + # 1. if the prefix_default_locale is enabled, we need to + # add the locale no matter if the locale is the same as the default one. + # + # 2. since we also store the locale in session, calling the index page ("/") + # will always return the page in the locale stored in session. + # In order to see the index page in the default locale, we need to allow + # "/" instead of just "/". + # if site.prefix_default_locale || !same_locale + segments << _locale + elsif fullpath.blank? && locale == default_locale && current_locale != locale segments << locale end - # fullpath - segments << sanitized_fullpath(page, same_locale) + # we don't want a trailing slash for the home page if a locale is set + fullpath = nil if segments.size == 2 && fullpath.blank? + + segments << fullpath end.compact.join('/') end diff --git a/spec/integration/server/auth_spec.rb b/spec/integration/server/auth_spec.rb index 3d4403b4..c37f9ada 100644 --- a/spec/integration/server/auth_spec.rb +++ b/spec/integration/server/auth_spec.rb @@ -171,11 +171,7 @@ def sign_in(params, follow_redirect = false) auth_id: email, auth_reset_password_url: 'http://acme.com/account/reset-password', auth_callback: '/account/sign-in', - auth_email_from: 'support@acme.com', auth_email_handle: 'reset_password_instructions', - auth_email_smtp_address: 'smtp.nowhere.net', - auth_email_smtp_user_name: 'jane', - auth_email_smtp_password: 'easyone' } } it 'renders the forgot password page with an error message' do diff --git a/spec/unit/liquid/tags/link_to_spec.rb b/spec/unit/liquid/tags/link_to_spec.rb index 6b7a202f..58625e72 100644 --- a/spec/unit/liquid/tags/link_to_spec.rb +++ b/spec/unit/liquid/tags/link_to_spec.rb @@ -71,7 +71,7 @@ context 'prefix_default_locale is true' do let(:prefix_default) { true } - it { is_expected.to eq 'My link: Home!' } + it { is_expected.to eq 'My link: Home!' } end diff --git a/spec/unit/liquid/tags/locale_switcher_spec.rb b/spec/unit/liquid/tags/locale_switcher_spec.rb index 8b13b74d..f92adfe9 100644 --- a/spec/unit/liquid/tags/locale_switcher_spec.rb +++ b/spec/unit/liquid/tags/locale_switcher_spec.rb @@ -30,7 +30,7 @@ context 'prefix_default_locale is true' do let(:prefix_default) { true } - it { is_expected.to eq '
en | fr
' } + it { is_expected.to eq '
en | fr
' } end diff --git a/spec/unit/liquid/tags/path_to_spec.rb b/spec/unit/liquid/tags/path_to_spec.rb index abd38e0c..ee9c9ab6 100644 --- a/spec/unit/liquid/tags/path_to_spec.rb +++ b/spec/unit/liquid/tags/path_to_spec.rb @@ -4,9 +4,11 @@ let(:prefix_default) { false } let(:assigns) { {} } + let(:current_locale) { 'en' } + let(:locales) { ['en'] } let(:services) { Locomotive::Steam::Services.build_instance } - let(:site) { instance_double('Site', locales: ['en'], default_locale: 'en', prefix_default_locale: prefix_default) } - let(:context) { ::Liquid::Context.new(assigns, {}, { services: services, site: site, locale: 'en' }) } + let(:site) { instance_double('Site', locales: locales, default_locale: 'en', prefix_default_locale: prefix_default) } + let(:context) { ::Liquid::Context.new(assigns, {}, { services: services, site: site, locale: current_locale }) } subject { render_template(source, context) } @@ -52,10 +54,31 @@ end + context 'the current locale in session is different from the requested locale' do + + let(:current_locale) { 'fr' } + let(:locales) { ['en', 'fr'] } + let(:source) { "{% path_to index, locale: 'en' %}" } + + before do + services.url_builder.current_locale = current_locale + end + + it { is_expected.to eq '/en' } + + context 'prefix_default_locale is true' do + + let(:prefix_default) { true } + it { is_expected.to eq '/en' } + + end + + end + context 'prefix_default_locale is true' do let(:prefix_default) { true } - it { is_expected.to eq '/en/' } + it { is_expected.to eq '/en' } end diff --git a/spec/unit/middlewares/auth_spec.rb b/spec/unit/middlewares/auth_spec.rb index 775200f5..17313731 100644 --- a/spec/unit/middlewares/auth_spec.rb +++ b/spec/unit/middlewares/auth_spec.rb @@ -16,7 +16,14 @@ subject { options.smtp } - it { is_expected.to eq('address': '127.0.0.1', 'user_name': 'John', 'password': 'doe', 'port': 25) } + it { is_expected.to eq( + address: '127.0.0.1', + user_name: 'John', + password: 'doe', + port: 25, + authentication: 'plain', + enable_starttls_auto: false, + ) } context 'no smtp metafields' do diff --git a/spec/unit/middlewares/locale_redirection_spec.rb b/spec/unit/middlewares/locale_redirection_spec.rb index 5c99da8c..a7a72c18 100644 --- a/spec/unit/middlewares/locale_redirection_spec.rb +++ b/spec/unit/middlewares/locale_redirection_spec.rb @@ -32,6 +32,17 @@ let(:locale_in_path) { false } it { is_expected.to eq [200, nil] } + context 'the lang elected is not the default lang' do + let(:locale) { 'fr' } + it { is_expected.to eq [302, '/fr'] } + end + + end + + describe 'locale is part of the path' do + let(:url) { 'http://models.example.com/fr' } + let(:locale) { 'fr' } + it { is_expected.to eq [200, nil] } end describe 'for seo purpose redirect to the path without the locale' do @@ -53,7 +64,7 @@ describe 'add default locale to root path' do let(:url) { 'http://models.example.com/' } - it { is_expected.to eq [301, '/de'] } + it { is_expected.to eq [302, '/de'] } end describe 'add default locale to long path' do diff --git a/spec/unit/middlewares/locale_spec.rb b/spec/unit/middlewares/locale_spec.rb index 83c78f2c..aa69ef2e 100644 --- a/spec/unit/middlewares/locale_spec.rb +++ b/spec/unit/middlewares/locale_spec.rb @@ -6,35 +6,104 @@ describe Locomotive::Steam::Middlewares::Locale do - let(:site) { instance_double('Site', default_locale: :de, locales: %w(de fr)) } + let(:site) { instance_double('Site', default_locale: :de, locales: [:de, :fr, :en]) } let(:url) { 'http://models.example.com' } let(:app) { ->(env) { [200, env, 'app'] } } - let(:services) { instance_double('Services', :locale= => 'en') } + let(:cookie_lang) { nil } + let(:cookie_service) { instance_double('Cookie Service', :get => cookie_lang) } + let(:services) { instance_double('Services', :locale= => 'en', :cookie => cookie_service) } let(:middleware) { Locomotive::Steam::Middlewares::Locale.new(app) } + let(:cookie) { {} } + let(:accept_language) { '' } + let(:expected_lang) { :de } + let(:cookie) { { value: expected_lang, path: '/', max_age: 1.year } } subject do - env = env_for(url, 'steam.site' => site) + env = env_for( + url, + 'steam.site' => site, + 'HTTP_ACCEPT_LANGUAGE' => accept_language) env['steam.request'] = Rack::Request.new(env) env['steam.services'] = services code, env = middleware.call(env) env['steam.locale'] end + describe 'no locale defined in the path' do + + describe 'first connexion' do + + context 'without accept-language header' do + + it 'should use default language' do + expect(cookie_service).to receive(:set).with('steam-locale', cookie).and_return(nil) + is_expected.to eq expected_lang + end + + end + + context 'with accept-language header' do + + let(:accept_language) { 'fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7' } + let(:expected_lang) { :fr } + + it 'should use "fr" in header' do + expect(cookie_service).to receive(:set).with('steam-locale', cookie).and_return(nil) + is_expected.to eq expected_lang + end + + context 'with url path' do + + let(:url) { 'http://models.example.com/werkzeug' } + let(:expected_lang) { :de } + + it 'should use "de" in path' do + expect(cookie_service).to receive(:set).with('steam-locale', cookie).and_return(nil) + is_expected.to eq expected_lang + end + + end + + end + + end + + context 'user with cookie, use it' do + + let(:cookie_lang) { 'en' } + let(:expected_lang) { :en } + + it 'should use "en" in cookie' do + expect(cookie_service).to receive(:set).with('steam-locale', cookie).and_return(nil) + is_expected.to eq expected_lang + end + + end + + end + describe 'locale asked in the request params' do context 'the locale is blank' do let(:url) { 'http://models.example.com?locale=' } - it { is_expected.to eq :de } + it 'should use default locale "de"' do + expect(cookie_service).to receive(:set).with('steam-locale', cookie).and_return(nil) + is_expected.to eq expected_lang + end end context 'the locale exists' do - let(:url) { 'http://models.example.com?locale=fr' } + let(:url) { 'http://models.example.com?locale=en' } + let(:expected_lang) { :en } - it { is_expected.to eq 'fr' } + it 'should use existing locale "en"' do + expect(cookie_service).to receive(:set).with('steam-locale', cookie).and_return(nil) + is_expected.to eq expected_lang + end end @@ -42,11 +111,12 @@ let(:url) { 'http://models.example.com?locale=onload' } - it { is_expected.to eq :de } + it 'should use default locale "de"' do + expect(cookie_service).to receive(:set).with('steam-locale', cookie).and_return(nil) + is_expected.to eq expected_lang + end end - end - end diff --git a/spec/unit/services/action_service_spec.rb b/spec/unit/services/action_service_spec.rb index 75bc1d04..afbf2e80 100644 --- a/spec/unit/services/action_service_spec.rb +++ b/spec/unit/services/action_service_spec.rb @@ -8,7 +8,8 @@ let(:entry_service) { instance_double('ContentService') } let(:api_service) { instance_double('ExternalAPIService') } let(:redirection_service) { instance_double('PageRedirectionService') } - let(:service) { described_class.new(site, email_service, content_entry: entry_service, api: api_service, redirection: redirection_service) } + let(:cookie_service) { instance_double('CookieService') } + let(:service) { described_class.new(site, email_service, content_entry: entry_service, api: api_service, redirection: redirection_service, cookie: cookie_service) } describe '#run' do @@ -112,6 +113,22 @@ end + describe 'getCookiesProp' do + let(:script) { "return getCookiesProp('name');" } + before do + expect(cookie_service).to receive(:get).with('name').and_return('John') + end + it { is_expected.to eq('John') } + end + + describe 'setCookiesProp' do + let(:script) { "return setCookiesProp('done', {'value': true});" } + before do + expect(cookie_service).to receive(:set).with('done', {'value' => true}) + end + it { is_expected.to eq(nil) } + end + describe 'allEntries' do let(:now) { Time.use_zone('America/Chicago') { Time.zone.local(2015, 'mar', 25, 10, 0) } } diff --git a/spec/unit/services/cookie_service_spec.rb b/spec/unit/services/cookie_service_spec.rb new file mode 100644 index 00000000..bc61c4da --- /dev/null +++ b/spec/unit/services/cookie_service_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe Locomotive::Steam::CookieService do + + let(:steam_cookies) { {} } + let(:request_cookies) { {} } + let(:request) { instance_double('Request', env: { 'steam.cookies' => steam_cookies }, cookies: request_cookies) } + let(:cookie) { {'value' => 'bar2'} } + let(:service) { described_class.new(request)} + + describe '#get cookies from request' do + + let(:request_cookies) { {'foo' => 'bar'} } + subject { service.get('foo') } + + context 'from request' do + it { is_expected.to eq 'bar' } + end + + context 'from response' do + let(:steam_cookies) { {'foo' => {'value' => 'bar2'}} } + it { is_expected.to eq 'bar2' } + end + + end + + describe '#set cookies from response' do + + subject { service.set('foo', cookie) } + + it 'set the cookies into steam' do + is_expected.to eq cookie + expect(steam_cookies).to eq({'foo' => cookie}) + end + + end + +end diff --git a/spec/unit/services/url_builder_service_spec.rb b/spec/unit/services/url_builder_service_spec.rb index b5d923a0..4f34b13d 100644 --- a/spec/unit/services/url_builder_service_spec.rb +++ b/spec/unit/services/url_builder_service_spec.rb @@ -7,13 +7,15 @@ let(:request) { instance_double('Request', env: { 'steam.mounted_on' => mounted_on }) } let(:site) { instance_double('Site', default_locale: 'en', prefix_default_locale: prefix_default) } let(:locale) { 'en' } - let(:service) { described_class.new(site, locale, request) } + let(:current_locale) { 'en' } + let(:locale) { nil } + let(:service) { described_class.new(site, current_locale, mounted_on) } describe '#url_for' do let(:page) { instance_double('AboutUs', fullpath: 'about-us', templatized?: false) } - subject { service.url_for(page) } + subject { service.url_for(page, locale) } it { is_expected.to eq '/about-us' } @@ -37,6 +39,16 @@ end + describe 'asking for the index page url in the defaut locale when the current locale is different from the default one' do + + let(:current_locale) { 'fr' } + let(:locale) { 'en' } + let(:page) { instance_double('index', fullpath: 'index', templatized?: false) } + + it { is_expected.to eq '/en' } + + end + describe 'no need to put the index slug' do let(:page) { instance_double('Index', fullpath: 'index', templatized?: false) }