mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-25 20:46:48 +00:00
Direct calls to Flipper have the downside that we can't add any new functionality like storing the feature in the database when used.
355 lines
11 KiB
Ruby
355 lines
11 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'spec_helper'
|
|
|
|
describe SplitCheckoutController, type: :controller do
|
|
let(:user) { order.user }
|
|
let(:address) { create(:address) }
|
|
let(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true) }
|
|
let(:order_cycle) { create(:order_cycle, distributors: [distributor]) }
|
|
let(:exchange) { order_cycle.exchanges.outgoing.first }
|
|
let(:order) {
|
|
create(:order_with_line_items, line_items_count: 1, distributor: distributor,
|
|
order_cycle: order_cycle)
|
|
}
|
|
let(:payment_method) { distributor.payment_methods.first }
|
|
let(:shipping_method) { distributor.shipping_methods.first }
|
|
|
|
before do
|
|
allow(OpenFoodNetwork::FeatureToggle).
|
|
to receive(:enabled?).with(:split_checkout) { true }
|
|
allow(OpenFoodNetwork::FeatureToggle).
|
|
to receive(:enabled?).with(:split_checkout, anything) { true }
|
|
|
|
exchange.variants << order.line_items.first.variant
|
|
allow(controller).to receive(:current_order) { order }
|
|
allow(controller).to receive(:spree_current_user) { user }
|
|
end
|
|
|
|
describe "#edit" do
|
|
it "renders the checkout" do
|
|
get :edit, params: { step: "details" }
|
|
expect(response.status).to eq 200
|
|
end
|
|
|
|
it "redirects to current step if no step is given" do
|
|
get :edit
|
|
expect(response).to redirect_to checkout_step_path(:details)
|
|
end
|
|
|
|
context "when line items in the cart are not valid" do
|
|
before { allow(controller).to receive(:valid_order_line_items?) { false } }
|
|
|
|
it "redirects to cart" do
|
|
get :edit
|
|
expect(response).to redirect_to cart_path
|
|
end
|
|
end
|
|
|
|
context "when the given `step` params is inconsistent with the current order state" do
|
|
context "when order state is `cart`" do
|
|
before do
|
|
order.update!(state: "cart")
|
|
end
|
|
|
|
it "redirects to the valid step if params is `payment`" do
|
|
get :edit, params: { step: "payment" }
|
|
expect(response).to redirect_to checkout_step_path(:details)
|
|
end
|
|
it "redirects to the valid step if params is `summary`" do
|
|
get :edit, params: { step: "summary" }
|
|
expect(response).to redirect_to checkout_step_path(:details)
|
|
end
|
|
end
|
|
|
|
context "when order state is `payment`" do
|
|
before do
|
|
order.update!(state: "payment")
|
|
end
|
|
|
|
it "redirects to the valid step if params is `summary`" do
|
|
get :edit, params: { step: "summary" }
|
|
expect(response).to redirect_to checkout_step_path(:payment)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#update" do
|
|
let(:checkout_params) { {} }
|
|
let(:params) { { step: step }.merge(checkout_params) }
|
|
|
|
context "details step" do
|
|
let(:step) { "details" }
|
|
|
|
context "with incomplete data" do
|
|
let(:checkout_params) { { order: { email: user.email } } }
|
|
|
|
it "returns 422 and some feedback" do
|
|
put :update, params: params
|
|
|
|
expect(response.status).to eq 422
|
|
expect(flash[:error]).to eq "Saving failed, please update the highlighted fields."
|
|
expect(order.reload.state).to eq "cart"
|
|
end
|
|
end
|
|
|
|
context "with complete data" do
|
|
let(:checkout_params) do
|
|
{
|
|
order: {
|
|
email: user.email,
|
|
bill_address_attributes: address.to_param,
|
|
ship_address_attributes: address.to_param
|
|
},
|
|
shipping_method_id: shipping_method.id
|
|
}
|
|
end
|
|
|
|
it "updates and redirects to payment step" do
|
|
put :update, params: params
|
|
|
|
expect(response).to redirect_to checkout_step_path(:payment)
|
|
expect(order.reload.state).to eq "payment"
|
|
end
|
|
|
|
describe "saving default addresses" do
|
|
it "doesn't update default bill address on user" do
|
|
expect {
|
|
put :update, params: params.merge(order: { save_bill_address: "0" })
|
|
}.to_not change {
|
|
order.user.reload.bill_address
|
|
}
|
|
end
|
|
|
|
it "updates default bill address on user and customer" do
|
|
put :update, params: params.merge(order: { save_bill_address: "1" })
|
|
|
|
expect(order.customer.bill_address).to eq(order.bill_address)
|
|
expect(order.user.bill_address).to eq(order.bill_address)
|
|
end
|
|
|
|
it "doesn't update default ship address on user" do
|
|
expect {
|
|
put :update, params: params.merge(order: { save_ship_address: "0" })
|
|
}.to_not change {
|
|
order.user.reload.ship_address
|
|
}
|
|
end
|
|
|
|
it "updates default ship address on user and customer" do
|
|
put :update, params: params.merge(order: { save_ship_address: "1" })
|
|
|
|
expect(order.customer.ship_address).to eq(order.ship_address)
|
|
expect(order.user.ship_address).to eq(order.ship_address)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "payment step" do
|
|
let(:step) { "payment" }
|
|
|
|
before do
|
|
order.bill_address = address
|
|
order.ship_address = address
|
|
order.select_shipping_method shipping_method.id
|
|
OrderWorkflow.new(order).advance_to_payment
|
|
end
|
|
|
|
context "with incomplete data" do
|
|
let(:checkout_params) { { order: { email: user.email } } }
|
|
|
|
it "returns 422 and some feedback" do
|
|
put :update, params: params
|
|
|
|
expect(response.status).to eq 422
|
|
expect(flash[:error]).to eq "Saving failed, please update the highlighted fields."
|
|
expect(order.reload.state).to eq "payment"
|
|
end
|
|
end
|
|
|
|
context "with complete data" do
|
|
let(:checkout_params) do
|
|
{
|
|
order: {
|
|
payments_attributes: [
|
|
{ payment_method_id: payment_method.id }
|
|
]
|
|
}
|
|
}
|
|
end
|
|
|
|
it "updates and redirects to payment step" do
|
|
put :update, params: params
|
|
|
|
expect(response).to redirect_to checkout_step_path(:summary)
|
|
expect(order.reload.state).to eq "confirmation"
|
|
end
|
|
end
|
|
|
|
context "with payment fees" do
|
|
let(:payment_method_with_fee) do
|
|
create(:payment_method, :flat_rate, amount: "1.23", distributors: [distributor])
|
|
end
|
|
let(:checkout_params) do
|
|
{
|
|
order: {
|
|
payments_attributes: [
|
|
{ payment_method_id: payment_method_with_fee.id }
|
|
]
|
|
}
|
|
}
|
|
end
|
|
|
|
it "applies the fee and updates the order total" do
|
|
put :update, params: params
|
|
|
|
expect(response).to redirect_to checkout_step_path(:summary)
|
|
|
|
order.reload
|
|
|
|
expect(order.state).to eq "confirmation"
|
|
expect(order.payments.first.adjustment.amount).to eq 1.23
|
|
expect(order.payments.first.amount).to eq order.item_total + order.adjustment_total
|
|
expect(order.adjustment_total).to eq 1.23
|
|
expect(order.total).to eq order.item_total + order.adjustment_total
|
|
end
|
|
end
|
|
|
|
context "with a saved credit card" do
|
|
let!(:saved_card) { create(:stored_credit_card, user: user) }
|
|
let(:checkout_params) do
|
|
{
|
|
order: {
|
|
payments_attributes: [
|
|
{ payment_method_id: payment_method.id }
|
|
]
|
|
},
|
|
existing_card_id: saved_card.id
|
|
}
|
|
end
|
|
|
|
it "updates and redirects to payment step" do
|
|
put :update, params: params
|
|
|
|
expect(response).to redirect_to checkout_step_path(:summary)
|
|
expect(order.reload.state).to eq "confirmation"
|
|
expect(order.payments.first.source.id).to eq saved_card.id
|
|
end
|
|
end
|
|
end
|
|
|
|
context "summary step" do
|
|
let(:step) { "summary" }
|
|
|
|
before do
|
|
order.bill_address = address
|
|
order.ship_address = address
|
|
order.select_shipping_method shipping_method.id
|
|
OrderWorkflow.new(order).advance_to_payment
|
|
|
|
order.payments << build(:payment, amount: order.total, payment_method: payment_method)
|
|
order.next
|
|
end
|
|
|
|
describe "confirming the order" do
|
|
it "completes the order and redirects to order confirmation" do
|
|
put :update, params: params
|
|
|
|
expect(response).to redirect_to order_path(order, order_token: order.token)
|
|
expect(order.reload.state).to eq "complete"
|
|
end
|
|
end
|
|
|
|
context "when accepting T&Cs is required" do
|
|
before do
|
|
allow(TermsOfService).to receive(:platform_terms_required?) { true }
|
|
end
|
|
|
|
describe "submitting without accepting the T&Cs" do
|
|
let(:checkout_params) { {} }
|
|
|
|
it "returns 422 and some feedback" do
|
|
put :update, params: params
|
|
|
|
expect(response.status).to eq 422
|
|
expect(flash[:error]).to eq "Saving failed, please update the highlighted fields."
|
|
expect(order.reload.state).to eq "confirmation"
|
|
end
|
|
end
|
|
|
|
describe "submitting and accepting the T&Cs" do
|
|
let(:checkout_params) { { accept_terms: true } }
|
|
|
|
it "completes the order and redirects to order confirmation" do
|
|
put :update, params: params
|
|
|
|
expect(response).to redirect_to order_path(order, order_token: order.token)
|
|
expect(order.reload.state).to eq "complete"
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when an external payment gateway is used" do
|
|
before do
|
|
expect(Checkout::PaymentMethodFetcher).
|
|
to receive_message_chain(:new, :call) { payment_method }
|
|
expect(payment_method).to receive(:external_gateway?) { true }
|
|
expect(payment_method).to receive(:external_payment_url) { "https://example.com/pay" }
|
|
end
|
|
|
|
describe "confirming the order" do
|
|
it "redirects to the payment gateway's URL" do
|
|
put :update, params: params
|
|
|
|
expect(response.body).to match("https://example.com/pay").and match("redirect")
|
|
expect(order.reload.state).to eq "confirmation"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "running out of stock" do
|
|
let(:order_cycle_distributed_variants) { double(:order_cycle_distributed_variants) }
|
|
|
|
before do
|
|
allow(controller).to receive(:current_order).and_return(order)
|
|
allow(order).to receive(:distributor).and_return(distributor)
|
|
order.update(order_cycle: order_cycle)
|
|
|
|
allow(OrderCycleDistributedVariants).to receive(:new).and_return(
|
|
order_cycle_distributed_variants
|
|
)
|
|
end
|
|
|
|
shared_examples "handling stock issues" do |step|
|
|
context "#{step} step" do
|
|
let(:step) { step.to_s }
|
|
|
|
it "redirects when some items are out of stock" do
|
|
allow(order).to receive_message_chain(:insufficient_stock_lines, :empty?).and_return false
|
|
|
|
get :edit
|
|
expect(response).to redirect_to cart_path
|
|
end
|
|
|
|
it "redirects when some items are not available" do
|
|
allow(order).to receive_message_chain(:insufficient_stock_lines, :empty?).and_return true
|
|
expect(order_cycle_distributed_variants).to receive(
|
|
:distributes_order_variants?
|
|
).with(order).and_return(false)
|
|
|
|
get :edit
|
|
expect(response).to redirect_to cart_path
|
|
end
|
|
end
|
|
end
|
|
|
|
it_behaves_like "handling stock issues", "details"
|
|
it_behaves_like "handling stock issues", "payment"
|
|
it_behaves_like "handling stock issues", "summary"
|
|
end
|
|
end
|