<commit_before>require 'spec_helper'

ActiveMerchant::Billing::Base.mode = :test

describe Killbill::PaypalExpress::PaymentPlugin do

  include ::Killbill::Plugin::ActiveMerchant::RSpec

  before(:all) do
    @plugin = build_plugin(::Killbill::PaypalExpress::PaymentPlugin, 'paypal_express')
    svcs = @plugin.kb_apis.proxied_services
    svcs[:payment_api] = PaypalExpressJavaPaymentApi.new(@plugin)
    @plugin.kb_apis = ::Killbill::Plugin::KillbillApi.new('paypal_express', svcs)
    @plugin.start_plugin

    @call_context = build_call_context

    @amount = BigDecimal.new('100')
    @currency = 'USD'
    @form_fields  = @plugin.hash_to_properties(
        :order_id => '1234',
        :amount   => @amount,
        :currency => @currency
    )

    kb_account_id = SecureRandom.uuid
    create_kb_account(kb_account_id, @plugin.kb_apis.proxied_services[:account_user_api])

    @pm = create_payment_method(::Killbill::PaypalExpress::PaypalExpressPaymentMethod, kb_account_id, @call_context.tenant_id)
    verify_payment_method
  end

  before(:each) do
    ::Killbill::PaypalExpress::PaypalExpressTransaction.delete_all
    ::Killbill::PaypalExpress::PaypalExpressResponse.delete_all
  end

  it 'should generate forms correctly' do
    form = @plugin.build_form_descriptor(@pm.kb_account_id, @form_fields, [], @call_context)
    validate_form(form)
    validate_nil_form_property(form, 'kb_payment_id')
    validate_nil_form_property(form, 'kb_transaction_external_key')
    token = validate_form_property(form, 'token')

    # Verify no payment was created in Kill Bill
    @plugin.kb_apis.proxied_services[:payment_api].payments.should be_empty

    # Verify the payment cannot go through without the token
    purchase_with_missing_token

    properties = []
    properties << build_property('token', token)

    # Verify the payment cannot go through until the token is validated
    purchase_with_invalid_token(properties)

    validate_token(form)

    purchase_and_refund(SecureRandom.uuid, SecureRandom.uuid, properties)

    # Verify no extra payment was created in Kill Bill by the plugin
    @plugin.kb_apis.proxied_services[:payment_api].payments.should be_empty

    # Verify the token cannot be re-used
    subsequent_purchase(properties)

    # Verify no token/baid was stored
    verify_payment_method
  end

  it 'should generate forms with pending payments correctly' do
    payment_external_key = SecureRandom.uuid
    properties = @plugin.hash_to_properties(
      :transaction_external_key => payment_external_key,
      :create_pending_payment => true
    )

    form = @plugin.build_form_descriptor(@pm.kb_account_id, @form_fields, properties, @call_context)
    validate_form(form)
    kb_payment_id = validate_form_property(form, 'kb_payment_id')
    validate_form_property(form, 'kb_transaction_external_key', payment_external_key)
    token = validate_form_property(form, 'token')

    # Verify the payment was created in Kill Bill
    @plugin.kb_apis.proxied_services[:payment_api].payments.size.should == 1
    @plugin.kb_apis.proxied_services[:payment_api].get_payment(kb_payment_id).transactions.first.external_key.should == payment_external_key

    # Verify GET API
    payment_infos = @plugin.get_payment_info(@pm.kb_account_id, kb_payment_id, [], @call_context)
    payment_infos.size.should == 1
    payment_infos[0].kb_payment_id.should == kb_payment_id
    payment_infos[0].transaction_type.should == :PURCHASE
    payment_infos[0].amount.should be_nil
    payment_infos[0].currency.should be_nil
    payment_infos[0].status.should == :PENDING
    payment_infos[0].gateway_error.should == '{"payment_plugin_status":"PENDING"}'
    payment_infos[0].gateway_error_code.should be_nil

    # Verify the payment cannot go through without the token
    purchase_with_missing_token

    properties = []
    properties << build_property('token', token)

    # Verify the payment cannot go through until the token is validated
    purchase_with_invalid_token(properties)

    validate_token(form)

    purchase_and_refund(kb_payment_id, payment_external_key, properties)

    # Verify no extra payment was created in Kill Bill by the plugin
    @plugin.kb_apis.proxied_services[:payment_api].payments.size.should == 1

    # Verify the token cannot be re-used
    subsequent_purchase(properties)

    # Verify no token/baid was stored
    verify_payment_method
  end

  private

  def validate_form(form)
    form.kb_account_id.should == @pm.kb_account_id
    form.form_url.should start_with('https://www.sandbox.paypal.com/cgi-bin/webscr')
  end

  def validate_nil_form_property(form, key)
    key_properties = form.properties.select { |prop| prop.key == key }
    key_properties.size.should == 0
  end<commit_msg>hpp: verify the flow can be invoked multiple times for the same payment method<commit_after>require 'spec_helper'

ActiveMerchant::Billing::Base.mode = :test

describe Killbill::PaypalExpress::PaymentPlugin do

  include ::Killbill::Plugin::ActiveMerchant::RSpec

  before(:all) do
    @plugin = build_plugin(::Killbill::PaypalExpress::PaymentPlugin, 'paypal_express')
    svcs = @plugin.kb_apis.proxied_services
    svcs[:payment_api] = PaypalExpressJavaPaymentApi.new(@plugin)
    @plugin.kb_apis = ::Killbill::Plugin::KillbillApi.new('paypal_express', svcs)
    @plugin.start_plugin

    @call_context = build_call_context

    @amount = BigDecimal.new('100')
    @currency = 'USD'
    @form_fields  = @plugin.hash_to_properties(
        :order_id => '1234',
        :amount   => @amount,
        :currency => @currency
    )

    kb_account_id = SecureRandom.uuid
    create_kb_account(kb_account_id, @plugin.kb_apis.proxied_services[:account_user_api])

    @pm = create_payment_method(::Killbill::PaypalExpress::PaypalExpressPaymentMethod, kb_account_id, @call_context.tenant_id)
    verify_payment_method
  end

  before(:each) do
    ::Killbill::PaypalExpress::PaypalExpressTransaction.delete_all
    ::Killbill::PaypalExpress::PaypalExpressResponse.delete_all
  end

  it 'should generate forms correctly' do
    ::Killbill::PaypalExpress::PaypalExpressTransaction.count.should == 0
    ::Killbill::PaypalExpress::PaypalExpressResponse.count.should == 0

    # Verify multiple payments can be triggered for the same payment method
    n = 2
    1.upto(n) do
      form = @plugin.build_form_descriptor(@pm.kb_account_id, @form_fields, [], @call_context)
      validate_form(form)
      validate_nil_form_property(form, 'kb_payment_id')
      validate_nil_form_property(form, 'kb_transaction_external_key')
      token = validate_form_property(form, 'token')

      # Verify no payment was created in Kill Bill
      @plugin.kb_apis.proxied_services[:payment_api].payments.should be_empty

      # Verify the payment cannot go through without the token
      purchase_with_missing_token

      properties = []
      properties << build_property('token', token)

      # Verify the payment cannot go through until the token is validated
      purchase_with_invalid_token(properties)

      validate_token(form)

      purchase_and_refund(SecureRandom.uuid, SecureRandom.uuid, properties)

      # Verify no extra payment was created in Kill Bill by the plugin
      @plugin.kb_apis.proxied_services[:payment_api].payments.should be_empty

      # Verify the token cannot be re-used
      subsequent_purchase(properties)

      # Verify no token/baid was stored
      verify_payment_method
    end

    # Each loop triggers one successful purchase and one successful refund
    ::Killbill::PaypalExpress::PaypalExpressTransaction.count.should == 2 * n
    ::Killbill::PaypalExpress::PaypalExpressResponse.count.should == 9 * n
  end

  it 'should generate forms with pending payments correctly' do
    ::Killbill::PaypalExpress::PaypalExpressTransaction.count.should == 0
    ::Killbill::PaypalExpress::PaypalExpressResponse.count.should == 0

    # Verify multiple payments can be triggered for the same payment method
    n = 2
    1.upto(n) do |i|
      payment_external_key = SecureRandom.uuid
      properties = @plugin.hash_to_properties(
          :transaction_external_key => payment_external_key,
          :create_pending_payment => true
      )

      form = @plugin.build_form_descriptor(@pm.kb_account_id, @form_fields, properties, @call_context)
      validate_form(form)
      kb_payment_id = validate_form_property(form, 'kb_payment_id')
      validate_form_property(form, 'kb_transaction_external_key', payment_external_key)
      token = validate_form_property(form, 'token')

      # Verify the payment was created in Kill Bill
      @plugin.kb_apis.proxied_services[:payment_api].payments.size.should == i
      @plugin.kb_apis.proxied_services[:payment_api].get_payment(kb_payment_id).transactions.first.external_key.should == payment_external_key

      # Verify GET API
      payment_infos = @plugin.get_payment_info(@pm.kb_account_id, kb_payment_id, [], @call_context)
      payment_infos.size.should == 1
      payment_infos[0].kb_payment_id.should == kb_payment_id
      payment_infos[0].transaction_type.should == :PURCHASE
      payment_infos[0].amount.should be_nil
      payment_infos[0].currency.should be_nil
      payment_infos[0].status.should == :PENDING
      payment_infos[0].gateway_error.should == '{"payment_plugin_status":"PENDING"}'
      payment_infos[0].gateway_error_code.should be_nil

      # Verify the payment cannot go through without the token
      purchase_with_missing_token

      properties = []
      properties << build_property('token', token)

      # Verify the payment cannot go through until the token is validated
      purchase_with_invalid_token(properties)

      validate_token(form)

      purchase_and_refund(kb_payment_id, payment_external_key, properties)

      # Verify no extra payment was created in Kill Bill by the plugin
      @plugin.kb_apis.proxied_services[:payment_api].payments.size.should == i

      # Verify the token cannot be re-used
      subsequent_purchase(properties)

      # Verify no token/baid was stored
      verify_payment_method
    end

    # Each loop triggers one successful purchase and one successful refund
    ::Killbill::PaypalExpress::PaypalExpressTransaction.count.should == 2 * n
    ::Killbill::PaypalExpress::PaypalExpressResponse.count.should == 10 * n
  end

  private

  def validate_form(form)
    form.kb_account_id.should == @pm.kb_account_id
    form.form_url.should start_with('https://www.sandbox.paypal.com/cgi-bin/webscr')
  end

  def validate_nil_form_property(form, key)
    key_properties = form.properties.select { |prop| prop.key == key }
    key_properties.size.should == 0
  end
{'fraction_non_alphanumeric': 0.0923149015932521, 'fraction_numerical': 0.004404873477038425, 'mean_word_length': 4.370407649723201, 'pattern_counts': {'":': 2, '<': 11, '<?xml version=': 0, '>': 13, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7472157', 'n_tokens_mistral': 3327, 'n_tokens_neox': 3205, 'n_words': 659}