diff --git a/spec/features/consumer/shopping/embedded_shopfronts_spec.rb b/spec/features/consumer/shopping/embedded_shopfronts_spec.rb index 20c7bfccb8..445a92186f 100644 --- a/spec/features/consumer/shopping/embedded_shopfronts_spec.rb +++ b/spec/features/consumer/shopping/embedded_shopfronts_spec.rb @@ -45,7 +45,7 @@ feature "Using embedded shopfront functionality", js: true do it "allows shopping and checkout" do on_embedded_page do - fill_in "variants[#{variant.id}]", with: 1 + click_add_to_cart edit_cart diff --git a/spec/features/consumer/shopping/shopping_spec.rb b/spec/features/consumer/shopping/shopping_spec.rb index b947b23d3d..cf825ca475 100644 --- a/spec/features/consumer/shopping/shopping_spec.rb +++ b/spec/features/consumer/shopping/shopping_spec.rb @@ -104,9 +104,8 @@ feature "As a consumer I want to shop with a distributor", js: true do expect(page).to have_content with_currency(1020.99) # -- Cart shows correct price - fill_in "variants[#{variant.id}]", with: 1 - toggle_cart - within(".cart-sidebar") { expect(page).to have_content with_currency(1020.99) } + click_add_to_cart variant + expect(page).to have_in_cart with_currency(1020.99) toggle_cart # -- Changing order cycle @@ -119,10 +118,8 @@ feature "As a consumer I want to shop with a distributor", js: true do # ng-animate means that the old product row is likely to be present, so we ensure # that we are not filling in the quantity on the outgoing row expect(page).not_to have_selector "tr.product-cart" - within('product:not(.ng-leave)') { fill_in "variants[#{variant.id}]", with: 1 } - - wait_for_cart - within(".cart-sidebar") { expect(page).to have_content with_currency(19.99) } + within('product:not(.ng-leave)') { click_add_to_cart variant } + expect(page).to have_in_cart with_currency(19.99) end describe "declining to clear the cart" do @@ -132,15 +129,14 @@ feature "As a consumer I want to shop with a distributor", js: true do visit shop_path select "turtles", from: "order_cycle_id" - fill_in "variants[#{variant.id}]", with: 1 + click_add_to_cart variant end it "leaves the cart untouched when the user declines" do handle_js_confirm(false) do select "frogs", from: "order_cycle_id" - toggle_cart + expect(page).to have_in_cart "1" expect(page).to have_selector "tr.product-cart" - expect(page).to have_selector '.cart-sidebar', text: '1' # The order cycle choice should not have changed expect(page).to have_select 'order_cycle_id', selected: 'turtles' @@ -148,17 +144,6 @@ feature "As a consumer I want to shop with a distributor", js: true do end end end - - context "when logged in" do - let!(:prev_order) { create(:completed_order_with_totals, order_cycle: oc1, distributor: distributor, user: order.user) } - - before do - distributor.allow_order_changes = true - distributor.save - quick_login_as order.user - visit shop_path - end - end end end @@ -230,11 +215,8 @@ feature "As a consumer I want to shop with a distributor", js: true do visit shop_path expect(page).to have_content product.name - # Add product to cart - fill_in "variants[#{variant.id}]", with: '1' - wait_for_debounce + click_add_to_cart variant expect(page).to have_in_cart product.name - wait_until { !cart_dirty } # Try to go to cart visit main_app.cart_path @@ -260,17 +242,14 @@ feature "As a consumer I want to shop with a distributor", js: true do it "should save group buy data to the cart and display it on shopfront reload" do # -- Quantity - fill_in "variants[#{variant.id}]", with: 6 - wait_for_debounce + click_add_bulk_to_cart variant, 6 expect(page).to have_in_cart product.name - wait_until { !cart_dirty } + toggle_cart expect(order.reload.line_items.first.quantity).to eq(6) # -- Max quantity - fill_in "variant_attributes[#{variant.id}][max_quantity]", with: 7 - wait_for_debounce - wait_until { !cart_dirty } + click_add_bulk_max_to_cart variant, 7 expect(order.reload.line_items.first.max_quantity).to eq(7) @@ -296,15 +275,15 @@ feature "As a consumer I want to shop with a distributor", js: true do end it "lets us add and remove products from our cart" do - fill_in "variants[#{variant.id}]", with: '1' + click_add_to_cart variant expect(page).to have_in_cart product.name - wait_until { !cart_dirty } li = Spree::Order.order(:created_at).last.line_items.order(:created_at).last expect(li.quantity).to eq(1) - fill_in "variants[#{variant.id}]", with: '0' + toggle_cart + click_remove_from_cart variant + toggle_cart within('.cart-sidebar') { expect(page).not_to have_content product.name } - wait_until { !cart_dirty } expect(Spree::LineItem.where(id: li)).to be_empty end @@ -313,7 +292,7 @@ feature "As a consumer I want to shop with a distributor", js: true do variant.update on_hand: 5, on_demand: true visit shop_path - fill_in "variants[#{variant.id}]", with: '10' + click_add_to_cart variant, 10 expect(page).to have_field "variants[#{variant.id}]", with: '10' end @@ -322,6 +301,7 @@ feature "As a consumer I want to shop with a distributor", js: true do variant.update on_hand: 5 visit shop_path + accept_alert 'Insufficient stock available, only 5 remaining' do fill_in "variants[#{variant.id}]", with: '10' end @@ -336,9 +316,7 @@ feature "As a consumer I want to shop with a distributor", js: true do variant.update! on_hand: 0 # -- Messaging - expect(page).to have_input "variants[#{variant.id}]" - fill_in "variants[#{variant.id}]", with: '1' - wait_until { !cart_dirty } + click_add_to_cart variant within(".out-of-stock-modal") do expect(page).to have_content "stock levels for one or more of the products in your cart have reduced" @@ -353,8 +331,6 @@ feature "As a consumer I want to shop with a distributor", js: true do # Update amount available in product list # If amount falls to zero, variant should be greyed out and input disabled expect(page).to have_selector "#variant-#{variant.id}.out-of-stock" - expect(page).to have_selector "#variants_#{variant.id}[ofn-on-hand='0']" - expect(page).to have_selector "#variants_#{variant.id}[disabled='disabled']" end it 'does not show out of stock modal if product is on_demand' do @@ -362,9 +338,7 @@ feature "As a consumer I want to shop with a distributor", js: true do variant.update! on_hand: 0, on_demand: true - expect(page).to have_input "variants[#{variant.id}]" - fill_in "variants[#{variant.id}]", with: '1' - wait_until { !cart_dirty } + click_add_to_cart variant expect(page).to_not have_selector '.out-of-stock-modal' end @@ -374,13 +348,11 @@ feature "As a consumer I want to shop with a distributor", js: true do it "does the same" do # -- Place in cart so we can set max_quantity, then make out of stock - fill_in "variants[#{variant.id}]", with: '1' - wait_until { !cart_dirty } + click_add_bulk_to_cart variant variant.update! on_hand: 0 # -- Messaging - fill_in "variant_attributes[#{variant.id}][max_quantity]", with: '1' - wait_until { !cart_dirty } + click_add_bulk_max_to_cart variant within(".out-of-stock-modal") do expect(page).to have_content "stock levels for one or more of the products in your cart have reduced" @@ -400,13 +372,11 @@ feature "As a consumer I want to shop with a distributor", js: true do context "when the update is for another product" do it "updates quantity" do - fill_in "variants[#{variant.id}]", with: '2' - wait_until { !cart_dirty } + click_add_to_cart variant, 2 variant.update! on_hand: 1 - fill_in "variants[#{variant2.id}]", with: '1' - wait_until { !cart_dirty } + click_add_to_cart variant2 within(".out-of-stock-modal") do expect(page).to have_content "stock levels for one or more of the products in your cart have reduced" @@ -418,13 +388,12 @@ feature "As a consumer I want to shop with a distributor", js: true do let(:product) { create(:simple_product, group_buy: true) } it "does not update max_quantity" do - fill_in "variants[#{variant.id}]", with: '2' - fill_in "variant_attributes[#{variant.id}][max_quantity]", with: '3' - wait_until { !cart_dirty } + click_add_bulk_to_cart variant, 2 + click_add_bulk_max_to_cart variant, 3 + variant.update! on_hand: 1 - fill_in "variants[#{variant2.id}]", with: '1' - wait_until { !cart_dirty } + click_add_bulk_to_cart variant2 within(".out-of-stock-modal") do expect(page).to have_content "stock levels for one or more of the products in your cart have reduced" @@ -443,7 +412,7 @@ feature "As a consumer I want to shop with a distributor", js: true do it "handles it as if the variant has gone out of stock" do variant.delete - fill_in "variants[#{variant.id}]", with: '1' + click_add_to_cart variant expect_out_of_stock_behavior end @@ -458,7 +427,7 @@ feature "As a consumer I want to shop with a distributor", js: true do it "handles it as if the variant has gone out of stock" do variant.delete - fill_in "variants[#{variant.id}]", with: '1' + click_add_to_cart variant expect_out_of_stock_behavior end @@ -578,16 +547,7 @@ feature "As a consumer I want to shop with a distributor", js: true do expect(page).to have_content product.name end - def wait_for_debounce - # The auto-submit on these specific form elements (add to cart) now has a small built-in - # waiting period before submitting the data... - sleep 0.6 - end - def expect_out_of_stock_behavior - wait_for_debounce - wait_until { !cart_dirty } - # Shows an "out of stock" modal, with helpful user feedback within(".out-of-stock-modal") do expect(page).to have_content I18n.t('js.out_of_stock.out_of_stock_text') @@ -598,9 +558,5 @@ feature "As a consumer I want to shop with a distributor", js: true do expect(page).to have_selector "#variant-#{variant.id}.out-of-stock" expect(page).to have_selector "#variants_#{variant.id}[ofn-on-hand='0']" expect(page).to have_selector "#variants_#{variant.id}[disabled='disabled']" - - # We need to wait again for the cart to finish updating in Angular or the test can fail - # as the session cannot be reset properly (after the test) while it's still loading - wait_until { !cart_dirty } end end diff --git a/spec/features/consumer/shopping/variant_overrides_spec.rb b/spec/features/consumer/shopping/variant_overrides_spec.rb index 6dfed074a7..9c7ca0a5d1 100644 --- a/spec/features/consumer/shopping/variant_overrides_spec.rb +++ b/spec/features/consumer/shopping/variant_overrides_spec.rb @@ -37,8 +37,7 @@ feature "shopping with variant overrides defined", js: true do outgoing_exchange.variants = [product1_variant1, product1_variant2, product2_variant1, product1_variant3, product3_variant1, product3_variant2, product4_variant1] outgoing_exchange.enterprise_fees << enterprise_fee sm.calculator.preferred_amount = 0 - visit shops_path - click_link hub.name + visit enterprise_shop_path(hub) end describe "viewing products" do @@ -66,9 +65,7 @@ feature "shopping with variant overrides defined", js: true do end it "shows the correct prices when products are in the cart" do - fill_in "variants[#{product1_variant1.id}]", with: "2" - toggle_cart - wait_until_enabled '.cart-sidebar a.edit-cart' + click_add_to_cart product1_variant1, 2 visit shop_path expect(page).to have_price with_currency(61.11) end @@ -77,14 +74,14 @@ feature "shopping with variant overrides defined", js: true do # https://github.com/openfoodfoundation/openfoodnetwork/issues/312 it "shows the overridden price with fees in the quick cart" do - fill_in "variants[#{product1_variant1.id}]", with: "2" + click_add_to_cart product1_variant1, 2 toggle_cart expect(page).to have_selector "#cart-variant-#{product1_variant1.id} .quantity", text: '2' expect(page).to have_selector "#cart-variant-#{product1_variant1.id} .total-price", text: with_currency(122.22) end it "shows the correct prices in the shopping cart" do - fill_in "variants[#{product1_variant1.id}]", with: "2" + click_add_to_cart product1_variant1, 2 edit_cart expect(page).to have_selector "tr.line-item.variant-#{product1_variant1.id} .cart-item-price", text: with_currency(61.11) @@ -96,7 +93,7 @@ feature "shopping with variant overrides defined", js: true do end it "shows the correct prices in the checkout" do - fill_in "variants[#{product1_variant1.id}]", with: "2" + click_add_to_cart product1_variant1, 2 click_checkout expect(page).to have_selector 'form.edit_order .cart-total', text: with_currency(122.22) @@ -107,7 +104,7 @@ feature "shopping with variant overrides defined", js: true do describe "creating orders" do it "creates the order with the correct prices" do - fill_in "variants[#{product1_variant1.id}]", with: "2" + click_add_to_cart product1_variant1, 2 click_checkout complete_checkout @@ -118,7 +115,7 @@ feature "shopping with variant overrides defined", js: true do end it "subtracts stock from the override" do - fill_in "variants[#{product1_variant3.id}]", with: "2" + click_add_to_cart product1_variant3, 2 click_checkout expect do @@ -129,7 +126,7 @@ feature "shopping with variant overrides defined", js: true do end it "subtracts stock from stock-overridden on_demand variants" do - fill_in "variants[#{product3_variant2.id}]", with: "2" + click_add_to_cart product3_variant2, 2 click_checkout expect do @@ -140,7 +137,7 @@ feature "shopping with variant overrides defined", js: true do end it "does not subtract stock from overrides that do not override count_on_hand" do - fill_in "variants[#{product1_variant1.id}]", with: "2" + click_add_to_cart product1_variant1, 2 click_checkout expect do complete_checkout @@ -149,7 +146,7 @@ feature "shopping with variant overrides defined", js: true do end it "does not subtract stock from variants where the override has on_demand: true" do - fill_in "variants[#{product4_variant1.id}]", with: "2" + click_add_to_cart product4_variant1, 2 click_checkout expect do complete_checkout @@ -159,7 +156,7 @@ feature "shopping with variant overrides defined", js: true do it "does not show out of stock flags on order confirmation page" do product1_variant3.on_hand = 0 - fill_in "variants[#{product1_variant3.id}]", with: "2" + click_add_to_cart product1_variant3, 2 click_checkout complete_checkout @@ -202,7 +199,7 @@ feature "shopping with variant overrides defined", js: true do def click_checkout toggle_cart - wait_until_enabled '.cart-sidebar a.edit-cart' - first(:link, I18n.t('shared.menu.cart_sidebar.checkout')).click + wait_for_cart + click_link I18n.t('shared.menu.cart_sidebar.checkout') end end diff --git a/spec/support/request/checkout_workflow.rb b/spec/support/request/checkout_workflow.rb index 8a4ea7974d..c6863a1bf5 100644 --- a/spec/support/request/checkout_workflow.rb +++ b/spec/support/request/checkout_workflow.rb @@ -4,7 +4,7 @@ module CheckoutWorkflow end def checkout_as_guest - find("button", text: "Checkout as guest").click + click_button "Checkout as guest" end def place_order diff --git a/spec/support/request/shop_workflow.rb b/spec/support/request/shop_workflow.rb index e5123715e0..c6a469e6c4 100644 --- a/spec/support/request/shop_workflow.rb +++ b/spec/support/request/shop_workflow.rb @@ -1,13 +1,28 @@ module ShopWorkflow + # If a spec uses `within` but we want to check something outside of that + # scope, we can search from the body element instead. + def find_body + page.all("body").first || page.find(:xpath, "ancestor::body") + end + def wait_for_cart - first("#cart").click - within '.cart-sidebar' do - expect(page).to_not have_link "Updating cart..." + # Wait for debounce + # + # The auto-submit on these specific form elements (add to cart) now has a small built-in + # waiting period before submitting the data... + sleep 0.6 + + within find_body do + # We ignore visibility in case the cart dropdown is not open. + within '.cart-sidebar', visible: false do + expect(page).to_not have_link "Updating cart...", visible: false + end end end def edit_cart wait_for_cart + toggle_cart within '.cart-sidebar' do expect(page).to have_link I18n.t('shared.menu.cart_sidebar.edit_cart') end @@ -34,6 +49,58 @@ module ShopWorkflow order.update_distribution_charge! end + # Add an item to the cart + # + # At the moment, the user enters the quantity into an input field. + # But with the coming mobile-friendly UX, the user will click a button to + # add an item, hence the naming. + # + # This is temporary code. The duplication will be removed by the mobile + # product listings feature. This has been backported to avoid merge + # conflicts and to make the current build more stable. + def click_add_to_cart(variant = nil, quantity = 1) + within_variant(variant) do + input = page.find("input") + new_quantity = input.value.to_i + quantity + fill_in input[:name], with: new_quantity + end + wait_for_cart + end + + def click_remove_from_cart(variant = nil, quantity = 1) + within_variant(variant) do + input = page.find("input") + new_quantity = input.value.to_i - quantity + fill_in input[:name], with: new_quantity + end + wait_for_cart + end + + def click_add_bulk_to_cart(variant = nil, quantity = 1) + within_variant(variant) do + input = page.find("input") + new_quantity = input.value.to_i + quantity + fill_in input[:name], with: new_quantity + end + wait_for_cart + end + + def click_add_bulk_max_to_cart(variant = nil, quantity = 1) + within_variant(variant) do + input = page.find(:field, "variant_attributes[#{variant.id}][max_quantity]") + new_quantity = input.value.to_i + quantity + fill_in input[:name], with: new_quantity + end + wait_for_cart + end + + def within_variant(variant = nil) + selector = variant ? "#variant-#{variant.id}" : ".variants" + within(selector) do + yield + end + end + def toggle_accordion(name) find("dd a", text: name).click end diff --git a/spec/support/request/ui_component_helper.rb b/spec/support/request/ui_component_helper.rb index b23002e3d7..dd2f38bd46 100644 --- a/spec/support/request/ui_component_helper.rb +++ b/spec/support/request/ui_component_helper.rb @@ -69,10 +69,6 @@ module UIComponentHelper page.find("#cart").click end - def cart_dirty - page.find("span.cart-span")[:class].include? 'pure-dirty' - end - def wait_for_ajax counter = 0 while page.execute_script("return $.active").to_i > 0 diff --git a/spec/support/request/web_helper.rb b/spec/support/request/web_helper.rb index 732e306a29..25ae07bbc1 100644 --- a/spec/support/request/web_helper.rb +++ b/spec/support/request/web_helper.rb @@ -95,10 +95,6 @@ module WebHelper end end - def wait_until_enabled(selector) - wait_until(10) { first("#{selector}:not([disabled='disabled'])") } - end - def select2_select(value, options) id = options[:from] options[:from] = "#s2id_#{id}"