solidus_paypal_commerce_platform 0.0.1

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 (101) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +41 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github/stale.yml +17 -0
  5. data/.gitignore +20 -0
  6. data/.rspec +2 -0
  7. data/.rubocop.yml +56 -0
  8. data/Gemfile +33 -0
  9. data/LICENSE +26 -0
  10. data/README.md +173 -0
  11. data/Rakefile +6 -0
  12. data/app/assets/javascripts/spree/backend/solidus_paypal_commerce_platform.js +2 -0
  13. data/app/assets/javascripts/spree/backend/solidus_paypal_commerce_platform/namespace.js +1 -0
  14. data/app/assets/javascripts/spree/backend/solidus_paypal_commerce_platform/wizard.js +28 -0
  15. data/app/assets/javascripts/spree/frontend/solidus_paypal_commerce_platform.js +3 -0
  16. data/app/assets/javascripts/spree/frontend/solidus_paypal_commerce_platform/button_actions.js +191 -0
  17. data/app/assets/javascripts/spree/frontend/solidus_paypal_commerce_platform/buttons.js +26 -0
  18. data/app/assets/javascripts/spree/frontend/solidus_paypal_commerce_platform/namespace.js +1 -0
  19. data/app/assets/stylesheets/spree/backend/solidus_paypal_commerce_platform.css +4 -0
  20. data/app/assets/stylesheets/spree/frontend/solidus_paypal_commerce_platform.css +17 -0
  21. data/app/controllers/solidus_paypal_commerce_platform/orders_controller.rb +83 -0
  22. data/app/controllers/solidus_paypal_commerce_platform/payments_controller.rb +44 -0
  23. data/app/controllers/solidus_paypal_commerce_platform/paypal_orders_controller.rb +19 -0
  24. data/app/controllers/solidus_paypal_commerce_platform/shipping_rates_controller.rb +31 -0
  25. data/app/controllers/solidus_paypal_commerce_platform/wizard_controller.rb +47 -0
  26. data/app/decorators/solidus_paypal_commerce_platform/remove_required_phone_from_address.rb +13 -0
  27. data/app/helpers/solidus_paypal_commerce_platform/button_options_helper.rb +21 -0
  28. data/app/jobs/solidus_paypal_commerce_platform/application_job.rb +6 -0
  29. data/app/jobs/solidus_paypal_commerce_platform/webhook_job.rb +22 -0
  30. data/app/models/solidus_paypal_commerce_platform/gateway.rb +88 -0
  31. data/app/models/solidus_paypal_commerce_platform/payment_method.rb +75 -0
  32. data/app/models/solidus_paypal_commerce_platform/payment_source.rb +27 -0
  33. data/app/models/solidus_paypal_commerce_platform/paypal_address.rb +81 -0
  34. data/app/models/solidus_paypal_commerce_platform/paypal_order.rb +107 -0
  35. data/app/models/solidus_paypal_commerce_platform/pricing_options.rb +9 -0
  36. data/app/models/solidus_paypal_commerce_platform/wizard.rb +40 -0
  37. data/app/overrides/spree/admin/payment_methods/form/insert_email_verification_notification.rb +9 -0
  38. data/app/overrides/spree/admin/payment_methods/index/insert_setup_wizards.rb +17 -0
  39. data/app/overrides/spree/admin/payments/log_entries/add_paypal_debug_id.rb +9 -0
  40. data/app/overrides/spree/orders/edit/insert_cart_buttons.rb +9 -0
  41. data/app/overrides/spree/payments/payment/add_paypal_email_to_payment.rb +9 -0
  42. data/app/overrides/spree/products/cart_form/insert_product_buttons.rb +10 -0
  43. data/app/views/solidus_paypal_commerce_platform/admin/payment_methods/_available_to_users.html.erb +6 -0
  44. data/app/views/solidus_paypal_commerce_platform/admin/payment_methods/_paypal_wizard.html.erb +16 -0
  45. data/app/views/solidus_paypal_commerce_platform/admin/payment_methods/_setup_wizards.html.erb +16 -0
  46. data/app/views/solidus_paypal_commerce_platform/admin/payments/_log_entries.html.erb +32 -0
  47. data/bin/console +17 -0
  48. data/bin/rails +7 -0
  49. data/bin/rails-engine +13 -0
  50. data/bin/rails-sandbox +18 -0
  51. data/bin/rake +7 -0
  52. data/bin/sandbox +86 -0
  53. data/bin/setup +8 -0
  54. data/codecov.yml +14 -0
  55. data/config/locales/en.yml +37 -0
  56. data/config/routes.rb +12 -0
  57. data/db/migrate/20200521190038_add_paypal_commerce_platform_sources.rb +13 -0
  58. data/lib/generators/solidus_paypal_commerce_platform/install/install_generator.rb +38 -0
  59. data/lib/solidus_paypal_commerce_platform.rb +21 -0
  60. data/lib/solidus_paypal_commerce_platform/access_token_authorization_request.rb +21 -0
  61. data/lib/solidus_paypal_commerce_platform/client.rb +84 -0
  62. data/lib/solidus_paypal_commerce_platform/configuration.rb +64 -0
  63. data/lib/solidus_paypal_commerce_platform/engine.rb +45 -0
  64. data/lib/solidus_paypal_commerce_platform/factories.rb +14 -0
  65. data/lib/solidus_paypal_commerce_platform/fetch_merchant_credentials_request.rb +17 -0
  66. data/lib/solidus_paypal_commerce_platform/version.rb +5 -0
  67. data/lib/views/api/spree/api/payments/source_views/_paypal_commerce_platform.json.jbuilder +3 -0
  68. data/lib/views/backend/spree/admin/payments/source_forms/_paypal_commerce_platform.html.erb +1 -0
  69. data/lib/views/backend/spree/admin/payments/source_views/_paypal_commerce_platform.html.erb +18 -0
  70. data/lib/views/backend/spree/admin/shared/preference_fields/_paypal_select.html.erb +13 -0
  71. data/lib/views/frontend/solidus_paypal_commerce_platform/cart/_cart_buttons.html.erb +3 -0
  72. data/lib/views/frontend/solidus_paypal_commerce_platform/payments/_payment.html.erb +4 -0
  73. data/lib/views/frontend/solidus_paypal_commerce_platform/product/_product_buttons.html.erb +3 -0
  74. data/lib/views/frontend/spree/checkout/payment/_paypal_commerce_platform.html.erb +13 -0
  75. data/lib/views/frontend/spree/orders/payment/_paypal_commerce_platform.html.erb +17 -0
  76. data/lib/views/frontend/spree/products/payment/_paypal_commerce_platform.html.erb +15 -0
  77. data/solidus_paypal_commerce_platform.gemspec +39 -0
  78. data/spec/features/backend/new_payment_method_spec.rb +40 -0
  79. data/spec/features/frontend/cart_spec.rb +38 -0
  80. data/spec/features/frontend/checkout_spec.rb +81 -0
  81. data/spec/features/frontend/product_spec.rb +79 -0
  82. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/CHECKOUT.ORDER.COMPLETED.v2.json +121 -0
  83. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/CHECKOUT.ORDER.PROCESSED.v2.json +121 -0
  84. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.COMPLETED.v1.json +50 -0
  85. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.COMPLETED.v2.json +72 -0
  86. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.DENIED.v1.json +50 -0
  87. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.DENIED.v2.json +68 -0
  88. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.REFUNDED.v1.json +51 -0
  89. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.REFUNDED.v2.json +63 -0
  90. data/spec/jobs/solidus_paypal_commerce_platform/webhook_job_spec.rb +44 -0
  91. data/spec/lib/solidus_paypal_commerce_platform/client_spec.rb +21 -0
  92. data/spec/lib/solidus_paypal_commerce_platform/configuration_spec.rb +67 -0
  93. data/spec/models/solidus_paypal_commerce_platform/payment_method_spec.rb +102 -0
  94. data/spec/models/solidus_paypal_commerce_platform/payment_source_spec.rb +62 -0
  95. data/spec/models/solidus_paypal_commerce_platform/paypal_address_spec.rb +55 -0
  96. data/spec/models/solidus_paypal_commerce_platform/wizard_spec.rb +9 -0
  97. data/spec/requests/solidus_paypal_commerce_platform/orders_controller_spec.rb +36 -0
  98. data/spec/requests/solidus_paypal_commerce_platform/shipping_rates_controller_spec.rb +44 -0
  99. data/spec/requests/solidus_paypal_commerce_platform/wizard_controller_spec.rb +44 -0
  100. data/spec/spec_helper.rb +30 -0
  101. metadata +258 -0
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'deface'
4
+ require 'spree/core'
5
+ require 'solidus_paypal_commerce_platform'
6
+ require 'solidus_webhooks'
7
+
8
+ module SolidusPaypalCommercePlatform
9
+ class Engine < Rails::Engine
10
+ include SolidusSupport::EngineExtensions
11
+
12
+ isolate_namespace SolidusPaypalCommercePlatform
13
+
14
+ engine_name 'solidus_paypal_commerce_platform'
15
+
16
+ initializer "solidus_paypal_commerce_platform.add_payment_method", after: "spree.register.payment_methods" do |app|
17
+ app.config.spree.payment_methods << SolidusPaypalCommercePlatform::PaymentMethod
18
+ SolidusPaypalCommercePlatform::PaymentMethod.allowed_admin_form_preference_types << :paypal_select
19
+ Spree::PermittedAttributes.source_attributes.concat [:paypal_order_id, :authorization_id, :paypal_email]
20
+ end
21
+
22
+ initializer "solidus_paypal_commerce_platform.add_wizard", after: "spree.register.payment_methods" do |app|
23
+ # Adding the class set below - if this is ported to core, we can remove this line.
24
+ Spree::Core::Environment.add_class_set("payment_setup_wizards")
25
+ app.config.spree.payment_setup_wizards << "SolidusPaypalCommercePlatform::Wizard"
26
+ end
27
+
28
+ initializer "solidus_paypal_commerce_platform.set_pricing_options_class" do
29
+ def (Spree::Config).pricing_options_class
30
+ SolidusPaypalCommercePlatform::PricingOptions
31
+ end
32
+ end
33
+
34
+ initializer "solidus_paypal_commerce_platform.webhooks" do
35
+ SolidusWebhooks.config.register_webhook_handler :solidus_paypal_commerce_platform, ->(payload) {
36
+ SolidusPaypalCommercePlatform::WebhooksJob.perform_now(payload)
37
+ }
38
+ end
39
+
40
+ # use rspec for tests
41
+ config.generators do |g|
42
+ g.test_framework :rspec
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ FactoryBot.define do
4
+ factory :paypal_payment_method, class: 'SolidusPaypalCommercePlatform::PaymentMethod' do
5
+ type { "SolidusPaypalCommercePlatform::PaymentMethod" }
6
+ name { "PayPal Payment Method" }
7
+ preferences {
8
+ {
9
+ client_id: SecureRandom.hex(8),
10
+ client_secret: SecureRandom.hex(10)
11
+ }
12
+ }
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusPaypalCommercePlatform
4
+ # https://developer.paypal.com/docs/api/partner-referrals/v1/#merchant-integration_credentials
5
+ class FetchMerchantCredentialsRequest
6
+ attr_accessor :verb, :path, :headers, :body
7
+
8
+ def initialize(partner_merchant_id:, access_token:)
9
+ @verb = "GET"
10
+ @path = "/v1/customer/partners/#{partner_merchant_id}/merchant-integrations/credentials"
11
+ @headers = {
12
+ "Content-Type" => "application/json",
13
+ "Authorization" => "Bearer #{access_token}"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusPaypalCommercePlatform
4
+ VERSION = '0.0.1'
5
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ json.call(payment_source, :id, :paypal_order_id, :created_at)
@@ -0,0 +1 @@
1
+ <%= t('virtual_terminal_notice_html') %>
@@ -0,0 +1,18 @@
1
+ <fieldset data-hook="credit_card">
2
+ <legend align="center"><%= SolidusPaypalCommercePlatform::PaymentMethod.model_name.human %></legend>
3
+
4
+ <div class="row">
5
+ <div class="alpha six columns">
6
+ <dl>
7
+ <dt><%= I18n.t("spree.identifier") %>:</dt>
8
+ <dd><%= payment.number %></dd>
9
+
10
+ <dt><%= I18n.t("paypal_capture_id") %>:</dt>
11
+ <dd><%= payment.source.capture_id %></dd>
12
+
13
+ <dt><%= I18n.t("paypal_email") %>:</dt>
14
+ <dd><%= payment.source.paypal_email %></dd>
15
+ </dl>
16
+ </div>
17
+ </div>
18
+ </fieldset>
@@ -0,0 +1,13 @@
1
+ <% label = local_assigns[:label].presence %>
2
+ <% html_options = {class: 'custom-select fullwidth'}.update(local_assigns[:html_options] || {}) %>
3
+ <% options = @object.send("#{attribute}_options") %>
4
+
5
+ <div class="field">
6
+ <% if local_assigns[:form] %>
7
+ <%= form.label attribute, label %>
8
+ <%= form.select attribute, options, {}, html_options %>
9
+ <% else %>
10
+ <%= label_tag name, label %>
11
+ <%= select_tag name, value, html_options %>
12
+ <% end %>
13
+ </div>
@@ -0,0 +1,3 @@
1
+ <% Spree::PaymentMethod.available_to_users.select{ |payment_method| payment_method.try(:display_on_cart) }.each do |payment_method| %>
2
+ <%= render partial: "spree/orders/payment/#{payment_method.cart_partial_name}", locals: {payment_method: payment_method} %>
3
+ <% end %>
@@ -0,0 +1,4 @@
1
+ <% if payment.source.respond_to?(:paypal_email) %>
2
+ <br />
3
+ <%= t('payment_email', email: payment.source.paypal_email) %>
4
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <% Spree::PaymentMethod.available_to_users.select{ |payment_method| payment_method.try(:display_on_product_page) }.each do |payment_method| %>
2
+ <%= render partial: "spree/products/payment/#{payment_method.product_page_partial_name}", locals: {payment_method: payment_method} %>
3
+ <% end %>
@@ -0,0 +1,13 @@
1
+ <script src="<%= payment_method.javascript_sdk_url(order: @order) %>"></script>
2
+
3
+ <div id="paypal-button-container"></div>
4
+ <input type="hidden" name="payment_source[<%= payment_method.id %>][paypal_order_id]" id="payments_source_paypal_order_id">
5
+ <input type="hidden" name="payment_source[<%= payment_method.id %>][paypal_email]" id="payments_source_paypal_email">
6
+
7
+ <script>
8
+ $( document ).ready(function() {
9
+ SolidusPaypalCommercePlatform.renderButton("<%= payment_method.id %>",<%= raw payment_method.button_style.to_json %>)
10
+ })
11
+ </script>
12
+
13
+ <div id="paypal_commerce_platform_overlay"></div>
@@ -0,0 +1,17 @@
1
+ <div style="margin-left:auto;margin-right:auto;width:50%;margin-top:20px;">
2
+ <script src="<%= payment_method.javascript_sdk_url(order: @order) %>">
3
+ </script>
4
+
5
+ <div id="paypal-button-container"></div>
6
+
7
+ <script>
8
+ Spree.current_order_id = "<%= @order.number %>"
9
+ Spree.current_order_token = "<%= @order.guest_token %>"
10
+ SolidusPaypalCommercePlatform.checkout_url = "<%= checkout_url %>"
11
+ $( document ).ready(function() {
12
+ SolidusPaypalCommercePlatform.renderCartButton("<%= payment_method.id %>",<%= raw payment_method.button_style.to_json %>)
13
+ })
14
+ </script>
15
+ </div>
16
+
17
+ <div id="paypal_commerce_platform_overlay"></div>
@@ -0,0 +1,15 @@
1
+ <div style="margin-top:20px;">
2
+ <script src="<%= payment_method.javascript_sdk_url %>">
3
+ </script>
4
+
5
+ <div id="paypal-button-container"></div>
6
+
7
+ <script>
8
+ SolidusPaypalCommercePlatform.checkout_url = "<%= checkout_url %>"
9
+ $( document ).ready(function() {
10
+ SolidusPaypalCommercePlatform.renderProductButton("<%= payment_method.id %>",<%= raw payment_method.button_style.to_json %>)
11
+ })
12
+ </script>
13
+ </div>
14
+
15
+ <div id="paypal_commerce_platform_overlay"></div>
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/solidus_paypal_commerce_platform/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'solidus_paypal_commerce_platform'
7
+ spec.version = SolidusPaypalCommercePlatform::VERSION
8
+ spec.authors = ['Sean Denny', 'Elia Schito']
9
+ spec.email = 'contact@solidus.io'
10
+
11
+ spec.summary = 'Integrate Solidus with Paypal Commerce Platform'
12
+ spec.homepage = 'https://github.com/nebulab/solidus_paypal_commerce_platform#readme'
13
+ spec.license = 'BSD-3-Clause'
14
+
15
+ spec.metadata['homepage_uri'] = spec.homepage
16
+ spec.metadata['source_code_uri'] = 'https://github.com/nebulab/solidus_paypal_commerce_platform'
17
+ spec.metadata['changelog_uri'] = 'https://github.com/nebulab/solidus_paypal_commerce_platform/releases'
18
+
19
+ spec.required_ruby_version = Gem::Requirement.new('~> 2.5')
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ files = Dir.chdir(__dir__) { `git ls-files -z`.split("\x0") }
24
+
25
+ spec.files = files.grep_v(%r{^(test|spec|features)/})
26
+ spec.test_files = files.grep(%r{^(test|spec|features)/})
27
+ spec.bindir = "exe"
28
+ spec.executables = files.grep(%r{^exe/}) { |f| File.basename(f) }
29
+ spec.require_paths = ["lib"]
30
+
31
+ spec.add_dependency 'deface', '~> 1.5'
32
+ spec.add_dependency 'solidus_core', ['>= 2.0.0', '< 3']
33
+ spec.add_dependency 'solidus_support', '~> 0.5'
34
+ spec.add_dependency 'solidus_webhooks', '~> 0.2.0'
35
+
36
+ spec.add_dependency 'paypal-checkout-sdk'
37
+
38
+ spec.add_development_dependency 'solidus_dev_support'
39
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe "creating a new payment" do
4
+ stub_authorization!
5
+
6
+ it "displays PayPal Commerce Platform as an option" do
7
+ visit "/admin/payment_methods/new"
8
+ expect(page).to have_select('payment_method_type', options: [
9
+ "PayPal Commerce Platform",
10
+ "Bogus Credit Card Payments",
11
+ "Check Payments",
12
+ "Simple Bogus Credit Card Payments",
13
+ "Store Credit Payments",
14
+ ])
15
+ select "PayPal Commerce Platform", from: 'payment_method_type'
16
+ fill_in "Name", with: "PayPal!"
17
+ click_on "Create"
18
+ expect(page).to have_text("Payment Method has been successfully created!")
19
+
20
+ fill_in "Client", with: "cli-123"
21
+ fill_in "Client secret", with: "cli-sec-123"
22
+ click_on "Update"
23
+ expect(page).to have_text("Payment Method has been successfully updated!")
24
+ end
25
+
26
+ it "displays the onboarding button", :js do
27
+ visit "/admin/payment_methods"
28
+
29
+ # main_window = current_window
30
+
31
+ within ".setup-wizard" do
32
+ paypal_button = page.find("button")
33
+ expect(paypal_button.text).to eq("Setup PayPal Commerce Platform")
34
+ # TODO: make this more complete
35
+ # paypal_window = window_opened_by do
36
+ # paypal_button.click
37
+ # end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe "Cart page" do
4
+ describe "paypal payment method" do
5
+ let(:order) { Spree::TestingSupport::OrderWalkthrough.up_to(:address) }
6
+ let(:paypal_payment_method) { create(:paypal_payment_method) }
7
+
8
+ before do
9
+ user = create(:user)
10
+ order.user = user
11
+
12
+ paypal_payment_method
13
+ allow_any_instance_of(Spree::OrdersController).to receive_messages(
14
+ current_order: order,
15
+ try_spree_current_user: user
16
+ )
17
+ end
18
+
19
+ def paypal_script_options
20
+ script_tag_url = URI(page.find('script[src*="sdk/js?"]', visible: false)[:src])
21
+ script_tag_url.query.split('&')
22
+ end
23
+
24
+ it "generate a js file with the correct credentials and intent attached" do
25
+ visit '/cart'
26
+ expect(paypal_script_options).to include("client-id=#{paypal_payment_method.preferences[:client_id]}")
27
+ end
28
+
29
+ context "when auto-capture is set to true" do
30
+ it "generate a js file with intent capture" do
31
+ paypal_payment_method.update(auto_capture: true)
32
+ visit '/cart'
33
+ expect(paypal_script_options).to include("client-id=#{paypal_payment_method.preferences[:client_id]}")
34
+ expect(paypal_script_options).to include("intent=capture")
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe "Checkout" do
4
+ describe "paypal payment method" do
5
+ let(:order) { Spree::TestingSupport::OrderWalkthrough.up_to(:payment) }
6
+ let(:paypal_payment_method) { create(:paypal_payment_method) }
7
+ let(:failed_response) { OpenStruct.new(status_code: 500) }
8
+
9
+ before do
10
+ user = create(:user)
11
+ order.user = user
12
+ order.recalculate
13
+
14
+ paypal_payment_method
15
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(
16
+ current_order: order, try_spree_current_user: user
17
+ )
18
+ end
19
+
20
+ def paypal_script_options
21
+ script_tag_url = URI(page.find('script[src*="sdk/js?"]', visible: false)[:src])
22
+ script_tag_url.query.split('&')
23
+ end
24
+
25
+ it "generates a js file with the correct credentials and intent attached" do
26
+ visit '/checkout/payment'
27
+ expect(paypal_script_options).to include("client-id=#{paypal_payment_method.preferences[:client_id]}")
28
+ end
29
+
30
+ context "when auto-capture is set to true" do
31
+ it "generates a js file with intent capture" do
32
+ paypal_payment_method.update(auto_capture: true)
33
+ visit '/checkout/payment'
34
+ expect(paypal_script_options).to include("client-id=#{paypal_payment_method.preferences[:client_id]}")
35
+ expect(paypal_script_options).to include("intent=capture")
36
+ end
37
+ end
38
+
39
+ context "when no payment has been made" do
40
+ it "fails to process" do
41
+ visit '/checkout/payment'
42
+ choose(option: paypal_payment_method.id)
43
+ click_button("Save and Continue")
44
+ expect(page).to have_content("Payments source PayPal order can't be blank")
45
+ end
46
+ end
47
+
48
+ context "when a payment has been made" do
49
+ it "proceeds to the next step" do
50
+ visit '/checkout/payment'
51
+ choose(option: paypal_payment_method.id)
52
+ find(:xpath, "//input[@id='payments_source_paypal_order_id']", visible: false).set SecureRandom.hex(8)
53
+ click_button("Save and Continue")
54
+ expect(page).to have_css(".current", text: "Confirm")
55
+ end
56
+
57
+ it "records the paypal email address" do
58
+ visit '/checkout/payment'
59
+ choose(option: paypal_payment_method.id)
60
+ find(:xpath, "//input[@id='payments_source_paypal_order_id']", visible: false).set SecureRandom.hex(8)
61
+ find(:xpath, "//input[@id='payments_source_paypal_email']", visible: false).set "fake@email.com"
62
+ click_button("Save and Continue")
63
+ expect(Spree::Payment.last.source.paypal_email).to eq "fake@email.com"
64
+ end
65
+ end
66
+
67
+ context "when a payment fails" do
68
+ before { allow_any_instance_of(PayPal::PayPalHttpClient).to receive(:execute) { failed_response } }
69
+
70
+ it "redirects the user back to the payments page" do
71
+ visit '/checkout/payment'
72
+ choose(option: paypal_payment_method.id)
73
+ find(:xpath, "//input[@id='payments_source_paypal_order_id']", visible: false).set SecureRandom.hex(8)
74
+ click_button("Save and Continue")
75
+ click_button("Place Order")
76
+ expect(page).to have_current_path("/checkout/payment")
77
+ expect(page).to have_content("Your payment was declined")
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe "Product page", js: true do
4
+ describe "paypal button" do
5
+ let(:paypal_payment_method) { create(:paypal_payment_method) }
6
+ let(:product) { create(:product, variants: [variant, variant_two]) }
7
+ let(:store) { create(:store) }
8
+ let(:variant) { create(:variant) }
9
+ let(:variant_two) { create(:variant) }
10
+
11
+ before do
12
+ paypal_payment_method
13
+ end
14
+
15
+ def paypal_script_options
16
+ script_tag_url = URI(page.find('script[src*="sdk/js?"]', visible: false)[:src])
17
+ script_tag_url.query.split('&')
18
+ end
19
+
20
+ it "generates a js file with the correct credentials and intent attached" do
21
+ visit '/products/' + product.slug
22
+ expect(paypal_script_options).to include("client-id=#{paypal_payment_method.preferences[:client_id]}")
23
+ end
24
+
25
+ context "when auto-capture is set to true" do
26
+ it "generates a js file with intent capture" do
27
+ paypal_payment_method.update(auto_capture: true)
28
+ visit '/products/' + product.slug
29
+ expect(paypal_script_options).to include("client-id=#{paypal_payment_method.preferences[:client_id]}")
30
+ expect(paypal_script_options).to include("intent=capture")
31
+ end
32
+ end
33
+
34
+ describe "order creation" do
35
+ before do
36
+ allow_any_instance_of(Spree::Core::ControllerHelpers::Store).to receive(:current_store) { store }
37
+ visit '/products/' + product.slug
38
+
39
+ # Stubbing out paypal methods since their JS doesn't load in correctly on tests
40
+ page.execute_script("paypal = {}")
41
+ page.execute_script("paypal.render = function(){}")
42
+ page.execute_script("paypal.Buttons = function(){return paypal}")
43
+
44
+ # Waiting until the paypal button becomes available, because the SPCP namespace
45
+ # isn't immediately available
46
+ page.find("#paypal-button-container")
47
+ end
48
+
49
+ it "creates an order successfully" do
50
+ page.evaluate_script("SolidusPaypalCommercePlatform.createOrder()")
51
+
52
+ expect(Spree::Order.last).not_to be nil
53
+ end
54
+
55
+ it "sets the Spree number and token variables" do
56
+ page.evaluate_script("SolidusPaypalCommercePlatform.createOrder()")
57
+
58
+ expect(page.evaluate_script("Spree.current_order_id")).to eq Spree::Order.last.number
59
+ expect(page.evaluate_script("Spree.current_order_token")).to eq Spree::Order.last.guest_token
60
+ end
61
+
62
+ it "uses the specified quantity" do
63
+ quantity = 12
64
+ fill_in('quantity', with: quantity)
65
+
66
+ page.evaluate_script("SolidusPaypalCommercePlatform.createOrder()")
67
+
68
+ expect(Spree::Order.last.line_items.first.quantity).to eq quantity
69
+ end
70
+
71
+ it "uses the selected variant" do
72
+ page.choose("variant_id_#{variant_two.id}")
73
+ page.evaluate_script("SolidusPaypalCommercePlatform.createOrder()")
74
+
75
+ expect(Spree::Order.last.line_items.first.variant_id).to eq variant_two.id
76
+ end
77
+ end
78
+ end
79
+ end