solidus_paypal_braintree 0.4.0 → 1.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 (135) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +40 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github/stale.yml +17 -0
  5. data/.gitignore +18 -0
  6. data/.rspec +2 -0
  7. data/.rubocop.yml +68 -0
  8. data/CHANGELOG.md +258 -0
  9. data/Gemfile +43 -0
  10. data/LICENSE +2 -2
  11. data/README.md +77 -23
  12. data/Rakefile +4 -25
  13. data/app/assets/javascripts/solidus_paypal_braintree/checkout.js +32 -3
  14. data/app/assets/javascripts/solidus_paypal_braintree/client.js +23 -4
  15. data/app/assets/javascripts/solidus_paypal_braintree/constants.js +19 -0
  16. data/app/assets/javascripts/solidus_paypal_braintree/frontend.js +1 -0
  17. data/app/assets/javascripts/solidus_paypal_braintree/hosted_form.js +15 -5
  18. data/app/assets/javascripts/solidus_paypal_braintree/paypal_button.js +47 -20
  19. data/app/assets/javascripts/solidus_paypal_braintree/paypal_messaging.js +22 -0
  20. data/app/decorators/controllers/solidus_paypal_braintree/admin_payments_controller_decorator.rb +11 -0
  21. data/app/decorators/controllers/solidus_paypal_braintree/checkout_controller_decorator.rb +11 -0
  22. data/app/decorators/controllers/solidus_paypal_braintree/client_tokens_controller.rb +41 -0
  23. data/app/decorators/controllers/solidus_paypal_braintree/orders_controller_decorator.rb +11 -0
  24. data/app/decorators/models/solidus_paypal_braintree/spree/store_decorator.rb +20 -0
  25. data/app/decorators/models/solidus_paypal_braintree/spree/user_decorator.rb +13 -0
  26. data/app/helpers/solidus_paypal_braintree/braintree_admin_helper.rb +23 -0
  27. data/app/helpers/solidus_paypal_braintree/braintree_checkout_helper.rb +46 -0
  28. data/app/models/application_record.rb +2 -0
  29. data/app/models/solidus_paypal_braintree/address.rb +30 -0
  30. data/app/models/solidus_paypal_braintree/configuration.rb +26 -3
  31. data/app/models/solidus_paypal_braintree/customer.rb +7 -3
  32. data/app/models/solidus_paypal_braintree/gateway.rb +52 -20
  33. data/app/models/solidus_paypal_braintree/response.rb +3 -2
  34. data/app/models/solidus_paypal_braintree/source.rb +21 -7
  35. data/app/models/solidus_paypal_braintree/transaction.rb +2 -0
  36. data/app/models/solidus_paypal_braintree/transaction_address.rb +30 -12
  37. data/app/models/solidus_paypal_braintree/transaction_import.rb +13 -9
  38. data/app/views/spree/api/payments/source_views/_paypal_braintree.json.jbuilder +3 -0
  39. data/app/views/spree/checkout/existing_payment/_paypal_braintree.html.erb +10 -0
  40. data/app/views/spree/shared/_apple_pay_button.html.erb +2 -2
  41. data/app/views/spree/shared/_braintree_errors.html.erb +11 -17
  42. data/app/views/spree/shared/_braintree_hosted_fields.html.erb +24 -9
  43. data/app/views/spree/shared/_paypal_braintree_head_scripts.html.erb +9 -6
  44. data/app/views/spree/shared/_paypal_cart_button.html.erb +16 -2
  45. data/app/views/spree/shared/_paypal_messaging.html.erb +13 -0
  46. data/bin/console +17 -0
  47. data/bin/rails +15 -0
  48. data/bin/setup +8 -0
  49. data/config/locales/en.yml +10 -0
  50. data/config/locales/it.yml +51 -8
  51. data/config/routes.rb +2 -0
  52. data/db/migrate/20160906201711_create_solidus_paypal_braintree_customers.rb +3 -1
  53. data/db/migrate/20161125172005_add_braintree_configuration_to_stores.rb +5 -7
  54. data/db/migrate/20170505193712_add_null_constraint_to_sources.rb +3 -1
  55. data/db/migrate/20190705115327_add_paypal_button_preferences_to_braintree_configurations.rb +5 -0
  56. data/db/migrate/20190911141712_add_3d_secure_to_braintree_configuration.rb +5 -0
  57. data/lib/controllers/backend/solidus_paypal_braintree/configurations_controller.rb +20 -5
  58. data/lib/controllers/frontend/solidus_paypal_braintree/checkouts_controller.rb +25 -21
  59. data/lib/controllers/frontend/solidus_paypal_braintree/transactions_controller.rb +55 -51
  60. data/lib/generators/solidus_paypal_braintree/install/install_generator.rb +7 -5
  61. data/lib/solidus_paypal_braintree.rb +4 -0
  62. data/lib/solidus_paypal_braintree/country_mapper.rb +4 -2
  63. data/lib/solidus_paypal_braintree/engine.rb +11 -11
  64. data/lib/solidus_paypal_braintree/factories.rb +8 -4
  65. data/lib/solidus_paypal_braintree/request_protection.rb +3 -0
  66. data/lib/solidus_paypal_braintree/version.rb +3 -1
  67. data/lib/views/backend/solidus_paypal_braintree/configurations/list.html.erb +30 -5
  68. data/lib/views/backend/spree/admin/payments/source_forms/_paypal_braintree.html.erb +2 -2
  69. data/lib/views/backend/spree/admin/payments/source_views/_paypal_braintree.html.erb +2 -2
  70. data/lib/views/backend_v1.2/spree/admin/payments/source_forms/_paypal_braintree.html.erb +2 -2
  71. data/lib/views/frontend/spree/checkout/payment/_paypal_braintree.html.erb +4 -2
  72. data/lib/views/frontend/spree/shared/_paypal_checkout_button.html.erb +30 -0
  73. data/solidus_paypal_braintree.gemspec +42 -0
  74. data/spec/controllers/solidus_paypal_braintree/checkouts_controller_spec.rb +99 -0
  75. data/spec/controllers/solidus_paypal_braintree/client_tokens_controller_spec.rb +55 -0
  76. data/spec/controllers/solidus_paypal_braintree/configurations_controller_spec.rb +73 -0
  77. data/spec/controllers/solidus_paypal_braintree/transactions_controller_spec.rb +183 -0
  78. data/spec/features/backend/configuration_spec.rb +23 -0
  79. data/spec/features/backend/new_payment_spec.rb +137 -0
  80. data/spec/features/frontend/braintree_credit_card_checkout_spec.rb +187 -0
  81. data/spec/features/frontend/paypal_checkout_spec.rb +166 -0
  82. data/spec/fixtures/cassettes/admin/invalid_credit_card.yml +63 -0
  83. data/spec/fixtures/cassettes/admin/resubmit_credit_card.yml +352 -0
  84. data/spec/fixtures/cassettes/admin/valid_credit_card.yml +412 -0
  85. data/spec/fixtures/cassettes/braintree/create_profile.yml +71 -0
  86. data/spec/fixtures/cassettes/braintree/generate_token.yml +63 -0
  87. data/spec/fixtures/cassettes/braintree/token.yml +63 -0
  88. data/spec/fixtures/cassettes/checkout/invalid_credit_card.yml +63 -0
  89. data/spec/fixtures/cassettes/checkout/resubmit_credit_card.yml +216 -0
  90. data/spec/fixtures/cassettes/checkout/update.yml +71 -0
  91. data/spec/fixtures/cassettes/checkout/valid_credit_card.yml +156 -0
  92. data/spec/fixtures/cassettes/gateway/authorize.yml +86 -0
  93. data/spec/fixtures/cassettes/gateway/authorize/credit_card/address.yml +86 -0
  94. data/spec/fixtures/cassettes/gateway/authorize/merchant_account/EUR.yml +154 -0
  95. data/spec/fixtures/cassettes/gateway/authorize/paypal/EUR.yml +90 -0
  96. data/spec/fixtures/cassettes/gateway/authorize/paypal/address.yml +90 -0
  97. data/spec/fixtures/cassettes/gateway/authorized_transaction.yml +73 -0
  98. data/spec/fixtures/cassettes/gateway/cancel/missing.yml +63 -0
  99. data/spec/fixtures/cassettes/gateway/cancel/refunds.yml +272 -0
  100. data/spec/fixtures/cassettes/gateway/cancel/void.yml +201 -0
  101. data/spec/fixtures/cassettes/gateway/capture.yml +141 -0
  102. data/spec/fixtures/cassettes/gateway/complete.yml +157 -0
  103. data/spec/fixtures/cassettes/gateway/credit.yml +208 -0
  104. data/spec/fixtures/cassettes/gateway/purchase.yml +87 -0
  105. data/spec/fixtures/cassettes/gateway/settled_transaction.yml +140 -0
  106. data/spec/fixtures/cassettes/gateway/void.yml +137 -0
  107. data/spec/fixtures/cassettes/source/card_type.yml +267 -0
  108. data/spec/fixtures/cassettes/source/last4.yml +267 -0
  109. data/spec/fixtures/cassettes/transaction/import/valid.yml +71 -0
  110. data/spec/fixtures/cassettes/transaction/import/valid/capture.yml +224 -0
  111. data/spec/fixtures/views/spree/orders/edit.html.erb +50 -0
  112. data/spec/helpers/solidus_paypal_braintree/braintree_admin_helper_spec.rb +17 -0
  113. data/spec/models/solidus_paypal_braintree/address_spec.rb +51 -0
  114. data/spec/models/solidus_paypal_braintree/avs_result_spec.rb +317 -0
  115. data/spec/models/solidus_paypal_braintree/gateway_spec.rb +692 -0
  116. data/spec/models/solidus_paypal_braintree/response_spec.rb +280 -0
  117. data/spec/models/solidus_paypal_braintree/source_spec.rb +360 -0
  118. data/spec/models/solidus_paypal_braintree/transaction_address_spec.rb +253 -0
  119. data/spec/models/solidus_paypal_braintree/transaction_import_spec.rb +283 -0
  120. data/spec/models/solidus_paypal_braintree/transaction_spec.rb +85 -0
  121. data/spec/models/spree/store_spec.rb +14 -0
  122. data/spec/requests/spree/api/orders_controller_spec.rb +36 -0
  123. data/spec/spec_helper.rb +26 -0
  124. data/spec/support/capybara.rb +7 -0
  125. data/spec/support/factories.rb +2 -0
  126. data/spec/support/gateway_helpers.rb +29 -0
  127. data/spec/support/order_ready_for_payment.rb +37 -0
  128. data/spec/support/vcr.rb +42 -0
  129. data/spec/support/views.rb +1 -0
  130. metadata +182 -194
  131. data/app/controllers/solidus_paypal_braintree/client_tokens_controller.rb +0 -22
  132. data/app/helpers/braintree_admin_helper.rb +0 -18
  133. data/app/models/spree/store_decorator.rb +0 -11
  134. data/app/views/spree/shared/_paypal_checkout_button.html.erb +0 -27
  135. data/config/initializers/braintree.rb +0 -1
@@ -1,10 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'solidus_support'
2
4
 
3
5
  module SolidusPaypalBraintree
4
6
  class Engine < Rails::Engine
7
+ include SolidusSupport::EngineExtensions
8
+
5
9
  isolate_namespace SolidusPaypalBraintree
6
10
  engine_name 'solidus_paypal_braintree'
7
11
 
12
+ ActiveSupport::Inflector.inflections do |inflect|
13
+ inflect.acronym 'AVS'
14
+ end
15
+
8
16
  # use rspec for tests
9
17
  config.generators do |g|
10
18
  g.test_framework :rspec
@@ -15,14 +23,6 @@ module SolidusPaypalBraintree
15
23
  Spree::PermittedAttributes.source_attributes.concat [:nonce, :payment_type]
16
24
  end
17
25
 
18
- def self.activate
19
- Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c|
20
- Rails.configuration.cache_classes ? require(c) : load(c)
21
- end
22
- end
23
-
24
- config.to_prepare(&method(:activate).to_proc)
25
-
26
26
  if SolidusSupport.frontend_available?
27
27
  config.assets.precompile += [
28
28
  'solidus_paypal_braintree/checkout.js',
@@ -39,17 +39,17 @@ module SolidusPaypalBraintree
39
39
 
40
40
  # We support Solidus v1.2, which requires some different markup in the
41
41
  # source form partial. This will take precedence over lib/views/backend.
42
- paths["app/views"] << "lib/views/backend_v1.2" if SolidusSupport.solidus_gem_version < Gem::Version.new('1.3')
42
+ paths["app/views"] << "lib/views/backend_v1.2" if Spree.solidus_gem_version < Gem::Version.new('1.3')
43
43
 
44
44
  # Solidus v2.4 introduced preference field partials but does not ship a hash field type.
45
45
  # This is solved in Solidus v2.5.
46
- if SolidusSupport.solidus_gem_version <= Gem::Version.new('2.5.0')
46
+ if Spree.solidus_gem_version <= Gem::Version.new('2.5.0')
47
47
  paths["app/views"] << "lib/views/backend_v2.4"
48
48
  end
49
49
 
50
50
  paths["app/views"] << "lib/views/backend"
51
51
 
52
- initializer "solidus_paypal_braintree_admin_menu_item", after: "register_solidus_paypal_braintree_gateway" do |app|
52
+ initializer "solidus_paypal_braintree_admin_menu_item", after: "register_solidus_paypal_braintree_gateway" do
53
53
  Spree::Backend::Config.configure do |config|
54
54
  config.menu_items << config.class::MenuItem.new(
55
55
  [:braintree],
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  FactoryBot.define do
2
- # Define your Spree extensions Factories within this file to enable applications, and other extensions to use and override them.
4
+ # Define your Spree extensions Factories within this file to enable applications,
5
+ # and other extensions to use and override them.
3
6
  #
4
7
  # Example adding this to your spec_helper will load these Factories for use:
5
8
  # require 'solidus_paypal_braintree/factories'
@@ -9,10 +12,11 @@ FactoryBot.modify do
9
12
  # The Solidus address factory randomizes the zipcode.
10
13
  # The OrderWalkThrough we use in the credit card checkout spec uses this factory for the user addresses.
11
14
  # For credit card payments we transmit the billing address to braintree, for paypal payments the shipping address.
12
- # As we match the body in our VCR settings VCR can not match the request anymore and therefore cannot replay existing cassettes.
15
+ # As we match the body in our VCR settings VCR can not match the request anymore and therefore cannot replay existing
16
+ # cassettes.
13
17
  #
14
18
  factory :address do
15
- zipcode '21088-0255'
16
- lastname "Doe"
19
+ zipcode { '21088-0255' }
20
+ lastname { 'Doe' }
17
21
  end
18
22
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_merchant/network_connection_retries'
2
4
 
3
5
  module SolidusPaypalBraintree
@@ -6,6 +8,7 @@ module SolidusPaypalBraintree
6
8
 
7
9
  def protected_request
8
10
  raise ArgumentError unless block_given?
11
+
9
12
  options = {
10
13
  connection_exceptions: {
11
14
  Braintree::BraintreeError => 'Error while connecting to Braintree gateway'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SolidusPaypalBraintree
2
- VERSION = '0.4.0'
4
+ VERSION = '1.0.0'
3
5
  end
@@ -6,25 +6,50 @@
6
6
  <% @configurations.each do |config| %>
7
7
  <div class="row">
8
8
  <fieldset>
9
- <h1><%= config.store.name %></h1>
9
+ <legend><%= config.store.name %></legend>
10
10
 
11
11
  <%= f.fields_for 'configuration_fields[]', config do |c| %>
12
12
  <div class="field">
13
- <%= c.label :paypal %>
14
13
  <%= c.check_box :paypal %>
14
+ <%= c.label :paypal do %>
15
+ <%= tag.i class: 'fa fa-paypal' %>
16
+ <%= c.object.class.human_attribute_name(:paypal) %>
17
+ <% end %>
15
18
  </div>
19
+
16
20
  <div class="field">
17
- <%= c.label :apple_pay %>
18
21
  <%= c.check_box :apple_pay %>
22
+ <%= c.label :apple_pay do %>
23
+ <%= tag.i class: 'fa fa-apple' %>
24
+ <%= c.object.class.human_attribute_name(:apple_pay) %>
25
+ <% end %>
19
26
  </div>
27
+
20
28
  <div class="field">
21
- <%= c.label :credit_card %>
22
29
  <%= c.check_box :credit_card %>
30
+ <%= c.label :credit_card do %>
31
+ <%= tag.i class: 'fa fa-credit-card' %>
32
+ <%= c.object.class.human_attribute_name(:credit_card) %>
33
+ <% end %>
34
+ +
35
+ <%= c.check_box :three_d_secure %>
36
+ <%= c.label :three_d_secure do %>
37
+ <%= tag.i class: 'fa fa-shield' %>
38
+ <%= c.object.class.human_attribute_name(:three_d_secure) %>
39
+ <% end %>
23
40
  </div>
41
+
42
+ <% config.admin_form_preference_names.each do |name| %>
43
+ <%= render "spree/admin/shared/preference_fields/#{config.preference_type(name)}",
44
+ form: c, attribute: "preferred_#{name}",
45
+ label: t(name, scope: 'spree', default: name.to_s.humanize) %>
46
+ <% end %>
24
47
  <% end %>
25
48
  </fieldset>
26
49
  </div>
27
50
  <% end %>
28
51
 
29
- <%= submit_tag %>
52
+ <div class="form-buttons filter-actions actions">
53
+ <%= submit_tag "Update", class: 'btn btn-primary' %>
54
+ </div>
30
55
  <% end %>
@@ -6,11 +6,11 @@
6
6
  <% previous_cards.each do |card| %>
7
7
  <label><%= radio_button_tag :card, card.id, card == previous_cards.first %> <%= card.display_number %><br /></label>
8
8
  <% end %>
9
- <label><%= radio_button_tag :card, "new", false, { id: "card_new#{id}" } %> <%= Spree.t(:use_new_cc) %></label>
9
+ <label><%= radio_button_tag :card, "new", false, { id: "card_new#{id}" } %> <%= I18n.t("spree.use_new_cc") %></label>
10
10
  <% end %>
11
11
  </div>
12
12
 
13
13
  <div id="card_form<%= id %>" data-hook style="display: none;">
14
- <%= render partial: "spree/shared/braintree_hosted_fields", locals: { id: id } %>
14
+ <%= render partial: "spree/shared/braintree_hosted_fields", locals: { payment_method: payment_method } %>
15
15
  </div>
16
16
  </fieldset>
@@ -4,10 +4,10 @@
4
4
  <div class="row">
5
5
  <div class="alpha six columns">
6
6
  <dl>
7
- <dt><%= Spree.t(:identifier) %>:</dt>
7
+ <dt><%= I18n.t("spree.identifier") %>:</dt>
8
8
  <dd><%= payment.number %></dd>
9
9
 
10
- <dt><%= Spree.t(:response_code) %>:</dt>
10
+ <dt><%= I18n.t("spree.response_code") %>:</dt>
11
11
  <dd><%= braintree_transaction_link(payment) %></dd>
12
12
 
13
13
  <% if payment.source.token.present? %>
@@ -6,11 +6,11 @@
6
6
  <% previous_cards.each do |card| %>
7
7
  <label><%= radio_button_tag :card, card.id, card == previous_cards.first %> <%= card.display_number %><br /></label>
8
8
  <% end %>
9
- <label><%= radio_button_tag :card, "new", false, { id: "card_new#{id}" } %> <%= Spree.t(:use_new_cc) %></label>
9
+ <label><%= radio_button_tag :card, "new", false, { id: "card_new#{id}" } %> <%= I18n.t("spree.use_new_cc") %></label>
10
10
  <% end %>
11
11
  </div>
12
12
 
13
13
  <div id="card_form<%= id %>" data-hook style="display: none;">
14
- <%= render partial: "spree/shared/braintree_hosted_fields", locals: { id: id } %>
14
+ <%= render partial: "spree/shared/braintree_hosted_fields", locals: { payment_method: payment_method } %>
15
15
  </div>
16
16
  </fieldset>
@@ -8,10 +8,12 @@
8
8
 
9
9
  <% if current_store.braintree_configuration.credit_card? %>
10
10
  <fieldset class="braintree-hosted-fields" data-braintree-hosted-fields data-id="<%= id %>">
11
- <%= render "spree/shared/braintree_hosted_fields", id: id %>
11
+ <%= render "spree/shared/braintree_hosted_fields", payment_method: payment_method %>
12
12
  </fieldset>
13
13
  <% end %>
14
14
 
15
15
  <% if current_store.braintree_configuration.apple_pay? %>
16
- <%= render "spree/shared/apple_pay_button" %>
16
+ <%= render "spree/shared/apple_pay_button", id: id %>
17
17
  <% end %>
18
+
19
+ <%= render "spree/shared/braintree_errors" %>
@@ -0,0 +1,30 @@
1
+ <div id="paypal-button"></div>
2
+ <div data-pp-message data-pp-placement="payment" data-pp-amount="<%= @order.total %>"></div>
3
+
4
+ <script>
5
+ var address = <%= sanitize SolidusPaypalBraintree::Address.new(current_order.ship_address).to_json %>
6
+
7
+ var paypalOptions = {
8
+ flow: '<%= SolidusPaypalBraintree::Gateway.first.preferred_paypal_flow %>',
9
+ amount: '<%= current_order.total %>',
10
+ currency: '<%= current_order.currency %>',
11
+ enableShippingAddress: true,
12
+ shippingAddressOverride: address,
13
+ shippingAddressEditable: false,
14
+ environment: '<%= Rails.env.production? ? "production" : "sandbox" %>',
15
+ locale: '<%= paypal_button_preference(:paypal_button_locale, store: current_store) %>',
16
+ style: {
17
+ color: '<%= paypal_button_preference(:paypal_button_color, store: current_store) %>',
18
+ shape: '<%= paypal_button_preference(:paypal_button_shape, store: current_store) %>',
19
+ label: '<%= paypal_button_preference(:paypal_button_label, store: current_store) %>',
20
+ layout: '<%= paypal_button_preference(:paypal_button_layout, store: current_store) %>',
21
+ <% if paypal_button_preference(:paypal_button_layout, store: current_store) == "horizontal" %>
22
+ tagline: '<%= paypal_button_preference(:paypal_button_tagline, store: current_store) %>',
23
+ <% end %>
24
+ messaging: '<%= paypal_button_preference(:paypal_button_messaging, store: current_store) %>'
25
+ }
26
+ }
27
+
28
+ var button = new SolidusPaypalBraintree.createPaypalButton(document.querySelector("#paypal-button"), paypalOptions);
29
+ button.initialize();
30
+ </script>
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ $:.push File.expand_path('lib', __dir__)
4
+ require 'solidus_paypal_braintree/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'solidus_paypal_braintree'
8
+ s.version = SolidusPaypalBraintree::VERSION
9
+ s.summary = 'Officially supported Paypal/Braintree extension'
10
+ s.description = 'Uses the javascript API for seamless braintree payments'
11
+ s.license = 'BSD-3-Clause'
12
+
13
+ s.author = 'Stembolt'
14
+ s.email = 'braintree+gemfile@stembolt.com'
15
+ s.homepage = 'https://github.com/solidusio/solidus_paypal_braintree'
16
+
17
+ s.required_ruby_version = '~> 2.4'
18
+
19
+ s.files = Dir.chdir(File.expand_path(__dir__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ end
22
+ s.test_files = Dir['spec/**/*']
23
+ s.bindir = "exe"
24
+ s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
+ s.require_paths = ["lib"]
26
+
27
+ if s.respond_to?(:metadata)
28
+ s.metadata["homepage_uri"] = s.homepage if s.homepage
29
+ s.metadata["source_code_uri"] = s.homepage if s.homepage
30
+ end
31
+
32
+ s.add_dependency 'activemerchant', '~> 1.48'
33
+ s.add_dependency 'braintree', '~> 2.65'
34
+ s.add_dependency 'solidus_api', ['>= 2.0.0', '< 3']
35
+ s.add_dependency 'solidus_core', ['>= 2.0.0', '< 3']
36
+ s.add_dependency 'solidus_support', '~> 0.5.0'
37
+
38
+ s.add_development_dependency 'selenium-webdriver'
39
+ s.add_development_dependency 'solidus_dev_support'
40
+ s.add_development_dependency 'vcr'
41
+ s.add_development_dependency 'webmock'
42
+ end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+ require 'support/order_ready_for_payment'
3
+
4
+ RSpec.describe SolidusPaypalBraintree::CheckoutsController, type: :controller do
5
+ routes { SolidusPaypalBraintree::Engine.routes }
6
+
7
+ include_context 'when order is ready for payment'
8
+
9
+ describe 'PATCH update' do
10
+ subject(:patch_update) { patch :update, params: params }
11
+
12
+ let(:params) do
13
+ {
14
+ "state" => "payment",
15
+ "order" => {
16
+ "payments_attributes" => [
17
+ {
18
+ "payment_method_id" => payment_method.id,
19
+ "source_attributes" => {
20
+ "nonce" => "fake-paypal-billing-agreement-nonce",
21
+ "payment_type" => SolidusPaypalBraintree::Source::PAYPAL
22
+ }
23
+ }
24
+ ],
25
+ "use_billing" => "1",
26
+ "use_postmates_shipping" => "0"
27
+ },
28
+ "reuse_credit" => "1",
29
+ "order_bill_address" => "",
30
+ "reuse_bill_address" => "1"
31
+ }
32
+ end
33
+
34
+ let!(:payment_method) do
35
+ create_gateway
36
+ end
37
+
38
+ before do
39
+ allow(controller).to receive(:try_spree_current_user) { user }
40
+ allow(controller).to receive(:spree_current_user) { user }
41
+ allow(controller).to receive(:current_order) { order }
42
+ end
43
+
44
+ context "when a payment is created successfully", vcr: {
45
+ cassette_name: 'checkout/update',
46
+ match_requests_on: [:braintree_uri]
47
+ } do
48
+ it 'creates a payment' do
49
+ expect { patch_update }.
50
+ to change { order.payments.count }.
51
+ from(0).
52
+ to(1)
53
+ end
54
+
55
+ it 'creates a payment source' do
56
+ expect { patch_update }.
57
+ to change { SolidusPaypalBraintree::Source.count }.
58
+ from(0).
59
+ to(1)
60
+ end
61
+
62
+ it 'assigns @order' do
63
+ patch_update
64
+ expect(assigns(:order)).to eq order
65
+ end
66
+
67
+ it "is successful" do
68
+ expect(patch_update).to be_successful
69
+ end
70
+
71
+ it "renders 'ok'" do
72
+ expect(patch_update.body).to eql("ok")
73
+ end
74
+ end
75
+
76
+ context "when a payment is not created successfully" do
77
+ before do
78
+ allow_any_instance_of(::Spree::Payment).to receive(:save).and_return(false)
79
+ end
80
+
81
+ # No idea why this is the case, but I'm just adding the tests here
82
+ it "is successful" do
83
+ expect(patch_update).to be_successful
84
+ end
85
+
86
+ it "renders 'not-ok'" do
87
+ expect(patch_update.body).to eq('not-ok')
88
+ end
89
+
90
+ it "does not change the number of payments in the system" do
91
+ expect{ patch_update }.not_to(change{ ::Spree::Payment.count })
92
+ end
93
+
94
+ it "does not change the number of sources in the system" do
95
+ expect{ patch_update }.not_to(change{ SolidusPaypalBraintree::Source.count })
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe SolidusPaypalBraintree::ClientTokensController do
4
+ routes { SolidusPaypalBraintree::Engine.routes }
5
+
6
+ cassette_options = { cassette_name: "braintree/token" }
7
+ describe "POST create", vcr: cassette_options do
8
+ let!(:gateway) { create_gateway }
9
+ let(:user) { create(:user) }
10
+ let(:json) { JSON.parse(response.body) }
11
+
12
+ before { user.generate_spree_api_key! }
13
+
14
+ context 'without a payment method id' do
15
+ subject(:response) do
16
+ post :create, params: { token: user.spree_api_key }
17
+ end
18
+
19
+ it "returns a client token", aggregate_failures: true do
20
+ expect(response).to have_http_status(:success)
21
+ expect(response.content_type).to include 'application/json'
22
+ expect(json["client_token"]).to be_present
23
+ expect(json["client_token"]).to be_a String
24
+ expect(json["payment_method_id"]).to eq gateway.id
25
+ end
26
+
27
+ context "when there's two gateway's for different stores" do
28
+ let!(:store1) { create(:store, code: 'store_1') }
29
+ let!(:store2) { create(:store, code: 'store_2') }
30
+ let!(:gateway_for_store1) { create_gateway.tap{ |gw| store1.payment_methods << gw } }
31
+ let!(:gateway_for_store2) { create_gateway.tap{ |gw| store2.payment_methods << gw } }
32
+
33
+ it "returns the correct gateway for store1" do
34
+ allow_any_instance_of(described_class).to receive(:current_store).and_return store1
35
+ expect(json["payment_method_id"]).to eq gateway_for_store1.id
36
+ end
37
+
38
+ it "returns the correct gateway for store2" do
39
+ allow_any_instance_of(described_class).to receive(:current_store).and_return store2
40
+ expect(json["payment_method_id"]).to eq gateway_for_store2.id
41
+ end
42
+ end
43
+ end
44
+
45
+ context 'with a payment method id' do
46
+ subject(:response) do
47
+ post :create, params: { token: user.spree_api_key, payment_method_id: gateway.id }
48
+ end
49
+
50
+ it 'uses the selected gateway' do
51
+ expect(json["payment_method_id"]).to eq gateway.id
52
+ end
53
+ end
54
+ end
55
+ end