mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-26 20:56:48 +00:00
390 lines
13 KiB
Ruby
390 lines
13 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "system_helper"
|
|
|
|
RSpec.describe "As a consumer, I want to checkout my order" do
|
|
include ShopWorkflow
|
|
include CheckoutHelper
|
|
include FileHelper
|
|
include StripeHelper
|
|
include StripeStubs
|
|
include PaypalHelper
|
|
include AuthenticationHelper
|
|
|
|
let!(:zone) { create(:zone_with_member) }
|
|
let(:supplier) { create(:supplier_enterprise) }
|
|
let(:distributor) { create(:distributor_enterprise, charges_sales_tax: true) }
|
|
let(:product) {
|
|
create(:taxed_product, supplier_id: supplier.id, price: 10, zone:, tax_rate_amount: 0.1)
|
|
}
|
|
let(:variant) { product.variants.first }
|
|
let!(:order_cycle) {
|
|
create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor],
|
|
coordinator: create(:distributor_enterprise), variants: [variant])
|
|
}
|
|
let(:order) {
|
|
create(:order, order_cycle:, distributor:, bill_address_id: nil,
|
|
ship_address_id: nil, state: "cart",
|
|
line_items: [create(:line_item, variant:)])
|
|
}
|
|
|
|
let(:fee_tax_rate) { create(:tax_rate, amount: 0.10, zone:, included_in_price: true) }
|
|
let(:fee_tax_category) { create(:tax_category, tax_rates: [fee_tax_rate]) }
|
|
let(:enterprise_fee) { create(:enterprise_fee, amount: 1.23, tax_category: fee_tax_category) }
|
|
|
|
let(:free_shipping_with_required_address) {
|
|
create(:shipping_method, require_ship_address: true,
|
|
name: "A Free Shipping with required address")
|
|
}
|
|
|
|
let!(:payment_with_fee) {
|
|
create(:payment_method, distributors: [distributor],
|
|
name: "Payment with Fee", description: "Payment with fee",
|
|
calculator: Calculator::FlatRate.new(preferred_amount: 1.23))
|
|
}
|
|
|
|
before do
|
|
add_enterprise_fee enterprise_fee
|
|
pick_order order
|
|
|
|
distributor.shipping_methods.push(free_shipping_with_required_address)
|
|
end
|
|
|
|
context "as a logged in user" do
|
|
let(:user) { create(:user) }
|
|
|
|
before do
|
|
login_as(user)
|
|
visit checkout_path
|
|
end
|
|
|
|
context "payment step" do
|
|
let(:order) { create(:order_ready_for_payment, distributor:) }
|
|
|
|
context "with one payment method, with a fee" do
|
|
it "preselect the payment method if only one is available" do
|
|
visit checkout_step_path(:payment)
|
|
|
|
expect(page).to have_title "Checkout Payment - Open Food Network"
|
|
expect(page).to have_checked_field "Payment with Fee"
|
|
expect(page).to have_content "Payment with Fee $1.23"
|
|
end
|
|
end
|
|
|
|
context "with a transaction fee" do
|
|
before do
|
|
click_button "Next - Order summary"
|
|
end
|
|
|
|
shared_examples "displays the transaction fee" do |checkout_page|
|
|
it "on the #{checkout_page} page" do
|
|
expect(page).to have_content("Transaction fee #{with_currency(1.23)}")
|
|
|
|
if checkout_page.eql?("order confirmation")
|
|
expect(page).to have_content "Your order has been processed successfully"
|
|
end
|
|
end
|
|
end
|
|
|
|
it_behaves_like "displays the transaction fee", "order summary"
|
|
|
|
context "after completing the order" do
|
|
before do
|
|
click_on "Complete order"
|
|
end
|
|
it_behaves_like "displays the transaction fee", "order confirmation"
|
|
end
|
|
end
|
|
|
|
context "with more than one payment method" do
|
|
let!(:payment_method) { create(:payment_method, distributors: [distributor]) }
|
|
|
|
before do
|
|
visit checkout_step_path(:payment)
|
|
end
|
|
|
|
it "don't preselect the payment method if more than one is available" do
|
|
expect(page).to have_field "payment_method_#{payment_with_fee.id}", checked: false
|
|
expect(page).to have_field "payment_method_#{payment_method.id}", checked: false
|
|
end
|
|
|
|
it "requires choosing a payment method" do
|
|
click_on "Next - Order summary"
|
|
expect(page).to have_content "Select a payment method"
|
|
end
|
|
end
|
|
|
|
describe "vouchers" do
|
|
context "with no voucher available" do
|
|
before do
|
|
visit checkout_step_path(:payment)
|
|
end
|
|
|
|
it "doesn't show voucher input" do
|
|
expect(page).not_to have_content "Apply voucher"
|
|
end
|
|
end
|
|
|
|
context "with voucher available" do
|
|
let!(:voucher) do
|
|
create(:voucher_flat_rate, code: 'some_code', enterprise: distributor, amount: 15)
|
|
end
|
|
|
|
describe "adding voucher to the order" do
|
|
before do
|
|
visit checkout_step_path(:payment)
|
|
end
|
|
|
|
it "adds a voucher to the order" do
|
|
apply_voucher "some_code"
|
|
|
|
expect(page).to have_content "$15.00 Voucher"
|
|
expect(order.reload.voucher_adjustments.length).to eq(1)
|
|
end
|
|
|
|
context "when voucher covers more then the order total" do
|
|
before do
|
|
order.total = 6
|
|
order.save!
|
|
end
|
|
|
|
it "shows a warning message and doesn't require payment" do
|
|
apply_voucher "some_code"
|
|
|
|
expect(page).to have_content "$15.00 Voucher"
|
|
expect(page).to have_content(
|
|
"Note: if your order total is less than your voucher " \
|
|
"you may not be able to spend the remaining value."
|
|
)
|
|
|
|
expect(page).to have_content "No payment required"
|
|
click_button "Next - Order summary"
|
|
# Expect to be on the Order Summary page
|
|
expect(page).to have_content "Delivery details"
|
|
end
|
|
end
|
|
|
|
context "voucher doesn't exist" do
|
|
it "show an error" do
|
|
fill_in "Enter voucher code", with: "non_code"
|
|
click_button("Apply")
|
|
|
|
expect(page).to have_content("Voucher code invalid")
|
|
end
|
|
end
|
|
|
|
context "with a VINE voucher", :vcr, feature: :connected_apps do
|
|
let!(:vine_connected_app) {
|
|
ConnectedApps::Vine.create(
|
|
enterprise: distributor, data: { api_key: "1234568", secret: "my_secret" }
|
|
)
|
|
}
|
|
before do
|
|
allow(ENV).to receive(:fetch).and_call_original
|
|
allow(ENV).to receive(:fetch).with("VINE_API_URL").and_return("https://vine-staging.openfoodnetwork.org.au/api/v1")
|
|
end
|
|
|
|
it "adds a voucher to the order" do
|
|
apply_voucher "CI3922"
|
|
|
|
expect(page).to have_content "$5.00 Voucher"
|
|
expect(order.reload.voucher_adjustments.length).to eq(1)
|
|
expect(Vouchers::Vine.find_by(code: "CI3922",
|
|
enterprise: distributor)).not_to be_nil
|
|
end
|
|
|
|
context "with an invalid voucher" do
|
|
it "show an error" do
|
|
fill_in "Enter voucher code", with: "KM1891"
|
|
click_button("Apply")
|
|
|
|
expect(page).to have_content("There was an error while adding the voucher")
|
|
expect(Vouchers::Vine.find_by(code: "KM1891", enterprise: distributor)).to be_nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "removing voucher from order" do
|
|
before do
|
|
add_voucher_to_order(voucher, order)
|
|
|
|
visit checkout_step_path(:payment)
|
|
|
|
accept_confirm "Are you sure you want to remove the voucher?" do
|
|
click_on "Remove code"
|
|
end
|
|
|
|
within '#voucher-section' do
|
|
expect(page).to have_button("Apply", disabled: true)
|
|
expect(page).to have_field "Enter voucher code" # Currently no confirmation msg
|
|
end
|
|
end
|
|
|
|
it "removes voucher" do
|
|
expect(page).not_to have_content "No payment required"
|
|
expect(order.voucher_adjustments.length).to eq(0)
|
|
end
|
|
|
|
it "can re-enter a voucher" do
|
|
apply_voucher "some_code"
|
|
|
|
expect(page).to have_content("$15.00 Voucher")
|
|
expect(order.reload.voucher_adjustments.length).to eq(1)
|
|
|
|
expect(page).to have_content "No payment required"
|
|
|
|
click_button "Next - Order summary"
|
|
# Expect to be on the Order Summary page
|
|
expect(page).to have_content "Delivery details"
|
|
end
|
|
|
|
it "can proceed with payment" do
|
|
click_button "Next - Order summary"
|
|
# Expect to be on the Order Summary page
|
|
expect(page).to have_content "Delivery details"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "choosing" do
|
|
shared_examples "different payment methods" do |pay_method|
|
|
context "checking out with #{pay_method}", if: pay_method.eql?("Stripe SCA") == false do
|
|
before do
|
|
visit checkout_step_path(:payment)
|
|
end
|
|
|
|
it "proceeds to the summary step and completes the order" do
|
|
choose pay_method.to_s
|
|
proceed_to_summary
|
|
|
|
place_order
|
|
expect(page).to have_content "Paying via: #{pay_method}"
|
|
expect(order.reload.state).to eq "complete"
|
|
end
|
|
end
|
|
|
|
context "for Stripe SCA", if: pay_method.eql?("Stripe SCA") do
|
|
around do |example|
|
|
with_stripe_setup { example.run }
|
|
end
|
|
|
|
before do
|
|
stripe_enable
|
|
visit checkout_step_path(:payment)
|
|
end
|
|
|
|
it "selects Stripe SCA and proceeds to the summary step" do
|
|
choose pay_method.to_s
|
|
fill_out_card_details
|
|
click_on "Next - Order summary"
|
|
proceed_to_summary
|
|
end
|
|
|
|
context "when saving card" do
|
|
it "selects Stripe SCA and proceeds to the summary step" do
|
|
stub_customers_post_request(email: order.user.email)
|
|
stub_payment_method_attach_request
|
|
|
|
choose pay_method.to_s
|
|
fill_out_card_details
|
|
check "Save card for future use"
|
|
|
|
click_on "Next - Order summary"
|
|
proceed_to_summary
|
|
|
|
# Verify card has been saved with correct stripe IDs
|
|
user_credit_card = order.reload.user.credit_cards.first
|
|
expect(user_credit_card.gateway_payment_profile_id).to eq "pm_123"
|
|
expect(user_credit_card.gateway_customer_profile_id).to eq "cus_A123"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "shared examples" do
|
|
let!(:cash) { create(:payment_method, distributors: [distributor], name: "Cash") }
|
|
|
|
context "Cash" do
|
|
it_behaves_like "different payment methods", "Cash"
|
|
end
|
|
|
|
context "Paypal" do
|
|
let!(:paypal) do
|
|
Spree::Gateway::PayPalExpress.create!(
|
|
name: "Paypal",
|
|
environment: "test",
|
|
distributor_ids: [distributor.id]
|
|
)
|
|
end
|
|
|
|
before do
|
|
stub_paypal_response(
|
|
success: true,
|
|
redirect: payment_gateways_confirm_paypal_path(
|
|
payment_method_id: paypal.id, token: "t123", PayerID: 'p123'
|
|
)
|
|
)
|
|
stub_paypal_confirm
|
|
end
|
|
|
|
it_behaves_like "different payment methods", "Paypal"
|
|
end
|
|
|
|
context "Stripe SCA" do
|
|
let!(:stripe_account) { create(:stripe_account, enterprise: distributor) }
|
|
let!(:stripe_sca_payment_method) {
|
|
create(:stripe_sca_payment_method, distributors: [distributor], name: "Stripe SCA")
|
|
}
|
|
|
|
it_behaves_like "different payment methods", "Stripe SCA"
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "hiding a payment method with a default rule" do
|
|
let!(:tagged_customer) { create(:customer, user:, enterprise: distributor) }
|
|
let!(:hidden_method) {
|
|
create(:payment_method, distributors: [distributor], name: "Hidden", tag_list: "hide_pm")
|
|
}
|
|
before do
|
|
create(:filter_payment_methods_tag_rule,
|
|
enterprise: distributor,
|
|
is_default: true,
|
|
preferred_payment_method_tags: "hide_pm",
|
|
preferred_matched_payment_methods_visibility: 'hidden')
|
|
visit checkout_step_path(:payment)
|
|
end
|
|
|
|
context "with no exceptions set to a customer" do
|
|
it "hides the payment method" do
|
|
expect(page).not_to have_content hidden_method.name
|
|
end
|
|
end
|
|
|
|
context "with an exception set to a customer" do
|
|
before do
|
|
create(:filter_payment_methods_tag_rule,
|
|
enterprise: distributor,
|
|
preferred_customer_tags: "show_pm",
|
|
preferred_payment_method_tags: "hide_pm",
|
|
preferred_matched_payment_methods_visibility: 'visible')
|
|
tagged_customer.update_attribute(:tag_list, "show_pm")
|
|
visit checkout_step_path(:payment)
|
|
end
|
|
|
|
it "displays the payment method" do
|
|
expect(page).to have_content hidden_method.name
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def add_voucher_to_order(voucher, order)
|
|
voucher.create_adjustment(voucher.code, order)
|
|
OrderManagement::Order::Updater.new(order).update_voucher
|
|
end
|
|
end
|