diff --git a/app/assets/stylesheets/darkswarm/embedded_shopfront.css.scss b/app/assets/stylesheets/darkswarm/embedded_shopfront.css.scss new file mode 100644 index 0000000000..827bd39724 --- /dev/null +++ b/app/assets/stylesheets/darkswarm/embedded_shopfront.css.scss @@ -0,0 +1,40 @@ +body.embedded { + nav.top-bar{ + ul.left, ul.center, ul.right li.current_hub { + display: none; + } + + ul.right { + width: auto !important; + li { + float: left; + line-height: 4.6875rem; + height: 4.6875rem; + vertical-align: top; + } + } + + &.show-for-large-up { + display: inherit !important; + } + &.show-for-medium-down { + display: none !important; + } + } + + footer { + .footer-local { + display: none; + } + .footer-global { + padding-bottom: 0; + + .row { + display: none; + } + .row:first-of-type { + display: block; + } + } + } +} diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0d31130c6e..2ec49a4880 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -20,6 +20,28 @@ class ApplicationController < ActionController::Base end end + def enable_embedded_styles + session[:embedded_shopfront] = true + render json: {}, status: 200 + end + + def disable_embedded_styles + session.delete :embedded_shopfront + session.delete :shopfront_redirect + render json: {}, status: 200 + end + + protected + + def after_sign_in_path_for(resource_or_scope) + return session[:shopfront_redirect] if session[:shopfront_redirect] + stored_location_for(resource_or_scope) || signed_in_root_path(resource_or_scope) + end + + def after_sign_out_path_for(resource_or_scope) + session[:shopfront_redirect] ? session[:shopfront_redirect] : root_path + end + private def restrict_iframes @@ -28,13 +50,32 @@ class ApplicationController < ActionController::Base end def enable_embedded_shopfront - return unless Spree::Config[:enable_embedded_shopfronts] + whitelist = Spree::Config[:embedded_shopfronts_whitelist] + return unless Spree::Config[:enable_embedded_shopfronts] and whitelist.present? - @session_data = session - - whitelist = Spree::Config[:embedded_shopfronts_whitelist] || "'none'" response.headers.delete 'X-Frame-Options' response.headers['Content-Security-Policy'] = "frame-ancestors #{whitelist}" + + check_embedded_request + set_embedded_layout + end + + def check_embedded_request + return unless params[:embedded_shopfront] + + # Show embedded shopfront CSS + session[:embedded_shopfront] = true + + # Get shopfront slug and set redirect path + if params[:controller] == 'enterprises' and params[:action] == 'shop' and params[:id] + slug = params[:id] + session[:shopfront_redirect] = '/' + slug + '/shop?embedded_shopfront=true' + end + end + + def set_embedded_layout + return unless session[:embedded_shopfront] + @shopfront_layout = 'embedded' end def action diff --git a/app/controllers/shops_controller.rb b/app/controllers/shops_controller.rb index 439e8fde06..aa0d2f8f33 100644 --- a/app/controllers/shops_controller.rb +++ b/app/controllers/shops_controller.rb @@ -4,6 +4,5 @@ class ShopsController < BaseController before_filter :enable_embedded_shopfront def index - #@embeddable = "test" end end diff --git a/app/views/layouts/_shopfront_script.html.haml b/app/views/layouts/_shopfront_script.html.haml new file mode 100644 index 0000000000..b00d2b65ca --- /dev/null +++ b/app/views/layouts/_shopfront_script.html.haml @@ -0,0 +1,29 @@ +:javascript + $(document).ready(function() { + var in_iframe = function(){ + try { + return window.self !== window.top; + } catch (e) { + return true; + } + }; + + var embedded_styles_active = $('body.off-canvas').hasClass('embedded'); + + var set_shopfront_styles = function(state) { + $.ajax({ + url: '/embedded_shopfront/'+state, + type: 'POST' + }); + }; + + if (in_iframe() && !embedded_styles_active){ + $('body.off-canvas').addClass('embedded'); + set_shopfront_styles('enable'); + } + + if (!in_iframe() && embedded_styles_active) { + $('body.off-canvas').removeClass('embedded'); + set_shopfront_styles('disable'); + } + }); diff --git a/app/views/layouts/darkswarm.html.haml b/app/views/layouts/darkswarm.html.haml index 20a47be970..b281d34c82 100644 --- a/app/views/layouts/darkswarm.html.haml +++ b/app/views/layouts/darkswarm.html.haml @@ -21,11 +21,13 @@ = render "layouts/bugherd_script" = csrf_meta_tags - %body.off-canvas{"ng-app" => "Darkswarm"} + %body.off-canvas{class: @shopfront_layout, ng: {app: "Darkswarm"}} / [if lte IE 8] = render partial: "shared/ie_warning" = javascript_include_tag "iehack" + = render "layouts/shopfront_script" if @shopfront_layout + = inject_current_hub = inject_json "user", "current_user" = inject_json "railsFlash", "flash" diff --git a/config/routes.rb b/config/routes.rb index ca5a8d5ade..8da98bd8bc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -57,6 +57,9 @@ Openfoodnetwork::Application.routes.draw do put '/checkout', :to => 'checkout#update' , :as => :update_checkout get '/checkout/paypal_payment/:order_id', to: 'checkout#paypal_payment', as: :paypal_payment + post 'embedded_shopfront/enable', to: 'application#enable_embedded_styles' + post 'embedded_shopfront/disable', to: 'application#disable_embedded_styles' + resources :enterprises do collection do post :search diff --git a/spec/dummy/iframe_test.html b/spec/dummy/iframe_test.html index 552cf8e8dc..fe71aa66e3 100644 --- a/spec/dummy/iframe_test.html +++ b/spec/dummy/iframe_test.html @@ -2,9 +2,7 @@ -

Iframe Test

- - + - \ No newline at end of file + diff --git a/spec/features/consumer/shopping/embedded_shopfronts_spec.rb b/spec/features/consumer/shopping/embedded_shopfronts_spec.rb index fd216c2a2b..c615a369c7 100644 --- a/spec/features/consumer/shopping/embedded_shopfronts_spec.rb +++ b/spec/features/consumer/shopping/embedded_shopfronts_spec.rb @@ -3,6 +3,11 @@ require 'spec_helper' feature "Using embedded shopfront functionality", js: true do include AuthenticationWorkflow include WebHelper + include ShopWorkflow + include CheckoutWorkflow + include UIComponentHelper + + Capybara.server_port = 9999 describe "enabling embedded shopfronts" do before do @@ -31,25 +36,118 @@ feature "Using embedded shopfront functionality", js: true do end end - describe "using iframes", js: true do + describe "using iframes" do + let(:distributor) { create(:distributor_enterprise, name: 'My Embedded Hub', permalink: 'test_enterprise', with_payment_and_shipping: true) } + let(:supplier) { create(:supplier_enterprise) } + let(:oc1) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise), orders_close_at: 2.days.from_now) } + let(:product) { create(:simple_product, name: 'Framed Apples', supplier: supplier) } + let(:variant) { create(:variant, product: product, price: 19.99) } + let(:exchange) { Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) } + let(:user) { create(:user) } + before do + add_variant_to_order_cycle(exchange, variant) + Spree::Config[:enable_embedded_shopfronts] = true + Spree::Config[:embedded_shopfronts_whitelist] = 'localhost' + + page.driver.browser.js_errors = false + Capybara.current_session.driver.visit('spec/dummy/iframe_test.html') end after do Spree::Config[:enable_embedded_shopfronts] = false end - pending "displays iframe content" do - Capybara.current_session.driver.visit('spec/dummy/iframe_test.html') - - expect(page).to have_text 'Iframe Test' + it "displays modified shopfront layout" do expect(page).to have_selector 'iframe#test_iframe' within_frame 'test_iframe' do - sleep 1 - expect(page).to have_content "OFN" # currently fails... + within 'nav.top-bar' do + expect(page).to have_selector 'ul.left', visible: false + expect(page).to have_selector 'ul.center', visible: false + end + + expect(page).to have_content "My Embedded Hub" + expect(page).to have_content "Framed Apples" + end + end + + it "allows shopping and checkout" do + within_frame 'test_iframe' do + fill_in "variants[#{variant.id}]", with: 1 + wait_until_enabled 'input.add_to_cart' + + first("input.add_to_cart:not([disabled='disabled'])").click + + expect(page).to have_text 'Your shopping cart' + find('a#checkout-link').click + + expect(page).to have_text 'Checkout now' + + click_button 'Login' + login_with_modal + + expect(page).to have_text 'Payment' + + within "#details" do + fill_in "First Name", with: "Some" + fill_in "Last Name", with: "One" + fill_in "Email", with: "test@example.com" + fill_in "Phone", with: "0456789012" + end + + toggle_billing + within "#billing" do + fill_in "Address", with: "123 Street" + select "Australia", from: "Country" + select "Victoria", from: "State" + fill_in "City", with: "Melbourne" + fill_in "Postcode", with: "3066" + end + + toggle_shipping + within "#shipping" do + find('input[type="radio"]').trigger 'click' + end + + toggle_payment + within "#payment" do + find('input[type="radio"]').trigger 'click' + end + + place_order + + expect(page).to have_content "Your order has been processed successfully" + end + end + + it "redirects to embedded hub on logout when embedded" do + within_frame 'test_iframe' do + + find('ul.right li#login-link a').click + login_with_modal + + wait_until { page.find('ul.right li.has-dropdown').value.present? } + logout_via_navigation + + expect(page).to have_text 'My Embedded Hub' end end end + + def login_with_modal + expect(page).to have_selector 'div.login-modal', visible: true + + within 'div.login-modal' do + fill_in "Email", with: user.email + fill_in "Password", with: user.password + find('input[type="submit"]').click + end + end + + def logout_via_navigation + first('ul.right li.has-dropdown a').click + find('ul.right ul.dropdown li a[title="Logout"]').click + end end