Files
openfoodnetwork/spec/system/admin/payment_method_spec.rb
Gaetan Craig-Riou bc23423521 Remove the link between enterprise and internal payment method
Enterprise have access to the internal payment method by default.
The access is handled at the application level so we don't have to
manage database links.
2026-03-10 16:07:43 +11:00

550 lines
22 KiB
Ruby

# frozen_string_literal: true
require "system_helper"
RSpec.describe '
As a Super Admin
I want to be able to set a distributor on each payment method
' do
include WebHelper
include AuthenticationHelper
before do
@distributors = (1..3).map { create(:distributor_enterprise) }
end
describe "creating a payment method" do
it "assigning a distributor to the payment method" do
login_as_admin
visit spree.edit_admin_general_settings_path
click_link 'Payment Methods'
click_link 'New Payment Method'
expect(page).to have_select2 "payment_method_type", selected: "Choose..."
fill_in 'payment_method_name', with: 'Cheque payment method'
cash_name = "Cash/EFT/etc. (payments for which automatic validation is not required)"
select2_select cash_name, from: "payment_method_type"
check "payment_method_distributor_ids_#{@distributors[0].id}"
click_button 'Create'
expect(flash_message).to eq('Payment Method has been successfully created!')
payment_method = Spree::PaymentMethod.find_by(name: 'Cheque payment method')
expect(payment_method.distributors).to eq([@distributors[0]])
end
context "using stripe connect" do
let(:user) { create(:user, enterprise_limit: 5) }
let!(:connected_enterprise) {
create(:distributor_enterprise, name: "Connected", owner: user)
}
let!(:revoked_account_enterprise) {
create(:distributor_enterprise, name: "Revoked", owner: user)
}
let!(:missing_account_enterprise) {
create(:distributor_enterprise, name: "Missing", owner: user)
}
let!(:valid_stripe_account) {
create(:stripe_account, enterprise: connected_enterprise,
stripe_user_id: "acc_connected123")
}
let!(:disconnected_stripe_account) {
create(:stripe_account, enterprise: revoked_account_enterprise,
stripe_user_id: "acc_revoked123")
}
let!(:stripe_account_mock) {
{ id: "acc_connected123", business_name: "My Org", charges_enabled: true }
}
before do
allow(Spree::Config).to receive(:stripe_connect_enabled).and_return(true)
Stripe.api_key = "sk_test_12345"
stub_request(:get,
"https://api.stripe.com/v1/accounts/acc_connected123")
.to_return(body: JSON.generate(stripe_account_mock))
stub_request(:get,
"https://api.stripe.com/v1/accounts/acc_revoked123").to_return(status: 404)
end
it "communicates the status of the stripe connection to the user" do
login_as user
visit spree.new_admin_payment_method_path
select2_select "Stripe", from: "payment_method_type"
select2_select "Missing", from: "payment_method_preferred_enterprise_id"
expect(page).to have_selector "#stripe-account-status .alert-box.error",
text: 'No Stripe account exists for this enterprise.'
click_link 'Connect One' # opens in new tab
new_window = windows.last
page.within_window new_window do
expect(page).to have_content "Settings: Missing"
# we should be on the Payment Methods tab already
expect(page).to have_content "Use the button to the right to get started."
page.find("a", text: "Connect with Stripe").click # it's not a proper link without href
expect(page).to have_content "connect your Stripe account to the OFN."
href = connect_admin_stripe_accounts_path(enterprise_id: missing_account_enterprise)
expect(page).to have_link "I Agree", href:
# Blocked by capybara. probably don't need to test this.
# click_link "I Agree"
# expect(page).to have_current_path("https://connect.stripe.com/", url: true)
end
new_window.close
select2_select "Revoked", from: "payment_method_preferred_enterprise_id"
expect(page).to have_selector "#stripe-account-status .alert-box.error",
text: 'Access to this Stripe account has been revoked, ' \
'please reconnect your account.'
select2_select "Connected", from: "payment_method_preferred_enterprise_id"
expect(page).to have_selector "#stripe-account-status .status", text: "Status: Connected"
expect(page).to have_selector "#stripe-account-status .account_id",
text: "Account ID: acc_connected123"
expect(page).to have_selector "#stripe-account-status .business_name",
text: "Business Name: My Org"
expect(page).to have_selector "#stripe-account-status .charges_enabled",
text: "Charges Enabled: Yes"
end
end
it "checking a single distributor is checked by default" do
2.times.each do
enterprise = Enterprise.last
enterprise.destroy!
end
login_as_admin
visit spree.new_admin_payment_method_path
expect(page).to have_field "payment_method_distributor_ids_#{@distributors[0].id}",
checked: true
end
it "checking more than a distributor displays no default choice" do
login_as_admin
visit spree.new_admin_payment_method_path
expect(page).to have_field "payment_method_distributor_ids_#{@distributors[0].id}",
checked: false
expect(page).to have_field "payment_method_distributor_ids_#{@distributors[1].id}",
checked: false
expect(page).to have_field "payment_method_distributor_ids_#{@distributors[2].id}",
checked: false
end
it "retains and displays data that was just submitted" do
login_as_admin
visit spree.edit_admin_general_settings_path
click_link 'Payment Methods'
click_link 'New Payment Method'
fill_in "payment_method_name", with: 'Cheque payment method'
fill_in "payment_method_description", with: "Payment description"
select2_select "PayPal Express", from: "payment_method_type"
select2_select "Flat Percent", from: 'calc_type'
click_button 'Create'
expect(page).to have_field "payment_method_name", with: "Cheque payment method"
expect(page).to have_field "payment_method_description", with: "Payment description"
expect(page).to have_select("payment_method_type", selected: "PayPal Express")
expect(page).to have_select("calc_type", selected: "Flat Percent")
select2_select "Price Sack", from: 'calc_type'
click_button 'Create'
expect(page).to have_select("calc_type", selected: "Price Sack")
expect(page).to have_field "payment_method_name", with: "Cheque payment method"
expect(page).to have_field "payment_method_description", with: "Payment description"
expect(page).to have_select("payment_method_type", selected: "PayPal Express")
check "payment_method_distributor_ids_#{@distributors[0].id}"
click_button 'Create'
expect(page).to have_field "payment_method_distributor_ids_#{@distributors[0].id}",
checked: true
expect(page).to have_select("calc_type", selected: "Price Sack")
expect(page).to have_field "payment_method_name", with: "Cheque payment method"
expect(page).to have_field "payment_method_description", with: "Payment description"
expect(page).to have_select("payment_method_type", selected: "PayPal Express")
end
end
it "updating a payment method" do
payment_method = create(:payment_method, distributors: [@distributors[0]],
calculator: build(:calculator_flat_rate))
login_as_admin
visit spree.edit_admin_payment_method_path payment_method
fill_in 'payment_method_name', with: 'New PM Name'
find(:css, "tags-input .tags input").set "member\n"
uncheck "payment_method_distributor_ids_#{@distributors[0].id}"
check "payment_method_distributor_ids_#{@distributors[1].id}"
check "payment_method_distributor_ids_#{@distributors[2].id}"
select2_select "PayPal Express", from: "payment_method_type"
expect(page).to have_field 'Login'
fill_in 'payment_method_preferred_login', with: 'testlogin'
fill_in 'payment_method_preferred_password', with: 'secret'
fill_in 'payment_method_preferred_signature', with: 'sig'
click_button 'Update'
expect(flash_message).to eq 'Payment Method has been successfully updated!'
expect(first('tags-input .tag-list ti-tag-item')).to have_content "member"
payment_method = Spree::PaymentMethod.find_by(name: 'New PM Name')
expect(payment_method.distributors).to include @distributors[1], @distributors[2]
expect(payment_method.distributors).not_to include @distributors[0]
expect(payment_method.type).to eq "Spree::Gateway::PayPalExpress"
expect(payment_method.preferences[:login]).to eq 'testlogin'
expect(payment_method.preferences[:password]).to eq 'secret'
expect(payment_method.preferences[:signature]).to eq 'sig'
fill_in 'payment_method_preferred_login', with: 'otherlogin'
click_button 'Update'
expect(flash_message).to eq 'Payment Method has been successfully updated!'
expect(page).to have_field 'Password', with: ''
expect(first('tags-input .tag-list ti-tag-item')).to have_content "member"
payment_method = Spree::PaymentMethod.find_by(name: 'New PM Name')
expect(payment_method.tag_list).to eq ["member"]
expect(payment_method.preferences[:login]).to eq 'otherlogin'
expect(payment_method.preferences[:password]).to eq 'secret'
expect(payment_method.preferences[:signature]).to eq 'sig'
end
context "as an enterprise user" do
let(:enterprise_user) { create(:user) }
let(:distributor1) { create(:distributor_enterprise, name: 'First Distributor') }
let(:distributor2) { create(:distributor_enterprise, name: 'Second Distributor') }
let(:distributor3) { create(:distributor_enterprise, name: 'Third Distributor') }
let(:payment_method1) { create(:payment_method, name: 'One', distributors: [distributor1]) }
let(:payment_method2) {
create(:payment_method, name: 'Two', distributors: [distributor1, distributor2])
}
let(:payment_method3) { create(:payment_method, name: 'Three', distributors: [distributor3]) }
before(:each) do
enterprise_user.enterprise_roles.build(enterprise: distributor1).save
enterprise_user.enterprise_roles.build(enterprise: distributor2).save
login_as enterprise_user
end
it "I can get to the new enterprise page" do
visit admin_enterprises_path
within("#e_#{distributor1.id}") { click_link 'Settings' }
within(".side_menu") do
click_link "Payment Methods"
end
click_link 'Create One Now'
expect(page).to have_current_path spree.new_admin_payment_method_path
end
it "creates payment methods" do
visit spree.new_admin_payment_method_path
fill_in 'payment_method_name', with: 'Cheque payment method'
cash_name = "Cash/EFT/etc. (payments for which automatic validation is not required)"
select2_select cash_name, from: "payment_method_type"
expect(page).to have_field 'payment_method_description'
expect(page).to have_select 'payment_method_display_on'
check "payment_method_distributor_ids_#{distributor1.id}"
find(:css, "tags-input .tags input").set "local\n"
click_button 'Create'
expect(flash_message).to eq('Payment Method has been successfully created!')
expect(first('tags-input .tag-list ti-tag-item')).to have_content "local"
payment_method = Spree::PaymentMethod.find_by(name: 'Cheque payment method')
expect(payment_method.distributors).to eq([distributor1])
expect(payment_method.tag_list).to eq(["local"])
end
it "shows me only payment methods I have access to" do
payment_method1
payment_method2
payment_method3
visit spree.admin_payment_methods_path
expect(page).to have_content payment_method1.name
expect(page).to have_content payment_method2.name
expect(page).not_to have_content payment_method3.name
end
it "does not show duplicates of payment methods" do
payment_method1
payment_method2
visit spree.admin_payment_methods_path
expect(page).to have_selector 'td', text: 'Two', count: 1
end
it "shows me only payment methods for the enterprise I select" do
payment_method1
payment_method2
visit admin_enterprises_path
within("#e_#{distributor1.id}") { click_link 'Settings' }
within(".side_menu") do
click_link "Payment Methods"
end
expect(page).to have_content payment_method1.name
expect(page).to have_content payment_method2.name
click_link 'Enterprises'
within("#e_#{distributor2.id}") { click_link 'Settings' }
within(".side_menu") do
click_link "Payment Methods"
end
expect(page).to have_content payment_method1.name
expect(page).to have_content payment_method2.name
expect(page).to have_checked_field "enterprise_payment_method_ids_#{payment_method2.id}"
expect(page).to have_unchecked_field "enterprise_payment_method_ids_#{payment_method1.id}"
end
end
describe "Setting transaction fees" do
let!(:payment_method) { create(:payment_method) }
before {
login_as_admin
visit spree.edit_admin_payment_method_path payment_method
}
it "set by default 'None' as calculator" do
expect(page).to have_select "calc_type", selected: "None"
end
it "handle the 'None' calculator" do
select2_select "None", from: 'calc_type'
click_button 'Update'
expect(page).to have_content("Payment Method has been successfully updated!")
expect(payment_method.reload.calculator_type).to eq "Calculator::None"
expect(page).to have_select "calc_type", selected: "None"
end
context "using Flat Percent calculator" do
before { select2_select "Flat Percent", from: 'calc_type' }
it "inserts values which persist" do
expect(page).to have_content("you must save first before")
click_button 'Update'
click_on "Dismiss"
fill_in "Flat Percent", with: '2.5'
click_button 'Update'
expect(page).to have_content("Payment Method has been successfully updated!")
expect(page).to have_field "Flat Percent", with: '2.5'
end
end
context "using Flat Rate (per order) calculator" do
before { select2_select "Flat Rate (per order)", from: 'calc_type' }
it "inserts values which persist" do
expect(page).to have_content("you must save first before")
click_button 'Update'
click_on "Dismiss"
fill_in "Amount", with: 2.2
click_button 'Update'
expect(page).to have_content("Payment Method has been successfully updated!")
expect(page).to have_field "Amount", with: 2.2
end
end
context "using Flexible Rate calculator" do
before { select2_select "Flexible Rate", from: 'calc_type' }
it "inserts values which persist" do
expect(page).to have_content("you must save first before")
click_button 'Update'
click_on "Dismiss"
fill_in "First Item Cost", with: 2
fill_in "Additional Item Cost", with: 1.1
fill_in "Max Items", with: 10
click_button 'Update'
expect(page).to have_content("Payment Method has been successfully updated!")
expect(page).to have_field "First Item Cost", with: '2.0'
expect(page).to have_field "Additional Item Cost", with: '1.1'
expect(page).to have_field "Max Items", with: '10'
end
end
context "using Flat Rate (per item) calculator" do
before { select2_select "Flat Rate (per item)", from: 'calc_type' }
it "inserts values which persist" do
expect(page).to have_content("you must save first before")
click_button 'Update'
click_on "Dismiss"
fill_in "Amount", with: 2.2
click_button 'Update'
expect(page).to have_content("Payment Method has been successfully updated!")
expect(page).to have_field "Amount", with: 2.2
end
end
context "using Price Sack calculator" do
before { select2_select "Price Sack", from: 'calc_type' }
it "inserts values which persist" do
expect(page).to have_content("you must save first before")
click_button 'Update'
fill_in "Minimal Amount", with: 10.2
fill_in "Normal Amount", with: 2.1
fill_in "Discount Amount", with: 1.1
click_button 'Update'
expect(page).to have_content("Payment Method has been successfully updated!")
expect(page).to have_field "Minimal Amount", with: '10.2'
expect(page).to have_field "Normal Amount", with: '2.1'
expect(page).to have_field "Discount Amount", with: '1.1'
end
end
end
context "when updating a payment method with invalid data" do
let(:payment_method) { create(:payment_method, :flat_rate, amount: 10) }
# Persist preferences to test that when preferred values are not found in the cache,
# they are fetched from the database and displayed correctly
before do
Spree::Preferences::Store.instance.persistence = true
login_as_admin
visit spree.edit_admin_payment_method_path payment_method
fill_in "payment_method_name", with: ""
fill_in "payment_method_description", with: "Edited description"
uncheck "payment_method_distributor_ids_#{@distributors[0].id}"
# Although text is not permitted by input[type=number], let's see what happens
fill_in "Amount", with: 'invalid'
click_button 'Update'
end
after do
Spree::Preferences::Store.instance.persistence = false
end
it "displays error details" do
expect(page).to have_content("2 errors")
expect(page).to have_content("Name can't be blank")
expect(page).to have_content("At least one hub must be selected")
# Highlighting invalid fields
within '.field_with_errors:has(#payment_method_name)' do
expect(page).to have_field "payment_method_name"
end
within '#hubs' do
expect(page).to have_selector(".red")
end
end
it "keeps information that was just edited, even after multiple unsuccessful updates" do
expect(page).to have_field "payment_method_name", with: ''
expect(page).to have_field "payment_method_description", with: "Edited description"
expect(page).to have_unchecked_field "payment_method_distributor_ids_#{@distributors[0].id}"
fill_in "payment_method_name", with: "Test name"
fill_in "Amount", with: 'invalid string'
click_button 'Update'
expect(page).to have_field "payment_method_name", with: 'Test name'
expect(page).to have_field "payment_method_description", with: "Edited description"
expect(page).to have_unchecked_field "payment_method_distributor_ids_#{@distributors[0].id}"
end
it 'displays data fetched from the database after navigating away from the page' do
click_link 'Back To Payment Methods List'
click_link href: /#{spree.edit_admin_payment_method_path(payment_method)}/
expect(page).to have_field 'Amount', with: '10.0'
expect(page).not_to have_field 'payment_method_name', with: ''
expect(page).not_to have_field 'payment_method_description', with: 'Edited description'
expect(page).to have_checked_field "payment_method_distributor_ids_#{@distributors[0].id}"
end
end
context 'when updating payment method with invalid data and changing calculator type' do
let(:payment_method) { create(:payment_method, :flat_rate, amount: 10) }
# Persist preferences to test that when preferred values are not found in the cache,
# they are fetched from the database and displayed correctly
before do
Spree::Preferences::Store.instance.persistence = true
login_as_admin
visit spree.edit_admin_payment_method_path payment_method
fill_in 'payment_method_name', with: ''
fill_in 'payment_method_description', with: 'Edited description'
uncheck "payment_method_distributor_ids_#{@distributors[0].id}"
select2_select 'Flat Percent', from: 'calc_type'
click_button 'Update'
end
after do
Spree::Preferences::Store.instance.persistence = false
end
it 'displays the number of errors' do
expect(page).to have_content('2 errors')
end
it 'displays error messages' do
expect(page).to have_content("Name can't be blank")
expect(page).to have_content('At least one hub must be selected')
end
it 'displays the new calculator fields' do
expect(page).to have_field 'Flat Percent'
end
it 'highlights invalid fields' do
within '.field_with_errors:has(#payment_method_name)' do
expect(page).to have_field 'payment_method_name'
end
within '#hubs' do
expect(page).to have_selector('.red')
end
end
it 'keeps information that was just edited, even after multiple unsuccessful updates' do
expect(page).to have_field 'payment_method_name', with: ''
expect(page).to have_field 'payment_method_description', with: 'Edited description'
expect(page).to have_unchecked_field "payment_method_distributor_ids_#{@distributors[0].id}"
fill_in 'payment_method_name', with: 'Test name'
fill_in 'Flat Percent', with: 'invalid string'
click_button 'Update'
expect(page).to have_field 'payment_method_name', with: 'Test name'
expect(page).to have_field 'payment_method_description', with: 'Edited description'
expect(page).to have_unchecked_field "payment_method_distributor_ids_#{@distributors[0].id}"
end
it 'displays data fetched from the database after navigating away from the page' do
click_link 'Back To Payment Methods List'
click_link href: /#{spree.edit_admin_payment_method_path(payment_method)}/
expect(page).to have_field 'Amount', with: '10.0'
expect(page).not_to have_field 'payment_method_name', with: ''
expect(page).not_to have_field 'payment_method_description', with: 'Edited description'
expect(page).to have_checked_field "payment_method_distributor_ids_#{@distributors[0].id}"
end
end
end