Merge pull request #13961 from mkllnk/taler-checkout-stock-error

Taler checkout stock error
This commit is contained in:
Maikel
2026-03-20 11:29:58 +11:00
committed by GitHub
19 changed files with 201 additions and 448 deletions

View File

@@ -10,17 +10,12 @@ RSpec.describe 'Multilingual' do
before do
login_as admin_user
visit spree.admin_dashboard_path
end
it 'has three locales available' do
expect(Rails.application.config.i18n[:default_locale]).to eq 'en'
expect(Rails.application.config.i18n[:locale]).to eq 'en'
expect(Rails.application.config.i18n[:available_locales]).to eq ['en', 'es', 'pt']
end
it 'can switch language by params' do
expect(pick_i18n_locale).to eq 'en'
visit spree.admin_dashboard_path
expect(pick_i18n_locale).to eq 'en_TST'
expect(get_i18n_translation('spree_admin_overview_enterprises_header')).to eq 'My Enterprises'
expect(page).to have_content 'My Enterprises'
expect(admin_user.locale).to be_nil
@@ -36,9 +31,9 @@ RSpec.describe 'Multilingual' do
it 'fallbacks to default_locale' do
visit spree.admin_dashboard_path(locale: 'it')
expect(pick_i18n_locale).to eq 'en'
expect(pick_i18n_locale).to eq 'en_TST'
expect(get_i18n_translation('spree_admin_overview_enterprises_header')).to eq 'My Enterprises'
expect(page).to have_content 'My Enterprises'
expect(admin_user.locale).to be_nil
expect(admin_user.reload.locale).to be_nil
end
end

View File

@@ -273,7 +273,7 @@ RSpec.describe "Authentication" do
expect_logged_in
expect(page).to have_content 'SHOP NOW'
expect(user.reload.locale).to eq "en"
expect(user.reload.locale).to eq "en_TST"
end
end

View File

@@ -49,7 +49,6 @@ RSpec.describe "As a consumer, I want to checkout my order" do
before do
login_as(user)
visit checkout_path
end
context "payment step" do
@@ -67,6 +66,7 @@ RSpec.describe "As a consumer, I want to checkout my order" do
context "with a transaction fee" do
before do
visit checkout_path
click_button "Next - Order summary"
end
@@ -84,6 +84,7 @@ RSpec.describe "As a consumer, I want to checkout my order" do
context "after completing the order" do
before do
visit checkout_path
click_on "Complete order"
end
it_behaves_like "displays the transaction fee", "order confirmation"
@@ -277,7 +278,7 @@ RSpec.describe "As a consumer, I want to checkout my order" do
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
context "checking out with #{pay_method}" do
before do
visit checkout_step_path(:payment)
end
@@ -291,46 +292,9 @@ RSpec.describe "As a consumer, I want to checkout my order" do
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
describe "payment method" do
let!(:cash) { create(:payment_method, distributors: [distributor], name: "Cash") }
context "Cash" do
@@ -365,7 +329,40 @@ RSpec.describe "As a consumer, I want to checkout my order" do
create(:stripe_sca_payment_method, distributors: [distributor], name: "Stripe SCA")
}
it_behaves_like "different payment methods", "Stripe SCA"
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 "Stripe SCA"
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 "Stripe SCA"
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
context "Taler" do

View File

@@ -5,189 +5,72 @@ require 'system_helper'
RSpec.describe 'Multilingual' do
include AuthenticationHelper
include WebHelper
include ShopWorkflow
include UIComponentHelper
include CookieHelper
let(:user) { create(:user) }
it 'has three locales available' do
expect(Rails.application.config.i18n[:default_locale]).to eq 'en'
expect(Rails.application.config.i18n[:locale]).to eq 'en'
expect(Rails.application.config.i18n[:available_locales]).to eq ['en', 'es', 'pt']
expect(Rails.application.config.i18n[:default_locale]).to eq 'en_TST'
expect(Rails.application.config.i18n[:locale]).to eq 'en_TST'
expect(Rails.application.config.i18n[:available_locales]).to eq ['en_TST', 'es', 'pt', 'en']
end
it '18n-js fallsback to default language' do
# in backend it doesn't until we change enforce_available_locales to `true`
it 'can switch language by params' do
visit root_path
set_i18n_locale('it')
expect(pick_i18n_locale).to eq 'en_TST'
expect(get_i18n_translation('label_shops')).to eq 'Shops'
expect(cookies_name).not_to include('locale')
expect(page).to have_content 'SHOPS'
visit root_path(locale: 'es')
expect(pick_i18n_locale).to eq 'es'
expect(get_i18n_translation('label_shops')).to eq 'Tiendas'
expect_menu_and_cookie_in_es
# it is not in the list of available of available_locales
visit root_path(locale: 'it')
expect(pick_i18n_locale).to eq 'es'
expect(get_i18n_translation('label_shops')).to eq 'Tiendas'
expect_menu_and_cookie_in_es
end
context 'can switch language by params' do
it 'in root path' do
visit root_path
expect(pick_i18n_locale).to eq 'en'
expect(get_i18n_translation('label_shops')).to eq 'Shops'
expect(cookies_name).not_to include('locale')
expect(page).to have_content 'SHOPS'
it 'updates user locale from cookie if it is empty' do
visit root_path(locale: 'es')
visit root_path(locale: 'es')
expect(pick_i18n_locale).to eq 'es'
expect(get_i18n_translation('label_shops')).to eq 'Tiendas'
expect_menu_and_cookie_in_es
expect_menu_and_cookie_in_es
expect(user.locale).to be_nil
login_as user
visit root_path
# it is not in the list of available of available_locales
visit root_path(locale: 'it')
expect(pick_i18n_locale).to eq 'es'
expect(get_i18n_translation('label_shops')).to eq 'Tiendas'
expect_menu_and_cookie_in_es
end
expect_menu_and_cookie_in_es
context 'with a product in the cart' do
let(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true) }
let!(:order_cycle) {
create(:simple_order_cycle, distributors: [distributor], variants: [product.variants.first])
}
let(:product) { create(:simple_product) }
let(:order) { create(:order, order_cycle:, distributor:) }
# The user's locale is not changed if the language was chosen before
# login. Is it a bug or a feature? Probably not important...
expect(user.reload.locale).to eq nil
before do
pick_order order
add_product_to_cart order, product, quantity: 1
end
visit root_path(locale: 'es')
expect(user.reload.locale).to eq 'es'
it "in the cart page" do
visit main_app.cart_path(locale: 'es')
logout
expect_menu_and_cookie_in_es
expect(page).to have_content 'Precio'
end
it "visiting checkout as a guest user" do
visit checkout_path(locale: 'es')
expect_menu_and_cookie_in_es
expect(page).to have_content 'Iniciar sesión'
end
end
expect_menu_and_cookie_in_es
expect(page).to have_content '¿Estás interesada en entrar en Open Food Network?'
end
context 'with user' do
let(:user) { create(:user) }
it "allows switching language via the main navigation" do
visit root_path
it 'updates user locale from cookie if it is empty' do
visit root_path(locale: 'es')
expect(page).to have_content 'SHOPS'
expect_menu_and_cookie_in_es
expect(user.locale).to be_nil
login_as user
visit root_path
find('.language-switcher').click
within '.language-switcher .dropdown' do
expect(page).not_to have_link 'English'
expect(page).to have_link 'Español'
expect_menu_and_cookie_in_es
click_link 'Español'
end
it 'updates user locale and stays in cookie after logout' do
login_as user
visit root_path(locale: 'es')
user.reload
expect(user.locale).to eq 'es'
logout
expect_menu_and_cookie_in_es
expect(page).to have_content '¿Estás interesada en entrar en Open Food Network?'
end
context "visiting checkout as logged user" do
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:)
}
let(:variant) { product.variants.first }
let!(:order_cycle) {
create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor],
coordinator: create(:distributor_enterprise),
variants: [variant])
}
let(:free_shipping) {
create(:shipping_method, require_ship_address: false)
}
let!(:payment) {
create(:payment_method, distributors: [distributor],
name: "Payment")
}
let(:order) {
create(:order_ready_for_confirmation, distributor:)
}
before do
pick_order order
login_as user
end
it "on the details step" do
visit checkout_step_path(:details, locale: 'es')
expect_menu_and_cookie_in_es
expect(page).to have_content "Sus detalles"
end
it "on the payment step" do
visit checkout_step_path(:payment, locale: 'es')
expect_menu_and_cookie_in_es
expect(page).to have_content "Puede revisar y confirmar su pedido"
end
it "on the summary step" do
visit checkout_step_path(:summary, locale: 'es')
expect_menu_and_cookie_in_es
expect(page).to have_content "Detalles de entrega"
end
end
end
describe "using the language switcher UI" do
context "when there is only one language available" do
before do
allow(ENV).to receive(:[]).and_call_original
allow(ENV).to receive(:[]).with("LOCALE").and_return("en")
allow(ENV).to receive(:[]).with("AVAILABLE_LOCALES").and_return("en")
end
it "hides the dropdown language menu" do
visit root_path
expect(page).not_to have_css 'ul.right li.language-switcher.has-dropdown'
end
end
context "when there are multiple languages available" do
before do
allow(ENV).to receive(:[]).and_call_original
allow(ENV).to receive(:[]).with("LOCALE").and_return("en")
allow(ENV).to receive(:[]).with("AVAILABLE_LOCALES").and_return("en,es")
end
it "allows switching language via the main navigation" do
visit root_path
expect(page).to have_content 'SHOPS'
find('.language-switcher').click
within '.language-switcher .dropdown' do
expect(page).not_to have_link 'English', href: '/locales/en'
expect(page).to have_link 'Español', href: '/locales/es'
find('li a[href="/locales/es"]').click
end
expect_menu_and_cookie_in_es
end
end
expect_menu_and_cookie_in_es
end
end

View File

@@ -3,221 +3,34 @@
require 'system_helper'
RSpec.describe "Check out with Stripe" do
include AuthenticationHelper
include ShopWorkflow
include CheckoutRequestsHelper
include StripeHelper
include StripeStubs
let(:distributor) { create(:distributor_enterprise) }
let!(:order_cycle) {
create(:simple_order_cycle, distributors: [distributor], variants: [variant])
}
let(:product) { create(:product, price: 10) }
let(:variant) { product.variants.first }
let(:order) {
create(:order, order_cycle:, distributor:, bill_address_id: nil,
ship_address_id: nil)
}
let(:shipping_with_fee) {
create(:shipping_method, require_ship_address: false, name: "Donkeys",
calculator: Calculator::FlatRate.new(preferred_amount: 4.56))
}
let(:free_shipping) { create(:shipping_method) }
let!(:check_with_fee) {
create(:payment_method, distributors: [distributor],
calculator: Calculator::FlatRate.new(preferred_amount: 5.67))
}
around do |example|
with_stripe_setup { example.run }
end
before do
stripe_enable
pick_order order
add_product_to_cart order, product
distributor.shipping_methods << [shipping_with_fee, free_shipping]
end
pending "using Stripe SCA" do
let!(:stripe_account) { create(:stripe_account, enterprise: distributor) }
let!(:stripe_sca_payment_method) {
create(:stripe_sca_payment_method, distributors: [distributor])
}
let!(:shipping_method) { create(:shipping_method) }
let(:error_message) { "Card was declined: insufficient funds." }
before do
stub_payment_intent_get_request
stub_payment_methods_post_request
end
describe "using Stripe SCA" do
context "with guest checkout" do
before do
stub_retrieve_payment_method_request("pm_123")
stub_list_customers_request(email: order.user.email, response: {})
stub_get_customer_payment_methods_request(customer: "cus_A456", response: {})
end
context "when the card is accepted" do
before do
stub_payment_intents_post_request(order:)
stub_successful_capture_request order:
end
it "completes checkout successfully" do
checkout_with_stripe
expect(page).to have_content "Confirmed"
expect(page.find("#amount-paid").text).to have_content "$19.99"
expect(order.reload.completed?).to eq true
expect(order.payments.first.state).to eq "completed"
end
it "completes checkout successfully"
end
context "when the card is rejected" do
before do
stub_payment_intents_post_request(order:)
stub_failed_capture_request order:, response: { message: error_message }
end
it "shows an error message from the Stripe response" do
checkout_with_stripe
expect(page).to have_content error_message
expect(order.reload.state).to eq "cart"
expect(order.payments.first.state).to eq "failed"
end
it "shows an error message from the Stripe response"
end
context "when the card needs extra SCA authorization" do
before do
stripe_redirect_url = checkout_path(payment_intent: "pi_123")
stub_payment_intents_post_request_with_redirect order:,
redirect_url: stripe_redirect_url
end
describe "and the authorization succeeds" do
before do
stub_successful_capture_request order:
end
it "completes checkout successfully" do
checkout_with_stripe
# We make stripe return stripe_redirect_url (which is already sending the user back
# to the checkout) as if the authorization was done. We can then control the actual
# authorization or failure of the payment through the mock
# stub_successful_capture_request
expect(page).to have_content "Confirmed"
expect(order.reload.completed?).to eq true
expect(order.payments.first.state).to eq "completed"
end
it "completes checkout successfully"
end
describe "and the authorization fails" do
before do
stub_failed_capture_request order:, response: { message: error_message }
end
it "shows an error message from the Stripe response" do
checkout_with_stripe
# We make stripe return stripe_redirect_url (which is already sending the user back to
# the checkout) as if the authorization was done. We can then control the actual
# authorization or failure of the payment through the mock stub_failed_capture_request
expect(page).to have_content error_message
expect(order.reload.state).to eq "cart"
expect(order.payments.first.state).to eq "failed"
end
it "shows an error message from the Stripe response"
end
end
context "with multiple payment attempts; one failed and one succeeded" do
before do
stub_payment_intents_post_request order:
end
it "records failed payment attempt and allows order completion" do
# First payment attempt is rejected
stub_failed_capture_request(order:, response: { message: error_message })
checkout_with_stripe
expect(page).to have_content error_message
expect(order.reload.payments.count).to eq 1
expect(order.state).to eq "cart"
expect(order.payments.first.state).to eq "failed"
# Second payment attempt is accepted
stub_successful_capture_request(order:)
place_order
expect(page).to have_content "Confirmed"
expect(order.reload.payments.count).to eq 2
expect(order.state).to eq "complete"
expect(order.payments.last.state).to eq "completed"
end
it "records failed payment attempt and allows order completion"
end
end
context "with a logged in user" do
let(:user) { order.user }
before do
login_as user
end
context "saving a card and re-using it" do
before do
stub_retrieve_payment_method_request("pm_123")
stub_list_customers_request(email: order.user.email, response: {})
stub_get_customer_payment_methods_request(customer: "cus_A456", response: {})
stub_get_customer_payment_methods_request(customer: "cus_A123", response: {})
stub_payment_methods_post_request(
request: { payment_method: "pm_123", customer: "cus_A123" },
response: { pm_id: "pm_123" }
)
stub_add_metadata_request(payment_method: "pm_123", response: {})
stub_payment_intents_post_request(order:)
stub_successful_capture_request(order:)
stub_customers_post_request email: "test@test.com" # First checkout with default details
stub_customers_post_request email: user.email # Second checkout with saved user details
stub_payment_method_attach_request
end
it "allows saving a card and re-using it" do
checkout_with_stripe guest_checkout: false, remember_card: true
expect(page).to have_content "Confirmed"
expect(order.reload.completed?).to eq true
expect(order.payments.first.state).to eq "completed"
# 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"
# Prepare a second order
new_order = create(:order, user:, order_cycle:,
distributor:, bill_address_id: nil,
ship_address_id: nil)
pick_order(new_order)
add_product_to_cart(new_order, product, quantity: 10)
stub_payment_intents_post_request order: new_order
stub_successful_capture_request order: new_order
# Checkout with saved card
visit checkout_path
choose free_shipping.name
choose stripe_sca_payment_method.name
expect(page).to have_content "Use a saved card"
expect(page).to have_select 'selected_card', selected: "Visa x-4242 Exp:10/2050"
place_order
end
it "allows saving a card and re-using it"
end
end
end