solidus_paypal_braintree 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +9 -1
- data/Gemfile +1 -3
- data/README.md +96 -5
- data/app/assets/config/solidus_paypal_braintree_manifest.js +1 -0
- data/app/assets/images/solidus_paypal_braintree/venmo/venmo_active_blue_button_280x48.svg +19 -0
- data/app/assets/images/solidus_paypal_braintree/venmo/venmo_active_blue_button_320x48.svg +19 -0
- data/app/assets/images/solidus_paypal_braintree/venmo/venmo_active_blue_button_375x48.svg +19 -0
- data/app/assets/images/solidus_paypal_braintree/venmo/venmo_active_white_button_280x48.svg +19 -0
- data/app/assets/images/solidus_paypal_braintree/venmo/venmo_active_white_button_320x48.svg +19 -0
- data/app/assets/images/solidus_paypal_braintree/venmo/venmo_active_white_button_375x48.svg +19 -0
- data/app/assets/images/solidus_paypal_braintree/venmo/venmo_blue_acceptance_mark.svg +15 -0
- data/app/assets/images/solidus_paypal_braintree/venmo/venmo_blue_button_280x48.svg +19 -0
- data/app/assets/images/solidus_paypal_braintree/venmo/venmo_blue_button_320x48.svg +19 -0
- data/app/assets/images/solidus_paypal_braintree/venmo/venmo_blue_button_375x48.svg +19 -0
- data/app/assets/images/solidus_paypal_braintree/venmo/venmo_blue_logo.svg +18 -0
- data/app/assets/images/solidus_paypal_braintree/venmo/venmo_white_acceptance_mark.svg +20 -0
- data/app/assets/images/solidus_paypal_braintree/venmo/venmo_white_button_280x48.svg +19 -0
- data/app/assets/images/solidus_paypal_braintree/venmo/venmo_white_button_320x48.svg +19 -0
- data/app/assets/images/solidus_paypal_braintree/venmo/venmo_white_button_375x48.svg +19 -0
- data/app/assets/images/solidus_paypal_braintree/venmo/venmo_white_logo.svg +18 -0
- data/app/assets/javascripts/solidus_paypal_braintree/client.js +34 -0
- data/app/assets/javascripts/solidus_paypal_braintree/constants.js +8 -0
- data/app/assets/javascripts/solidus_paypal_braintree/frontend.js +1 -0
- data/app/assets/javascripts/solidus_paypal_braintree/paypal_button.js +26 -3
- data/app/assets/javascripts/solidus_paypal_braintree/venmo_button.js +86 -0
- data/app/assets/javascripts/spree/backend/solidus_paypal_braintree.js +2 -2
- data/app/assets/javascripts/spree/frontend/paypal_button.js +3 -3
- data/app/assets/stylesheets/spree/frontend/solidus_paypal_braintree.css +12 -0
- data/app/decorators/controllers/solidus_paypal_braintree/checkout_controller_decorator.rb +1 -1
- data/app/decorators/controllers/solidus_paypal_braintree/orders_controller_decorator.rb +1 -1
- data/app/helpers/solidus_paypal_braintree/braintree_checkout_helper.rb +19 -5
- data/app/models/solidus_paypal_braintree/address.rb +43 -9
- data/app/models/solidus_paypal_braintree/avs_result.rb +3 -0
- data/app/models/solidus_paypal_braintree/configuration.rb +15 -2
- data/app/models/solidus_paypal_braintree/gateway.rb +27 -2
- data/app/models/solidus_paypal_braintree/source.rb +31 -2
- data/app/models/solidus_paypal_braintree/transaction.rb +1 -1
- data/app/models/solidus_paypal_braintree/transaction_address.rb +17 -13
- data/app/models/solidus_paypal_braintree/transaction_import.rb +2 -1
- data/app/overrides/spree/payments/payment/add_paypal_funding_source_to_payment.rb +9 -0
- data/app/views/spree/shared/_braintree_errors.html.erb +3 -0
- data/app/views/spree/shared/_paypal_braintree_head_scripts.html.erb +10 -6
- data/app/views/spree/shared/_paypal_cart_button.html.erb +2 -0
- data/app/views/spree/shared/_venmo_button.html.erb +33 -0
- data/config/locales/en.yml +34 -0
- data/config/locales/it.yml +2 -0
- data/db/migrate/20211222170950_add_paypal_funding_source_to_solidus_paypal_braintree_sources.rb +5 -0
- data/db/migrate/20220104150301_add_venmo_to_braintree_configuration.rb +5 -0
- data/lib/controllers/backend/solidus_paypal_braintree/configurations_controller.rb +4 -1
- data/lib/controllers/frontend/solidus_paypal_braintree/transactions_controller.rb +1 -0
- data/lib/solidus_paypal_braintree/engine.rb +4 -2
- data/lib/solidus_paypal_braintree/factories.rb +32 -1
- data/lib/solidus_paypal_braintree/version.rb +1 -1
- data/lib/views/backend/solidus_paypal_braintree/configurations/list.html.erb +8 -0
- data/lib/views/backend/spree/admin/payments/source_views/_paypal_braintree.html.erb +5 -0
- data/lib/views/backend/spree/admin/shared/preference_fields/_preference_select.html.erb +13 -0
- data/lib/views/frontend/solidus_paypal_braintree/payments/_payment.html.erb +12 -0
- data/lib/views/frontend/spree/checkout/payment/_paypal_braintree.html.erb +4 -0
- data/lib/views/frontend/spree/shared/_paypal_checkout_button.html.erb +2 -0
- data/solidus_paypal_braintree.gemspec +6 -5
- data/spec/controllers/solidus_paypal_braintree/transactions_controller_spec.rb +1 -1
- data/spec/features/frontend/braintree_credit_card_checkout_spec.rb +5 -1
- data/spec/features/frontend/venmo_checkout_spec.rb +189 -0
- data/spec/fixtures/cassettes/checkout/valid_venmo_transaction.yml +599 -0
- data/spec/helpers/solidus_paypal_braintree/braintree_checkout_helper_spec.rb +70 -0
- data/spec/models/solidus_paypal_braintree/address_spec.rb +20 -0
- data/spec/models/solidus_paypal_braintree/gateway_spec.rb +1 -1
- data/spec/models/solidus_paypal_braintree/source_spec.rb +139 -0
- data/spec/models/solidus_paypal_braintree/transaction_address_spec.rb +8 -26
- data/spec/models/solidus_paypal_braintree/transaction_import_spec.rb +17 -0
- data/spec/spec_helper.rb +3 -0
- metadata +52 -15
@@ -0,0 +1,189 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'spree/testing_support/order_walkthrough'
|
5
|
+
|
6
|
+
describe "Checkout", type: :feature, js: true do
|
7
|
+
let(:braintree_preferences) { { venmo: true }.merge(preferences) }
|
8
|
+
let(:preferences) { {} }
|
9
|
+
let(:user) { create(:user) }
|
10
|
+
let!(:payment_method) { create_gateway }
|
11
|
+
|
12
|
+
before do
|
13
|
+
create(:store, payment_methods: [payment_method]).tap do |s|
|
14
|
+
s.braintree_configuration.update!(braintree_preferences)
|
15
|
+
end
|
16
|
+
|
17
|
+
go_to_payment_checkout_page
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with Venmo checkout' do
|
21
|
+
context 'when Venmo is disabled' do
|
22
|
+
let(:preferences) { { venmo: false } }
|
23
|
+
|
24
|
+
it 'does not load the Venmo payment button' do
|
25
|
+
expect(page).not_to have_selector('#venmo-button')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when Venmo is enabled' do
|
30
|
+
it 'loads the Venmo payment button' do
|
31
|
+
expect(page).to have_selector('#venmo-button')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when Venmo's button style is customized" do
|
36
|
+
context 'when venmo_button_color is "blue" and venmo_button_width is "280"' do
|
37
|
+
let(:preferences) { { preferred_venmo_button_color: 'blue', preferred_venmo_button_width: '280' } }
|
38
|
+
|
39
|
+
it 'has the correct style' do
|
40
|
+
venmo_button.assert_matches_style(width: '280px', 'background-image': /venmo_blue_button_280x48/)
|
41
|
+
venmo_button.hover
|
42
|
+
venmo_button.assert_matches_style('background-image': /venmo_active_blue_button_280x48/)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when venmo_button_color is "white" and venmo_button_width is "375"' do
|
47
|
+
let(:preferences) { { preferred_venmo_button_color: 'white', preferred_venmo_button_width: '375' } }
|
48
|
+
|
49
|
+
it 'has the correct style' do
|
50
|
+
venmo_button.assert_matches_style(width: '375px', 'background-image': /venmo_white_button_375x48/)
|
51
|
+
venmo_button.hover
|
52
|
+
venmo_button.assert_matches_style('background-image': /venmo_active_white_button_375x48/)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when the Venmo button is clicked' do
|
58
|
+
before { venmo_button.click }
|
59
|
+
|
60
|
+
it 'opens the QR modal which shows an error when closed' do
|
61
|
+
within_frame(venmo_frame) do
|
62
|
+
expect(page).to have_selector('#venmo-qr-code-view')
|
63
|
+
|
64
|
+
click_button('close-icon')
|
65
|
+
|
66
|
+
expect(page).not_to have_selector('#venmo-qr-code-view')
|
67
|
+
end
|
68
|
+
|
69
|
+
expect(page).to have_content('Venmo authorization was canceled by closing the Venmo Desktop modal.')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'with Venmo transactions', vcr: { cassette_name: 'checkout/valid_venmo_transaction' } do
|
74
|
+
before do
|
75
|
+
fake_venmo_successful_tokenization
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'with CreditCard disabled' do
|
79
|
+
it 'can checkout with Venmo' do
|
80
|
+
next_checkout_step
|
81
|
+
finalize_checkout
|
82
|
+
|
83
|
+
expect(Spree::Order.last.complete?).to eq(true)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# To test that the hosted-fields inputs do not conflict with Venmo's
|
88
|
+
context 'with CreditCard enabled' do
|
89
|
+
let(:preferences) { { credit_card: true } }
|
90
|
+
|
91
|
+
it 'can checkout with Venmo' do
|
92
|
+
disable_hosted_fields_inputs
|
93
|
+
disable_hosted_fields_form_listener
|
94
|
+
|
95
|
+
next_checkout_step
|
96
|
+
finalize_checkout
|
97
|
+
|
98
|
+
expect(Spree::Order.last.complete?).to eq(true)
|
99
|
+
expect(Spree::Payment.last.source.venmo?).to eq(true)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# https://developer.paypal.com/braintree/docs/guides/venmo/client-side#custom-integration
|
104
|
+
it "meet's Braintree's acceptance criteria during checkout", aggregate_failures: true do
|
105
|
+
next_checkout_step
|
106
|
+
|
107
|
+
expect(page).to have_content('Payment Type: Venmo')
|
108
|
+
|
109
|
+
finalize_checkout
|
110
|
+
|
111
|
+
expect(page).to have_content('Venmo Account: venmojoe')
|
112
|
+
end
|
113
|
+
|
114
|
+
# the VCR must be based on this test, so it includes HTTP requests of the second order
|
115
|
+
it 'saves the used Venmo source in the wallet and can be reused' do
|
116
|
+
next_checkout_step
|
117
|
+
finalize_checkout
|
118
|
+
go_to_payment_checkout_page(order_number: 'R300000002')
|
119
|
+
|
120
|
+
expect(Spree::User.first.wallet.wallet_payment_sources).not_to be_empty
|
121
|
+
expect(page).to have_selector('#existing_cards')
|
122
|
+
expect(page).to have_content('venmojoe')
|
123
|
+
|
124
|
+
next_checkout_step
|
125
|
+
finalize_checkout
|
126
|
+
|
127
|
+
expect(Spree::Order.all.all?(&:complete?)).to eq(true)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def go_to_payment_checkout_page(order_number: 'R300000001' )
|
135
|
+
order = if Spree.solidus_gem_version >= Gem::Version.new('2.6.0')
|
136
|
+
Spree::TestingSupport::OrderWalkthrough.up_to(:address)
|
137
|
+
else
|
138
|
+
OrderWalkthrough.up_to(:address)
|
139
|
+
end
|
140
|
+
|
141
|
+
order.update!(user: user, number: order_number) # constant order number for VCRs
|
142
|
+
|
143
|
+
allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order)
|
144
|
+
allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: Spree::User.first)
|
145
|
+
allow_any_instance_of(Spree::Payment).to receive(:gateway_order_id).and_return(order_number)
|
146
|
+
|
147
|
+
visit spree.checkout_state_path(order.state)
|
148
|
+
next_checkout_step
|
149
|
+
end
|
150
|
+
|
151
|
+
def next_checkout_step
|
152
|
+
click_button('Save and Continue')
|
153
|
+
end
|
154
|
+
|
155
|
+
def finalize_checkout
|
156
|
+
click_button('Place Order')
|
157
|
+
end
|
158
|
+
|
159
|
+
def venmo_button
|
160
|
+
find_button('venmo-button', disabled: false)
|
161
|
+
end
|
162
|
+
|
163
|
+
def venmo_frame
|
164
|
+
find('#venmo-desktop-iframe')
|
165
|
+
end
|
166
|
+
|
167
|
+
def fake_venmo_successful_tokenization
|
168
|
+
enable_venmo_inputs
|
169
|
+
fake_payment_method_nonce
|
170
|
+
end
|
171
|
+
|
172
|
+
def enable_venmo_inputs
|
173
|
+
page.execute_script("$('.venmo-fields input').each(function(_index, input){input.removeAttribute('disabled');});")
|
174
|
+
end
|
175
|
+
|
176
|
+
def fake_payment_method_nonce
|
177
|
+
page.execute_script("$('#venmo_payment_method_nonce').val('fake-venmo-account-nonce');")
|
178
|
+
end
|
179
|
+
|
180
|
+
def disable_hosted_fields_inputs
|
181
|
+
page.execute_script("$('.hosted-fields input').each(function(_index, input){input.disabled=true;});")
|
182
|
+
end
|
183
|
+
|
184
|
+
def disable_hosted_fields_form_listener
|
185
|
+
# Once the submit button is enabled, the submit listener has been added
|
186
|
+
find("#checkout_form_payment input[type='submit']:not(:disabled)")
|
187
|
+
page.execute_script("$('#checkout_form_payment').off('submit');")
|
188
|
+
end
|
189
|
+
end
|