Files
openfoodnetwork/spec/models/spree/gateway/stripe_sca_spec.rb
2025-05-21 09:41:00 +02:00

202 lines
6.0 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Spree::Gateway::StripeSCA, :vcr, :stripe_version do
let(:order) { create(:order_ready_for_payment) }
let(:year_valid) { Time.zone.now.year.next }
let(:credit_card) { create(:credit_card, gateway_payment_profile_id: pm_card.id) }
let(:payment) {
create(
:payment,
order:,
amount: order.total,
payment_method: subject,
source: credit_card,
response_code: payment_intent.id
)
}
let(:gateway_options) {
{ order_id: order.number }
}
# Stripe testing card:
# https://stripe.com/docs/testing?testing-method=payment-methods
let(:pm_card) { Stripe::PaymentMethod.retrieve('pm_card_mastercard') }
let(:payment_intent) do
Stripe::PaymentIntent.create({
amount: 1000, # given in AUD cents
currency: 'aud', # AUD to match order currency
payment_method: pm_card,
payment_method_types: ['card'],
capture_method: 'manual',
})
end
let(:connected_account) do
Stripe::Account.create({
type: 'standard',
country: 'AU',
email: 'carrot.producer@example.com'
})
end
after do
Stripe::Account.delete(connected_account.id)
end
describe "#purchase" do
# Stripe acepts amounts as positive integers representing how much to charge
# in the smallest currency unit
let(:capture_amount) { order.total.to_i * 100 } # order total is 10 AUD
before do
# confirms the payment
Stripe::PaymentIntent.confirm(payment_intent.id)
end
it "completes the purchase" do
payment
response = subject.purchase(capture_amount, credit_card, gateway_options)
expect(response.success?).to eq true
end
it "provides an error message to help developer debug" do
response_error = subject.purchase(capture_amount, credit_card, gateway_options)
expect(response_error.success?).to eq false
expect(response_error.message).to eq "No pending payments"
end
end
describe "#void" do
let(:stripe_test_account) { connected_account.id }
before do
# Inject our test stripe account
stripe_account = create(:stripe_account, stripe_user_id: stripe_test_account)
allow(StripeAccount).to receive(:find_by).and_return(stripe_account)
create(
:payment,
order:,
amount: order.total,
payment_method: subject,
source: credit_card,
response_code: payment_intent.id
)
end
context "with a confirmed payment" do
# Link the payment intent to our test stripe account, and automatically confirm and capture
# the payment.
let(:payment_intent) do
Stripe::PaymentIntent.create(
{
amount: 1000, # given in AUD cents
currency: 'aud', # AUD to match order currency
payment_method: 'pm_card_mastercard',
payment_method_types: ['card'],
capture_method: 'automatic',
confirm: true,
},
stripe_account: stripe_test_account
)
end
it "refunds the payment" do
response = subject.void(payment_intent.id, nil, {})
expect(response.success?).to eq true
end
end
context "with a voidable payment" do
# Link the payment intent to our test stripe account
let(:payment_intent) do
Stripe::PaymentIntent.create(
{
amount: 1000, # given in AUD cents
currency: 'aud', # AUD to match order currency
payment_method: 'pm_card_mastercard',
payment_method_types: ['card'],
capture_method: 'manual'
},
stripe_account: stripe_test_account
)
end
it "void the payment" do
response = subject.void(payment_intent.id, nil, {})
expect(response.success?).to eq true
end
end
end
describe "#credit" do
let(:stripe_test_account) { connected_account.id }
before do
# Inject our test stripe account
stripe_account = create(:stripe_account, stripe_user_id: stripe_test_account)
allow(StripeAccount).to receive(:find_by).and_return(stripe_account)
end
it "refunds the payment" do
# Link the payment intent to our test stripe account, and automatically confirm and capture
# the payment.
payment_intent = Stripe::PaymentIntent.create(
{
amount: 1000, # given in AUD cents
currency: 'aud', # AUD to match order currency
payment_method: 'pm_card_mastercard',
payment_method_types: ['card'],
capture_method: 'automatic',
confirm: true,
},
stripe_account: stripe_test_account
)
response = subject.credit(1000, nil, payment_intent.id, {})
expect(response.success?).to eq true
end
end
describe "#error message" do
context "when payment intent state is not in 'requires_capture' state" do
before do
payment
end
it "does not succeed if payment intent state is not requires_capture" do
response = subject.purchase(order.total, credit_card, gateway_options)
expect(response.success?).to eq false
expect(response.message).to eq "Invalid payment state: requires_confirmation"
end
end
end
describe "#external_payment_url" do
let(:redirect_double) { instance_double(Checkout::StripeRedirect) }
it "returns nil when an order is not supplied" do
expect(subject.external_payment_url({})).to eq nil
end
it "calls Checkout::StripeRedirect" do
expect(Checkout::StripeRedirect).to receive(:new).with(subject, order) { redirect_double }
expect(redirect_double).to receive(:path).and_return("http://stripe-test.org")
expect(subject.external_payment_url(order:)).to eq "http://stripe-test.org"
end
end
end