braintree 2.90.0 → 2.91.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/braintree.gemspec +5 -0
- data/lib/braintree/configuration.rb +39 -1
- data/lib/braintree/credit_card.rb +1 -0
- data/lib/braintree/error_codes.rb +8 -0
- data/lib/braintree/graphql_client.rb +28 -0
- data/lib/braintree/http.rb +21 -9
- data/lib/braintree/local_payment_completed.rb +20 -0
- data/lib/braintree/test/credit_card.rb +2 -0
- data/lib/braintree/transaction.rb +8 -0
- data/lib/braintree/transaction_gateway.rb +4 -0
- data/lib/braintree/util.rb +44 -3
- data/lib/braintree/validation_error.rb +10 -2
- data/lib/braintree/validation_error_collection.rb +2 -1
- data/lib/braintree/version.rb +1 -1
- data/lib/braintree/webhook_notification.rb +5 -1
- data/lib/braintree/webhook_testing_gateway.rb +34 -3
- data/lib/braintree.rb +3 -1
- data/spec/integration/braintree/credit_card_spec.rb +14 -0
- data/spec/integration/braintree/dispute_spec.rb +3 -0
- data/spec/integration/braintree/graphql_client_spec.rb +74 -0
- data/spec/integration/braintree/http_spec.rb +1 -1
- data/spec/integration/braintree/transaction_search_spec.rb +19 -0
- data/spec/integration/braintree/transaction_spec.rb +203 -2
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/braintree/configuration_spec.rb +37 -0
- data/spec/unit/braintree/http_spec.rb +65 -0
- data/spec/unit/braintree/local_payment_completed_spec.rb +24 -0
- data/spec/unit/braintree/transaction_spec.rb +8 -0
- data/spec/unit/braintree/util_spec.rb +109 -0
- data/spec/unit/braintree/validation_error_collection_spec.rb +335 -132
- data/spec/unit/braintree/webhook_notification_spec.rb +31 -0
- metadata +10 -3
@@ -18,7 +18,7 @@ describe Braintree::Http do
|
|
18
18
|
it "raises an AuthorizationError if authorization fails" do
|
19
19
|
expect do
|
20
20
|
config = Braintree::Configuration.instantiate
|
21
|
-
config.http.get("#{config.base_merchant_path}/
|
21
|
+
config.http.get("#{config.base_merchant_path}/home")
|
22
22
|
end.to raise_error(Braintree::AuthorizationError)
|
23
23
|
end
|
24
24
|
end
|
@@ -293,6 +293,25 @@ describe Braintree::Transaction, "search" do
|
|
293
293
|
collection.maximum_size.should == 0
|
294
294
|
end
|
295
295
|
|
296
|
+
it "searches for an Elo card" do
|
297
|
+
transaction = Braintree::Transaction.sale!(
|
298
|
+
:amount => Braintree::Test::TransactionAmounts::Authorize,
|
299
|
+
:merchant_account_id => SpecHelper::AdyenMerchantAccountId,
|
300
|
+
:credit_card => {
|
301
|
+
:number => Braintree::Test::CreditCardNumbers::Elo,
|
302
|
+
:cvv => "737",
|
303
|
+
:expiration_date => "10/2020"
|
304
|
+
}
|
305
|
+
)
|
306
|
+
|
307
|
+
collection = Braintree::Transaction.search do |search|
|
308
|
+
search.id.is transaction.id
|
309
|
+
search.credit_card_card_type.is Braintree::CreditCard::CardType::Elo
|
310
|
+
end
|
311
|
+
|
312
|
+
collection.maximum_size.should == 1
|
313
|
+
end
|
314
|
+
|
296
315
|
it "searches by payment instrument type CreditCardDetail" do
|
297
316
|
transaction = Braintree::Transaction.sale!(
|
298
317
|
:amount => Braintree::Test::TransactionAmounts::Authorize,
|
@@ -248,6 +248,31 @@ describe Braintree::Transaction do
|
|
248
248
|
end
|
249
249
|
end
|
250
250
|
|
251
|
+
context "elo" do
|
252
|
+
it "returns a successful result if successful" do
|
253
|
+
result = Braintree::Transaction.create(
|
254
|
+
:type => "sale",
|
255
|
+
:merchant_account_id => SpecHelper::AdyenMerchantAccountId,
|
256
|
+
:amount => Braintree::Test::TransactionAmounts::Authorize,
|
257
|
+
:credit_card => {
|
258
|
+
:number => Braintree::Test::CreditCardNumbers::Elo,
|
259
|
+
:cvv => "737",
|
260
|
+
:expiration_date => "10/2020"
|
261
|
+
}
|
262
|
+
)
|
263
|
+
result.success?.should == true
|
264
|
+
result.transaction.id.should =~ /^\w{6,}$/
|
265
|
+
result.transaction.type.should == "sale"
|
266
|
+
result.transaction.amount.should == BigDecimal.new(Braintree::Test::TransactionAmounts::Authorize)
|
267
|
+
result.transaction.processor_authorization_code.should_not be_nil
|
268
|
+
result.transaction.voice_referral_number.should be_nil
|
269
|
+
result.transaction.credit_card_details.bin.should == Braintree::Test::CreditCardNumbers::Elo[0, 6]
|
270
|
+
result.transaction.credit_card_details.last_4.should == Braintree::Test::CreditCardNumbers::Elo[-4..-1]
|
271
|
+
result.transaction.credit_card_details.expiration_date.should == "10/2020"
|
272
|
+
result.transaction.credit_card_details.customer_location.should == "US"
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
251
276
|
it "returns a successful result if successful" do
|
252
277
|
result = Braintree::Transaction.create(
|
253
278
|
:type => "sale",
|
@@ -3617,6 +3642,182 @@ describe Braintree::Transaction do
|
|
3617
3642
|
result.errors.for(:transaction).on(:ships_from_postal_code)[0].code.should == Braintree::ErrorCodes::Transaction::ShipsFromPostalCodeInvalidCharacters
|
3618
3643
|
end
|
3619
3644
|
end
|
3645
|
+
|
3646
|
+
context "network_transaction_id" do
|
3647
|
+
it "receives network_transaction_id for visa transaction" do
|
3648
|
+
result = Braintree::Transaction.create(
|
3649
|
+
:type => "sale",
|
3650
|
+
:credit_card => {
|
3651
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
3652
|
+
:expiration_date => "05/2009"
|
3653
|
+
},
|
3654
|
+
:amount => "10.00",
|
3655
|
+
)
|
3656
|
+
result.success?.should == true
|
3657
|
+
result.transaction.network_transaction_id.should_not be_nil
|
3658
|
+
end
|
3659
|
+
end
|
3660
|
+
|
3661
|
+
context "external vault" do
|
3662
|
+
it "returns a validation error if used with an unsupported instrument type" do
|
3663
|
+
customer = Braintree::Customer.create!
|
3664
|
+
result = Braintree::PaymentMethod.create(
|
3665
|
+
:payment_method_nonce => Braintree::Test::Nonce::PayPalFuturePayment,
|
3666
|
+
:customer_id => customer.id
|
3667
|
+
)
|
3668
|
+
payment_method_token = result.payment_method.token
|
3669
|
+
|
3670
|
+
result = Braintree::Transaction.create(
|
3671
|
+
:type => "sale",
|
3672
|
+
:customer_id => customer.id,
|
3673
|
+
:payment_method_token => payment_method_token,
|
3674
|
+
:external_vault => {
|
3675
|
+
:status => Braintree::Transaction::ExternalVault::Status::WillVault,
|
3676
|
+
},
|
3677
|
+
:amount => "10.00",
|
3678
|
+
)
|
3679
|
+
result.success?.should == false
|
3680
|
+
result.errors.for(:transaction)[0].code.should == Braintree::ErrorCodes::Transaction::PaymentInstrumentWithExternalVaultIsInvalid
|
3681
|
+
end
|
3682
|
+
|
3683
|
+
it "reject invalid status" do
|
3684
|
+
result = Braintree::Transaction.create(
|
3685
|
+
:type => "sale",
|
3686
|
+
:credit_card => {
|
3687
|
+
:number => Braintree::Test::CreditCardNumbers::MasterCard,
|
3688
|
+
:expiration_date => "05/2009"
|
3689
|
+
},
|
3690
|
+
:external_vault => {
|
3691
|
+
:status => "not_valid",
|
3692
|
+
},
|
3693
|
+
:amount => "10.00",
|
3694
|
+
)
|
3695
|
+
result.success?.should == false
|
3696
|
+
result.errors.for(:transaction).for(:external_vault).on(:status)[0].code.should == Braintree::ErrorCodes::Transaction::ExternalVault::StatusIsInvalid
|
3697
|
+
end
|
3698
|
+
|
3699
|
+
context "Visa" do
|
3700
|
+
it "accepts status" do
|
3701
|
+
result = Braintree::Transaction.create(
|
3702
|
+
:type => "sale",
|
3703
|
+
:credit_card => {
|
3704
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
3705
|
+
:expiration_date => "05/2009"
|
3706
|
+
},
|
3707
|
+
:external_vault => {
|
3708
|
+
:status => Braintree::Transaction::ExternalVault::Status::WillVault,
|
3709
|
+
},
|
3710
|
+
:amount => "10.00",
|
3711
|
+
)
|
3712
|
+
result.success?.should == true
|
3713
|
+
result.transaction.network_transaction_id.should_not be_nil
|
3714
|
+
end
|
3715
|
+
|
3716
|
+
it "accepts previous_network_transaction_id" do
|
3717
|
+
result = Braintree::Transaction.create(
|
3718
|
+
:type => "sale",
|
3719
|
+
:credit_card => {
|
3720
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
3721
|
+
:expiration_date => "05/2009"
|
3722
|
+
},
|
3723
|
+
:external_vault => {
|
3724
|
+
:status => Braintree::Transaction::ExternalVault::Status::Vaulted,
|
3725
|
+
:previous_network_transaction_id => "123456789012345",
|
3726
|
+
},
|
3727
|
+
:amount => "10.00",
|
3728
|
+
)
|
3729
|
+
result.success?.should == true
|
3730
|
+
result.transaction.network_transaction_id.should_not be_nil
|
3731
|
+
end
|
3732
|
+
|
3733
|
+
it "rejects non-vaulted status with previous_network_transaction_id" do
|
3734
|
+
result = Braintree::Transaction.create(
|
3735
|
+
:type => "sale",
|
3736
|
+
:credit_card => {
|
3737
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
3738
|
+
:expiration_date => "05/2009"
|
3739
|
+
},
|
3740
|
+
:external_vault => {
|
3741
|
+
:status => Braintree::Transaction::ExternalVault::Status::WillVault,
|
3742
|
+
:previous_network_transaction_id => "123456789012345",
|
3743
|
+
},
|
3744
|
+
:amount => "10.00",
|
3745
|
+
)
|
3746
|
+
result.success?.should == false
|
3747
|
+
result.errors.for(:transaction).for(:external_vault).on(:status)[0].code.should == Braintree::ErrorCodes::Transaction::ExternalVault::StatusWithPreviousNetworkTransactionIdIsInvalid
|
3748
|
+
end
|
3749
|
+
|
3750
|
+
it "rejects invalid previous_network_transaction_id" do
|
3751
|
+
result = Braintree::Transaction.create(
|
3752
|
+
:type => "sale",
|
3753
|
+
:credit_card => {
|
3754
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
3755
|
+
:expiration_date => "05/2009"
|
3756
|
+
},
|
3757
|
+
:external_vault => {
|
3758
|
+
:status => Braintree::Transaction::ExternalVault::Status::Vaulted,
|
3759
|
+
:previous_network_transaction_id => "not_and_valid_id",
|
3760
|
+
},
|
3761
|
+
:amount => "10.00",
|
3762
|
+
)
|
3763
|
+
result.success?.should == false
|
3764
|
+
result.errors.for(:transaction).for(:external_vault).on(:previous_network_transaction_id)[0].code.should == Braintree::ErrorCodes::Transaction::ExternalVault::PreviousNetworkTransactionIdIsInvalid
|
3765
|
+
end
|
3766
|
+
end
|
3767
|
+
|
3768
|
+
context "Non-Visa" do
|
3769
|
+
it "accepts status" do
|
3770
|
+
result = Braintree::Transaction.create(
|
3771
|
+
:type => "sale",
|
3772
|
+
:credit_card => {
|
3773
|
+
:number => Braintree::Test::CreditCardNumbers::MasterCard,
|
3774
|
+
:expiration_date => "05/2009"
|
3775
|
+
},
|
3776
|
+
:external_vault => {
|
3777
|
+
:status => Braintree::Transaction::ExternalVault::Status::WillVault,
|
3778
|
+
},
|
3779
|
+
:amount => "10.00",
|
3780
|
+
)
|
3781
|
+
result.success?.should == true
|
3782
|
+
result.transaction.network_transaction_id.should be_nil
|
3783
|
+
end
|
3784
|
+
|
3785
|
+
it "accepts blank previous_network_transaction_id" do
|
3786
|
+
result = Braintree::Transaction.create(
|
3787
|
+
:type => "sale",
|
3788
|
+
:credit_card => {
|
3789
|
+
:number => Braintree::Test::CreditCardNumbers::MasterCard,
|
3790
|
+
:expiration_date => "05/2009"
|
3791
|
+
},
|
3792
|
+
:external_vault => {
|
3793
|
+
:status => Braintree::Transaction::ExternalVault::Status::Vaulted,
|
3794
|
+
:previous_network_transaction_id => "",
|
3795
|
+
},
|
3796
|
+
:amount => "10.00",
|
3797
|
+
)
|
3798
|
+
result.success?.should == true
|
3799
|
+
result.transaction.network_transaction_id.should be_nil
|
3800
|
+
end
|
3801
|
+
|
3802
|
+
it "rejects previous_network_transaction_id" do
|
3803
|
+
result = Braintree::Transaction.create(
|
3804
|
+
:type => "sale",
|
3805
|
+
:credit_card => {
|
3806
|
+
:number => Braintree::Test::CreditCardNumbers::Discover,
|
3807
|
+
:expiration_date => "05/2009"
|
3808
|
+
},
|
3809
|
+
:external_vault => {
|
3810
|
+
:status => Braintree::Transaction::ExternalVault::Status::Vaulted,
|
3811
|
+
:previous_network_transaction_id => "123456789012345",
|
3812
|
+
},
|
3813
|
+
:amount => "10.00",
|
3814
|
+
)
|
3815
|
+
result.success?.should == false
|
3816
|
+
result.errors.for(:transaction).for(:external_vault).on(:previous_network_transaction_id)[0].code.should == Braintree::ErrorCodes::Transaction::ExternalVault::CardTypeIsInvalid
|
3817
|
+
end
|
3818
|
+
end
|
3819
|
+
|
3820
|
+
end
|
3620
3821
|
end
|
3621
3822
|
|
3622
3823
|
describe "self.create!" do
|
@@ -4808,8 +5009,8 @@ describe Braintree::Transaction do
|
|
4808
5009
|
it "returns an error with an invalid payment instrument type" do
|
4809
5010
|
authorized_transaction = Braintree::Transaction.sale!(
|
4810
5011
|
:amount => Braintree::Test::TransactionAmounts::Authorize,
|
4811
|
-
:merchant_account_id => SpecHelper::
|
4812
|
-
:payment_method_nonce => Braintree::Test::Nonce::
|
5012
|
+
:merchant_account_id => SpecHelper::FakeVenmoAccountMerchantAccountId,
|
5013
|
+
:payment_method_nonce => Braintree::Test::Nonce::VenmoAccount
|
4813
5014
|
)
|
4814
5015
|
|
4815
5016
|
result = Braintree::Transaction.submit_for_partial_settlement(authorized_transaction.id, 100)
|
data/spec/spec_helper.rb
CHANGED
@@ -42,6 +42,7 @@ unless defined?(SPEC_HELPER_LOADED)
|
|
42
42
|
UsBankMerchantAccountId = "us_bank_merchant_account"
|
43
43
|
AnotherUsBankMerchantAccountId = "another_us_bank_merchant_account"
|
44
44
|
IdealMerchantAccountId = "ideal_merchant_account"
|
45
|
+
AdyenMerchantAccountId = "adyen_ma"
|
45
46
|
|
46
47
|
TrialPlan = {
|
47
48
|
:description => "Plan for integration tests -- with trial",
|
@@ -167,6 +167,19 @@ describe Braintree::Configuration do
|
|
167
167
|
config = Braintree::Configuration.new :logger => nil
|
168
168
|
config.logger.should_not == nil
|
169
169
|
end
|
170
|
+
|
171
|
+
it "can set logger on gateway instance" do
|
172
|
+
gateway = Braintree::Configuration.gateway
|
173
|
+
old_logger = Braintree::Configuration.logger
|
174
|
+
|
175
|
+
new_logger = Logger.new("/dev/null")
|
176
|
+
|
177
|
+
gateway.config.logger = new_logger
|
178
|
+
|
179
|
+
expect(gateway.config.logger).to eq(new_logger)
|
180
|
+
|
181
|
+
gateway.config.logger = old_logger
|
182
|
+
end
|
170
183
|
end
|
171
184
|
|
172
185
|
describe "self.environment" do
|
@@ -183,6 +196,14 @@ describe Braintree::Configuration do
|
|
183
196
|
Braintree::Configuration.environment
|
184
197
|
end.to raise_error(Braintree::ConfigurationError, "Braintree::Configuration.environment needs to be set")
|
185
198
|
end
|
199
|
+
|
200
|
+
it "converts environment to symbol" do
|
201
|
+
config = Braintree::Configuration.new({
|
202
|
+
:environment => "sandbox"
|
203
|
+
})
|
204
|
+
|
205
|
+
expect(config.environment).to eq(:sandbox)
|
206
|
+
end
|
186
207
|
end
|
187
208
|
|
188
209
|
describe "self.gateway" do
|
@@ -335,6 +356,22 @@ describe Braintree::Configuration do
|
|
335
356
|
end
|
336
357
|
end
|
337
358
|
|
359
|
+
describe "graphql_server" do
|
360
|
+
it "is localhost or GRAPHQL_HOST environment variable for development" do
|
361
|
+
Braintree::Configuration.environment = :development
|
362
|
+
old_gateway_url = ENV['GRAPHQL_HOST']
|
363
|
+
begin
|
364
|
+
ENV['GRAPHQL_HOST'] = nil
|
365
|
+
Braintree::Configuration.instantiate.graphql_server.should == "graphql.bt.local"
|
366
|
+
|
367
|
+
ENV['GRAPHQL_HOST'] = 'gateway'
|
368
|
+
Braintree::Configuration.instantiate.graphql_server.should == 'gateway'
|
369
|
+
ensure
|
370
|
+
ENV['GRAPHQL_HOST'] = old_gateway_url
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
338
375
|
describe "server" do
|
339
376
|
it "is localhost or GATEWAY_HOST environment variable for development" do
|
340
377
|
Braintree::Configuration.environment = :development
|
@@ -59,7 +59,9 @@ END
|
|
59
59
|
END
|
60
60
|
Braintree::Http.new(:config)._format_and_sanitize_body_for_log(input_xml).should == expected_xml
|
61
61
|
end
|
62
|
+
end
|
62
63
|
|
64
|
+
describe "self._http_do" do
|
63
65
|
it "connects when proxy address is specified" do
|
64
66
|
config = Braintree::Configuration.new(
|
65
67
|
:proxy_address => "localhost",
|
@@ -116,6 +118,69 @@ END
|
|
116
118
|
end
|
117
119
|
end
|
118
120
|
|
121
|
+
describe "_compose_headers" do
|
122
|
+
before (:each) do
|
123
|
+
config = Braintree::Configuration.new
|
124
|
+
@http = Braintree::Http.new(config)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "returns a hash of default headers" do
|
128
|
+
default_headers = @http._compose_headers
|
129
|
+
expect(default_headers["Accept"]).to eq("application/xml")
|
130
|
+
expect(default_headers["Accept-Encoding"]).to eq("gzip")
|
131
|
+
expect(default_headers["Content-Type"]).to eq("application/xml")
|
132
|
+
expect(default_headers["User-Agent"]).to match(/Braintree Ruby Gem .*/)
|
133
|
+
expect(default_headers["X-ApiVersion"]).to eq("5")
|
134
|
+
end
|
135
|
+
|
136
|
+
it "overwrites defaults with override headers" do
|
137
|
+
override_headers = {
|
138
|
+
"Accept" => "application/pdf",
|
139
|
+
"Authorization" => "token"
|
140
|
+
}
|
141
|
+
headers = @http._compose_headers(override_headers)
|
142
|
+
expect(headers["Accept"]).to eq("application/pdf")
|
143
|
+
expect(headers["Accept-Encoding"]).to eq("gzip")
|
144
|
+
expect(headers["Authorization"]).to eq("token")
|
145
|
+
expect(headers["Content-Type"]).to eq("application/xml")
|
146
|
+
expect(headers["User-Agent"]).to match(/Braintree Ruby Gem .*/)
|
147
|
+
expect(headers["X-ApiVersion"]).to eq("5")
|
148
|
+
end
|
149
|
+
|
150
|
+
it "extends default headers when new headers are specified" do
|
151
|
+
override_headers = {
|
152
|
+
"New-Header" => "New Value"
|
153
|
+
}
|
154
|
+
headers = @http._compose_headers(override_headers)
|
155
|
+
expect(headers["Accept"]).to eq("application/xml")
|
156
|
+
expect(headers["Accept-Encoding"]).to eq("gzip")
|
157
|
+
expect(headers["Content-Type"]).to eq("application/xml")
|
158
|
+
expect(headers["User-Agent"]).to match(/Braintree Ruby Gem .*/)
|
159
|
+
expect(headers["X-ApiVersion"]).to eq("5")
|
160
|
+
expect(headers["New-Header"]).to eq("New Value")
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe "_setup_connection" do
|
165
|
+
it "creates a new Net::HTTP object using default server and port" do
|
166
|
+
config = Braintree::Configuration.new
|
167
|
+
http = Braintree::Http.new(config)
|
168
|
+
|
169
|
+
connection = http._setup_connection
|
170
|
+
expect(connection.address).to eq(nil)
|
171
|
+
expect(connection.port).to eq(80)
|
172
|
+
end
|
173
|
+
|
174
|
+
it "overrides the default server and port when replacements are specified" do
|
175
|
+
config = Braintree::Configuration.new
|
176
|
+
http = Braintree::Http.new(config)
|
177
|
+
|
178
|
+
connection = http._setup_connection("localhost", 3443)
|
179
|
+
expect(connection.address).to eq("localhost")
|
180
|
+
expect(connection.port).to eq(3443)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
119
184
|
describe "_build_query_string" do
|
120
185
|
it "returns an empty string for empty query params" do
|
121
186
|
Braintree::Http.new(:config)._build_query_string({}).should == ""
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
2
|
+
|
3
|
+
describe Braintree::LocalPaymentCompleted do
|
4
|
+
describe "self.new" do
|
5
|
+
it "is protected" do
|
6
|
+
expect do
|
7
|
+
Braintree::LocalPaymentCompleted.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
|
+
params = {
|
15
|
+
payment_id: "a-payment-id",
|
16
|
+
payer_id: "a-payer-id",
|
17
|
+
}
|
18
|
+
local_payment_completed = Braintree::LocalPaymentCompleted._new(params)
|
19
|
+
|
20
|
+
local_payment_completed.payment_id.should eq("a-payment-id")
|
21
|
+
local_payment_completed.payer_id.should eq("a-payer-id")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -255,6 +255,14 @@ describe Braintree::Transaction do
|
|
255
255
|
)
|
256
256
|
transaction.risk_data.should be_nil
|
257
257
|
end
|
258
|
+
|
259
|
+
it "accepts network_transaction_id" do
|
260
|
+
transaction = Braintree::Transaction._new(
|
261
|
+
:gateway,
|
262
|
+
:network_transaction_id => "123456789012345"
|
263
|
+
)
|
264
|
+
transaction.network_transaction_id.should == "123456789012345"
|
265
|
+
end
|
258
266
|
end
|
259
267
|
|
260
268
|
describe "inspect" do
|
@@ -119,6 +119,58 @@ describe Braintree::Util do
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
+
describe "self.keys_valid?" do
|
123
|
+
it "returns true for wildcard matches" do
|
124
|
+
response = Braintree::Util.keys_valid?(
|
125
|
+
[:allowed, {:custom_fields => :_any_key_}],
|
126
|
+
:allowed => "ok",
|
127
|
+
:custom_fields => {
|
128
|
+
:custom_allowed => "ok",
|
129
|
+
:custom_allowed2 => "also ok",
|
130
|
+
}
|
131
|
+
)
|
132
|
+
expect(response).to eq(true)
|
133
|
+
end
|
134
|
+
it "raises an exception if the hash contains an invalid key" do
|
135
|
+
response = Braintree::Util.keys_valid?([:allowed], :allowed => "ok", :disallowed => "bad")
|
136
|
+
expect(response).to eq(false)
|
137
|
+
end
|
138
|
+
|
139
|
+
it "raises an exception with all keys listed if the hash contains invalid keys" do
|
140
|
+
response = Braintree::Util.keys_valid?([:allowed], :allowed => "ok", :disallowed => "bad", "also_invalid" => true)
|
141
|
+
expect(response).to eq(false)
|
142
|
+
end
|
143
|
+
|
144
|
+
it "returns false for invalid key inside of array" do
|
145
|
+
response = Braintree::Util.keys_valid?(
|
146
|
+
[{:add_ons => [{:update => [:amount]}, {:add => [:amount]}]}],
|
147
|
+
:add_ons => {
|
148
|
+
:update => [{:foo => 10}],
|
149
|
+
:add => [{:bar => 5}]
|
150
|
+
}
|
151
|
+
)
|
152
|
+
expect(response).to eq(false)
|
153
|
+
end
|
154
|
+
|
155
|
+
it "returns false if a deeply nested hash contains an invalid key" do
|
156
|
+
response = Braintree::Util.keys_valid?(
|
157
|
+
[:allowed, {:nested => [:nested_allowed, :nested_allowed2, {:deeply_allowed => [:super_deep_allowed]}]}],
|
158
|
+
:allowed => "ok",
|
159
|
+
:top_level_invalid => "bad",
|
160
|
+
:nested => {
|
161
|
+
:nested_allowed => "ok",
|
162
|
+
:nested_allowed2 => "also ok",
|
163
|
+
:nested_invalid => "bad",
|
164
|
+
:deeply_allowed => {
|
165
|
+
:super_deep_allowed => "yep",
|
166
|
+
:real_deep_invalid => "nope"
|
167
|
+
}
|
168
|
+
}
|
169
|
+
)
|
170
|
+
expect(response).to eq(false)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
122
174
|
describe "self._flatten_hash_keys" do
|
123
175
|
it "flattens hash keys" do
|
124
176
|
Braintree::Util._flatten_hash_keys(:nested => {
|
@@ -199,6 +251,63 @@ describe Braintree::Util do
|
|
199
251
|
end
|
200
252
|
end
|
201
253
|
|
254
|
+
describe "self.raise_exception_for_graphql_error" do
|
255
|
+
errors = {
|
256
|
+
"AUTHENTICATION" => Braintree::AuthenticationError,
|
257
|
+
"AUTHORIZATION" => Braintree::AuthorizationError,
|
258
|
+
"NOT_FOUND" => Braintree::NotFoundError,
|
259
|
+
"UNSUPPORTED_CLIENT" => Braintree::UpgradeRequiredError,
|
260
|
+
"RESOURCE_LIMIT" => Braintree::TooManyRequestsError,
|
261
|
+
"INTERNAL" => Braintree::ServerError,
|
262
|
+
"SERVICE_AVAILABILITY" => Braintree::DownForMaintenanceError,
|
263
|
+
}
|
264
|
+
|
265
|
+
errors.each do |graphQLError, exception|
|
266
|
+
it "raises an #{exception} when GraphQL returns an #{graphQLError} error" do
|
267
|
+
response = {
|
268
|
+
errors: [{
|
269
|
+
extensions: {
|
270
|
+
errorClass: graphQLError
|
271
|
+
}
|
272
|
+
}]
|
273
|
+
}
|
274
|
+
expect do
|
275
|
+
Braintree::Util.raise_exception_for_graphql_error(response)
|
276
|
+
end.to raise_error(exception)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
it "does not raise an exception when GraphQL returns a validation error" do
|
281
|
+
response = {
|
282
|
+
errors: [{
|
283
|
+
extensions: {
|
284
|
+
errorClass: "VALIDATION"
|
285
|
+
}
|
286
|
+
}]
|
287
|
+
}
|
288
|
+
expect do
|
289
|
+
Braintree::Util.raise_exception_for_graphql_error(response)
|
290
|
+
end.to_not raise_error()
|
291
|
+
end
|
292
|
+
|
293
|
+
it "raises any non-validation errorClass response" do
|
294
|
+
response = {
|
295
|
+
errors: [{
|
296
|
+
extensions: {
|
297
|
+
errorClass: "VALIDATION"
|
298
|
+
}
|
299
|
+
}, {
|
300
|
+
extensions: {
|
301
|
+
errorClass: "NOT_FOUND"
|
302
|
+
}
|
303
|
+
}]
|
304
|
+
}
|
305
|
+
expect do
|
306
|
+
Braintree::Util.raise_exception_for_graphql_error(response)
|
307
|
+
end.to raise_error(Braintree::NotFoundError)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
202
311
|
describe "self.raise_exception_for_status_code" do
|
203
312
|
it "raises an AuthenticationError if authentication fails" do
|
204
313
|
expect do
|