braintree 2.80.1 → 2.81.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/lib/braintree.rb +4 -1
  3. data/lib/braintree/account_updater_daily_report.rb +1 -1
  4. data/lib/braintree/ach_mandate.rb +2 -1
  5. data/lib/braintree/address.rb +16 -3
  6. data/lib/braintree/amex_express_checkout_card.rb +14 -2
  7. data/lib/braintree/android_pay_card.rb +16 -3
  8. data/lib/braintree/apple_pay_card.rb +15 -3
  9. data/lib/braintree/bin_data.rb +9 -2
  10. data/lib/braintree/coinbase_account.rb +10 -1
  11. data/lib/braintree/connected_merchant_paypal_status_changed.rb +3 -1
  12. data/lib/braintree/connected_merchant_status_transitioned.rb +3 -1
  13. data/lib/braintree/credentials_parser.rb +5 -1
  14. data/lib/braintree/credit_card.rb +25 -10
  15. data/lib/braintree/credit_card_verification.rb +32 -14
  16. data/lib/braintree/customer.rb +24 -11
  17. data/lib/braintree/descriptor.rb +3 -1
  18. data/lib/braintree/disbursement.rb +9 -1
  19. data/lib/braintree/dispute.rb +1 -6
  20. data/lib/braintree/dispute/transaction_details.rb +2 -1
  21. data/lib/braintree/document_upload.rb +6 -7
  22. data/lib/braintree/error_codes.rb +30 -0
  23. data/lib/braintree/error_result.rb +8 -1
  24. data/lib/braintree/europe_bank_account.rb +3 -1
  25. data/lib/braintree/facilitated_details.rb +3 -1
  26. data/lib/braintree/facilitator_details.rb +2 -1
  27. data/lib/braintree/gateway.rb +4 -0
  28. data/lib/braintree/granted_payment_instrument_update.rb +5 -1
  29. data/lib/braintree/ideal_payment.rb +15 -2
  30. data/lib/braintree/masterpass_card.rb +26 -11
  31. data/lib/braintree/merchant.rb +8 -1
  32. data/lib/braintree/merchant_account.rb +8 -3
  33. data/lib/braintree/merchant_account/address_details.rb +4 -1
  34. data/lib/braintree/merchant_account/business_details.rb +4 -1
  35. data/lib/braintree/merchant_account/funding_details.rb +6 -1
  36. data/lib/braintree/merchant_account/individual_details.rb +7 -2
  37. data/lib/braintree/oauth_credentials.rb +4 -1
  38. data/lib/braintree/paginated_result.rb +3 -1
  39. data/lib/braintree/payment_method_nonce.rb +5 -1
  40. data/lib/braintree/paypal_account.rb +8 -1
  41. data/lib/braintree/plan.rb +4 -4
  42. data/lib/braintree/risk_data.rb +3 -1
  43. data/lib/braintree/settlement_batch_summary.rb +1 -0
  44. data/lib/braintree/subscription.rb +27 -17
  45. data/lib/braintree/subscription/status_details.rb +8 -1
  46. data/lib/braintree/successful_result.rb +19 -1
  47. data/lib/braintree/three_d_secure_info.rb +5 -1
  48. data/lib/braintree/transaction.rb +54 -48
  49. data/lib/braintree/transaction/address_details.rb +13 -4
  50. data/lib/braintree/transaction/amex_express_checkout_details.rb +9 -2
  51. data/lib/braintree/transaction/android_pay_details.rb +10 -3
  52. data/lib/braintree/transaction/apple_pay_details.rb +7 -2
  53. data/lib/braintree/transaction/coinbase_details.rb +4 -1
  54. data/lib/braintree/transaction/credit_card_details.rb +40 -6
  55. data/lib/braintree/transaction/customer_details.rb +8 -1
  56. data/lib/braintree/transaction/disbursement_details.rb +5 -1
  57. data/lib/braintree/transaction/ideal_payment_details.rb +5 -1
  58. data/lib/braintree/transaction/masterpass_card_details.rb +18 -4
  59. data/lib/braintree/transaction/paypal_details.rb +18 -4
  60. data/lib/braintree/transaction/status_details.rb +5 -1
  61. data/lib/braintree/transaction/subscription_details.rb +2 -1
  62. data/lib/braintree/transaction/us_bank_account_details.rb +8 -1
  63. data/lib/braintree/transaction/venmo_account_details.rb +5 -1
  64. data/lib/braintree/transaction/visa_checkout_card_details.rb +19 -4
  65. data/lib/braintree/transaction_gateway.rb +1 -0
  66. data/lib/braintree/transaction_line_item.rb +34 -0
  67. data/lib/braintree/transaction_line_item_gateway.rb +19 -0
  68. data/lib/braintree/unknown_payment_method.rb +2 -1
  69. data/lib/braintree/us_bank_account.rb +9 -1
  70. data/lib/braintree/util.rb +14 -0
  71. data/lib/braintree/validation_error.rb +3 -1
  72. data/lib/braintree/venmo_account.rb +10 -3
  73. data/lib/braintree/version.rb +2 -2
  74. data/lib/braintree/visa_checkout_card.rb +27 -11
  75. data/lib/braintree/webhook_notification.rb +9 -9
  76. data/spec/httpsd.pid +1 -0
  77. data/spec/integration/braintree/apple_pay_spec.rb +2 -31
  78. data/spec/integration/braintree/http_spec.rb +1 -1
  79. data/spec/integration/braintree/transaction_spec.rb +1142 -0
  80. metadata +205 -207
  81. data/README.rdoc +0 -102
@@ -3,7 +3,11 @@ module Braintree
3
3
  class StatusDetails # :nodoc:
4
4
  include BaseModule
5
5
 
6
- attr_reader :amount, :status, :timestamp, :transaction_source, :user
6
+ attr_reader :amount
7
+ attr_reader :status
8
+ attr_reader :timestamp
9
+ attr_reader :transaction_source
10
+ attr_reader :user
7
11
 
8
12
  def initialize(attributes)
9
13
  set_instance_variables_from_hash attributes unless attributes.nil?
@@ -3,7 +3,8 @@ module Braintree
3
3
  class SubscriptionDetails # :nodoc:
4
4
  include BaseModule
5
5
 
6
- attr_reader :billing_period_start_date, :billing_period_end_date
6
+ attr_reader :billing_period_end_date
7
+ attr_reader :billing_period_start_date
7
8
 
8
9
  def initialize(attributes)
9
10
  set_instance_variables_from_hash attributes unless attributes.nil?
@@ -3,7 +3,14 @@ module Braintree
3
3
  class UsBankAccountDetails # :nodoc:
4
4
  include BaseModule
5
5
 
6
- attr_reader :routing_number, :last_4, :account_type, :account_holder_name, :token, :image_url, :bank_name, :ach_mandate
6
+ attr_reader :account_holder_name
7
+ attr_reader :account_type
8
+ attr_reader :ach_mandate
9
+ attr_reader :bank_name
10
+ attr_reader :image_url
11
+ attr_reader :last_4
12
+ attr_reader :routing_number
13
+ attr_reader :token
7
14
 
8
15
  def initialize(attributes)
9
16
  set_instance_variables_from_hash attributes unless attributes.nil?
@@ -3,7 +3,11 @@ module Braintree
3
3
  class VenmoAccountDetails
4
4
  include BaseModule
5
5
 
6
- attr_reader :username, :venmo_user_id, :token, :source_description, :image_url
6
+ attr_reader :image_url
7
+ attr_reader :source_description
8
+ attr_reader :token
9
+ attr_reader :username
10
+ attr_reader :venmo_user_id
7
11
 
8
12
  def initialize(attributes)
9
13
  set_instance_variables_from_hash attributes unless attributes.nil?
@@ -3,10 +3,25 @@ module Braintree
3
3
  class VisaCheckoutCardDetails # :nodoc:
4
4
  include BaseModule
5
5
 
6
- attr_reader :bin, :card_type, :cardholder_name, :commercial, :country_of_issuance,
7
- :customer_location, :debit, :durbin_regulated, :expiration_month, :expiration_year,
8
- :healthcare, :image_url, :issuing_bank, :last_4, :payroll, :prepaid, :product_id,
9
- :token, :call_id
6
+ attr_reader :bin
7
+ attr_reader :call_id
8
+ attr_reader :card_type
9
+ attr_reader :cardholder_name
10
+ attr_reader :commercial
11
+ attr_reader :country_of_issuance
12
+ attr_reader :customer_location
13
+ attr_reader :debit
14
+ attr_reader :durbin_regulated
15
+ attr_reader :expiration_month
16
+ attr_reader :expiration_year
17
+ attr_reader :healthcare
18
+ attr_reader :image_url
19
+ attr_reader :issuing_bank
20
+ attr_reader :last_4
21
+ attr_reader :payroll
22
+ attr_reader :prepaid
23
+ attr_reader :product_id
24
+ attr_reader :token
10
25
 
11
26
  def initialize(attributes)
12
27
  set_instance_variables_from_hash attributes unless attributes.nil?
@@ -149,6 +149,7 @@ module Braintree
149
149
  :shipping_amount, :discount_amount, :ships_from_postal_code,
150
150
  :billing_address_id, :payment_method_nonce, :three_d_secure_token,
151
151
  :shared_payment_method_token, :shared_billing_address_id, :shared_customer_id, :shared_shipping_address_id, :shared_payment_method_nonce,
152
+ {:line_items => [:quantity, :name, :description, :kind, :unit_amount, :unit_tax_amount, :total_amount, :discount_amount, :unit_of_measure, :product_code, :commodity_code, :url]},
152
153
  {:risk_data => [:customer_browser, :customer_ip]},
153
154
  {:credit_card => [:token, :cardholder_name, :cvv, :expiration_date, :expiration_month, :expiration_year, :number]},
154
155
  {:customer => [:id, :company, :email, :fax, :first_name, :last_name, :phone, :website]},
@@ -0,0 +1,34 @@
1
+ module Braintree
2
+ class TransactionLineItem
3
+ include BaseModule
4
+ attr_reader :quantity
5
+ attr_reader :name
6
+ attr_reader :description
7
+ attr_reader :kind
8
+ attr_reader :unit_amount
9
+ attr_reader :unit_tax_amount
10
+ attr_reader :unit_of_measure
11
+ attr_reader :discount_amount
12
+ attr_reader :total_amount
13
+ attr_reader :product_code
14
+ attr_reader :commodity_code
15
+ attr_reader :url
16
+
17
+ def initialize(gateway, attributes) # :nodoc:
18
+ @gateway = gateway
19
+ set_instance_variables_from_hash(attributes)
20
+ @quantity = Util.to_big_decimal(quantity)
21
+ @unit_amount = Util.to_big_decimal(unit_amount)
22
+ @unit_tax_amount = Util.to_big_decimal(unit_tax_amount)
23
+ @discount_amount = Util.to_big_decimal(discount_amount)
24
+ @total_amount = Util.to_big_decimal(total_amount)
25
+ end
26
+
27
+ class << self
28
+ protected :new
29
+ def _new(*args) # :nodoc:
30
+ self.new *args
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,19 @@
1
+ module Braintree
2
+ class TransactionLineItemGateway # :nodoc:
3
+ def initialize(gateway)
4
+ @gateway = gateway
5
+ @config = gateway.config
6
+ @config.assert_has_access_token_or_keys
7
+ end
8
+
9
+ def find_all(transaction_id)
10
+ raise ArgumentError, "transaction_id cannot be blank" if transaction_id.nil? || transaction_id.strip.to_s == ""
11
+ response = @config.http.get("#{@config.base_merchant_path}/transactions/#{transaction_id}/line_items")
12
+ response[:line_items].map do |line_item_params|
13
+ TransactionLineItem._new(@gateway, line_item_params)
14
+ end
15
+ rescue NotFoundError
16
+ raise NotFoundError, "transaction with id #{transaction_id.inspect} not found"
17
+ end
18
+ end
19
+ end
@@ -2,7 +2,8 @@ module Braintree
2
2
  class UnknownPaymentMethod
3
3
  include BaseModule
4
4
 
5
- attr_reader :token, :customer_id
5
+ attr_reader :customer_id
6
+ attr_reader :token
6
7
 
7
8
  def initialize(gateway, attributes)
8
9
  @gateway = gateway
@@ -2,7 +2,15 @@ module Braintree
2
2
  class UsBankAccount
3
3
  include BaseModule
4
4
 
5
- attr_reader :routing_number, :last_4, :account_type, :account_holder_name, :token, :image_url, :bank_name, :ach_mandate, :default
5
+ attr_reader :account_holder_name
6
+ attr_reader :account_type
7
+ attr_reader :ach_mandate
8
+ attr_reader :bank_name
9
+ attr_reader :default
10
+ attr_reader :image_url
11
+ attr_reader :last_4
12
+ attr_reader :routing_number
13
+ attr_reader :token
6
14
 
7
15
  def initialize(gateway, attributes) # :nodoc:
8
16
  @gateway = gateway
@@ -137,5 +137,19 @@ module Braintree
137
137
  end
138
138
  end
139
139
  end
140
+
141
+ module IdEquality
142
+ def ==(other) # :nodoc:
143
+ return false unless other.is_a?(self.class)
144
+ id == other.id
145
+ end
146
+ end
147
+
148
+ module TokenEquality
149
+ def ==(other) # :nodoc:
150
+ return false unless other.is_a?(self.class)
151
+ token == other.token
152
+ end
153
+ end
140
154
  end
141
155
  end
@@ -2,7 +2,9 @@ module Braintree
2
2
  class ValidationError
3
3
  include BaseModule
4
4
 
5
- attr_reader :attribute, :code, :message
5
+ attr_reader :attribute
6
+ attr_reader :code
7
+ attr_reader :message
6
8
 
7
9
  def initialize(attributes)
8
10
  set_instance_variables_from_hash attributes
@@ -2,8 +2,16 @@ module Braintree
2
2
  class VenmoAccount
3
3
  include BaseModule # :nodoc:
4
4
 
5
- attr_reader :customer_id, :username, :venmo_user_id, :token, :source_description, :subscriptions,
6
- :image_url, :default, :updated_at, :created_at
5
+ attr_reader :created_at
6
+ attr_reader :customer_id
7
+ attr_reader :default
8
+ attr_reader :image_url
9
+ attr_reader :source_description
10
+ attr_reader :subscriptions
11
+ attr_reader :token
12
+ attr_reader :updated_at
13
+ attr_reader :username
14
+ attr_reader :venmo_user_id
7
15
 
8
16
  def initialize(gateway, attributes) # :nodoc:
9
17
  @gateway = gateway
@@ -24,4 +32,3 @@ module Braintree
24
32
  end
25
33
  end
26
34
  end
27
-
@@ -1,8 +1,8 @@
1
1
  module Braintree
2
2
  module Version
3
3
  Major = 2
4
- Minor = 80
5
- Tiny = 1
4
+ Minor = 81
5
+ Tiny = 0
6
6
 
7
7
  String = "#{Major}.#{Minor}.#{Tiny}"
8
8
  end
@@ -1,13 +1,34 @@
1
1
  module Braintree
2
2
  class VisaCheckoutCard
3
3
  include BaseModule # :nodoc:
4
+ include Braintree::Util::TokenEquality
4
5
 
5
- attr_reader :billing_address, :bin, :card_type, :cardholder_name,
6
- :commercial, :country_of_issuance, :created_at, :customer_id,
7
- :customer_location, :debit, :durbin_regulated, :expiration_month,
8
- :expiration_year, :healthcare, :issuing_bank, :last_4, :payroll,
9
- :prepaid, :product_id, :subscriptions, :token, :unique_number_identifier,
10
- :updated_at, :image_url, :verification, :call_id
6
+ attr_reader :billing_address
7
+ attr_reader :bin
8
+ attr_reader :call_id
9
+ attr_reader :card_type
10
+ attr_reader :cardholder_name
11
+ attr_reader :commercial
12
+ attr_reader :country_of_issuance
13
+ attr_reader :created_at
14
+ attr_reader :customer_id
15
+ attr_reader :customer_location
16
+ attr_reader :debit
17
+ attr_reader :durbin_regulated
18
+ attr_reader :expiration_month
19
+ attr_reader :expiration_year
20
+ attr_reader :healthcare
21
+ attr_reader :image_url
22
+ attr_reader :issuing_bank
23
+ attr_reader :last_4
24
+ attr_reader :payroll
25
+ attr_reader :prepaid
26
+ attr_reader :product_id
27
+ attr_reader :subscriptions
28
+ attr_reader :token
29
+ attr_reader :unique_number_identifier
30
+ attr_reader :updated_at
31
+ attr_reader :verification
11
32
 
12
33
  def initialize(gateway, attributes) # :nodoc:
13
34
  @gateway = gateway
@@ -48,11 +69,6 @@ module Braintree
48
69
  "#{bin}******#{last_4}"
49
70
  end
50
71
 
51
- def ==(other)
52
- return false unless other.is_a?(VisaCheckoutCard)
53
- token == other.token
54
- end
55
-
56
72
  class << self
57
73
  protected :new
58
74
  end
@@ -42,18 +42,18 @@ module Braintree
42
42
  GrantedPaymentInstrumentUpdate = "granted_payment_instrument_update"
43
43
  end
44
44
 
45
- attr_reader :subscription
46
- attr_reader :kind
47
- attr_reader :timestamp
48
- attr_reader :transaction
49
- attr_reader :partner_merchant
50
- attr_reader :disbursement
51
- attr_reader :dispute
52
45
  attr_reader :account_updater_daily_report
53
- attr_reader :ideal_payment
54
- attr_reader :connected_merchant_status_transitioned
55
46
  attr_reader :connected_merchant_paypal_status_changed
47
+ attr_reader :connected_merchant_status_transitioned
48
+ attr_reader :disbursement
49
+ attr_reader :dispute
56
50
  attr_reader :granted_payment_instrument_update
51
+ attr_reader :ideal_payment
52
+ attr_reader :kind
53
+ attr_reader :partner_merchant
54
+ attr_reader :subscription
55
+ attr_reader :timestamp
56
+ attr_reader :transaction
57
57
 
58
58
  def self.parse(signature, payload)
59
59
  Configuration.gateway.webhook_notification.parse(signature, payload)
@@ -0,0 +1 @@
1
+ 32587
@@ -36,57 +36,28 @@ describe Braintree::ApplePayGateway do
36
36
  describe "unregister_domain" do
37
37
  it "unregisters an apple pay domain" do
38
38
  domain = "example.org"
39
- result = @gateway.apple_pay.register_domain(domain)
40
- result.should be_success
41
-
42
39
  result = @gateway.apple_pay.unregister_domain(domain)
43
40
  result.should be_success
44
- @gateway.apple_pay.registered_domains.apple_pay_options.domains.should be_empty
45
41
  end
46
42
 
47
43
  it "unregisters an apple pay domain with scheme in url" do
48
44
  domain = "http://example.org"
49
- result = @gateway.apple_pay.register_domain(domain)
50
- result.should be_success
51
-
52
45
  result = @gateway.apple_pay.unregister_domain(domain)
53
46
  result.should be_success
54
- @gateway.apple_pay.registered_domains.apple_pay_options.domains.should be_empty
55
- end
56
-
57
- it "does not fail when unregistering a non-registered domain" do
58
- result = @gateway.apple_pay.unregister_domain("unregistered.com")
59
- result.should be_success
60
47
  end
61
48
 
62
49
  it "escapes the unregistered domain query parameter" do
63
50
  domain = "ex&mple.org"
64
- result = @gateway.apple_pay.register_domain(domain)
65
- result.should be_success
66
- @gateway.apple_pay.registered_domains.apple_pay_options.domains.should_not be_empty
67
-
68
51
  result = @gateway.apple_pay.unregister_domain(domain)
69
52
  result.should be_success
70
- @gateway.apple_pay.registered_domains.apple_pay_options.domains.should be_empty
71
53
  end
72
54
  end
73
55
 
74
56
  describe "registered_domains" do
75
- it "returns registered domains" do
76
- result = @gateway.apple_pay.register_domain("www.example.com")
77
- result.should be_success
78
- result = @gateway.apple_pay.register_domain("www.example.org")
79
- result.should be_success
80
-
81
- result = @gateway.apple_pay.registered_domains
82
- result.should be_success
83
- result.apple_pay_options.domains.should =~ ["www.example.org", "www.example.com"]
84
- end
85
-
86
- it "returns an empty list if no domains are registered" do
57
+ it "returns stubbed registered domains" do
87
58
  result = @gateway.apple_pay.registered_domains
88
59
  result.should be_success
89
- result.apple_pay_options.domains.should == []
60
+ result.apple_pay_options.domains.should == ["www.example.com"]
90
61
  end
91
62
  end
92
63
  end
@@ -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}/users")
21
+ config.http.get("#{config.base_merchant_path}/downloads")
22
22
  end.to raise_error(Braintree::AuthorizationError)
23
23
  end
24
24
  end
@@ -2243,6 +2243,1052 @@ describe Braintree::Transaction do
2243
2243
  end
2244
2244
  end
2245
2245
 
2246
+ context "line items" do
2247
+ it "allows creation with empty line items and returns none" do
2248
+ result = Braintree::Transaction.create(
2249
+ :type => "sale",
2250
+ :amount => "35.05",
2251
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2252
+ :line_items => [],
2253
+ )
2254
+ result.success?.should == true
2255
+ result.transaction.line_items.should == []
2256
+ end
2257
+
2258
+ it "allows creation with single line item with minimal fields and returns it" do
2259
+ result = Braintree::Transaction.create(
2260
+ :type => "sale",
2261
+ :amount => "45.15",
2262
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2263
+ :line_items => [
2264
+ {
2265
+ :quantity => "1.0232",
2266
+ :name => "Name #1",
2267
+ :kind => "debit",
2268
+ :unit_amount => "45.1232",
2269
+ :total_amount => "45.15",
2270
+ },
2271
+ ],
2272
+ )
2273
+ result.success?.should == true
2274
+ result.transaction.line_items.length.should == 1
2275
+ line_item = result.transaction.line_items[0]
2276
+ line_item.quantity.should == BigDecimal.new("1.0232")
2277
+ line_item.name.should == "Name #1"
2278
+ line_item.kind.should == "debit"
2279
+ line_item.unit_amount.should == BigDecimal.new("45.1232")
2280
+ line_item.total_amount.should == BigDecimal.new("45.15")
2281
+ end
2282
+
2283
+ it "allows creation with single line item and returns it" do
2284
+ result = Braintree::Transaction.create(
2285
+ :type => "sale",
2286
+ :amount => "45.15",
2287
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2288
+ :line_items => [
2289
+ {
2290
+ :quantity => "1.0232",
2291
+ :name => "Name #1",
2292
+ :description => "Description #1",
2293
+ :kind => "debit",
2294
+ :unit_amount => "45.1232",
2295
+ :unit_tax_amount => "1.23",
2296
+ :unit_of_measure => "gallon",
2297
+ :discount_amount => "1.02",
2298
+ :total_amount => "45.15",
2299
+ :product_code => "23434",
2300
+ :commodity_code => "9SAASSD8724",
2301
+ :url => "https://example.com/products/23434",
2302
+ },
2303
+ ],
2304
+ )
2305
+ result.success?.should == true
2306
+ result.transaction.line_items.length.should == 1
2307
+ line_item = result.transaction.line_items[0]
2308
+ line_item.quantity.should == BigDecimal.new("1.0232")
2309
+ line_item.name.should == "Name #1"
2310
+ line_item.description.should == "Description #1"
2311
+ line_item.kind.should == "debit"
2312
+ line_item.unit_amount.should == BigDecimal.new("45.1232")
2313
+ line_item.unit_tax_amount.should == BigDecimal.new("1.23")
2314
+ line_item.unit_of_measure.should == "gallon"
2315
+ line_item.discount_amount.should == BigDecimal.new("1.02")
2316
+ line_item.total_amount.should == BigDecimal.new("45.15")
2317
+ line_item.product_code.should == "23434"
2318
+ line_item.commodity_code.should == "9SAASSD8724"
2319
+ line_item.url.should == "https://example.com/products/23434"
2320
+ end
2321
+
2322
+ it "allows creation with multiple line items and returns them" do
2323
+ result = Braintree::Transaction.create(
2324
+ :type => "sale",
2325
+ :amount => "35.05",
2326
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2327
+ :line_items => [
2328
+ {
2329
+ :quantity => "1.0232",
2330
+ :name => "Name #1",
2331
+ :kind => "debit",
2332
+ :unit_amount => "45.1232",
2333
+ :unit_of_measure => "gallon",
2334
+ :discount_amount => "1.02",
2335
+ :total_amount => "45.15",
2336
+ :product_code => "23434",
2337
+ :commodity_code => "9SAASSD8724",
2338
+ },
2339
+ {
2340
+ :quantity => "2.02",
2341
+ :name => "Name #2",
2342
+ :kind => "credit",
2343
+ :unit_amount => "5",
2344
+ :unit_of_measure => "gallon",
2345
+ :total_amount => "10.1",
2346
+ },
2347
+ ],
2348
+ )
2349
+ result.success?.should == true
2350
+ result.transaction.line_items.length.should == 2
2351
+ line_item_1 = result.transaction.line_items.find { |line_item| line_item.name == "Name #1" }
2352
+ line_item_1.quantity.should == BigDecimal.new("1.0232")
2353
+ line_item_1.name.should == "Name #1"
2354
+ line_item_1.kind.should == "debit"
2355
+ line_item_1.unit_amount.should == BigDecimal.new("45.1232")
2356
+ line_item_1.unit_of_measure.should == "gallon"
2357
+ line_item_1.discount_amount.should == BigDecimal.new("1.02")
2358
+ line_item_1.total_amount.should == BigDecimal.new("45.15")
2359
+ line_item_1.product_code.should == "23434"
2360
+ line_item_1.commodity_code.should == "9SAASSD8724"
2361
+ line_item_2 = result.transaction.line_items.find { |line_item| line_item.name == "Name #2" }
2362
+ line_item_2.quantity.should == BigDecimal.new("2.02")
2363
+ line_item_2.name.should == "Name #2"
2364
+ line_item_2.kind.should == "credit"
2365
+ line_item_2.unit_amount.should == BigDecimal.new("5")
2366
+ line_item_2.unit_of_measure.should == "gallon"
2367
+ line_item_2.total_amount.should == BigDecimal.new("10.1")
2368
+ line_item_2.discount_amount.should == nil
2369
+ line_item_2.product_code.should == nil
2370
+ line_item_2.commodity_code.should == nil
2371
+ end
2372
+
2373
+ it "handles validation error commodity code is too long" do
2374
+ result = Braintree::Transaction.create(
2375
+ :type => "sale",
2376
+ :amount => "35.05",
2377
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2378
+ :line_items => [
2379
+ {
2380
+ :quantity => "1.2322",
2381
+ :name => "Name #1",
2382
+ :kind => "debit",
2383
+ :unit_amount => "45.1232",
2384
+ :unit_of_measure => "gallon",
2385
+ :discount_amount => "1.02",
2386
+ :total_amount => "45.15",
2387
+ :product_code => "23434",
2388
+ :commodity_code => "9SAASSD8724",
2389
+ },
2390
+ {
2391
+ :quantity => "1.2322",
2392
+ :name => "Name #2",
2393
+ :kind => "credit",
2394
+ :unit_amount => "45.1232",
2395
+ :unit_of_measure => "gallon",
2396
+ :discount_amount => "1.02",
2397
+ :total_amount => "45.15",
2398
+ :product_code => "23434",
2399
+ :commodity_code => "1234567890123",
2400
+ },
2401
+ ],
2402
+ )
2403
+ result.success?.should == false
2404
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:commodity_code)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::CommodityCodeIsTooLong
2405
+ end
2406
+
2407
+ it "handles validation error description is too long" do
2408
+ result = Braintree::Transaction.create(
2409
+ :type => "sale",
2410
+ :amount => "35.05",
2411
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2412
+ :line_items => [
2413
+ {
2414
+ :quantity => "1.2322",
2415
+ :name => "Name #1",
2416
+ :kind => "debit",
2417
+ :unit_amount => "45.1232",
2418
+ :unit_of_measure => "gallon",
2419
+ :discount_amount => "1.02",
2420
+ :total_amount => "45.15",
2421
+ :product_code => "23434",
2422
+ :commodity_code => "9SAASSD8724",
2423
+ },
2424
+ {
2425
+ :quantity => "1.2322",
2426
+ :name => "Name #2",
2427
+ :description => "X" * 128,
2428
+ :kind => "credit",
2429
+ :unit_amount => "45.1232",
2430
+ :unit_of_measure => "gallon",
2431
+ :discount_amount => "1.02",
2432
+ :total_amount => "45.15",
2433
+ :product_code => "23434",
2434
+ :commodity_code => "9SAASSD8724",
2435
+ },
2436
+ ],
2437
+ )
2438
+ result.success?.should == false
2439
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:description)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::DescriptionIsTooLong
2440
+ end
2441
+
2442
+ it "handles validation error discount amount format is invalid" do
2443
+ result = Braintree::Transaction.create(
2444
+ :type => "sale",
2445
+ :amount => "35.05",
2446
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2447
+ :line_items => [
2448
+ {
2449
+ :quantity => "1.2322",
2450
+ :name => "Name #1",
2451
+ :kind => "debit",
2452
+ :unit_amount => "45.1232",
2453
+ :unit_of_measure => "gallon",
2454
+ :discount_amount => "1.02",
2455
+ :total_amount => "45.15",
2456
+ :product_code => "23434",
2457
+ :commodity_code => "9SAASSD8724",
2458
+ },
2459
+ {
2460
+ :quantity => "1.2322",
2461
+ :name => "Name #2",
2462
+ :kind => "credit",
2463
+ :unit_amount => "45.1232",
2464
+ :unit_of_measure => "gallon",
2465
+ :discount_amount => "$1.02",
2466
+ :total_amount => "45.15",
2467
+ :product_code => "23434",
2468
+ :commodity_code => "9SAASSD8724",
2469
+ },
2470
+ ],
2471
+ )
2472
+ result.success?.should == false
2473
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:discount_amount)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::DiscountAmountFormatIsInvalid
2474
+ end
2475
+
2476
+ it "handles validation error discount amount is too large" do
2477
+ result = Braintree::Transaction.create(
2478
+ :type => "sale",
2479
+ :amount => "35.05",
2480
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2481
+ :line_items => [
2482
+ {
2483
+ :quantity => "1.2322",
2484
+ :name => "Name #1",
2485
+ :kind => "debit",
2486
+ :unit_amount => "45.1232",
2487
+ :unit_of_measure => "gallon",
2488
+ :discount_amount => "1.02",
2489
+ :total_amount => "45.15",
2490
+ :product_code => "23434",
2491
+ :commodity_code => "9SAASSD8724",
2492
+ },
2493
+ {
2494
+ :quantity => "1.2322",
2495
+ :name => "Name #2",
2496
+ :kind => "credit",
2497
+ :unit_amount => "45.1232",
2498
+ :unit_of_measure => "gallon",
2499
+ :discount_amount => "2147483648",
2500
+ :total_amount => "45.15",
2501
+ :product_code => "23434",
2502
+ :commodity_code => "9SAASSD8724",
2503
+ },
2504
+ ],
2505
+ )
2506
+ result.success?.should == false
2507
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:discount_amount)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::DiscountAmountIsTooLarge
2508
+ end
2509
+
2510
+ it "handles validation error discount amount must be greater than zero" do
2511
+ result = Braintree::Transaction.create(
2512
+ :type => "sale",
2513
+ :amount => "35.05",
2514
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2515
+ :line_items => [
2516
+ {
2517
+ :quantity => "1.2322",
2518
+ :name => "Name #1",
2519
+ :kind => "debit",
2520
+ :unit_amount => "45.1232",
2521
+ :unit_of_measure => "gallon",
2522
+ :discount_amount => "1.02",
2523
+ :total_amount => "45.15",
2524
+ :product_code => "23434",
2525
+ :commodity_code => "9SAASSD8724",
2526
+ },
2527
+ {
2528
+ :quantity => "1.2322",
2529
+ :name => "Name #2",
2530
+ :kind => "credit",
2531
+ :unit_amount => "45.1232",
2532
+ :unit_of_measure => "gallon",
2533
+ :discount_amount => "-2",
2534
+ :total_amount => "45.15",
2535
+ :product_code => "23434",
2536
+ :commodity_code => "9SAASSD8724",
2537
+ },
2538
+ ],
2539
+ )
2540
+ result.success?.should == false
2541
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:discount_amount)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::DiscountAmountMustBeGreaterThanZero
2542
+ end
2543
+
2544
+ it "handles validation error kind is invalid" do
2545
+ result = Braintree::Transaction.create(
2546
+ :type => "sale",
2547
+ :amount => "35.05",
2548
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2549
+ :line_items => [
2550
+ {
2551
+ :quantity => "1.2322",
2552
+ :name => "Name #1",
2553
+ :kind => "debit",
2554
+ :unit_amount => "45.1232",
2555
+ :unit_of_measure => "gallon",
2556
+ :discount_amount => "1.02",
2557
+ :total_amount => "45.15",
2558
+ :product_code => "23434",
2559
+ :commodity_code => "9SAASSD8724",
2560
+ },
2561
+ {
2562
+ :quantity => "1.2322",
2563
+ :name => "Name #2",
2564
+ :kind => "sale",
2565
+ :unit_amount => "45.1232",
2566
+ :unit_of_measure => "gallon",
2567
+ :discount_amount => "1.02",
2568
+ :total_amount => "45.15",
2569
+ :product_code => "23434",
2570
+ :commodity_code => "9SAASSD8724",
2571
+ },
2572
+ ],
2573
+ )
2574
+ result.success?.should == false
2575
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:kind)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::KindIsInvalid
2576
+ end
2577
+
2578
+ it "handles validation error kind is required" do
2579
+ result = Braintree::Transaction.create(
2580
+ :type => "sale",
2581
+ :amount => "35.05",
2582
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2583
+ :line_items => [
2584
+ {
2585
+ :quantity => "1.2322",
2586
+ :name => "Name #1",
2587
+ :kind => "debit",
2588
+ :unit_amount => "45.1232",
2589
+ :unit_of_measure => "gallon",
2590
+ :discount_amount => "1.02",
2591
+ :total_amount => "45.15",
2592
+ :product_code => "23434",
2593
+ :commodity_code => "9SAASSD8724",
2594
+ },
2595
+ {
2596
+ :quantity => "1.2322",
2597
+ :name => "Name #2",
2598
+ :unit_amount => "45.1232",
2599
+ :unit_of_measure => "gallon",
2600
+ :discount_amount => "1.02",
2601
+ :total_amount => "45.15",
2602
+ :product_code => "23434",
2603
+ :commodity_code => "9SAASSD8724",
2604
+ },
2605
+ ],
2606
+ )
2607
+ result.success?.should == false
2608
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:kind)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::KindIsRequired
2609
+ end
2610
+
2611
+ it "handles validation error name is required" do
2612
+ result = Braintree::Transaction.create(
2613
+ :type => "sale",
2614
+ :amount => "35.05",
2615
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2616
+ :line_items => [
2617
+ {
2618
+ :quantity => "1.2322",
2619
+ :name => "Name #1",
2620
+ :kind => "debit",
2621
+ :unit_amount => "45.1232",
2622
+ :unit_of_measure => "gallon",
2623
+ :discount_amount => "1.02",
2624
+ :total_amount => "45.15",
2625
+ :product_code => "23434",
2626
+ :commodity_code => "9SAASSD8724",
2627
+ },
2628
+ {
2629
+ :quantity => "1.2322",
2630
+ :kind => "debit",
2631
+ :unit_amount => "45.1232",
2632
+ :unit_of_measure => "gallon",
2633
+ :discount_amount => "1.02",
2634
+ :total_amount => "45.15",
2635
+ :product_code => "23434",
2636
+ :commodity_code => "9SAASSD8724",
2637
+ },
2638
+ ],
2639
+ )
2640
+ result.success?.should == false
2641
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:name)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::NameIsRequired
2642
+ end
2643
+
2644
+ it "handles validation error name is too long" do
2645
+ result = Braintree::Transaction.create(
2646
+ :type => "sale",
2647
+ :amount => "35.05",
2648
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2649
+ :line_items => [
2650
+ {
2651
+ :quantity => "1.2322",
2652
+ :name => "Name #1",
2653
+ :kind => "debit",
2654
+ :unit_amount => "45.1232",
2655
+ :unit_of_measure => "gallon",
2656
+ :discount_amount => "1.02",
2657
+ :total_amount => "45.15",
2658
+ :product_code => "23434",
2659
+ :commodity_code => "9SAASSD8724",
2660
+ },
2661
+ {
2662
+ :quantity => "1.2322",
2663
+ :name => "X"*36,
2664
+ :kind => "debit",
2665
+ :unit_amount => "45.1232",
2666
+ :unit_of_measure => "gallon",
2667
+ :discount_amount => "1.02",
2668
+ :total_amount => "45.15",
2669
+ :product_code => "23434",
2670
+ :commodity_code => "9SAASSD8724",
2671
+ },
2672
+ ],
2673
+ )
2674
+ result.success?.should == false
2675
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:name)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::NameIsTooLong
2676
+ end
2677
+
2678
+ it "handles validation error product code is too long" do
2679
+ result = Braintree::Transaction.create(
2680
+ :type => "sale",
2681
+ :amount => "35.05",
2682
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2683
+ :line_items => [
2684
+ {
2685
+ :quantity => "1.2322",
2686
+ :name => "Name #1",
2687
+ :kind => "debit",
2688
+ :unit_amount => "45.1232",
2689
+ :unit_of_measure => "gallon",
2690
+ :discount_amount => "1.02",
2691
+ :total_amount => "45.15",
2692
+ :product_code => "23434",
2693
+ :commodity_code => "9SAASSD8724",
2694
+ },
2695
+ {
2696
+ :quantity => "1.2322",
2697
+ :name => "Name #2",
2698
+ :kind => "credit",
2699
+ :unit_amount => "45.1232",
2700
+ :unit_of_measure => "gallon",
2701
+ :discount_amount => "1.02",
2702
+ :total_amount => "45.15",
2703
+ :product_code => "1234567890123",
2704
+ :commodity_code => "9SAASSD8724",
2705
+ },
2706
+ ],
2707
+ )
2708
+ result.success?.should == false
2709
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:product_code)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::ProductCodeIsTooLong
2710
+ end
2711
+
2712
+ it "handles validation error quantity format is invalid" do
2713
+ result = Braintree::Transaction.create(
2714
+ :type => "sale",
2715
+ :amount => "35.05",
2716
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2717
+ :line_items => [
2718
+ {
2719
+ :quantity => "1.2322",
2720
+ :name => "Name #1",
2721
+ :kind => "debit",
2722
+ :unit_amount => "45.1232",
2723
+ :unit_of_measure => "gallon",
2724
+ :discount_amount => "1.02",
2725
+ :total_amount => "45.15",
2726
+ :product_code => "23434",
2727
+ :commodity_code => "9SAASSD8724",
2728
+ },
2729
+ {
2730
+ :quantity => "1,2322",
2731
+ :name => "Name #2",
2732
+ :kind => "credit",
2733
+ :unit_amount => "45.1232",
2734
+ :unit_of_measure => "gallon",
2735
+ :discount_amount => "1.02",
2736
+ :total_amount => "45.15",
2737
+ :product_code => "23434",
2738
+ :commodity_code => "9SAASSD8724",
2739
+ },
2740
+ ],
2741
+ )
2742
+ result.success?.should == false
2743
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:quantity)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::QuantityFormatIsInvalid
2744
+ end
2745
+
2746
+ it "handles validation error quantity is required" do
2747
+ result = Braintree::Transaction.create(
2748
+ :type => "sale",
2749
+ :amount => "35.05",
2750
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2751
+ :line_items => [
2752
+ {
2753
+ :quantity => "1.2322",
2754
+ :name => "Name #1",
2755
+ :kind => "debit",
2756
+ :unit_amount => "45.1232",
2757
+ :unit_of_measure => "gallon",
2758
+ :discount_amount => "1.02",
2759
+ :total_amount => "45.15",
2760
+ :product_code => "23434",
2761
+ :commodity_code => "9SAASSD8724",
2762
+ },
2763
+ {
2764
+ :name => "Name #2",
2765
+ :kind => "credit",
2766
+ :unit_amount => "45.1232",
2767
+ :unit_of_measure => "gallon",
2768
+ :discount_amount => "1.02",
2769
+ :total_amount => "45.15",
2770
+ :product_code => "23434",
2771
+ :commodity_code => "9SAASSD8724",
2772
+ },
2773
+ ],
2774
+ )
2775
+ result.success?.should == false
2776
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:quantity)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::QuantityIsRequired
2777
+ end
2778
+
2779
+ it "handles validation error quantity is too large" do
2780
+ result = Braintree::Transaction.create(
2781
+ :type => "sale",
2782
+ :amount => "35.05",
2783
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2784
+ :line_items => [
2785
+ {
2786
+ :quantity => "1.2322",
2787
+ :name => "Name #1",
2788
+ :kind => "debit",
2789
+ :unit_amount => "45.1232",
2790
+ :unit_of_measure => "gallon",
2791
+ :discount_amount => "1.02",
2792
+ :total_amount => "45.15",
2793
+ :product_code => "23434",
2794
+ :commodity_code => "9SAASSD8724",
2795
+ },
2796
+ {
2797
+ :quantity => "2147483648",
2798
+ :name => "Name #2",
2799
+ :kind => "credit",
2800
+ :unit_amount => "45.1232",
2801
+ :unit_of_measure => "gallon",
2802
+ :discount_amount => "1.02",
2803
+ :total_amount => "45.15",
2804
+ :product_code => "23434",
2805
+ :commodity_code => "9SAASSD8724",
2806
+ },
2807
+ ],
2808
+ )
2809
+ result.success?.should == false
2810
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:quantity)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::QuantityIsTooLarge
2811
+ end
2812
+
2813
+ it "handles validation error total amount format is invalid" do
2814
+ result = Braintree::Transaction.create(
2815
+ :type => "sale",
2816
+ :amount => "35.05",
2817
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2818
+ :line_items => [
2819
+ {
2820
+ :quantity => "1.2322",
2821
+ :name => "Name #1",
2822
+ :kind => "debit",
2823
+ :unit_amount => "45.1232",
2824
+ :unit_of_measure => "gallon",
2825
+ :discount_amount => "1.02",
2826
+ :total_amount => "45.15",
2827
+ :product_code => "23434",
2828
+ :commodity_code => "9SAASSD8724",
2829
+ },
2830
+ {
2831
+ :quantity => "1.2322",
2832
+ :name => "Name #2",
2833
+ :kind => "credit",
2834
+ :unit_amount => "45.1232",
2835
+ :unit_of_measure => "gallon",
2836
+ :discount_amount => "1.02",
2837
+ :total_amount => "$45.15",
2838
+ :product_code => "23434",
2839
+ :commodity_code => "9SAASSD8724",
2840
+ },
2841
+ ],
2842
+ )
2843
+ result.success?.should == false
2844
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:total_amount)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::TotalAmountFormatIsInvalid
2845
+ end
2846
+
2847
+ it "handles validation error total amount is required" do
2848
+ result = Braintree::Transaction.create(
2849
+ :type => "sale",
2850
+ :amount => "35.05",
2851
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2852
+ :line_items => [
2853
+ {
2854
+ :quantity => "1.2322",
2855
+ :name => "Name #1",
2856
+ :kind => "debit",
2857
+ :unit_amount => "45.1232",
2858
+ :unit_of_measure => "gallon",
2859
+ :discount_amount => "1.02",
2860
+ :total_amount => "45.15",
2861
+ :product_code => "23434",
2862
+ :commodity_code => "9SAASSD8724",
2863
+ },
2864
+ {
2865
+ :quantity => "1.2322",
2866
+ :name => "Name #2",
2867
+ :kind => "credit",
2868
+ :unit_amount => "45.1232",
2869
+ :unit_of_measure => "gallon",
2870
+ :discount_amount => "1.02",
2871
+ :product_code => "23434",
2872
+ :commodity_code => "9SAASSD8724",
2873
+ },
2874
+ ],
2875
+ )
2876
+ result.success?.should == false
2877
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:total_amount)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::TotalAmountIsRequired
2878
+ end
2879
+
2880
+ it "handles validation error total amount is too large" do
2881
+ result = Braintree::Transaction.create(
2882
+ :type => "sale",
2883
+ :amount => "35.05",
2884
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2885
+ :line_items => [
2886
+ {
2887
+ :quantity => "1.2322",
2888
+ :name => "Name #1",
2889
+ :kind => "debit",
2890
+ :unit_amount => "45.1232",
2891
+ :unit_of_measure => "gallon",
2892
+ :discount_amount => "1.02",
2893
+ :total_amount => "45.15",
2894
+ :product_code => "23434",
2895
+ :commodity_code => "9SAASSD8724",
2896
+ },
2897
+ {
2898
+ :quantity => "1.2322",
2899
+ :name => "Name #2",
2900
+ :kind => "credit",
2901
+ :unit_amount => "45.1232",
2902
+ :unit_of_measure => "gallon",
2903
+ :discount_amount => "1.02",
2904
+ :total_amount => "2147483648",
2905
+ :product_code => "23434",
2906
+ :commodity_code => "9SAASSD8724",
2907
+ },
2908
+ ],
2909
+ )
2910
+ result.success?.should == false
2911
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:total_amount)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::TotalAmountIsTooLarge
2912
+ end
2913
+
2914
+ it "handles validation error total amount must be greater than zero" do
2915
+ result = Braintree::Transaction.create(
2916
+ :type => "sale",
2917
+ :amount => "35.05",
2918
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2919
+ :line_items => [
2920
+ {
2921
+ :quantity => "1.2322",
2922
+ :name => "Name #1",
2923
+ :kind => "debit",
2924
+ :unit_amount => "45.1232",
2925
+ :unit_of_measure => "gallon",
2926
+ :discount_amount => "1.02",
2927
+ :total_amount => "45.15",
2928
+ :product_code => "23434",
2929
+ :commodity_code => "9SAASSD8724",
2930
+ },
2931
+ {
2932
+ :quantity => "1.2322",
2933
+ :name => "Name #2",
2934
+ :kind => "credit",
2935
+ :unit_amount => "45.1232",
2936
+ :unit_of_measure => "gallon",
2937
+ :discount_amount => "1.02",
2938
+ :total_amount => "-2",
2939
+ :product_code => "23434",
2940
+ :commodity_code => "9SAASSD8724",
2941
+ },
2942
+ ],
2943
+ )
2944
+ result.success?.should == false
2945
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:total_amount)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::TotalAmountMustBeGreaterThanZero
2946
+ end
2947
+
2948
+ it "handles validation error unit amount format is invalid" do
2949
+ result = Braintree::Transaction.create(
2950
+ :type => "sale",
2951
+ :amount => "35.05",
2952
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2953
+ :line_items => [
2954
+ {
2955
+ :quantity => "1.2322",
2956
+ :name => "Name #1",
2957
+ :kind => "debit",
2958
+ :unit_amount => "45.1232",
2959
+ :unit_of_measure => "gallon",
2960
+ :discount_amount => "1.02",
2961
+ :total_amount => "45.15",
2962
+ :product_code => "23434",
2963
+ :commodity_code => "9SAASSD8724",
2964
+ },
2965
+ {
2966
+ :quantity => "1.2322",
2967
+ :name => "Name #2",
2968
+ :kind => "credit",
2969
+ :unit_amount => "45.01232",
2970
+ :unit_of_measure => "gallon",
2971
+ :discount_amount => "1.02",
2972
+ :total_amount => "45.15",
2973
+ :product_code => "23434",
2974
+ :commodity_code => "9SAASSD8724",
2975
+ },
2976
+ ],
2977
+ )
2978
+ result.success?.should == false
2979
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:unit_amount)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::UnitAmountFormatIsInvalid
2980
+ end
2981
+
2982
+ it "handles validation error unit amount is required" do
2983
+ result = Braintree::Transaction.create(
2984
+ :type => "sale",
2985
+ :amount => "35.05",
2986
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
2987
+ :line_items => [
2988
+ {
2989
+ :quantity => "1.2322",
2990
+ :name => "Name #1",
2991
+ :kind => "debit",
2992
+ :unit_amount => "45.1232",
2993
+ :unit_of_measure => "gallon",
2994
+ :discount_amount => "1.02",
2995
+ :total_amount => "45.15",
2996
+ :product_code => "23434",
2997
+ :commodity_code => "9SAASSD8724",
2998
+ },
2999
+ {
3000
+ :quantity => "1.2322",
3001
+ :name => "Name #2",
3002
+ :kind => "credit",
3003
+ :unit_of_measure => "gallon",
3004
+ :discount_amount => "1.02",
3005
+ :product_code => "23434",
3006
+ :commodity_code => "9SAASSD8724",
3007
+ },
3008
+ ],
3009
+ )
3010
+ result.success?.should == false
3011
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:unit_amount)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::UnitAmountIsRequired
3012
+ end
3013
+
3014
+ it "handles validation error unit amount is too large" do
3015
+ result = Braintree::Transaction.create(
3016
+ :type => "sale",
3017
+ :amount => "35.05",
3018
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
3019
+ :line_items => [
3020
+ {
3021
+ :quantity => "1.2322",
3022
+ :name => "Name #1",
3023
+ :kind => "debit",
3024
+ :unit_amount => "45.1232",
3025
+ :unit_of_measure => "gallon",
3026
+ :discount_amount => "1.02",
3027
+ :total_amount => "45.15",
3028
+ :product_code => "23434",
3029
+ :commodity_code => "9SAASSD8724",
3030
+ },
3031
+ {
3032
+ :quantity => "1.2322",
3033
+ :name => "Name #2",
3034
+ :kind => "credit",
3035
+ :unit_amount => "2147483648",
3036
+ :unit_of_measure => "gallon",
3037
+ :discount_amount => "1.02",
3038
+ :total_amount => "45.15",
3039
+ :product_code => "23434",
3040
+ :commodity_code => "9SAASSD8724",
3041
+ },
3042
+ ],
3043
+ )
3044
+ result.success?.should == false
3045
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:unit_amount)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::UnitAmountIsTooLarge
3046
+ end
3047
+
3048
+ it "handles validation error unit amount must be greater than zero" do
3049
+ result = Braintree::Transaction.create(
3050
+ :type => "sale",
3051
+ :amount => "35.05",
3052
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
3053
+ :line_items => [
3054
+ {
3055
+ :quantity => "1.2322",
3056
+ :name => "Name #1",
3057
+ :kind => "debit",
3058
+ :unit_amount => "45.1232",
3059
+ :unit_of_measure => "gallon",
3060
+ :discount_amount => "1.02",
3061
+ :total_amount => "45.15",
3062
+ :product_code => "23434",
3063
+ :commodity_code => "9SAASSD8724",
3064
+ },
3065
+ {
3066
+ :quantity => "1.2322",
3067
+ :name => "Name #2",
3068
+ :kind => "credit",
3069
+ :unit_amount => "-2",
3070
+ :unit_of_measure => "gallon",
3071
+ :discount_amount => "1.02",
3072
+ :total_amount => "45.15",
3073
+ :product_code => "23434",
3074
+ :commodity_code => "9SAASSD8724",
3075
+ },
3076
+ ],
3077
+ )
3078
+ result.success?.should == false
3079
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:unit_amount)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::UnitAmountMustBeGreaterThanZero
3080
+ end
3081
+
3082
+ it "handles validation error unit of measure is too long" do
3083
+ result = Braintree::Transaction.create(
3084
+ :type => "sale",
3085
+ :amount => "35.05",
3086
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
3087
+ :line_items => [
3088
+ {
3089
+ :quantity => "1.2322",
3090
+ :name => "Name #1",
3091
+ :kind => "debit",
3092
+ :unit_amount => "45.1232",
3093
+ :unit_of_measure => "gallon",
3094
+ :discount_amount => "1.02",
3095
+ :total_amount => "45.15",
3096
+ :product_code => "23434",
3097
+ :commodity_code => "9SAASSD8724",
3098
+ },
3099
+ {
3100
+ :quantity => "1.2322",
3101
+ :name => "Name #2",
3102
+ :kind => "credit",
3103
+ :unit_amount => "45.1232",
3104
+ :unit_of_measure => "1234567890123",
3105
+ :discount_amount => "1.02",
3106
+ :total_amount => "45.15",
3107
+ :product_code => "23434",
3108
+ :commodity_code => "9SAASSD8724",
3109
+ },
3110
+ ],
3111
+ )
3112
+ result.success?.should == false
3113
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:unit_of_measure)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::UnitOfMeasureIsTooLong
3114
+ end
3115
+
3116
+ it "handles validation error unit tax amount format is invalid" do
3117
+ result = Braintree::Transaction.create(
3118
+ :type => "sale",
3119
+ :amount => "35.05",
3120
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
3121
+ :line_items => [
3122
+ {
3123
+ :quantity => "1.2322",
3124
+ :name => "Name #1",
3125
+ :kind => "debit",
3126
+ :unit_amount => "45.1232",
3127
+ :unit_tax_amount => "2.34",
3128
+ :unit_of_measure => "gallon",
3129
+ :discount_amount => "1.02",
3130
+ :total_amount => "45.15",
3131
+ :product_code => "23434",
3132
+ :commodity_code => "9SAASSD8724",
3133
+ },
3134
+ {
3135
+ :quantity => "1.2322",
3136
+ :name => "Name #2",
3137
+ :kind => "credit",
3138
+ :unit_amount => "45.0122",
3139
+ :unit_tax_amount => "2.012",
3140
+ :unit_of_measure => "gallon",
3141
+ :discount_amount => "1.02",
3142
+ :total_amount => "45.15",
3143
+ :product_code => "23434",
3144
+ :commodity_code => "9SAASSD8724",
3145
+ },
3146
+ ],
3147
+ )
3148
+ result.success?.should == false
3149
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:unit_tax_amount)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::UnitTaxAmountFormatIsInvalid
3150
+ end
3151
+
3152
+ it "handles validation error unit tax amount is too large" do
3153
+ result = Braintree::Transaction.create(
3154
+ :type => "sale",
3155
+ :amount => "35.05",
3156
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
3157
+ :line_items => [
3158
+ {
3159
+ :quantity => "1.2322",
3160
+ :name => "Name #1",
3161
+ :kind => "debit",
3162
+ :unit_amount => "45.1232",
3163
+ :unit_tax_amount => "1.23",
3164
+ :unit_of_measure => "gallon",
3165
+ :discount_amount => "1.02",
3166
+ :total_amount => "45.15",
3167
+ :product_code => "23434",
3168
+ :commodity_code => "9SAASSD8724",
3169
+ },
3170
+ {
3171
+ :quantity => "1.2322",
3172
+ :name => "Name #2",
3173
+ :kind => "credit",
3174
+ :unit_amount => "45.0122",
3175
+ :unit_tax_amount => "2147483648",
3176
+ :unit_of_measure => "gallon",
3177
+ :discount_amount => "1.02",
3178
+ :total_amount => "45.15",
3179
+ :product_code => "23434",
3180
+ :commodity_code => "9SAASSD8724",
3181
+ },
3182
+ ],
3183
+ )
3184
+ result.success?.should == false
3185
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:unit_tax_amount)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::UnitTaxAmountIsTooLarge
3186
+ end
3187
+
3188
+ it "handles validation error unit tax amount must be greater than zero" do
3189
+ result = Braintree::Transaction.create(
3190
+ :type => "sale",
3191
+ :amount => "35.05",
3192
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
3193
+ :line_items => [
3194
+ {
3195
+ :quantity => "1.2322",
3196
+ :name => "Name #1",
3197
+ :kind => "debit",
3198
+ :unit_amount => "45.1232",
3199
+ :unit_of_measure => "gallon",
3200
+ :discount_amount => "1.02",
3201
+ :total_amount => "45.15",
3202
+ :product_code => "23434",
3203
+ :commodity_code => "9SAASSD8724",
3204
+ },
3205
+ {
3206
+ :quantity => "1.2322",
3207
+ :name => "Name #2",
3208
+ :kind => "credit",
3209
+ :unit_amount => "45.0122",
3210
+ :unit_tax_amount => "-1.23",
3211
+ :unit_of_measure => "gallon",
3212
+ :discount_amount => "1.02",
3213
+ :total_amount => "45.15",
3214
+ :product_code => "23434",
3215
+ :commodity_code => "9SAASSD8724",
3216
+ },
3217
+ ],
3218
+ )
3219
+ result.success?.should == false
3220
+ result.errors.for(:transaction).for(:line_items).for(:index_1).on(:unit_tax_amount)[0].code.should == Braintree::ErrorCodes::TransactionLineItem::UnitTaxAmountMustBeGreaterThanZero
3221
+ end
3222
+
3223
+ it "handles validation errors on line items structure" do
3224
+ result = Braintree::Transaction.create(
3225
+ :type => "sale",
3226
+ :amount => "35.05",
3227
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
3228
+ :line_items => {
3229
+ :quantity => "2.02",
3230
+ :name => "Name #2",
3231
+ :kind => "credit",
3232
+ :unit_amount => "5",
3233
+ :unit_of_measure => "gallon",
3234
+ :total_amount => "10.1",
3235
+ },
3236
+ )
3237
+ result.success?.should == false
3238
+ result.errors.for(:transaction).on(:line_items)[0].code.should == Braintree::ErrorCodes::Transaction::LineItemsExpected
3239
+ end
3240
+
3241
+ it "handles invalid arguments on line items structure" do
3242
+ expect do
3243
+ Braintree::Transaction.create(
3244
+ :type => "sale",
3245
+ :amount => "35.05",
3246
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
3247
+ :line_items => [
3248
+ {
3249
+ :quantity => "2.02",
3250
+ :name => "Name #1",
3251
+ :kind => "credit",
3252
+ :unit_amount => "5",
3253
+ :unit_of_measure => "gallon",
3254
+ :total_amount => "10.1",
3255
+ },
3256
+ ['Name #2'],
3257
+ {
3258
+ :quantity => "2.02",
3259
+ :name => "Name #3",
3260
+ :kind => "credit",
3261
+ :unit_amount => "5",
3262
+ :unit_of_measure => "gallon",
3263
+ :total_amount => "10.1",
3264
+ },
3265
+ ],
3266
+ )
3267
+ end.to raise_error(ArgumentError)
3268
+ end
3269
+
3270
+ it "handles validation errors on too many line items" do
3271
+ line_items = 250.times.map do |i|
3272
+ {
3273
+ :quantity => "2.02",
3274
+ :name => "Line item ##{i}",
3275
+ :kind => "credit",
3276
+ :unit_amount => "5",
3277
+ :unit_of_measure => "gallon",
3278
+ :total_amount => "10.1",
3279
+ }
3280
+ end
3281
+ result = Braintree::Transaction.create(
3282
+ :type => "sale",
3283
+ :amount => "35.05",
3284
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
3285
+ :line_items => line_items,
3286
+ )
3287
+ result.success?.should == false
3288
+ result.errors.for(:transaction).on(:line_items)[0].code.should == Braintree::ErrorCodes::Transaction::TooManyLineItems
3289
+ end
3290
+ end
3291
+
2246
3292
  context "level 3 summary data" do
2247
3293
  it "accepts level 3 summary data" do
2248
3294
  result = Braintree::Transaction.create(
@@ -2275,6 +3321,102 @@ describe Braintree::Transaction do
2275
3321
  result.errors.for(:transaction).on(:discount_amount)[0].code.should == Braintree::ErrorCodes::Transaction::DiscountAmountCannotBeNegative
2276
3322
  result.errors.for(:transaction).on(:ships_from_postal_code)[0].code.should == Braintree::ErrorCodes::Transaction::ShipsFromPostalCodeInvalidCharacters
2277
3323
  end
3324
+
3325
+ it "handles validation error discount amount format is invalid" do
3326
+ result = Braintree::Transaction.create(
3327
+ :type => "sale",
3328
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
3329
+ :amount => "10.00",
3330
+ :discount_amount => "2.001",
3331
+ )
3332
+
3333
+ result.success?.should == false
3334
+ result.errors.for(:transaction).on(:discount_amount)[0].code.should == Braintree::ErrorCodes::Transaction::DiscountAmountFormatIsInvalid
3335
+ end
3336
+
3337
+ it "handles validation error discount amount cannot be negative" do
3338
+ result = Braintree::Transaction.create(
3339
+ :type => "sale",
3340
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
3341
+ :amount => "10.00",
3342
+ :discount_amount => "-2",
3343
+ )
3344
+
3345
+ result.success?.should == false
3346
+ result.errors.for(:transaction).on(:discount_amount)[0].code.should == Braintree::ErrorCodes::Transaction::DiscountAmountCannotBeNegative
3347
+ end
3348
+
3349
+ it "handles validation error discount amount is too large" do
3350
+ result = Braintree::Transaction.create(
3351
+ :type => "sale",
3352
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
3353
+ :amount => "10.00",
3354
+ :discount_amount => "2147483648",
3355
+ )
3356
+
3357
+ result.success?.should == false
3358
+ result.errors.for(:transaction).on(:discount_amount)[0].code.should == Braintree::ErrorCodes::Transaction::DiscountAmountIsTooLarge
3359
+ end
3360
+
3361
+ it "handles validation error shipping amount format is invalid" do
3362
+ result = Braintree::Transaction.create(
3363
+ :type => "sale",
3364
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
3365
+ :amount => "10.00",
3366
+ :shipping_amount => "2.001",
3367
+ )
3368
+
3369
+ result.success?.should == false
3370
+ result.errors.for(:transaction).on(:shipping_amount)[0].code.should == Braintree::ErrorCodes::Transaction::ShippingAmountFormatIsInvalid
3371
+ end
3372
+
3373
+ it "handles validation error shipping amount cannot be negative" do
3374
+ result = Braintree::Transaction.create(
3375
+ :type => "sale",
3376
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
3377
+ :amount => "10.00",
3378
+ :shipping_amount => "-2",
3379
+ )
3380
+
3381
+ result.success?.should == false
3382
+ result.errors.for(:transaction).on(:shipping_amount)[0].code.should == Braintree::ErrorCodes::Transaction::ShippingAmountCannotBeNegative
3383
+ end
3384
+
3385
+ it "handles validation error shipping amount is too large" do
3386
+ result = Braintree::Transaction.create(
3387
+ :type => "sale",
3388
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
3389
+ :amount => "10.00",
3390
+ :shipping_amount => "2147483648",
3391
+ )
3392
+
3393
+ result.success?.should == false
3394
+ result.errors.for(:transaction).on(:shipping_amount)[0].code.should == Braintree::ErrorCodes::Transaction::ShippingAmountIsTooLarge
3395
+ end
3396
+
3397
+ it "handles validation error ships from postal code is too long" do
3398
+ result = Braintree::Transaction.create(
3399
+ :type => "sale",
3400
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
3401
+ :amount => "10.00",
3402
+ :ships_from_postal_code => "1234567890",
3403
+ )
3404
+
3405
+ result.success?.should == false
3406
+ result.errors.for(:transaction).on(:ships_from_postal_code)[0].code.should == Braintree::ErrorCodes::Transaction::ShipsFromPostalCodeIsTooLong
3407
+ end
3408
+
3409
+ it "handles validation error ships from postal code invalid characters" do
3410
+ result = Braintree::Transaction.create(
3411
+ :type => "sale",
3412
+ :payment_method_nonce => Braintree::Test::Nonce::Transactable,
3413
+ :amount => "10.00",
3414
+ :ships_from_postal_code => "12345%78",
3415
+ )
3416
+
3417
+ result.success?.should == false
3418
+ result.errors.for(:transaction).on(:ships_from_postal_code)[0].code.should == Braintree::ErrorCodes::Transaction::ShipsFromPostalCodeInvalidCharacters
3419
+ end
2278
3420
  end
2279
3421
  end
2280
3422