braintree 4.5.0 → 4.8.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/braintree.gemspec +1 -1
  3. data/lib/braintree/enriched_customer_data.rb +21 -0
  4. data/lib/braintree/exchange_rate.rb +13 -0
  5. data/lib/braintree/exchange_rate_quote.rb +24 -0
  6. data/lib/braintree/exchange_rate_quote_gateway.rb +35 -0
  7. data/lib/braintree/exchange_rate_quote_input.rb +21 -0
  8. data/lib/braintree/exchange_rate_quote_request.rb +18 -0
  9. data/lib/braintree/exchange_rate_quote_response.rb +18 -0
  10. data/lib/braintree/gateway.rb +4 -0
  11. data/lib/braintree/payment_method_customer_data_updated_metadata.rb +24 -0
  12. data/lib/braintree/plan_gateway.rb +3 -3
  13. data/lib/braintree/risk_data/liability_shift.rb +22 -0
  14. data/lib/braintree/risk_data.rb +3 -1
  15. data/lib/braintree/successful_result.rb +2 -1
  16. data/lib/braintree/transaction.rb +24 -19
  17. data/lib/braintree/transaction_search.rb +2 -1
  18. data/lib/braintree/venmo_profile_data.rb +23 -0
  19. data/lib/braintree/version.rb +1 -1
  20. data/lib/braintree/webhook_notification.rb +5 -0
  21. data/lib/braintree/webhook_testing_gateway.rb +45 -15
  22. data/lib/braintree.rb +18 -8
  23. data/spec/integration/braintree/exchange_rate_quote_spec.rb +97 -0
  24. data/spec/integration/braintree/graphql_client_spec.rb +0 -2
  25. data/spec/integration/braintree/payment_method_nonce_spec.rb +2 -1
  26. data/spec/integration/braintree/payment_method_spec.rb +2 -2
  27. data/spec/integration/braintree/transaction_search_spec.rb +79 -0
  28. data/spec/integration/braintree/transaction_spec.rb +59 -6
  29. data/spec/integration/spec_helper.rb +6 -0
  30. data/spec/unit/braintree/enriched_customer_data_spec.rb +32 -0
  31. data/spec/unit/braintree/exchange_rate_quote_input_spec.rb +42 -0
  32. data/spec/unit/braintree/exchange_rate_quote_request_spec.rb +82 -0
  33. data/spec/unit/braintree/exchange_rate_quote_response_spec.rb +52 -0
  34. data/spec/unit/braintree/exchange_rate_quote_spec.rb +42 -0
  35. data/spec/unit/braintree/exchange_rate_spec.rb +23 -0
  36. data/spec/unit/braintree/payment_method_customer_data_updated_metadata_spec.rb +45 -0
  37. data/spec/unit/braintree/risk_data/liability_shift.rb +26 -0
  38. data/spec/unit/braintree/risk_data_spec.rb +33 -7
  39. data/spec/unit/braintree/transaction_spec.rb +8 -0
  40. data/spec/unit/braintree/venmo_profile_data_spec.rb +32 -0
  41. data/spec/unit/braintree/webhook_notification_spec.rb +26 -0
  42. metadata +24 -4
@@ -0,0 +1,97 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
2
+ require File.expand_path(File.dirname(__FILE__) + "/client_api/spec_helper")
3
+
4
+ describe Braintree::ExchangeRateQuoteGateway do
5
+ let(:gateway) do
6
+ Braintree::Gateway.new(
7
+ :environment => :development,
8
+ :merchant_id => "integration_merchant_id",
9
+ :public_key => "integration_public_key",
10
+ :private_key => "integration_private_key",
11
+ )
12
+ end
13
+
14
+ describe "generate" do
15
+ def quote_input_request
16
+ gateway.exchange_rate_quote.generate({quotes: [quote_input]})
17
+ end
18
+
19
+ let(:quote_input) do
20
+ {
21
+ :baseCurrency => "EUR",
22
+ :quoteCurrency => "GBP",
23
+ :baseAmount => "20.00",
24
+ :markup => "4.00"
25
+ }
26
+ end
27
+
28
+ it "generates exchange rate quotes" do
29
+ result = quote_input_request
30
+ quotes = result[:quotes]
31
+
32
+ expect(quotes[0][:id]).not_to be_nil
33
+ expect(quotes[0][:baseAmount]).not_to be_nil
34
+ expect(quotes[0][:quoteAmount]).not_to be_nil
35
+ expect(quotes[0][:exchangeRate]).not_to be_nil
36
+ expect(quotes[0][:expiresAt]).not_to be_nil
37
+ expect(quotes[0][:refreshesAt]).not_to be_nil
38
+
39
+ expect(quotes[1][:id]).not_to be_nil
40
+ expect(quotes[1][:baseAmount]).not_to be_nil
41
+ expect(quotes[1][:quoteAmount]).not_to be_nil
42
+ expect(quotes[1][:exchangeRate]).not_to be_nil
43
+ expect(quotes[1][:expiresAt]).not_to be_nil
44
+ expect(quotes[1][:refreshesAt]).not_to be_nil
45
+ end
46
+
47
+ context "when base currency input param is not passed" do
48
+ let(:quote_input) do
49
+ {
50
+ :quoteCurrency => "GBP",
51
+ :baseAmount => "20.00",
52
+ :markup => "4.00"
53
+ }
54
+ end
55
+ let(:error_message) { "baseCurrency" }
56
+
57
+ it "raises an UnexpectedError" do
58
+ expect do
59
+ quote_input_request
60
+ end.to raise_error(Braintree::UnexpectedError, /#{error_message}/)
61
+ end
62
+ end
63
+
64
+ context "when quote currency input param is not passed" do
65
+ let(:quote_input) do
66
+ {
67
+ :baseCurrency => "GBP",
68
+ :baseAmount => "20.00",
69
+ :markup => "4.00"
70
+ }
71
+ end
72
+ let(:error_message) { "quoteCurrency" }
73
+
74
+ it "raises an UnexpectedError" do
75
+ expect do
76
+ quote_input_request
77
+ end.to raise_error(Braintree::UnexpectedError, /#{error_message}/)
78
+ end
79
+ end
80
+
81
+ context "when base and quote currency input params are not passed" do
82
+ let(:quote_input) do
83
+ {
84
+ :baseAmount => "20.00",
85
+ :markup => "4.00"
86
+ }
87
+ end
88
+ let(:error_message) { "baseCurrency" }
89
+
90
+ it "raises an UnexpectedError" do
91
+ expect do
92
+ quote_input_request
93
+ end.to raise_error(Braintree::UnexpectedError, /#{error_message}/)
94
+ end
95
+ end
96
+ end
97
+ end
@@ -28,7 +28,6 @@ describe Braintree::GraphQLClient do
28
28
  definition = <<-GRAPHQL
29
29
  mutation CreateClientToken($input: CreateClientTokenInput!) {
30
30
  createClientToken(input: $input) {
31
- clientMutationId
32
31
  clientToken
33
32
  }
34
33
  }
@@ -36,7 +35,6 @@ mutation CreateClientToken($input: CreateClientTokenInput!) {
36
35
 
37
36
  variables = {
38
37
  input: {
39
- clientMutationId: "abc123",
40
38
  clientToken: {
41
39
  merchantAccountId: "ABC123"
42
40
  }
@@ -1,5 +1,6 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
2
  require File.expand_path(File.dirname(__FILE__) + "/client_api/spec_helper")
3
+ require "date"
3
4
 
4
5
  describe Braintree::PaymentMethodNonce do
5
6
  let(:config) { Braintree::Configuration.instantiate }
@@ -84,7 +85,7 @@ describe Braintree::PaymentMethodNonce do
84
85
  nonce.details.bin.should == "401288"
85
86
  nonce.details.card_type.should == "Visa"
86
87
  nonce.details.expiration_month.should == "12"
87
- nonce.details.expiration_year.should == "2022"
88
+ nonce.details.expiration_year.should == Date.today.next_year.year.to_s
88
89
  nonce.details.is_network_tokenized?.should be_nil
89
90
  nonce.details.last_two.should == "81"
90
91
  nonce.details.payer_info.should be_nil
@@ -200,7 +200,7 @@ describe Braintree::PaymentMethod do
200
200
  venmo_account.default.should == true
201
201
  venmo_account.token.should == token
202
202
  venmo_account.username.should == "venmojoe"
203
- venmo_account.venmo_user_id.should == "Venmo-Joe-1"
203
+ venmo_account.venmo_user_id.should == "1234567891234567891"
204
204
  venmo_account.image_url.should include(".png")
205
205
  venmo_account.source_description.should == "Venmo Account: venmojoe"
206
206
  venmo_account.customer_id.should == customer.id
@@ -1163,7 +1163,7 @@ describe Braintree::PaymentMethod do
1163
1163
  venmo_account.default.should == true
1164
1164
  venmo_account.image_url.should =~ /venmo/
1165
1165
  venmo_account.username.should == "venmojoe"
1166
- venmo_account.venmo_user_id.should == "Venmo-Joe-1"
1166
+ venmo_account.venmo_user_id.should == "1234567891234567891"
1167
1167
  venmo_account.source_description.should == "Venmo Account: venmojoe"
1168
1168
  venmo_account.customer_id.should == customer.id
1169
1169
  end
@@ -174,6 +174,29 @@ describe Braintree::Transaction, "search" do
174
174
  collection.first.id.should == transaction_id
175
175
  end
176
176
 
177
+ it "searches on reason_code" do
178
+ transaction_id = "ach_txn_ret1"
179
+ reason_code = "R01"
180
+
181
+ collection = Braintree::Transaction.search do |search|
182
+ search.reason_code.in reason_code
183
+ end
184
+
185
+ collection.maximum_size.should == 1
186
+ collection.first.id.should == transaction_id
187
+ collection.first.ach_return_responses.first[:reason_code].should == "R01"
188
+ end
189
+
190
+ it "searches on reason_codes" do
191
+ reason_code = "any_reason_code"
192
+
193
+ collection = Braintree::Transaction.search do |search|
194
+ search.reason_code.is reason_code
195
+ end
196
+
197
+ collection.maximum_size.should == 2
198
+ end
199
+
177
200
  context "multiple value fields" do
178
201
  it "searches on created_using" do
179
202
  transaction = Braintree::Transaction.sale!(
@@ -419,6 +442,17 @@ describe Braintree::Transaction, "search" do
419
442
  collection.maximum_size.should == 0
420
443
  end
421
444
 
445
+ it "searches for settlement_confirmed transaction" do
446
+ transaction_id = "settlement_confirmed_txn"
447
+
448
+ collection = Braintree::Transaction.search do |search|
449
+ search.id.is transaction_id
450
+ end
451
+
452
+ collection.maximum_size.should == 1
453
+ collection.first.id.should == transaction_id
454
+ end
455
+
422
456
  it "finds expired authorizations by status" do
423
457
  collection = Braintree::Transaction.search do |search|
424
458
  search.status.in Braintree::Transaction::Status::AuthorizationExpired
@@ -521,6 +555,29 @@ describe Braintree::Transaction, "search" do
521
555
  collection.maximum_size.should == 1
522
556
  collection.first.id.should == transaction_id
523
557
  end
558
+
559
+ it "searches on reason_codes for 2 items" do
560
+ reason_code = ["R01", "R02"]
561
+
562
+ collection = Braintree::Transaction.search do |search|
563
+ search.reason_code.in reason_code
564
+ end
565
+
566
+ collection.maximum_size.should == 2
567
+ end
568
+
569
+ it "searches on a reason_code" do
570
+ reason_code = ["R01"]
571
+ transaction_id = "ach_txn_ret1"
572
+
573
+ collection = Braintree::Transaction.search do |search|
574
+ search.reason_code.in reason_code
575
+ end
576
+
577
+ collection.maximum_size.should == 1
578
+ collection.first.id.should == transaction_id
579
+ end
580
+
524
581
  end
525
582
 
526
583
  context "invalid search" do
@@ -725,6 +782,28 @@ describe Braintree::Transaction, "search" do
725
782
  end
726
783
  end
727
784
 
785
+ context "ach return response created at" do
786
+ it "it finds records within date range of the custom field" do
787
+ reason_code = "any_reason_code"
788
+
789
+ date_search = Braintree::Transaction.search do |search|
790
+ search.ach_return_responses_created_at.between(DateTime.now - 1.0, DateTime.now + 1.0)
791
+ end
792
+
793
+ date_search.maximum_size.should == 2
794
+ end
795
+
796
+ it "it does not find records not within date range of the custom field" do
797
+ reason_code = "any_reason_code"
798
+
799
+ neg_date_search = Braintree::Transaction.search do |search|
800
+ search.ach_return_responses_created_at.between(DateTime.now + 1.0, DateTime.now - 1.0)
801
+ end
802
+
803
+ neg_date_search.maximum_size.should == 0
804
+ end
805
+ end
806
+
728
807
  context "disbursement_date" do
729
808
  it "searches on disbursement_date in UTC, as a date" do
730
809
  disbursement_time = Date.parse("2013-04-10")
@@ -133,16 +133,36 @@ describe Braintree::Transaction do
133
133
  :expiration_date => "05/2009"
134
134
  },
135
135
  )
136
- result.transaction.risk_data.should be_a(Braintree::RiskData)
137
- result.transaction.risk_data.id.should_not be_nil
138
- result.transaction.risk_data.decision.should_not be_nil
139
- result.transaction.risk_data.decision_reasons.should_not be_nil
136
+ expect(result.transaction.risk_data).to be_a(Braintree::RiskData)
137
+ expect(result.transaction.risk_data.id).not_to be_nil
138
+ expect(result.transaction.risk_data.decision).not_to be_nil
139
+ expect(result.transaction.risk_data.decision_reasons).not_to be_nil
140
140
  expect(result.transaction.risk_data).to respond_to(:device_data_captured)
141
141
  expect(result.transaction.risk_data).to respond_to(:fraud_service_provider)
142
142
  expect(result.transaction.risk_data).to respond_to(:transaction_risk_score)
143
143
  end
144
144
  end
145
145
 
146
+ it "returns decision, device_data_captured, id, liability_shift, and decision_reasons" do
147
+ with_chargeback_protection_merchant do
148
+ result = Braintree::Transaction.create(
149
+ :type => "sale",
150
+ :amount => 1_00,
151
+ :credit_card => {
152
+ :number => "4111111111111111",
153
+ :expiration_date => "05/2009"
154
+ },
155
+ )
156
+ expect(result.transaction.risk_data).to be_a(Braintree::RiskData)
157
+ expect(result.transaction.risk_data.id).not_to be_nil
158
+ expect(result.transaction.risk_data.decision).not_to be_nil
159
+ expect(result.transaction.risk_data.decision_reasons).not_to be_nil
160
+ expect(result.transaction.risk_data).to respond_to(:device_data_captured)
161
+ expect(result.transaction.risk_data).to respond_to(:fraud_service_provider)
162
+ expect(result.transaction.risk_data).to respond_to(:liability_shift)
163
+ end
164
+ end
165
+
146
166
  it "handles validation errors for invalid risk data attributes" do
147
167
  with_advanced_fraud_kount_integration_merchant do
148
168
  result = Braintree::Transaction.create(
@@ -160,7 +180,7 @@ describe Braintree::Transaction do
160
180
  :customer_tenure => "20#{"0" * 500}"
161
181
  },
162
182
  )
163
- result.success?.should == false
183
+ expect(result.success?).to eq(false)
164
184
  result.errors.for(:transaction).for(:risk_data).on(:customer_device_id).map { |e| e.code }.should include Braintree::ErrorCodes::RiskData::CustomerDeviceIdIsTooLong
165
185
  result.errors.for(:transaction).for(:risk_data).on(:customer_location_zip).map { |e| e.code }.should include Braintree::ErrorCodes::RiskData::CustomerLocationZipInvalidCharacters
166
186
  result.errors.for(:transaction).for(:risk_data).on(:customer_tenure).map { |e| e.code }.should include Braintree::ErrorCodes::RiskData::CustomerTenureIsTooLong
@@ -1947,7 +1967,7 @@ describe Braintree::Transaction do
1947
1967
  venmo_account_details.should be_a(Braintree::Transaction::VenmoAccountDetails)
1948
1968
  venmo_account_details.token.should respond_to(:to_str)
1949
1969
  venmo_account_details.username.should == "venmojoe"
1950
- venmo_account_details.venmo_user_id.should == "Venmo-Joe-1"
1970
+ venmo_account_details.venmo_user_id.should == "1234567891234567891"
1951
1971
  venmo_account_details.image_url.should include(".png")
1952
1972
  venmo_account_details.source_description.should == "Venmo Account: venmojoe"
1953
1973
  end
@@ -6941,6 +6961,39 @@ describe Braintree::Transaction do
6941
6961
  end
6942
6962
  end
6943
6963
 
6964
+ describe "retried flag presence in response" do
6965
+ it "creates a retried transaction" do
6966
+ result = Braintree::Transaction.sale(
6967
+ :amount => Braintree::Test::TransactionAmounts::Decline,
6968
+ :payment_method_token => "network_tokenized_credit_card",
6969
+ )
6970
+ transaction = result.transaction
6971
+ transaction.retried.should == true
6972
+ end
6973
+
6974
+ it "creates a non-retried transaction" do
6975
+ result = Braintree::Transaction.sale(
6976
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
6977
+ :payment_method_token => "network_tokenized_credit_card",
6978
+ )
6979
+ transaction = result.transaction
6980
+ transaction.retried.should == nil
6981
+ end
6982
+
6983
+ it "creates a transaction that is ineligible for retries" do
6984
+ result = Braintree::Transaction.sale(
6985
+ :merchant_account_id => SpecHelper::NonDefaultMerchantAccountId,
6986
+ :credit_card => {
6987
+ :number => Braintree::Test::CreditCardNumbers::Visa,
6988
+ :expiration_date => "05/2009"
6989
+ },
6990
+ :amount => Braintree::Test::TransactionAmounts::Authorize,
6991
+ )
6992
+ transaction = result.transaction
6993
+ transaction.retried.should == nil
6994
+ end
6995
+ end
6996
+
6944
6997
  describe "installments" do
6945
6998
  it "creates a transaction with an installment count" do
6946
6999
  result = Braintree::Transaction.create(
@@ -54,6 +54,12 @@ unless defined?(INTEGRATION_SPEC_HELPER_LOADED)
54
54
  end
55
55
  end
56
56
 
57
+ def with_chargeback_protection_merchant(&block)
58
+ with_other_merchant("fraud_protection_effortless_chargeback_protection_merchant_id", "effortless_chargeback_protection_public_key", "effortless_chargeback_protection_private_key") do
59
+ block.call
60
+ end
61
+ end
62
+
57
63
  def with_altpay_merchant(&block)
58
64
  with_other_merchant("altpay_merchant", "altpay_merchant_public_key", "altpay_merchant_private_key", &block)
59
65
  end
@@ -0,0 +1,32 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Braintree::EnrichedCustomerData do
4
+ describe "self.new" do
5
+ it "is protected" do
6
+ expect do
7
+ Braintree::EnrichedCustomerData.new
8
+ end.to raise_error(NoMethodError, /protected method .new/)
9
+ end
10
+ end
11
+
12
+ describe "self._new" do
13
+ it "initializes the object with the appropriate attributes set" do
14
+
15
+ params = {
16
+ fields_updated: ["username"],
17
+ profile_data: {
18
+ username: "a-username",
19
+ first_name: "a-first-name",
20
+ last_name: "a-last-name",
21
+ phone_number: "a-phone-number",
22
+ email: "a-email",
23
+ },
24
+ }
25
+
26
+ payment_method_customer_data_updated = Braintree::EnrichedCustomerData._new(params)
27
+
28
+ payment_method_customer_data_updated.profile_data.should be_a(Braintree::VenmoProfileData)
29
+ payment_method_customer_data_updated.fields_updated.should eq(["username"])
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,42 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Braintree::ExchangeRateQuoteInput do
4
+ let(:exchange_rate_quote_input) do
5
+ {
6
+ base_currency: "USD",
7
+ quote_currency: "EUR",
8
+ base_amount: "10.00",
9
+ markup: "2.00"
10
+ }
11
+ end
12
+
13
+ describe "#initialize" do
14
+ it "initialize and sets the input keys to attrs variable" do
15
+ quote_input = described_class.new(exchange_rate_quote_input)
16
+
17
+ expect(quote_input.attrs).to include(:base_currency)
18
+ expect(quote_input.attrs).to include(:quote_currency)
19
+ expect(quote_input.attrs).to include(:base_amount)
20
+ expect(quote_input.attrs).to include(:markup)
21
+ expect(quote_input.attrs.length).to eq(4)
22
+ end
23
+ end
24
+
25
+ describe "inspect" do
26
+ it "includes the base_currency first" do
27
+ output = described_class.new(base_currency: "USD").inspect
28
+
29
+ expect(output).to include("#<Braintree::ExchangeRateQuoteInput base_currency:\"USD\">")
30
+ end
31
+
32
+ it "includes all quote input attributes" do
33
+ quote_input = described_class.new(exchange_rate_quote_input)
34
+ output = quote_input.inspect
35
+
36
+ expect(output).to include("base_currency:\"USD\"")
37
+ expect(output).to include("quote_currency:\"EUR\"")
38
+ expect(output).to include("base_amount:\"10.00\"")
39
+ expect(output).to include("markup:\"2.00\"")
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,82 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Braintree::ExchangeRateQuoteRequest do
4
+ describe "#initialize" do
5
+ it "creates and validates the exchange rate quote request" do
6
+ req = Braintree::ExchangeRateQuoteRequest.new(
7
+ :quotes => [
8
+ {
9
+ :base_currency => "USD",
10
+ :quote_currency => "EUR",
11
+ :base_amount => "10.00",
12
+ :markup => "2.00"
13
+ },
14
+ {
15
+ :base_currency => "EUR",
16
+ :quote_currency => "GBP",
17
+ :base_amount => "20.00",
18
+ :markup => "4.00"
19
+ }
20
+ ],
21
+ )
22
+
23
+ expect(req.quotes[0].base_currency).to eq("USD")
24
+ expect(req.quotes[0].quote_currency).to eq("EUR")
25
+ expect(req.quotes[0].base_amount).to eq("10.00")
26
+ expect(req.quotes[0].markup).to eq("2.00")
27
+
28
+ expect(req.quotes[1].base_currency).to eq("EUR")
29
+ expect(req.quotes[1].quote_currency).to eq("GBP")
30
+ expect(req.quotes[1].base_amount).to eq("20.00")
31
+ expect(req.quotes[1].markup).to eq("4.00")
32
+ end
33
+
34
+ it "creates and validates the exchange rate quote request without amount and markup" do
35
+ req = Braintree::ExchangeRateQuoteRequest.new(
36
+ :quotes => [
37
+ {
38
+ :base_currency => "USD",
39
+ :quote_currency => "EUR",
40
+ },
41
+ {
42
+ :base_currency => "EUR",
43
+ :quote_currency => "GBP",
44
+ }
45
+ ],
46
+ )
47
+
48
+ expect(req.quotes[0].base_currency).to eq("USD")
49
+ expect(req.quotes[0].quote_currency).to eq("EUR")
50
+ expect(req.quotes[0].base_amount).to be_nil
51
+ expect(req.quotes[0].markup).to be_nil
52
+
53
+ expect(req.quotes[1].base_currency).to eq("EUR")
54
+ expect(req.quotes[1].quote_currency).to eq("GBP")
55
+ expect(req.quotes[1].base_amount).to be_nil
56
+ expect(req.quotes[1].markup).to be_nil
57
+ end
58
+
59
+ end
60
+
61
+ describe "inspect" do
62
+ it "prints the attributes" do
63
+ exchange_rate_req = Braintree::ExchangeRateQuoteRequest.new(
64
+ :quotes => [
65
+ {
66
+ :base_currency => "USD",
67
+ :quote_currency => "EUR",
68
+ :base_amount => "10.00",
69
+ :markup => "2.00"
70
+ },
71
+ {
72
+ :base_currency => "EUR",
73
+ :quote_currency => "GBP",
74
+ :base_amount => "20.00",
75
+ :markup => "4.00"
76
+ }
77
+ ],
78
+ )
79
+ expect(exchange_rate_req.inspect).to eq(%(#<Braintree::ExchangeRateQuoteRequest quotes:[#<Braintree::ExchangeRateQuoteInput base_currency:"USD" quote_currency:"EUR" base_amount:"10.00" markup:"2.00">, #<Braintree::ExchangeRateQuoteInput base_currency:"EUR" quote_currency:"GBP" base_amount:"20.00" markup:"4.00">]>))
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,52 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Braintree::ExchangeRateQuoteResponse do
4
+ describe "#initialize" do
5
+ it "creates and validated the exchange rate quote payload" do
6
+ quote_payload = Braintree::ExchangeRateQuoteResponse.new(
7
+ quotes: [
8
+ {
9
+ :base_amount => "10.00",
10
+ :quote_amount => "9.03",
11
+ :exchange_rate => "0.90"
12
+ },
13
+ {
14
+ :base_amount => "20.00",
15
+ :quote_amount => "18.06",
16
+ :exchange_rate => "0.90"
17
+ }
18
+ ],
19
+ )
20
+
21
+ quote_1 = quote_payload.quotes[0]
22
+ quote_2 = quote_payload.quotes[1]
23
+
24
+ expect(quote_1.base_amount).to eq("10.00")
25
+ expect(quote_1.quote_amount).to eq("9.03")
26
+ expect(quote_1.exchange_rate).to eq("0.90")
27
+
28
+ expect(quote_2.base_amount).to eq("20.00")
29
+ expect(quote_2.quote_amount).to eq("18.06")
30
+ expect(quote_1.exchange_rate).to eq("0.90")
31
+ end
32
+ end
33
+
34
+ describe "inspect" do
35
+ it "prints the attributes" do
36
+ exchange_rate_quote_payload = Braintree::ExchangeRateQuoteResponse.new(
37
+ quotes: [
38
+ {
39
+ :base_amount => "10.00",
40
+ :quote_amount => "9.03"
41
+ },
42
+ {
43
+ :base_amount => "20.00",
44
+ :quote_amount => "18.06"
45
+ }
46
+ ],
47
+ )
48
+
49
+ expect(exchange_rate_quote_payload.inspect).to eq(%(#<Braintree::ExchangeRateQuoteResponse quotes:[#<Braintree::ExchangeRateQuote base_amount:"10.00" quote_amount:"9.03">, #<Braintree::ExchangeRateQuote base_amount:"20.00" quote_amount:"18.06">]>))
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,42 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Braintree::ExchangeRateQuote do
4
+ let(:rate_quote) do
5
+ {
6
+ id: "1234",
7
+ base_amount: "10.00",
8
+ exchange_rate: "74",
9
+ quote_amount: "740"
10
+ }
11
+ end
12
+
13
+ describe "#initialize" do
14
+ it "initialize and sets the input keys to attrs variable" do
15
+ quote = described_class.new(rate_quote)
16
+
17
+ expect(quote.attrs).to include(:id)
18
+ expect(quote.attrs).to include(:base_amount)
19
+ expect(quote.attrs).to include(:exchange_rate)
20
+ expect(quote.attrs).to include(:quote_amount)
21
+ expect(quote.attrs.length).to eq(4)
22
+ end
23
+ end
24
+
25
+ describe "inspect" do
26
+ it "includes the id first" do
27
+ output = described_class.new(id: "1234").inspect
28
+
29
+ expect(output).to include("#<Braintree::ExchangeRateQuote id:\"1234\">")
30
+ end
31
+
32
+ it "includes all quote attributes" do
33
+ quote = described_class.new(rate_quote)
34
+ output = quote.inspect
35
+
36
+ expect(output).to include("id:\"1234\"")
37
+ expect(output).to include("base_amount:\"10.00\"")
38
+ expect(output).to include("exchange_rate:\"74\"")
39
+ expect(output).to include("quote_amount:\"740\"")
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe ::Braintree::ExchangeRate do
4
+ let(:rate_quote) do
5
+ {
6
+ id: "1234",
7
+ base_amount: "10.00",
8
+ exchange_rate: "74",
9
+ quote_amount: "740"
10
+ }
11
+ end
12
+
13
+ describe "#initialize" do
14
+ it "initialize and sets the attributes" do
15
+ exchange_rate = described_class.new(:gateway, rate_quote).inspect
16
+
17
+ expect(exchange_rate).to include("@id=\"1234\"")
18
+ expect(exchange_rate).to include("@base_amount=\"10.00\"")
19
+ expect(exchange_rate).to include("@exchange_rate=\"74\"")
20
+ expect(exchange_rate).to include("@quote_amount=\"740\"")
21
+ end
22
+ end
23
+ end