solidus_braintree 1.4.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +12 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github_changelog_generator +2 -0
  5. data/.gitignore +20 -11
  6. data/.rspec +1 -1
  7. data/.rubocop.yml +79 -0
  8. data/CHANGELOG.md +178 -18
  9. data/Gemfile +31 -23
  10. data/LICENSE +26 -0
  11. data/README.md +387 -26
  12. data/Rakefile +4 -19
  13. data/app/assets/config/solidus_braintree_manifest.js +1 -0
  14. data/app/assets/images/solidus_braintree/venmo/venmo_active_blue_button_280x48.svg +19 -0
  15. data/app/assets/images/solidus_braintree/venmo/venmo_active_blue_button_320x48.svg +19 -0
  16. data/app/assets/images/solidus_braintree/venmo/venmo_active_blue_button_375x48.svg +19 -0
  17. data/app/assets/images/solidus_braintree/venmo/venmo_active_white_button_280x48.svg +19 -0
  18. data/app/assets/images/solidus_braintree/venmo/venmo_active_white_button_320x48.svg +19 -0
  19. data/app/assets/images/solidus_braintree/venmo/venmo_active_white_button_375x48.svg +19 -0
  20. data/app/assets/images/solidus_braintree/venmo/venmo_blue_acceptance_mark.svg +15 -0
  21. data/app/assets/images/solidus_braintree/venmo/venmo_blue_button_280x48.svg +19 -0
  22. data/app/assets/images/solidus_braintree/venmo/venmo_blue_button_320x48.svg +19 -0
  23. data/app/assets/images/solidus_braintree/venmo/venmo_blue_button_375x48.svg +19 -0
  24. data/app/assets/images/solidus_braintree/venmo/venmo_blue_logo.svg +18 -0
  25. data/app/assets/images/solidus_braintree/venmo/venmo_white_acceptance_mark.svg +20 -0
  26. data/app/assets/images/solidus_braintree/venmo/venmo_white_button_280x48.svg +19 -0
  27. data/app/assets/images/solidus_braintree/venmo/venmo_white_button_320x48.svg +19 -0
  28. data/app/assets/images/solidus_braintree/venmo/venmo_white_button_375x48.svg +19 -0
  29. data/app/assets/images/solidus_braintree/venmo/venmo_white_logo.svg +18 -0
  30. data/app/assets/javascripts/solidus_braintree/apple_pay_button.js +179 -0
  31. data/app/assets/javascripts/solidus_braintree/checkout.js +108 -0
  32. data/app/assets/javascripts/solidus_braintree/client.js +239 -0
  33. data/app/assets/javascripts/solidus_braintree/constants.js +89 -0
  34. data/app/assets/javascripts/solidus_braintree/frontend.js +14 -0
  35. data/app/assets/javascripts/solidus_braintree/hosted_form.js +46 -0
  36. data/app/assets/javascripts/solidus_braintree/paypal_button.js +178 -0
  37. data/app/assets/javascripts/solidus_braintree/paypal_messaging.js +22 -0
  38. data/app/assets/javascripts/solidus_braintree/promise.js +20 -0
  39. data/app/assets/javascripts/solidus_braintree/venmo_button.js +86 -0
  40. data/app/assets/javascripts/spree/backend/solidus_braintree.js +96 -0
  41. data/app/assets/javascripts/spree/frontend/paypal_button.js +34 -0
  42. data/app/assets/javascripts/spree/frontend/solidus_braintree.js +1 -0
  43. data/app/assets/stylesheets/spree/backend/solidus_braintree.scss +28 -0
  44. data/app/assets/stylesheets/spree/frontend/solidus_braintree.scss +51 -0
  45. data/app/decorators/controllers/solidus_braintree/admin_payments_controller_decorator.rb +11 -0
  46. data/app/decorators/controllers/solidus_braintree/checkout_controller_decorator.rb +11 -0
  47. data/app/decorators/controllers/solidus_braintree/client_tokens_controller.rb +41 -0
  48. data/app/decorators/controllers/solidus_braintree/orders_controller_decorator.rb +11 -0
  49. data/app/decorators/models/solidus_braintree/spree/store_decorator.rb +20 -0
  50. data/app/decorators/models/solidus_braintree/spree/user_decorator.rb +13 -0
  51. data/app/helpers/solidus_braintree/braintree_admin_helper.rb +23 -0
  52. data/app/helpers/solidus_braintree/braintree_checkout_helper.rb +60 -0
  53. data/app/models/application_record.rb +5 -0
  54. data/app/models/solidus_braintree/address.rb +64 -0
  55. data/app/models/solidus_braintree/avs_result.rb +69 -0
  56. data/app/models/solidus_braintree/configuration.rb +39 -0
  57. data/app/models/solidus_braintree/customer.rb +8 -0
  58. data/app/models/solidus_braintree/gateway.rb +433 -0
  59. data/app/models/solidus_braintree/response.rb +80 -0
  60. data/app/models/solidus_braintree/source.rb +135 -0
  61. data/app/models/solidus_braintree/transaction.rb +31 -0
  62. data/app/models/solidus_braintree/transaction_address.rb +88 -0
  63. data/app/models/solidus_braintree/transaction_import.rb +98 -0
  64. data/app/overrides/spree/payments/payment/add_paypal_funding_source_to_payment.rb +9 -0
  65. data/app/views/spree/api/payments/source_views/_braintree.json.jbuilder +1 -1
  66. data/app/views/spree/checkout/existing_payment/_braintree.html.erb +10 -0
  67. data/app/views/spree/shared/_apple_pay_button.html.erb +27 -0
  68. data/app/views/spree/shared/_braintree_errors.html.erb +16 -0
  69. data/app/views/spree/shared/_braintree_head_scripts.html.erb +26 -0
  70. data/app/views/spree/shared/_braintree_hosted_fields.html.erb +43 -0
  71. data/app/views/spree/shared/_paypal_cart_button.html.erb +38 -0
  72. data/app/views/spree/shared/_paypal_messaging.html.erb +13 -0
  73. data/app/views/spree/shared/_venmo_button.html.erb +33 -0
  74. data/bin/console +4 -1
  75. data/bin/rails +5 -5
  76. data/bin/rails-engine +13 -0
  77. data/bin/rails-sandbox +16 -0
  78. data/bin/rake +7 -0
  79. data/bin/sandbox +103 -0
  80. data/bin/setup +5 -4
  81. data/config/locales/en.yml +94 -2
  82. data/config/locales/it.yml +56 -0
  83. data/config/routes.rb +12 -3
  84. data/db/migrate/20160830061749_create_solidus_paypal_braintree_sources.rb +16 -0
  85. data/db/migrate/20160906201711_create_solidus_paypal_braintree_customers.rb +13 -0
  86. data/db/migrate/20161114231422_create_solidus_paypal_braintree_configurations.rb +11 -0
  87. data/db/migrate/20161125172005_add_braintree_configuration_to_stores.rb +7 -0
  88. data/db/migrate/20170203191030_add_credit_card_to_braintree_configuration.rb +6 -0
  89. data/db/migrate/20170505193712_add_null_constraint_to_sources.rb +38 -0
  90. data/db/migrate/20170508085402_add_not_null_constraint_to_sources_payment_type.rb +14 -0
  91. data/db/migrate/20190705115327_add_paypal_button_preferences_to_braintree_configurations.rb +5 -0
  92. data/db/migrate/20190911141712_add_3d_secure_to_braintree_configuration.rb +5 -0
  93. data/db/migrate/20211222170950_add_paypal_funding_source_to_solidus_paypal_braintree_sources.rb +5 -0
  94. data/db/migrate/20220104150301_add_venmo_to_braintree_configuration.rb +5 -0
  95. data/db/migrate/20230109080950_rename_solidus_paypal_braintree_source_type.rb +31 -0
  96. data/lib/controllers/backend/solidus_braintree/configurations_controller.rb +48 -0
  97. data/lib/controllers/frontend/solidus_braintree/checkouts_controller.rb +31 -0
  98. data/lib/controllers/frontend/solidus_braintree/transactions_controller.rb +67 -0
  99. data/lib/generators/solidus_braintree/install/install_generator.rb +54 -18
  100. data/lib/generators/solidus_braintree/install/templates/initializer.rb +6 -0
  101. data/lib/solidus_braintree/country_mapper.rb +37 -0
  102. data/lib/solidus_braintree/engine.rb +55 -10
  103. data/lib/solidus_braintree/extension_configuration.rb +23 -0
  104. data/lib/solidus_braintree/request_protection.rb +21 -0
  105. data/lib/solidus_braintree/testing_support/factories.rb +53 -0
  106. data/lib/solidus_braintree/version.rb +3 -1
  107. data/lib/solidus_braintree.rb +14 -2
  108. data/lib/solidus_paypal_braintree.rb +6 -0
  109. data/lib/views/backend/solidus_braintree/configurations/list.html.erb +63 -0
  110. data/lib/views/backend/spree/admin/payments/source_forms/_braintree.html.erb +16 -0
  111. data/lib/views/backend/spree/admin/payments/source_views/_braintree.html.erb +39 -0
  112. data/lib/views/backend/spree/admin/shared/preference_fields/_preference_select.html.erb +13 -0
  113. data/lib/views/backend_v1.2/spree/admin/payments/source_forms/_braintree.html.erb +16 -0
  114. data/lib/views/backend_v2.4/spree/admin/shared/preference_fields/_hash.html.erb +12 -0
  115. data/lib/views/frontend/solidus_braintree/payments/_payment.html.erb +12 -0
  116. data/lib/views/frontend/spree/checkout/payment/_braintree.html.erb +23 -0
  117. data/lib/views/frontend/spree/shared/_paypal_checkout_button.html.erb +32 -0
  118. data/solidus_braintree.gemspec +39 -38
  119. data/spec/controllers/solidus_braintree/checkouts_controller_spec.rb +99 -0
  120. data/spec/controllers/solidus_braintree/client_tokens_controller_spec.rb +55 -0
  121. data/spec/controllers/solidus_braintree/configurations_controller_spec.rb +73 -0
  122. data/spec/controllers/solidus_braintree/transactions_controller_spec.rb +183 -0
  123. data/spec/features/backend/configuration_spec.rb +23 -0
  124. data/spec/features/backend/new_payment_spec.rb +137 -0
  125. data/spec/features/frontend/braintree_credit_card_checkout_spec.rb +191 -0
  126. data/spec/features/frontend/paypal_checkout_spec.rb +166 -0
  127. data/spec/features/frontend/venmo_checkout_spec.rb +194 -0
  128. data/spec/fixtures/cassettes/admin/invalid_credit_card.yml +63 -0
  129. data/spec/fixtures/cassettes/admin/resubmit_credit_card.yml +352 -0
  130. data/spec/fixtures/cassettes/admin/valid_credit_card.yml +412 -0
  131. data/spec/fixtures/cassettes/braintree/create_profile.yml +71 -0
  132. data/spec/fixtures/cassettes/braintree/generate_token.yml +63 -0
  133. data/spec/fixtures/cassettes/braintree/token.yml +63 -0
  134. data/spec/fixtures/cassettes/checkout/invalid_credit_card.yml +63 -0
  135. data/spec/fixtures/cassettes/checkout/resubmit_credit_card.yml +216 -0
  136. data/spec/fixtures/cassettes/checkout/update.yml +71 -0
  137. data/spec/fixtures/cassettes/checkout/valid_credit_card.yml +171 -0
  138. data/spec/fixtures/cassettes/checkout/valid_venmo_transaction.yml +599 -0
  139. data/spec/fixtures/cassettes/gateway/authorize/credit_card/address.yml +86 -0
  140. data/spec/fixtures/cassettes/gateway/authorize/merchant_account/EUR.yml +154 -0
  141. data/spec/fixtures/cassettes/gateway/authorize/paypal/EUR.yml +90 -0
  142. data/spec/fixtures/cassettes/gateway/authorize/paypal/address.yml +90 -0
  143. data/spec/fixtures/cassettes/gateway/authorize.yml +86 -0
  144. data/spec/fixtures/cassettes/gateway/authorized_transaction.yml +73 -0
  145. data/spec/fixtures/cassettes/gateway/cancel/missing.yml +63 -0
  146. data/spec/fixtures/cassettes/gateway/cancel/refunds.yml +272 -0
  147. data/spec/fixtures/cassettes/gateway/cancel/void.yml +201 -0
  148. data/spec/fixtures/cassettes/gateway/capture.yml +141 -0
  149. data/spec/fixtures/cassettes/gateway/complete.yml +157 -0
  150. data/spec/fixtures/cassettes/gateway/credit.yml +208 -0
  151. data/spec/fixtures/cassettes/gateway/customer.yml +79 -0
  152. data/spec/fixtures/cassettes/gateway/purchase.yml +87 -0
  153. data/spec/fixtures/cassettes/gateway/settled_transaction.yml +140 -0
  154. data/spec/fixtures/cassettes/gateway/void.yml +137 -0
  155. data/spec/fixtures/cassettes/source/bin.yml +295 -0
  156. data/spec/fixtures/cassettes/source/card_type.yml +267 -0
  157. data/spec/fixtures/cassettes/source/last4.yml +267 -0
  158. data/spec/fixtures/cassettes/transaction/import/valid/capture.yml +224 -0
  159. data/spec/fixtures/cassettes/transaction/import/valid.yml +71 -0
  160. data/spec/fixtures/views/spree/orders/edit.html.erb +50 -0
  161. data/spec/helpers/solidus_braintree/braintree_admin_helper_spec.rb +17 -0
  162. data/spec/helpers/solidus_braintree/braintree_checkout_helper_spec.rb +70 -0
  163. data/spec/models/solidus_braintree/address_spec.rb +71 -0
  164. data/spec/models/solidus_braintree/avs_result_spec.rb +317 -0
  165. data/spec/models/solidus_braintree/gateway_spec.rb +742 -0
  166. data/spec/models/solidus_braintree/response_spec.rb +280 -0
  167. data/spec/models/solidus_braintree/source_spec.rb +539 -0
  168. data/spec/models/solidus_braintree/transaction_address_spec.rb +235 -0
  169. data/spec/models/solidus_braintree/transaction_import_spec.rb +302 -0
  170. data/spec/models/solidus_braintree/transaction_spec.rb +86 -0
  171. data/spec/models/spree/store_spec.rb +14 -0
  172. data/spec/requests/spree/api/orders_controller_spec.rb +36 -0
  173. data/spec/spec_helper.rb +32 -0
  174. data/spec/support/capybara.rb +7 -0
  175. data/spec/support/gateway_helpers.rb +29 -0
  176. data/spec/support/order_ready_for_payment.rb +37 -0
  177. data/spec/support/vcr.rb +42 -0
  178. data/spec/support/views.rb +1 -0
  179. metadata +276 -224
  180. data/LICENSE.txt +0 -21
  181. data/app/controllers/spree/api/braintree_client_token_controller.rb +0 -13
  182. data/app/decorators/lib/solidus_braintree/spree/permitted_attributes_decorator.rb +0 -9
  183. data/app/decorators/models/solidus_braintree/spree/credit_card_decorator.rb +0 -11
  184. data/app/decorators/models/solidus_braintree/spree/payment_decorator.rb +0 -10
  185. data/app/helpers/braintree_view_helpers.rb +0 -20
  186. data/app/models/concerns/solidus_braintree/add_name_validation_concern.rb +0 -8
  187. data/app/models/concerns/solidus_braintree/inject_device_data_concern.rb +0 -18
  188. data/app/models/concerns/solidus_braintree/payment_braintree_nonce_concern.rb +0 -8
  189. data/app/models/concerns/solidus_braintree/permitted_attributes_concern.rb +0 -11
  190. data/app/models/concerns/solidus_braintree/skip_require_card_numbers_concern.rb +0 -14
  191. data/app/models/concerns/solidus_braintree/use_data_field_concern.rb +0 -23
  192. data/app/models/solidus/gateway/braintree_gateway.rb +0 -306
  193. data/app/overrides/spree/checkout/_confirm/braintree_security.html.erb.deface +0 -9
  194. data/app/views/spree/admin/payments/source_forms/_braintree.html.erb +0 -38
  195. data/app/views/spree/admin/payments/source_views/_braintree.html.erb +0 -30
  196. data/app/views/spree/checkout/payment/_braintree.html.erb +0 -55
  197. data/app/views/spree/checkout/payment/_braintree_initialization.html.erb +0 -12
  198. data/config/initializers/braintree.rb +0 -3
  199. data/db/migrate/20150910170527_add_data_to_credit_card.rb +0 -5
  200. data/db/migrate/20160426221931_add_braintree_device_data_to_order.rb +0 -5
  201. data/lib/assets/javascripts/spree/backend/braintree/solidus_braintree.js +0 -59
  202. data/lib/assets/javascripts/spree/frontend/braintree/solidus_braintree.js +0 -144
  203. data/lib/assets/javascripts/vendor/braintree.js +0 -8
  204. data/lib/assets/stylesheets/spree/frontend/solidus_braintree.scss +0 -26
@@ -0,0 +1,166 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Checkout", type: :feature, js: true do
4
+ Capybara.default_max_wait_time = 60
5
+
6
+ # let!(:store) do
7
+ # create(:store, payment_methods: [payment_method]).tap do |s|
8
+ # s.braintree_configuration.update!(braintree_preferences)
9
+ # end
10
+ # end
11
+ let(:braintree_preferences) { { paypal: true }.merge(paypal_options) }
12
+ let(:paypal_options) { {} }
13
+
14
+ let!(:country) { create(:country, states_required: true) }
15
+ # let!(:state) { create(:state, country: country, abbr: "CA", name: "California") }
16
+ # let!(:shipping_method) { create(:shipping_method) }
17
+ # let!(:stock_location) { create(:stock_location) }
18
+ let!(:mug) { create(:product, name: "RoR Mug") }
19
+ let!(:payment_method) { create_gateway }
20
+ # let!(:zone) { create(:zone) }
21
+
22
+ before do
23
+ create(:store, payment_methods: [payment_method]).tap do |s|
24
+ s.braintree_configuration.update!(braintree_preferences)
25
+ end
26
+ create(:state, country: country, abbr: "CA", name: "California")
27
+ create(:shipping_method)
28
+ create(:stock_location)
29
+ create(:zone)
30
+ end
31
+
32
+ context "when going through express checkout using paypal cart button" do
33
+ before do
34
+ payment_method
35
+ add_mug_to_cart
36
+ end
37
+
38
+ it "checks out successfully", skip: "Broken. To be revisited" do
39
+ pend_if_paypal_slow do
40
+ expect_any_instance_of(Spree::Order).to receive(:restart_checkout_flow)
41
+ move_through_paypal_popup
42
+ expect(page).to have_content("Shipments")
43
+ click_on "Place Order"
44
+ expect(page).to have_content("Your order has been processed successfully")
45
+ end
46
+ end
47
+
48
+ context 'when using custom paypal button style' do
49
+ let(:paypal_options) { { preferred_paypal_button_color: 'blue' } }
50
+
51
+ it 'displays required PayPal button style' do
52
+ within_frame find('#paypal-button iframe') do
53
+ expect(page).to have_selector('.paypal-button-color-blue')
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ context "when going through regular checkout using paypal payment method" do
60
+ before do
61
+ payment_method
62
+ add_mug_to_cart
63
+ click_button("Checkout")
64
+ fill_in("order_email", with: "paypal_buyer@paypaltest.com")
65
+ click_button("Continue")
66
+ fill_in_address
67
+ click_button("Save and Continue")
68
+ click_button("Save and Continue")
69
+ end
70
+
71
+ it "formats the address variable correctly" do
72
+ expect(page.evaluate_script("address['recipientName']")).to eq "Ryan Bigg"
73
+ end
74
+
75
+ it "checks out successfully", skip: "Broken. To be revisited" do
76
+ pend_if_paypal_slow do
77
+ expect_any_instance_of(Spree::Order).not_to receive(:restart_checkout_flow)
78
+ move_through_paypal_popup
79
+
80
+ expect(page).to have_content("Shipments")
81
+ click_on "Place Order"
82
+ expect(page).to have_content("Your order has been processed successfully")
83
+ end
84
+ end
85
+ end
86
+
87
+ # Selenium does not clear cookies properly between test runs, even when
88
+ # using Capybara.reset_sessions!, see:
89
+ # https://github.com/jnicklas/capybara/issues/535
90
+ #
91
+ # This causes Paypal to remain logged in and not prompt for an email on the
92
+ # second test run and causes the test to fail. Adding conditional logic for
93
+ # this greatly increases the test time, so it is left out since CI runs
94
+ # these with poltergeist.
95
+ def move_through_paypal_popup
96
+ expect(page).to have_css('#paypal-button .paypal-button')
97
+
98
+ sleep 2 # the PayPal button is not immediately ready
99
+
100
+ popup = page.window_opened_by do
101
+ within_frame find('#paypal-button iframe') do
102
+ find('div.paypal-button').click
103
+ end
104
+ end
105
+ page.switch_to_window(popup)
106
+
107
+ # We don't control this popup window.
108
+ # So javascript errors are not our errors.
109
+ begin
110
+ expect(page).not_to have_selector('body.loading')
111
+ fill_in("login_email", with: "stembolt_buyer@stembolttest.com")
112
+ click_on "Next"
113
+ fill_in("login_password", with: "test1234")
114
+
115
+ expect(page).not_to have_selector('body.loading')
116
+ click_button("btnLogin")
117
+
118
+ expect(page).not_to have_selector('body.loading')
119
+ click_button("Continue")
120
+ click_button("Agree & Continue")
121
+ rescue Selenium::WebDriver::Error::JavascriptError => e
122
+ pending "PayPal had javascript errors in their popup window."
123
+ raise e
124
+ rescue Capybara::ElementNotFound => e
125
+ pending "PayPal delivered unkown HTML in their popup window."
126
+ raise e
127
+ rescue Selenium::WebDriver::Error::NoSuchWindowError => e
128
+ pending "PayPal popup not available."
129
+ raise e
130
+ end
131
+
132
+ page.switch_to_window(page.windows.first)
133
+ end
134
+
135
+ def fill_in_address
136
+ address = "order_bill_address_attributes"
137
+ if page.has_css?("##{address}_firstname", wait: 0)
138
+ fill_in "#{address}_firstname", with: "Ryan"
139
+ fill_in "#{address}_lastname", with: "Bigg"
140
+ else
141
+ fill_in "#{address}_name", with: "Ryan Bigg"
142
+ end
143
+ fill_in "#{address}_address1", with: "143 Swan Street"
144
+ fill_in "#{address}_city", with: "San Jose"
145
+ select "United States of America", from: "#{address}_country_id"
146
+ select "California", from: "#{address}_state_id"
147
+ fill_in "#{address}_zipcode", with: "95131"
148
+ fill_in "#{address}_phone", with: "(555) 555-0111"
149
+ end
150
+
151
+ def add_mug_to_cart
152
+ visit spree.root_path
153
+ click_link mug.name
154
+ click_button "add-to-cart-button"
155
+ end
156
+
157
+ def pend_if_paypal_slow
158
+ yield
159
+ rescue RSpec::Expectations::ExpectationNotMetError => e
160
+ pending "PayPal did not answer in #{Capybara.default_max_wait_time} seconds."
161
+ raise e
162
+ rescue Selenium::WebDriver::Error::JavascriptError => e
163
+ pending "PayPal delivered wrong payload because of errors in their popup window."
164
+ raise e
165
+ end
166
+ end
@@ -0,0 +1,194 @@
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
+ # TODO: Reenable these specs once Venmo is enabled on the Braintree sandbox.
74
+ xcontext 'with Venmo transactions', vcr: { cassette_name: 'checkout/valid_venmo_transaction' } do
75
+ before do
76
+ fake_venmo_successful_tokenization
77
+ end
78
+
79
+ context 'with CreditCard disabled' do
80
+ it 'can checkout with Venmo' do
81
+ next_checkout_step
82
+ finalize_checkout
83
+
84
+ expect(Spree::Order.last.complete?).to be(true)
85
+ end
86
+ end
87
+
88
+ # To test that the hosted-fields inputs do not conflict with Venmo's
89
+ context 'with CreditCard enabled' do
90
+ let(:preferences) { { credit_card: true } }
91
+
92
+ it 'can checkout with Venmo' do
93
+ disable_hosted_fields_inputs
94
+ disable_hosted_fields_form_listener
95
+
96
+ next_checkout_step
97
+ finalize_checkout
98
+
99
+ expect(Spree::Order.last.complete?).to be(true)
100
+ expect(Spree::Payment.last.source.venmo?).to be(true)
101
+ end
102
+ end
103
+
104
+ # https://developer.paypal.com/braintree/docs/guides/venmo/client-side#custom-integration
105
+ it "meet's Braintree's acceptance criteria during checkout", aggregate_failures: true do
106
+ next_checkout_step
107
+
108
+ expect(page).to have_content('Payment Type: Venmo')
109
+
110
+ finalize_checkout
111
+
112
+ expect(page).to have_content('Venmo Account: venmojoe')
113
+ end
114
+
115
+ # the VCR must be based on this test, so it includes HTTP requests of the second order
116
+ it 'saves the used Venmo source in the wallet and can be reused' do
117
+ next_checkout_step
118
+ finalize_checkout
119
+ go_to_payment_checkout_page(order_number: 'R300000002')
120
+
121
+ expect(Spree::User.first.wallet.wallet_payment_sources).not_to be_empty
122
+ expect(page).to have_selector('#existing_cards')
123
+ expect(page).to have_content('venmojoe')
124
+
125
+ next_checkout_step
126
+ finalize_checkout
127
+
128
+ expect(Spree::Order.all.all?(&:complete?)).to be(true)
129
+ end
130
+ end
131
+ end
132
+
133
+ private
134
+
135
+ def go_to_payment_checkout_page(order_number: 'R300000001' )
136
+ order = if Spree.solidus_gem_version >= Gem::Version.new('2.6.0')
137
+ Spree::TestingSupport::OrderWalkthrough.up_to(:address)
138
+ else
139
+ OrderWalkthrough.up_to(:address)
140
+ end
141
+
142
+ order.update!(user: user, number: order_number) # constant order number for VCRs
143
+
144
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order)
145
+
146
+ first_user = Spree::User.first
147
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: first_user)
148
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(spree_current_user: first_user)
149
+
150
+ allow_any_instance_of(Spree::Payment).to receive(:gateway_order_id).and_return(order_number)
151
+
152
+ visit spree.checkout_state_path(order.state)
153
+ next_checkout_step
154
+ end
155
+
156
+ def next_checkout_step
157
+ click_button('Save and Continue')
158
+ end
159
+
160
+ def finalize_checkout
161
+ click_button('Place Order')
162
+ end
163
+
164
+ def venmo_button
165
+ find_button('venmo-button', disabled: false)
166
+ end
167
+
168
+ def venmo_frame
169
+ find('#venmo-desktop-iframe')
170
+ end
171
+
172
+ def fake_venmo_successful_tokenization
173
+ enable_venmo_inputs
174
+ fake_payment_method_nonce
175
+ end
176
+
177
+ def enable_venmo_inputs
178
+ page.execute_script("$('.venmo-fields input').each(function(_index, input){input.removeAttribute('disabled');});")
179
+ end
180
+
181
+ def fake_payment_method_nonce
182
+ page.execute_script("$('#venmo_payment_method_nonce').val('fake-venmo-account-nonce');")
183
+ end
184
+
185
+ def disable_hosted_fields_inputs
186
+ page.execute_script("$('.hosted-fields input').each(function(_index, input){input.disabled=true;});")
187
+ end
188
+
189
+ def disable_hosted_fields_form_listener
190
+ # Once the submit button is enabled, the submit listener has been added
191
+ find("#checkout_form_payment input[type='submit']:not(:disabled)")
192
+ page.execute_script("$('#checkout_form_payment').off('submit');")
193
+ end
194
+ end
@@ -0,0 +1,63 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://api.sandbox.braintreegateway.com/merchants/7rdg92j7bm7fk5h3/client_token
6
+ body:
7
+ encoding: UTF-8
8
+ string: |
9
+ <?xml version="1.0" encoding="UTF-8"?>
10
+ <client-token>
11
+ <version type="integer">2</version>
12
+ </client-token>
13
+ headers:
14
+ Accept-Encoding:
15
+ - gzip
16
+ Accept:
17
+ - application/xml
18
+ User-Agent:
19
+ - Braintree Ruby Gem 2.98.0
20
+ X-Apiversion:
21
+ - '5'
22
+ Content-Type:
23
+ - application/xml
24
+ Authorization:
25
+ - Basic bXdqa2t4d2NwMzJja2huZjphOTI5OGY0M2IzMGM2OTlkYjMwNzJjYzRhMDBmN2Y0OQ==
26
+ response:
27
+ status:
28
+ code: 201
29
+ message: Created
30
+ headers:
31
+ Server:
32
+ - nginx
33
+ Date:
34
+ - Fri, 13 Sep 2019 14:27:11 GMT
35
+ Content-Type:
36
+ - application/xml; charset=utf-8
37
+ Transfer-Encoding:
38
+ - chunked
39
+ X-Authentication:
40
+ - server_to_server
41
+ Braintree-Service-Origin:
42
+ - clientauth
43
+ Vary:
44
+ - Accept-Encoding
45
+ Content-Encoding:
46
+ - gzip
47
+ Etag:
48
+ - W/"c95fd3caa086065297edd0aeeb8e6d55"
49
+ Cache-Control:
50
+ - max-age=0, private, must-revalidate
51
+ X-Request-Id:
52
+ - 51cbbac6-bce1-4f90-ab14-6d61a064e77b
53
+ X-Runtime:
54
+ - '0.200715'
55
+ Strict-Transport-Security:
56
+ - max-age=31536000; includeSubDomains
57
+ body:
58
+ encoding: ASCII-8BIT
59
+ string: !binary |-
60
+ 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
61
+ http_version:
62
+ recorded_at: Fri, 13 Sep 2019 14:27:11 GMT
63
+ recorded_with: VCR 5.0.0