braintree 4.5.0 → 4.8.0

Sign up to get free protection for your applications and to get access to all the features.
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