braintree 2.4.0 → 2.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/README.rdoc +4 -0
  2. data/lib/braintree.rb +43 -32
  3. data/lib/braintree/add_on.rb +4 -0
  4. data/lib/braintree/address.rb +18 -72
  5. data/lib/braintree/address_gateway.rb +76 -0
  6. data/lib/braintree/advanced_search.rb +31 -13
  7. data/lib/braintree/base_module.rb +6 -0
  8. data/lib/braintree/configuration.rb +57 -39
  9. data/lib/braintree/credit_card.rb +75 -129
  10. data/lib/braintree/credit_card_gateway.rb +133 -0
  11. data/lib/braintree/credit_card_verification.rb +8 -0
  12. data/lib/braintree/customer.rb +70 -123
  13. data/lib/braintree/customer_gateway.rb +121 -0
  14. data/lib/braintree/digest.rb +2 -2
  15. data/lib/braintree/discount.rb +4 -0
  16. data/lib/braintree/error_codes.rb +50 -5
  17. data/lib/braintree/error_result.rb +4 -18
  18. data/lib/braintree/errors.rb +1 -2
  19. data/lib/braintree/exceptions.rb +11 -16
  20. data/lib/braintree/gateway.rb +39 -0
  21. data/lib/braintree/http.rb +30 -26
  22. data/lib/braintree/modification.rb +23 -0
  23. data/lib/braintree/resource_collection.rb +1 -1
  24. data/lib/braintree/subscription.rb +29 -129
  25. data/lib/braintree/subscription_gateway.rb +122 -0
  26. data/lib/braintree/subscription_search.rb +6 -7
  27. data/lib/braintree/successful_result.rb +1 -12
  28. data/lib/braintree/test/credit_card_numbers.rb +4 -2
  29. data/lib/braintree/test/transaction_amounts.rb +3 -0
  30. data/lib/braintree/transaction.rb +83 -243
  31. data/lib/braintree/transaction/credit_card_details.rb +4 -4
  32. data/lib/braintree/transaction_gateway.rb +124 -0
  33. data/lib/braintree/transaction_search.rb +5 -3
  34. data/lib/braintree/transparent_redirect.rb +19 -112
  35. data/lib/braintree/transparent_redirect_gateway.rb +105 -0
  36. data/lib/braintree/util.rb +4 -0
  37. data/lib/braintree/validation_error.rb +1 -0
  38. data/lib/braintree/validation_error_collection.rb +5 -23
  39. data/lib/braintree/version.rb +2 -2
  40. data/lib/braintree/xml/parser.rb +1 -1
  41. data/lib/braintree/xml/rexml.rb +2 -2
  42. data/spec/integration/braintree/advanced_search_spec.rb +532 -0
  43. data/spec/integration/braintree/credit_card_spec.rb +5 -8
  44. data/spec/integration/braintree/http_spec.rb +53 -39
  45. data/spec/integration/braintree/subscription_spec.rb +678 -213
  46. data/spec/integration/braintree/transaction_search_spec.rb +318 -43
  47. data/spec/integration/braintree/transaction_spec.rb +134 -3
  48. data/spec/integration/braintree/transparent_redirect_spec.rb +1 -1
  49. data/spec/spec_helper.rb +55 -4
  50. data/spec/unit/braintree/address_spec.rb +8 -8
  51. data/spec/unit/braintree/base_module_spec.rb +1 -1
  52. data/spec/unit/braintree/configuration_spec.rb +34 -29
  53. data/spec/unit/braintree/credit_card_spec.rb +14 -12
  54. data/spec/unit/braintree/credit_card_verification_spec.rb +16 -0
  55. data/spec/unit/braintree/customer_spec.rb +10 -8
  56. data/spec/unit/braintree/digest_spec.rb +8 -17
  57. data/spec/unit/braintree/error_result_spec.rb +12 -2
  58. data/spec/unit/braintree/http_spec.rb +2 -2
  59. data/spec/unit/braintree/subscription_search_spec.rb +77 -0
  60. data/spec/unit/braintree/subscription_spec.rb +16 -8
  61. data/spec/unit/braintree/transaction_spec.rb +17 -12
  62. data/spec/unit/braintree/transparent_redirect_spec.rb +12 -12
  63. data/spec/unit/braintree/util_spec.rb +24 -0
  64. data/spec/unit/braintree/xml/parser_spec.rb +1 -1
  65. data/spec/unit/braintree_spec.rb +1 -1
  66. metadata +16 -5
@@ -807,13 +807,7 @@ describe Braintree::CreditCard do
807
807
  end
808
808
 
809
809
  describe "self.expired" do
810
- it "finds expired payment methods, paginated" do
811
- collection = Braintree::CreditCard.expired
812
- collection.maximum_size.should > 0
813
- collection.all? { |pm| pm.expired?.should == true }
814
- end
815
-
816
- it "can iterate over all items" do
810
+ it "can iterate over all items, and make sure they are all expired" do
817
811
  customer = Braintree::Customer.all.first
818
812
 
819
813
  (110 - Braintree::CreditCard.expired.maximum_size).times do
@@ -827,7 +821,10 @@ describe Braintree::CreditCard do
827
821
  collection = Braintree::CreditCard.expired
828
822
  collection.maximum_size.should > 100
829
823
 
830
- credit_card_ids = collection.map {|c| c.token }.uniq.compact
824
+ credit_card_ids = collection.map do |c|
825
+ c.expired?.should == true
826
+ c.token
827
+ end.uniq.compact
831
828
  credit_card_ids.size.should == collection.maximum_size
832
829
  end
833
830
  end
@@ -7,7 +7,7 @@ describe Braintree::Http do
7
7
  original_key = Braintree::Configuration.public_key
8
8
  Braintree::Configuration.public_key = "invalid_public_key"
9
9
  expect do
10
- Braintree::Http.get "/customers"
10
+ Braintree::Configuration.instantiate.http.get "/customers"
11
11
  end.to raise_error(Braintree::AuthenticationError)
12
12
  ensure
13
13
  Braintree::Configuration.public_key = original_key
@@ -16,7 +16,7 @@ describe Braintree::Http do
16
16
 
17
17
  it "raises an AuthorizationError if authorization fails" do
18
18
  expect do
19
- Braintree::Http.get "/users"
19
+ Braintree::Configuration.instantiate.http.get "/users"
20
20
  end.to raise_error(Braintree::AuthorizationError)
21
21
  end
22
22
  end
@@ -73,47 +73,43 @@ describe Braintree::Http do
73
73
  end
74
74
 
75
75
  it "sets the User-Agent header using the default user agent" do
76
- response = Braintree::Http.get("/test/headers")
76
+ response = Braintree::Configuration.instantiate.http.get "/test/headers"
77
77
  response[:headers][:HTTP_USER_AGENT].should == "Braintree Ruby Gem #{Braintree::Version::String}"
78
78
  end
79
79
 
80
80
  it "sets the User-Agent header using a customer user agent" do
81
81
  Braintree::Configuration.custom_user_agent = "ActiveMerchant 1.2.3"
82
- response = Braintree::Http.get("/test/headers")
82
+ response = Braintree::Configuration.instantiate.http.get "/test/headers"
83
83
  response[:headers][:HTTP_USER_AGENT].should == "Braintree Ruby Gem #{Braintree::Version::String} (ActiveMerchant 1.2.3)"
84
84
  end
85
85
  end
86
86
 
87
87
  describe "ssl verification" do
88
88
  it "rejects when the certificate isn't verified by our certificate authority (self-signed)" do
89
- begin
90
- use_ssl = Braintree::Configuration.ssl?
91
- Braintree::Configuration.stub(:ssl?).and_return(true)
92
- Braintree::Configuration.stub(:port).and_return(8443)
93
-
94
- start_ssl_server do
95
- expect { Braintree::Http._http_do(Net::HTTP::Get, "/login") }.to raise_error(Braintree::SSLCertificateError, /Preverify: false, Error: self signed certificate/)
96
- end
97
- ensure
98
- Braintree::Configuration.stub(:ssl?).and_return(use_ssl)
89
+ config = Braintree::Configuration.instantiate
90
+ config.stub(:ssl?).and_return(true)
91
+ config.stub(:port).and_return(8443)
92
+
93
+ start_ssl_server do
94
+ expect do
95
+ config.http._http_do(Net::HTTP::Get, "/login")
96
+ end.to raise_error(Braintree::SSLCertificateError, /Preverify: false, Error: self signed certificate/)
99
97
  end
100
98
  end
101
99
 
102
100
  it "rejets when the certificate is signed by a different (but valid) root CA" do
103
101
  # Random CA root file from a different certificate authority
104
- begin
105
- original_ca_file = Braintree::Configuration.ca_file
106
- Braintree::Configuration.stub(:ca_file).and_return(File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "ssl", "geotrust_global.crt")))
107
- use_ssl = Braintree::Configuration.ssl?
108
- Braintree::Configuration.stub(:ssl?).and_return(true)
109
- Braintree::Configuration.stub(:port).and_return(8443)
110
-
111
- start_ssl_server do
112
- expect { Braintree::Http._http_do(Net::HTTP::Get, "/login") }.to raise_error(Braintree::SSLCertificateError, /Preverify: false, Error: self signed certificate/)
113
- end
114
- ensure
115
- Braintree::Configuration.stub(:ssl?).and_return(use_ssl)
116
- Braintree::Configuration.stub(:ca_file).and_return(original_ca_file)
102
+ config = Braintree::Configuration.instantiate
103
+ config.stub(:ca_file).and_return(
104
+ File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "ssl", "geotrust_global.crt"))
105
+ )
106
+ config.stub(:ssl?).and_return(true)
107
+ config.stub(:port).and_return(8443)
108
+
109
+ start_ssl_server do
110
+ expect do
111
+ config.http._http_do(Net::HTTP::Get, "/login")
112
+ end.to raise_error(Braintree::SSLCertificateError, /Preverify: false, Error: self signed certificate/)
117
113
  end
118
114
  end
119
115
 
@@ -123,7 +119,9 @@ describe Braintree::Http do
123
119
  Braintree::Configuration.environment = :qa
124
120
  Braintree::Configuration.stub(:base_merchant_path).and_return("/")
125
121
 
126
- expect { Braintree::Http._http_do(Net::HTTP::Get, "/login") }.to_not raise_error
122
+ expect do
123
+ Braintree::Configuration.instantiate.http._http_do(Net::HTTP::Get, "/login")
124
+ end.to_not raise_error
127
125
  ensure
128
126
  Braintree::Configuration.environment = original_env
129
127
  end
@@ -135,7 +133,9 @@ describe Braintree::Http do
135
133
  Braintree::Configuration.environment = :sandbox
136
134
  Braintree::Configuration.stub(:base_merchant_path).and_return("/")
137
135
 
138
- expect { Braintree::Http._http_do(Net::HTTP::Get, "/login") }.to_not raise_error
136
+ expect do
137
+ Braintree::Configuration.instantiate.http._http_do(Net::HTTP::Get, "/login")
138
+ end.to_not raise_error
139
139
  ensure
140
140
  Braintree::Configuration.environment = original_env
141
141
  end
@@ -147,7 +147,9 @@ describe Braintree::Http do
147
147
  Braintree::Configuration.environment = :production
148
148
  Braintree::Configuration.stub(:base_merchant_path).and_return("/")
149
149
 
150
- expect { Braintree::Http._http_do(Net::HTTP::Get, "/login") }.to_not raise_error
150
+ expect do
151
+ Braintree::Configuration.instantiate.http._http_do(Net::HTTP::Get, "/login")
152
+ end.to_not raise_error
151
153
  ensure
152
154
  Braintree::Configuration.environment = original_env
153
155
  end
@@ -157,11 +159,13 @@ describe Braintree::Http do
157
159
  begin
158
160
  original_env = Braintree::Configuration.environment
159
161
  Braintree::Configuration.environment = :qa
160
- Braintree::Configuration.stub(:base_merchant_path).and_return("/")
161
- original_ca_file = Braintree::Configuration.ca_file
162
- Braintree::Configuration.stub(:ca_file).and_return(nil)
162
+ config = Braintree::Configuration.instantiate
163
+ config.stub(:base_merchant_path).and_return("/")
164
+ config.stub(:ca_file).and_return(nil)
163
165
 
164
- expect { Braintree::Http._http_do(Net::HTTP::Get, "/login") }.to raise_error(Braintree::SSLCertificateError)
166
+ expect do
167
+ config.http._http_do(Net::HTTP::Get, "/login")
168
+ end.to raise_error(Braintree::SSLCertificateError)
165
169
  ensure
166
170
  Braintree::Configuration.environment = original_env
167
171
  end
@@ -172,18 +176,24 @@ describe Braintree::Http do
172
176
  describe "self._verify_ssl_certificate" do
173
177
  it "raises if preverify is false" do
174
178
  context = OpenSSL::X509::StoreContext.new(OpenSSL::X509::Store.new)
175
- expect { Braintree::Http._verify_ssl_certificate(false, context) }.to raise_error(Braintree::SSLCertificateError)
179
+ expect do
180
+ Braintree::Configuration.instantiate.http._verify_ssl_certificate(false, context)
181
+ end.to raise_error(Braintree::SSLCertificateError)
176
182
  end
177
183
 
178
184
  it "raise if ssl_context doesn't have an error code of 0" do
179
185
  context = OpenSSL::X509::StoreContext.new(OpenSSL::X509::Store.new)
180
186
  context.error = 19 # ca_file incorrect, self-signed
181
- expect { Braintree::Http._verify_ssl_certificate(true, context) }.to raise_error(Braintree::SSLCertificateError)
187
+ expect do
188
+ Braintree::Configuration.instantiate.http._verify_ssl_certificate(true, context)
189
+ end.to raise_error(Braintree::SSLCertificateError)
182
190
  end
183
191
 
184
192
  it "doesn't raise if there is no error" do
185
193
  context = OpenSSL::X509::StoreContext.new(OpenSSL::X509::Store.new)
186
- expect { Braintree::Http._verify_ssl_certificate(true, context) }.to_not raise_error
194
+ expect do
195
+ Braintree::Configuration.instantiate.http._verify_ssl_certificate(true, context)
196
+ end.to_not raise_error
187
197
  end
188
198
 
189
199
  it "logs when there is an error" do
@@ -194,7 +204,9 @@ describe Braintree::Http do
194
204
  utc_or_gmt = Time.now.utc.strftime("%Z")
195
205
  context = OpenSSL::X509::StoreContext.new(OpenSSL::X509::Store.new)
196
206
  context.error = 19
197
- expect { Braintree::Http._verify_ssl_certificate(false, context) }.to raise_error(Braintree::SSLCertificateError)
207
+ expect do
208
+ Braintree::Configuration.instantiate.http._verify_ssl_certificate(false, context)
209
+ end.to raise_error(Braintree::SSLCertificateError)
198
210
  output.string.should include("SSL Verification failed -- Preverify: false, Error: self signed certificate in certificate chain (19)")
199
211
  ensure
200
212
  Braintree::Configuration.logger = old_logger
@@ -208,7 +220,9 @@ describe Braintree::Http do
208
220
  Braintree::Configuration.logger = Logger.new(output)
209
221
  utc_or_gmt = Time.now.utc.strftime("%Z")
210
222
  context = OpenSSL::X509::StoreContext.new(OpenSSL::X509::Store.new)
211
- expect { Braintree::Http._verify_ssl_certificate(true, context) }.to_not raise_error(Braintree::SSLCertificateError)
223
+ expect do
224
+ Braintree::Configuration.instantiate.http._verify_ssl_certificate(true, context)
225
+ end.to_not raise_error(Braintree::SSLCertificateError)
212
226
  output.string.should == ""
213
227
  ensure
214
228
  Braintree::Configuration.logger = old_logger
@@ -1,21 +1,6 @@
1
1
  require File.dirname(__FILE__) + "/../spec_helper"
2
2
 
3
3
  describe Braintree::Subscription do
4
- TrialPlan = {
5
- :description => "Plan for integration tests -- with trial",
6
- :id => "integration_trial_plan",
7
- :price => BigDecimal.new("43.21"),
8
- :trial_period => true,
9
- :trial_duration => 2,
10
- :trial_duration_unit => Braintree::Subscription::TrialDurationUnit::Day
11
- }
12
-
13
- TriallessPlan = {
14
- :description => "Plan for integration tests -- without a trial",
15
- :id => "integration_trialless_plan",
16
- :price => BigDecimal.new("12.34"),
17
- :trial_period => false
18
- }
19
4
 
20
5
  before(:each) do
21
6
  @credit_card = Braintree::Customer.create!(
@@ -30,7 +15,7 @@ describe Braintree::Subscription do
30
15
  it "is successful with a miniumum of params" do
31
16
  result = Braintree::Subscription.create(
32
17
  :payment_method_token => @credit_card.token,
33
- :plan_id => TriallessPlan[:id]
18
+ :plan_id => SpecHelper::TriallessPlan[:id]
34
19
  )
35
20
 
36
21
  date_format = /^\d{4}\D\d{1,2}\D\d{1,2}$/
@@ -45,6 +30,7 @@ describe Braintree::Subscription do
45
30
  result.subscription.billing_period_end_date.should match(date_format)
46
31
 
47
32
  result.subscription.failure_count.should == 0
33
+ result.subscription.next_bill_amount.should == "12.34"
48
34
  result.subscription.payment_method_token.should == @credit_card.token
49
35
  end
50
36
 
@@ -52,7 +38,7 @@ describe Braintree::Subscription do
52
38
  new_id = rand(36**9).to_s(36)
53
39
  result = Braintree::Subscription.create(
54
40
  :payment_method_token => @credit_card.token,
55
- :plan_id => TriallessPlan[:id],
41
+ :plan_id => SpecHelper::TrialPlan[:id],
56
42
  :id => new_id
57
43
  )
58
44
 
@@ -61,11 +47,72 @@ describe Braintree::Subscription do
61
47
  result.subscription.id.should == new_id
62
48
  end
63
49
 
50
+ context "billing_day_of_month" do
51
+ it "inherits from the plan if not provided" do
52
+ result = Braintree::Subscription.create(
53
+ :payment_method_token => @credit_card.token,
54
+ :plan_id => SpecHelper::BillingDayOfMonthPlan[:id]
55
+ )
56
+
57
+ result.success?.should == true
58
+ result.subscription.billing_day_of_month.should == 5
59
+ end
60
+
61
+ it "allows overriding" do
62
+ result = Braintree::Subscription.create(
63
+ :payment_method_token => @credit_card.token,
64
+ :plan_id => SpecHelper::BillingDayOfMonthPlan[:id],
65
+ :billing_day_of_month => 25
66
+ )
67
+
68
+ result.success?.should == true
69
+ result.subscription.billing_day_of_month.should == 25
70
+ end
71
+
72
+ it "allows overriding with start_immediately" do
73
+ result = Braintree::Subscription.create(
74
+ :payment_method_token => @credit_card.token,
75
+ :plan_id => SpecHelper::BillingDayOfMonthPlan[:id],
76
+ :options => {
77
+ :start_immediately => true
78
+ }
79
+ )
80
+
81
+ result.success?.should == true
82
+ result.subscription.transactions.size.should == 1
83
+ end
84
+ end
85
+
86
+ context "first_billing_date" do
87
+ it "allows specifying" do
88
+ result = Braintree::Subscription.create(
89
+ :payment_method_token => @credit_card.token,
90
+ :plan_id => SpecHelper::BillingDayOfMonthPlan[:id],
91
+ :first_billing_date => Date.today + 3
92
+ )
93
+
94
+ result.success?.should == true
95
+ result.subscription.first_billing_date.should == (Date.today + 3).to_s
96
+ result.subscription.status.should == Braintree::Subscription::Status::Pending
97
+ end
98
+
99
+ it "returns an error if the date is in the past" do
100
+ result = Braintree::Subscription.create(
101
+ :payment_method_token => @credit_card.token,
102
+ :plan_id => SpecHelper::BillingDayOfMonthPlan[:id],
103
+ :first_billing_date => Date.today - 3
104
+ )
105
+
106
+ result.success?.should == false
107
+ result.errors.for(:subscription).on(:first_billing_date).first.code.should == Braintree::ErrorCodes::Subscription::FirstBillingDateCannotBeInThePast
108
+ end
109
+ end
110
+
64
111
  context "merchant_account_id" do
65
112
  it "defaults to the default merchant account if no merchant_account_id is provided" do
66
113
  result = Braintree::Subscription.create(
67
114
  :payment_method_token => @credit_card.token,
68
- :plan_id => TriallessPlan[:id]
115
+ :plan_id => SpecHelper::TrialPlan[:id]
69
116
  )
70
117
 
71
118
  result.success?.should == true
@@ -75,7 +122,7 @@ describe Braintree::Subscription do
75
122
  it "allows setting the merchant_account_id" do
76
123
  result = Braintree::Subscription.create(
77
124
  :payment_method_token => @credit_card.token,
78
- :plan_id => TriallessPlan[:id],
125
+ :plan_id => SpecHelper::TrialPlan[:id],
79
126
  :merchant_account_id => SpecHelper::NonDefaultMerchantAccountId
80
127
  )
81
128
 
@@ -84,12 +131,36 @@ describe Braintree::Subscription do
84
131
  end
85
132
  end
86
133
 
134
+ context "number_of_billing_cycles" do
135
+ it "sets the number of billing cycles on the subscription when provided" do
136
+ result = Braintree::Subscription.create(
137
+ :payment_method_token => @credit_card.token,
138
+ :plan_id => SpecHelper::TrialPlan[:id],
139
+ :number_of_billing_cycles => 10
140
+ )
141
+
142
+ result.success?.should == true
143
+ result.subscription.number_of_billing_cycles.should == 10
144
+ end
145
+
146
+ it "sets the number of billing cycles to nil if :never_expires => true" do
147
+ result = Braintree::Subscription.create(
148
+ :payment_method_token => @credit_card.token,
149
+ :plan_id => SpecHelper::TrialPlan[:id],
150
+ :never_expires => true
151
+ )
152
+
153
+ result.success?.should == true
154
+ result.subscription.number_of_billing_cycles.should == nil
155
+ end
156
+ end
157
+
87
158
  context "trial period" do
88
159
  context "defaults to the plan's trial period settings" do
89
160
  it "with no trial" do
90
161
  result = Braintree::Subscription.create(
91
162
  :payment_method_token => @credit_card.token,
92
- :plan_id => TriallessPlan[:id]
163
+ :plan_id => SpecHelper::TriallessPlan[:id]
93
164
  )
94
165
 
95
166
  result.subscription.trial_period.should == false
@@ -100,7 +171,7 @@ describe Braintree::Subscription do
100
171
  it "with a trial" do
101
172
  result = Braintree::Subscription.create(
102
173
  :payment_method_token => @credit_card.token,
103
- :plan_id => TrialPlan[:id]
174
+ :plan_id => SpecHelper::TrialPlan[:id]
104
175
  )
105
176
 
106
177
  result.subscription.trial_period.should == true
@@ -111,7 +182,7 @@ describe Braintree::Subscription do
111
182
  it "can alter the trial period params" do
112
183
  result = Braintree::Subscription.create(
113
184
  :payment_method_token => @credit_card.token,
114
- :plan_id => TrialPlan[:id],
185
+ :plan_id => SpecHelper::TrialPlan[:id],
115
186
  :trial_duration => 5,
116
187
  :trial_duration_unit => Braintree::Subscription::TrialDurationUnit::Month
117
188
  )
@@ -124,7 +195,7 @@ describe Braintree::Subscription do
124
195
  it "can override the trial_period param" do
125
196
  result = Braintree::Subscription.create(
126
197
  :payment_method_token => @credit_card.token,
127
- :plan_id => TrialPlan[:id],
198
+ :plan_id => SpecHelper::TrialPlan[:id],
128
199
  :trial_period => false
129
200
  )
130
201
 
@@ -134,7 +205,7 @@ describe Braintree::Subscription do
134
205
  it "doesn't create a transaction if there's a trial period" do
135
206
  result = Braintree::Subscription.create(
136
207
  :payment_method_token => @credit_card.token,
137
- :plan_id => TrialPlan[:id]
208
+ :plan_id => SpecHelper::TrialPlan[:id]
138
209
  )
139
210
 
140
211
  result.subscription.transactions.size.should == 0
@@ -145,12 +216,12 @@ describe Braintree::Subscription do
145
216
  it "creates a transaction if no trial period" do
146
217
  result = Braintree::Subscription.create(
147
218
  :payment_method_token => @credit_card.token,
148
- :plan_id => TriallessPlan[:id]
219
+ :plan_id => SpecHelper::TriallessPlan[:id]
149
220
  )
150
221
 
151
222
  result.subscription.transactions.size.should == 1
152
223
  result.subscription.transactions.first.should be_a(Braintree::Transaction)
153
- result.subscription.transactions.first.amount.should == TriallessPlan[:price]
224
+ result.subscription.transactions.first.amount.should == SpecHelper::TriallessPlan[:price]
154
225
  result.subscription.transactions.first.type.should == Braintree::Transaction::Type::Sale
155
226
  result.subscription.transactions.first.subscription_id.should == result.subscription.id
156
227
  end
@@ -158,7 +229,7 @@ describe Braintree::Subscription do
158
229
  it "does not create the subscription and returns the transaction if the transaction is not successful" do
159
230
  result = Braintree::Subscription.create(
160
231
  :payment_method_token => @credit_card.token,
161
- :plan_id => TriallessPlan[:id],
232
+ :plan_id => SpecHelper::TriallessPlan[:id],
162
233
  :price => Braintree::Test::TransactionAmounts::Decline
163
234
  )
164
235
 
@@ -172,16 +243,16 @@ describe Braintree::Subscription do
172
243
  it "defaults to the plan's price" do
173
244
  result = Braintree::Subscription.create(
174
245
  :payment_method_token => @credit_card.token,
175
- :plan_id => TrialPlan[:id]
246
+ :plan_id => SpecHelper::TrialPlan[:id]
176
247
  )
177
248
 
178
- result.subscription.price.should == TrialPlan[:price]
249
+ result.subscription.price.should == SpecHelper::TrialPlan[:price]
179
250
  end
180
251
 
181
252
  it "can be overridden" do
182
253
  result = Braintree::Subscription.create(
183
254
  :payment_method_token => @credit_card.token,
184
- :plan_id => TrialPlan[:id],
255
+ :plan_id => SpecHelper::TrialPlan[:id],
185
256
  :price => 98.76
186
257
  )
187
258
 
@@ -194,7 +265,7 @@ describe Braintree::Subscription do
194
265
  it "has validation errors on id" do
195
266
  result = Braintree::Subscription.create(
196
267
  :payment_method_token => @credit_card.token,
197
- :plan_id => TrialPlan[:id],
268
+ :plan_id => SpecHelper::TrialPlan[:id],
198
269
  :id => "invalid token"
199
270
  )
200
271
  result.success?.should == false
@@ -205,14 +276,14 @@ describe Braintree::Subscription do
205
276
  duplicate_token = "duplicate_token_#{rand(36**8).to_s(36)}"
206
277
  result = Braintree::Subscription.create(
207
278
  :payment_method_token => @credit_card.token,
208
- :plan_id => TrialPlan[:id],
279
+ :plan_id => SpecHelper::TrialPlan[:id],
209
280
  :id => duplicate_token
210
281
  )
211
282
  result.success?.should == true
212
283
 
213
284
  result = Braintree::Subscription.create(
214
285
  :payment_method_token => @credit_card.token,
215
- :plan_id => TrialPlan[:id],
286
+ :plan_id => SpecHelper::TrialPlan[:id],
216
287
  :id => duplicate_token
217
288
  )
218
289
  result.success?.should == false
@@ -222,7 +293,7 @@ describe Braintree::Subscription do
222
293
  it "trial duration required" do
223
294
  result = Braintree::Subscription.create(
224
295
  :payment_method_token => @credit_card.token,
225
- :plan_id => TrialPlan[:id],
296
+ :plan_id => SpecHelper::TrialPlan[:id],
226
297
  :trial_period => true,
227
298
  :trial_duration => nil
228
299
  )
@@ -233,7 +304,7 @@ describe Braintree::Subscription do
233
304
  it "trial duration unit required" do
234
305
  result = Braintree::Subscription.create(
235
306
  :payment_method_token => @credit_card.token,
236
- :plan_id => TrialPlan[:id],
307
+ :plan_id => SpecHelper::TrialPlan[:id],
237
308
  :trial_period => true,
238
309
  :trial_duration => 2,
239
310
  :trial_duration_unit => nil
@@ -242,13 +313,218 @@ describe Braintree::Subscription do
242
313
  result.errors.for(:subscription).on(:trial_duration_unit)[0].message.should == "Trial Duration Unit is invalid."
243
314
  end
244
315
  end
316
+
317
+ context "add_ons and discounts" do
318
+ it "does not inherit the add_ons and discounts from the plan when do_not_inherit_add_ons_or_discounts is set" do
319
+ result = Braintree::Subscription.create(
320
+ :payment_method_token => @credit_card.token,
321
+ :plan_id => SpecHelper::AddOnDiscountPlan[:id],
322
+ :options => {:do_not_inherit_add_ons_or_discounts => true}
323
+ )
324
+ result.success?.should == true
325
+
326
+ subscription = result.subscription
327
+
328
+ subscription.add_ons.size.should == 0
329
+ subscription.discounts.size.should == 0
330
+ end
331
+
332
+ it "inherits the add_ons and discounts from the plan when not specified" do
333
+ result = Braintree::Subscription.create(
334
+ :payment_method_token => @credit_card.token,
335
+ :plan_id => SpecHelper::AddOnDiscountPlan[:id]
336
+ )
337
+ result.success?.should == true
338
+
339
+ subscription = result.subscription
340
+
341
+ subscription.add_ons.size.should == 2
342
+ add_ons = subscription.add_ons.sort_by { |add_on| add_on.id }
343
+
344
+ add_ons.first.id.should == "increase_10"
345
+ add_ons.first.amount.should == BigDecimal.new("10.00")
346
+ add_ons.first.quantity.should == 1
347
+ add_ons.first.number_of_billing_cycles.should be_nil
348
+ add_ons.first.never_expires?.should be_true
349
+
350
+ add_ons.last.id.should == "increase_20"
351
+ add_ons.last.amount.should == BigDecimal.new("20.00")
352
+ add_ons.last.quantity.should == 1
353
+ add_ons.last.number_of_billing_cycles.should be_nil
354
+ add_ons.last.never_expires?.should be_true
355
+
356
+ subscription.discounts.size.should == 2
357
+ discounts = subscription.discounts.sort_by { |discount| discount.id }
358
+
359
+ discounts.first.id.should == "discount_11"
360
+ discounts.first.amount.should == BigDecimal.new("11.00")
361
+ discounts.first.quantity.should == 1
362
+ discounts.first.number_of_billing_cycles.should be_nil
363
+ discounts.first.never_expires?.should be_true
364
+
365
+ discounts.last.id.should == "discount_7"
366
+ discounts.last.amount.should == BigDecimal.new("7.00")
367
+ discounts.last.quantity.should == 1
368
+ discounts.last.number_of_billing_cycles.should be_nil
369
+ discounts.last.never_expires?.should be_true
370
+ end
371
+
372
+ it "allows overriding of inherited add_ons and discounts" do
373
+ result = Braintree::Subscription.create(
374
+ :payment_method_token => @credit_card.token,
375
+ :plan_id => SpecHelper::AddOnDiscountPlan[:id],
376
+ :add_ons => {
377
+ :update => [
378
+ {
379
+ :amount => BigDecimal.new("50.00"),
380
+ :existing_id => SpecHelper::AddOnIncrease10,
381
+ :quantity => 2,
382
+ :number_of_billing_cycles => 5
383
+ }
384
+ ]
385
+ },
386
+ :discounts => {
387
+ :update => [
388
+ {
389
+ :amount => BigDecimal.new("15.00"),
390
+ :existing_id => SpecHelper::Discount7,
391
+ :quantity => 3,
392
+ :never_expires => true
393
+ }
394
+ ]
395
+ }
396
+ )
397
+ result.success?.should == true
398
+
399
+ subscription = result.subscription
400
+
401
+ subscription.add_ons.size.should == 2
402
+ add_ons = subscription.add_ons.sort_by { |add_on| add_on.id }
403
+
404
+ add_ons.first.id.should == "increase_10"
405
+ add_ons.first.amount.should == BigDecimal.new("50.00")
406
+ add_ons.first.quantity.should == 2
407
+ add_ons.first.number_of_billing_cycles.should == 5
408
+ add_ons.first.never_expires?.should be_false
409
+
410
+ add_ons.last.id.should == "increase_20"
411
+ add_ons.last.amount.should == BigDecimal.new("20.00")
412
+ add_ons.last.quantity.should == 1
413
+
414
+ subscription.discounts.size.should == 2
415
+ discounts = subscription.discounts.sort_by { |discount| discount.id }
416
+
417
+ discounts.first.id.should == "discount_11"
418
+ discounts.first.amount.should == BigDecimal.new("11.00")
419
+ discounts.first.quantity.should == 1
420
+
421
+ discounts.last.id.should == "discount_7"
422
+ discounts.last.amount.should == BigDecimal.new("15.00")
423
+ discounts.last.quantity.should == 3
424
+ discounts.last.number_of_billing_cycles.should be_nil
425
+ discounts.last.never_expires?.should be_true
426
+ end
427
+
428
+ it "allows deleting of inherited add_ons and discounts" do
429
+ result = Braintree::Subscription.create(
430
+ :payment_method_token => @credit_card.token,
431
+ :plan_id => SpecHelper::AddOnDiscountPlan[:id],
432
+ :add_ons => {
433
+ :remove => [SpecHelper::AddOnIncrease10]
434
+ },
435
+ :discounts => {
436
+ :remove => [SpecHelper::Discount7]
437
+ }
438
+ )
439
+ result.success?.should == true
440
+
441
+ subscription = result.subscription
442
+
443
+ subscription.add_ons.size.should == 1
444
+ subscription.add_ons.first.id.should == "increase_20"
445
+ subscription.add_ons.first.amount.should == BigDecimal.new("20.00")
446
+ subscription.add_ons.first.quantity.should == 1
447
+
448
+ subscription.discounts.size.should == 1
449
+ subscription.discounts.last.id.should == "discount_11"
450
+ subscription.discounts.last.amount.should == BigDecimal.new("11.00")
451
+ subscription.discounts.last.quantity.should == 1
452
+ end
453
+
454
+ it "allows adding new add_ons and discounts" do
455
+ result = Braintree::Subscription.create(
456
+ :payment_method_token => @credit_card.token,
457
+ :plan_id => SpecHelper::AddOnDiscountPlan[:id],
458
+ :add_ons => {
459
+ :add => [{:inherited_from_id => SpecHelper::AddOnIncrease30}]
460
+ },
461
+ :discounts => {
462
+ :add => [{:inherited_from_id => SpecHelper::Discount15}]
463
+ }
464
+ )
465
+ result.success?.should == true
466
+ subscription = result.subscription
467
+
468
+ subscription.add_ons.size.should == 3
469
+ add_ons = subscription.add_ons.sort_by { |add_on| add_on.id }
470
+
471
+ add_ons[0].id.should == "increase_10"
472
+ add_ons[0].amount.should == BigDecimal.new("10.00")
473
+ add_ons[0].quantity.should == 1
474
+
475
+ add_ons[1].id.should == "increase_20"
476
+ add_ons[1].amount.should == BigDecimal.new("20.00")
477
+ add_ons[1].quantity.should == 1
478
+
479
+ add_ons[2].id.should == "increase_30"
480
+ add_ons[2].amount.should == BigDecimal.new("30.00")
481
+ add_ons[2].quantity.should == 1
482
+
483
+ subscription.discounts.size.should == 3
484
+ discounts = subscription.discounts.sort_by { |discount| discount.id }
485
+
486
+ discounts[0].id.should == "discount_11"
487
+ discounts[0].amount.should == BigDecimal.new("11.00")
488
+ discounts[0].quantity.should == 1
489
+
490
+ discounts[1].id.should == "discount_15"
491
+ discounts[1].amount.should == BigDecimal.new("15.00")
492
+ discounts[1].quantity.should == 1
493
+
494
+ discounts[2].id.should == "discount_7"
495
+ discounts[2].amount.should == BigDecimal.new("7.00")
496
+ discounts[2].quantity.should == 1
497
+ end
498
+
499
+ it "properly parses validation errors for arrays" do
500
+ result = Braintree::Subscription.create(
501
+ :payment_method_token => @credit_card.token,
502
+ :plan_id => SpecHelper::AddOnDiscountPlan[:id],
503
+ :add_ons => {
504
+ :update => [
505
+ {
506
+ :existing_id => SpecHelper::AddOnIncrease10,
507
+ :amount => "invalid"
508
+ },
509
+ {
510
+ :existing_id => SpecHelper::AddOnIncrease20,
511
+ :quantity => -10,
512
+ }
513
+ ]
514
+ }
515
+ )
516
+ result.success?.should == false
517
+ result.errors.for(:subscription).for(:add_ons).for(:update).for_index(0).on(:amount)[0].code.should == Braintree::ErrorCodes::Subscription::Modification::AmountIsInvalid
518
+ result.errors.for(:subscription).for(:add_ons).for(:update).for_index(1).on(:quantity)[0].code.should == Braintree::ErrorCodes::Subscription::Modification::QuantityIsInvalid
519
+ end
520
+ end
245
521
  end
246
522
 
247
523
  describe "self.find" do
248
524
  it "finds a subscription" do
249
525
  result = Braintree::Subscription.create(
250
526
  :payment_method_token => @credit_card.token,
251
- :plan_id => TriallessPlan[:id]
527
+ :plan_id => SpecHelper::TrialPlan[:id]
252
528
  )
253
529
  result.success?.should == true
254
530
 
@@ -267,7 +543,7 @@ describe Braintree::Subscription do
267
543
  @subscription = Braintree::Subscription.create(
268
544
  :payment_method_token => @credit_card.token,
269
545
  :price => 54.32,
270
- :plan_id => TriallessPlan[:id]
546
+ :plan_id => SpecHelper::TriallessPlan[:id]
271
547
  ).subscription
272
548
  end
273
549
 
@@ -300,12 +576,12 @@ describe Braintree::Subscription do
300
576
  result = Braintree::Subscription.update(@subscription.id,
301
577
  :id => new_id,
302
578
  :price => 9999.88,
303
- :plan_id => TrialPlan[:id]
579
+ :plan_id => SpecHelper::TrialPlan[:id]
304
580
  )
305
581
 
306
582
  result.success?.should == true
307
583
  result.subscription.id.should =~ /#{new_id}/
308
- result.subscription.plan_id.should == TrialPlan[:id]
584
+ result.subscription.plan_id.should == SpecHelper::TrialPlan[:id]
309
585
  result.subscription.price.should == BigDecimal.new("9999.88")
310
586
  end
311
587
 
@@ -319,6 +595,28 @@ describe Braintree::Subscription do
319
595
  result.subscription.transactions.size.should == @subscription.transactions.size + 1
320
596
  end
321
597
 
598
+ it "allows the user to force proration if there is a charge" do
599
+ result = Braintree::Subscription.update(@subscription.id,
600
+ :price => @subscription.price.to_f + 1,
601
+ :options => { :prorate_charges => true }
602
+ )
603
+
604
+ result.success?.should == true
605
+ result.subscription.price.to_f.should == @subscription.price.to_f + 1
606
+ result.subscription.transactions.size.should == @subscription.transactions.size + 1
607
+ end
608
+
609
+ it "allows the user to prevent proration if there is a charge" do
610
+ result = Braintree::Subscription.update(@subscription.id,
611
+ :price => @subscription.price.to_f + 1,
612
+ :options => { :prorate_charges => false }
613
+ )
614
+
615
+ result.success?.should == true
616
+ result.subscription.price.to_f.should == @subscription.price.to_f + 1
617
+ result.subscription.transactions.size.should == @subscription.transactions.size
618
+ end
619
+
322
620
  it "doesn't prorate if price decreases" do
323
621
  result = Braintree::Subscription.update(@subscription.id,
324
622
  :price => @subscription.price.to_f - 1
@@ -334,7 +632,7 @@ describe Braintree::Subscription do
334
632
  before(:each) do
335
633
  @subscription = Braintree::Subscription.create(
336
634
  :payment_method_token => @credit_card.token,
337
- :plan_id => TrialPlan[:id]
635
+ :plan_id => SpecHelper::TrialPlan[:id]
338
636
  ).subscription
339
637
  end
340
638
 
@@ -368,7 +666,7 @@ describe Braintree::Subscription do
368
666
  duplicate_id = "new_id_#{rand(36**6).to_s(36)}"
369
667
  duplicate = Braintree::Subscription.create(
370
668
  :payment_method_token => @credit_card.token,
371
- :plan_id => TrialPlan[:id],
669
+ :plan_id => SpecHelper::TrialPlan[:id],
372
670
  :id => duplicate_id
373
671
  )
374
672
  result = Braintree::Subscription.update(
@@ -383,7 +681,7 @@ describe Braintree::Subscription do
383
681
  subscription = Braintree::Subscription.create(
384
682
  :payment_method_token => @credit_card.token,
385
683
  :price => 54.32,
386
- :plan_id => TriallessPlan[:id]
684
+ :plan_id => SpecHelper::TriallessPlan[:id]
387
685
  ).subscription
388
686
 
389
687
  result = Braintree::Subscription.cancel(subscription.id)
@@ -396,15 +694,201 @@ describe Braintree::Subscription do
396
694
  result.errors.for(:subscription)[0].code.should == Braintree::ErrorCodes::Subscription::CannotEditCanceledSubscription
397
695
  end
398
696
  end
399
- end
400
697
 
698
+ context "number_of_billing_cycles" do
699
+ it "sets the number of billing cycles on the subscription when provided" do
700
+ subscription = Braintree::Subscription.create(
701
+ :payment_method_token => @credit_card.token,
702
+ :plan_id => SpecHelper::TriallessPlan[:id],
703
+ :number_of_billing_cycles => 10
704
+ ).subscription
705
+
706
+ result = Braintree::Subscription.update(
707
+ subscription.id,
708
+ :number_of_billing_cycles => 5
709
+ )
710
+
711
+ result.subscription.number_of_billing_cycles.should == 5
712
+ end
713
+
714
+ it "sets the number of billing cycles to nil if :never_expires => true" do
715
+ subscription = Braintree::Subscription.create(
716
+ :payment_method_token => @credit_card.token,
717
+ :plan_id => SpecHelper::TriallessPlan[:id],
718
+ :number_of_billing_cycles => 10
719
+ ).subscription
720
+
721
+ result = Braintree::Subscription.update(
722
+ subscription.id,
723
+ :never_expires => true
724
+ )
725
+
726
+ result.success?.should == true
727
+ result.subscription.number_of_billing_cycles.should == nil
728
+ result.subscription.never_expires?.should be_true
729
+ end
730
+ end
731
+
732
+ context "add_ons and discounts" do
733
+ it "can update add_ons and discounts" do
734
+ result = Braintree::Subscription.create(
735
+ :payment_method_token => @credit_card.token,
736
+ :plan_id => SpecHelper::AddOnDiscountPlan[:id]
737
+ )
738
+ result.success?.should == true
739
+ subscription = result.subscription
740
+
741
+ result = Braintree::Subscription.update(
742
+ subscription.id,
743
+ :add_ons => {
744
+ :update => [
745
+ {
746
+ :existing_id => subscription.add_ons.first.id,
747
+ :amount => BigDecimal.new("99.99"),
748
+ :quantity => 12
749
+ }
750
+ ]
751
+ },
752
+ :discounts => {
753
+ :update => [
754
+ {
755
+ :existing_id => subscription.discounts.first.id,
756
+ :amount => BigDecimal.new("88.88"),
757
+ :quantity => 9
758
+ }
759
+ ]
760
+ }
761
+ )
762
+
763
+ subscription = result.subscription
764
+
765
+ subscription.add_ons.size.should == 2
766
+ add_ons = subscription.add_ons.sort_by { |add_on| add_on.id }
767
+
768
+ add_ons.first.amount.should == BigDecimal.new("99.99")
769
+ add_ons.first.quantity.should == 12
770
+
771
+ subscription.discounts.size.should == 2
772
+ discounts = subscription.discounts.sort_by { |discount| discount.id }
773
+
774
+ discounts.last.amount.should == BigDecimal.new("88.88")
775
+ discounts.last.quantity.should == 9
776
+ end
777
+
778
+ it "allows adding new add_ons and discounts" do
779
+ subscription = Braintree::Subscription.create(
780
+ :payment_method_token => @credit_card.token,
781
+ :plan_id => SpecHelper::AddOnDiscountPlan[:id]
782
+ ).subscription
783
+
784
+ result = Braintree::Subscription.update(subscription.id,
785
+ :add_ons => {
786
+ :add => [{:inherited_from_id => SpecHelper::AddOnIncrease30}]
787
+ },
788
+ :discounts => {
789
+ :add => [{:inherited_from_id => SpecHelper::Discount15}]
790
+ }
791
+ )
792
+
793
+ result.success?.should == true
794
+ subscription = result.subscription
795
+
796
+ subscription.add_ons.size.should == 3
797
+ add_ons = subscription.add_ons.sort_by { |add_on| add_on.id }
798
+
799
+ add_ons[0].id.should == "increase_10"
800
+ add_ons[0].amount.should == BigDecimal.new("10.00")
801
+ add_ons[0].quantity.should == 1
802
+
803
+ add_ons[1].id.should == "increase_20"
804
+ add_ons[1].amount.should == BigDecimal.new("20.00")
805
+ add_ons[1].quantity.should == 1
806
+
807
+ add_ons[2].id.should == "increase_30"
808
+ add_ons[2].amount.should == BigDecimal.new("30.00")
809
+ add_ons[2].quantity.should == 1
810
+
811
+ subscription.discounts.size.should == 3
812
+ discounts = subscription.discounts.sort_by { |discount| discount.id }
813
+
814
+ discounts[0].id.should == "discount_11"
815
+ discounts[0].amount.should == BigDecimal.new("11.00")
816
+ discounts[0].quantity.should == 1
817
+
818
+ discounts[1].id.should == "discount_15"
819
+ discounts[1].amount.should == BigDecimal.new("15.00")
820
+ discounts[1].quantity.should == 1
821
+
822
+ discounts[2].id.should == "discount_7"
823
+ discounts[2].amount.should == BigDecimal.new("7.00")
824
+ discounts[2].quantity.should == 1
825
+ end
826
+
827
+ it "allows replacing entire set of add_ons and discounts" do
828
+ subscription = Braintree::Subscription.create(
829
+ :payment_method_token => @credit_card.token,
830
+ :plan_id => SpecHelper::AddOnDiscountPlan[:id]
831
+ ).subscription
832
+
833
+ result = Braintree::Subscription.update(subscription.id,
834
+ :add_ons => {
835
+ :add => [{:inherited_from_id => SpecHelper::AddOnIncrease30}]
836
+ },
837
+ :discounts => {
838
+ :add => [{:inherited_from_id => SpecHelper::Discount15}]
839
+ },
840
+ :options => {:replace_all_add_ons_and_discounts => true}
841
+ )
842
+
843
+ result.success?.should == true
844
+ subscription = result.subscription
845
+
846
+ subscription.add_ons.size.should == 1
847
+
848
+ subscription.add_ons[0].amount.should == BigDecimal.new("30.00")
849
+ subscription.add_ons[0].quantity.should == 1
850
+
851
+ subscription.discounts.size.should == 1
852
+
853
+ subscription.discounts[0].amount.should == BigDecimal.new("15.00")
854
+ subscription.discounts[0].quantity.should == 1
855
+ end
856
+
857
+ it "allows deleting of add_ons and discounts" do
858
+ subscription = Braintree::Subscription.create(
859
+ :payment_method_token => @credit_card.token,
860
+ :plan_id => SpecHelper::AddOnDiscountPlan[:id]
861
+ ).subscription
862
+
863
+ result = Braintree::Subscription.update(subscription.id,
864
+ :add_ons => {
865
+ :remove => [SpecHelper::AddOnIncrease10]
866
+ },
867
+ :discounts => {
868
+ :remove => [SpecHelper::Discount7]
869
+ }
870
+ )
871
+ result.success?.should == true
872
+
873
+ subscription = result.subscription
874
+
875
+ subscription.add_ons.size.should == 1
876
+ subscription.add_ons.first.amount.should == BigDecimal.new("20.00")
877
+ subscription.add_ons.first.quantity.should == 1
878
+
879
+ subscription.discounts.size.should == 1
880
+ subscription.discounts.last.amount.should == BigDecimal.new("11.00")
881
+ subscription.discounts.last.quantity.should == 1
882
+ end
883
+ end
884
+ end
401
885
 
402
886
  describe "self.cancel" do
403
887
  it "returns a success response with the updated subscription if valid" do
404
888
  subscription = Braintree::Subscription.create(
405
889
  :payment_method_token => @credit_card.token,
406
890
  :price => 54.32,
407
- :plan_id => TriallessPlan[:id]
891
+ :plan_id => SpecHelper::TriallessPlan[:id]
408
892
  ).subscription
409
893
 
410
894
  result = Braintree::Subscription.cancel(subscription.id)
@@ -422,7 +906,7 @@ describe Braintree::Subscription do
422
906
  subscription = Braintree::Subscription.create(
423
907
  :payment_method_token => @credit_card.token,
424
908
  :price => 54.32,
425
- :plan_id => TriallessPlan[:id]
909
+ :plan_id => SpecHelper::TriallessPlan[:id]
426
910
  ).subscription
427
911
 
428
912
  result = Braintree::Subscription.cancel(subscription.id)
@@ -436,212 +920,190 @@ describe Braintree::Subscription do
436
920
  end
437
921
 
438
922
  describe "self.search" do
439
- context "search_fields" do
440
- it "correctly returns a result with no matches" do
923
+ describe "id" do
924
+ it "works using the is operator" do
925
+ id = rand(36**8).to_s(36)
926
+ subscription1 = Braintree::Subscription.create(
927
+ :payment_method_token => @credit_card.token,
928
+ :plan_id => SpecHelper::TrialPlan[:id],
929
+ :id => "subscription1_#{id}"
930
+ ).subscription
931
+
932
+ subscription2 = Braintree::Subscription.create(
933
+ :payment_method_token => @credit_card.token,
934
+ :plan_id => SpecHelper::TrialPlan[:id],
935
+ :id => "subscription2_#{id}"
936
+ ).subscription
937
+
441
938
  collection = Braintree::Subscription.search do |search|
442
- search.plan_id.is "not_a_real_plan_id"
939
+ search.id.is "subscription1_#{id}"
443
940
  end
444
941
 
445
- collection.maximum_size.should == 0
942
+ collection.should include(subscription1)
943
+ collection.should_not include(subscription2)
446
944
  end
945
+ end
447
946
 
448
- context "is statement" do
449
- it "returns resource collection with matching results" do
450
- trialless_subscription = Braintree::Subscription.create(
451
- :payment_method_token => @credit_card.token,
452
- :plan_id => TriallessPlan[:id]
453
- ).subscription
454
-
455
- trial_subscription = Braintree::Subscription.create(
456
- :payment_method_token => @credit_card.token,
457
- :plan_id => TrialPlan[:id]
458
- ).subscription
947
+ describe "merchant_account_id" do
948
+ it "is searchable using the is or in operator" do
949
+ subscription1 = Braintree::Subscription.create(
950
+ :payment_method_token => @credit_card.token,
951
+ :plan_id => SpecHelper::TrialPlan[:id],
952
+ :merchant_account_id => SpecHelper::DefaultMerchantAccountId,
953
+ :price => "1"
954
+ ).subscription
459
955
 
460
- collection = Braintree::Subscription.search do |search|
461
- search.plan_id.is TriallessPlan[:id]
462
- end
956
+ subscription2 = Braintree::Subscription.create(
957
+ :payment_method_token => @credit_card.token,
958
+ :plan_id => SpecHelper::TrialPlan[:id],
959
+ :merchant_account_id => SpecHelper::NonDefaultMerchantAccountId,
960
+ :price => "1"
961
+ ).subscription
463
962
 
464
- collection.should include(trialless_subscription)
465
- collection.should_not include(trial_subscription)
963
+ collection = Braintree::Subscription.search do |search|
964
+ search.merchant_account_id.is SpecHelper::DefaultMerchantAccountId
965
+ search.price.is "1"
466
966
  end
467
- end
468
967
 
469
- context "is_not statement" do
470
- it "returns resource collection without matching results" do
471
- trialless_subscription = Braintree::Subscription.create(
472
- :payment_method_token => @credit_card.token,
473
- :plan_id => TriallessPlan[:id]
474
- ).subscription
968
+ collection.should include(subscription1)
969
+ collection.should_not include(subscription2)
475
970
 
476
- trial_subscription = Braintree::Subscription.create(
477
- :payment_method_token => @credit_card.token,
478
- :plan_id => TrialPlan[:id]
479
- ).subscription
480
-
481
- collection = Braintree::Subscription.search do |search|
482
- search.plan_id.is_not TriallessPlan[:id]
483
- end
484
-
485
- collection.should_not include(trialless_subscription)
486
- collection.should include(trial_subscription)
971
+ collection = Braintree::Subscription.search do |search|
972
+ search.merchant_account_id.in [SpecHelper::DefaultMerchantAccountId, SpecHelper::NonDefaultMerchantAccountId]
973
+ search.price.is "1"
487
974
  end
488
- end
489
-
490
- context "ends_with statement" do
491
- it "returns resource collection with matching results" do
492
- trialless_subscription = Braintree::Subscription.create(
493
- :payment_method_token => @credit_card.token,
494
- :plan_id => TriallessPlan[:id]
495
- ).subscription
496
-
497
- trial_subscription = Braintree::Subscription.create(
498
- :payment_method_token => @credit_card.token,
499
- :plan_id => TrialPlan[:id]
500
- ).subscription
501
975
 
502
- collection = Braintree::Subscription.search do |search|
503
- search.plan_id.ends_with "trial_plan"
504
- end
505
-
506
- collection.should include(trial_subscription)
507
- collection.should_not include(trialless_subscription)
508
- end
976
+ collection.should include(subscription1)
977
+ collection.should include(subscription2)
509
978
  end
979
+ end
510
980
 
511
- context "starts_with statement" do
512
- it "returns resource collection with matching results" do
513
- trialless_subscription = Braintree::Subscription.create(
514
- :payment_method_token => @credit_card.token,
515
- :plan_id => TriallessPlan[:id]
516
- ).subscription
517
-
518
- trial_subscription = Braintree::Subscription.create(
519
- :payment_method_token => @credit_card.token,
520
- :plan_id => TrialPlan[:id]
521
- ).subscription
981
+ describe "plan_id" do
982
+ it "works using the is operator" do
983
+ trialless_subscription = Braintree::Subscription.create(
984
+ :payment_method_token => @credit_card.token,
985
+ :plan_id => SpecHelper::TriallessPlan[:id],
986
+ :price => "2"
987
+ ).subscription
522
988
 
523
- collection = Braintree::Subscription.search do |search|
524
- search.plan_id.starts_with "integration_trial_p"
525
- end
989
+ trial_subscription = Braintree::Subscription.create(
990
+ :payment_method_token => @credit_card.token,
991
+ :plan_id => SpecHelper::TrialPlan[:id],
992
+ :price => "2"
993
+ ).subscription
526
994
 
527
- collection.should include(trial_subscription)
528
- collection.should_not include(trialless_subscription)
995
+ collection = Braintree::Subscription.search do |search|
996
+ search.plan_id.is SpecHelper::TriallessPlan[:id]
997
+ search.price.is "2"
529
998
  end
530
- end
531
-
532
- context "contains statement" do
533
- it "returns resource collection with matching results" do
534
- trialless_subscription = Braintree::Subscription.create(
535
- :payment_method_token => @credit_card.token,
536
- :plan_id => TriallessPlan[:id]
537
- ).subscription
538
-
539
- trial_subscription = Braintree::Subscription.create(
540
- :payment_method_token => @credit_card.token,
541
- :plan_id => TrialPlan[:id]
542
- ).subscription
543
999
 
544
- collection = Braintree::Subscription.search do |search|
545
- search.plan_id.contains "trial_p"
546
- end
547
-
548
- collection.should include(trial_subscription)
549
- collection.should_not include(trialless_subscription)
550
- end
1000
+ collection.should include(trialless_subscription)
1001
+ collection.should_not include(trial_subscription)
551
1002
  end
552
1003
  end
553
1004
 
554
- context "multiple_value_fields" do
555
- context "in" do
556
- it "matches all values if none are specified" do
557
- subscription1 = Braintree::Subscription.create(
558
- :payment_method_token => @credit_card.token,
559
- :plan_id => TriallessPlan[:id]
560
- ).subscription
561
-
562
- subscription2 = Braintree::Subscription.create(
563
- :payment_method_token => @credit_card.token,
564
- :plan_id => TriallessPlan[:id]
565
- ).subscription
566
-
567
- Braintree::Subscription.cancel(subscription2.id)
1005
+ describe "price" do
1006
+ it "works using the is operator" do
1007
+ subscription_500 = Braintree::Subscription.create(
1008
+ :payment_method_token => @credit_card.token,
1009
+ :plan_id => SpecHelper::TrialPlan[:id],
1010
+ :price => "5.00"
1011
+ ).subscription
568
1012
 
569
- collection = Braintree::Subscription.search do |search|
570
- search.plan_id.is TriallessPlan[:id]
571
- end
1013
+ subscription_501 = Braintree::Subscription.create(
1014
+ :payment_method_token => @credit_card.token,
1015
+ :plan_id => SpecHelper::TrialPlan[:id],
1016
+ :price => "5.01"
1017
+ ).subscription
572
1018
 
573
- collection.should include(subscription1)
574
- collection.should include(subscription2)
1019
+ collection = Braintree::Subscription.search do |search|
1020
+ search.price.is "5.00"
575
1021
  end
576
1022
 
577
- it "returns only matching results" do
578
- subscription1 = Braintree::Subscription.create(
579
- :payment_method_token => @credit_card.token,
580
- :plan_id => TriallessPlan[:id]
581
- ).subscription
1023
+ collection.should include(subscription_500)
1024
+ collection.should_not include(subscription_501)
1025
+ end
1026
+ end
582
1027
 
583
- subscription2 = Braintree::Subscription.create(
584
- :payment_method_token => @credit_card.token,
585
- :plan_id => TriallessPlan[:id]
586
- ).subscription
1028
+ describe "days_past_due" do
1029
+ it "is backwards-compatible for 'is'" do
1030
+ active_subscription = Braintree::Subscription.create(
1031
+ :payment_method_token => @credit_card.token,
1032
+ :plan_id => SpecHelper::TrialPlan[:id],
1033
+ :price => "6"
1034
+ ).subscription
587
1035
 
588
- Braintree::Subscription.cancel(subscription2.id)
1036
+ past_due_subscription = Braintree::Subscription.create(
1037
+ :payment_method_token => @credit_card.token,
1038
+ :plan_id => SpecHelper::TrialPlan[:id],
1039
+ :price => "6"
1040
+ ).subscription
589
1041
 
590
- collection = Braintree::Subscription.search do |search|
591
- search.status.in Braintree::Subscription::Status::Active
592
- end
1042
+ SpecHelper.make_past_due(past_due_subscription, 5)
593
1043
 
594
- collection.should include(subscription1)
595
- collection.should_not include(subscription2)
1044
+ collection = Braintree::Subscription.search do |search|
1045
+ search.price.is "6.00"
1046
+ search.days_past_due.is 5
596
1047
  end
597
1048
 
598
- it "returns only matching results given an argument list" do
599
- subscription1 = Braintree::Subscription.create(
600
- :payment_method_token => @credit_card.token,
601
- :plan_id => TriallessPlan[:id]
602
- ).subscription
603
-
604
- subscription2 = Braintree::Subscription.create(
605
- :payment_method_token => @credit_card.token,
606
- :plan_id => TriallessPlan[:id]
607
- ).subscription
608
-
609
- Braintree::Subscription.cancel(subscription2.id)
1049
+ collection.should include(past_due_subscription)
1050
+ collection.should_not include(active_subscription)
1051
+ collection.each do |s|
1052
+ s.status.should == Braintree::Subscription::Status::PastDue
1053
+ end
1054
+ end
610
1055
 
611
- collection = Braintree::Subscription.search do |search|
612
- search.status.in Braintree::Subscription::Status::Active, Braintree::Subscription::Status::Canceled
613
- end
1056
+ it "passes a smoke test" do
1057
+ subscription = Braintree::Subscription.create(
1058
+ :payment_method_token => @credit_card.token,
1059
+ :plan_id => SpecHelper::TrialPlan[:id]
1060
+ ).subscription
614
1061
 
615
- collection.should include(subscription1)
616
- collection.should include(subscription2)
1062
+ collection = Braintree::Subscription.search do |search|
1063
+ search.days_past_due.between 1, 20
617
1064
  end
618
1065
 
619
- it "returns only matching results given an array" do
620
- subscription1 = Braintree::Subscription.create(
621
- :payment_method_token => @credit_card.token,
622
- :plan_id => TriallessPlan[:id]
623
- ).subscription
1066
+ collection.should_not include(subscription)
1067
+ collection.each do |s|
1068
+ s.days_past_due.should >= 1
1069
+ s.days_past_due.should <= 20
1070
+ end
1071
+ end
1072
+ end
624
1073
 
625
- subscription2 = Braintree::Subscription.create(
626
- :payment_method_token => @credit_card.token,
627
- :plan_id => TriallessPlan[:id]
628
- ).subscription
1074
+ describe "billing_cycles_remaining" do
1075
+ it "passes a smoke test" do
1076
+ subscription_5 = Braintree::Subscription.create(
1077
+ :payment_method_token => @credit_card.token,
1078
+ :plan_id => SpecHelper::TrialPlan[:id],
1079
+ :number_of_billing_cycles => 5
1080
+ ).subscription
629
1081
 
630
- Braintree::Subscription.cancel(subscription2.id)
1082
+ subscription_9 = Braintree::Subscription.create(
1083
+ :payment_method_token => @credit_card.token,
1084
+ :plan_id => SpecHelper::TriallessPlan[:id],
1085
+ :number_of_billing_cycles => 10
1086
+ ).subscription
631
1087
 
632
- collection = Braintree::Subscription.search do |search|
633
- search.status.in [Braintree::Subscription::Status::Active, Braintree::Subscription::Status::Canceled]
634
- end
1088
+ subscription_15 = Braintree::Subscription.create(
1089
+ :payment_method_token => @credit_card.token,
1090
+ :plan_id => SpecHelper::TriallessPlan[:id],
1091
+ :number_of_billing_cycles => 15
1092
+ ).subscription
635
1093
 
636
- collection.should include(subscription1)
637
- collection.should include(subscription2)
1094
+ collection = Braintree::Subscription.search do |search|
1095
+ search.billing_cycles_remaining.between 5, 10
638
1096
  end
1097
+
1098
+ collection.should include(subscription_5)
1099
+ collection.should include(subscription_9)
1100
+ collection.should_not include(subscription_15)
639
1101
  end
640
1102
  end
641
1103
 
642
1104
  it "returns multiple results" do
643
1105
  (110 - Braintree::Subscription.search.maximum_size).times do
644
- Braintree::Subscription.create(:payment_method_token => @credit_card.token, :plan_id => TriallessPlan[:id])
1106
+ Braintree::Subscription.create(:payment_method_token => @credit_card.token, :plan_id => SpecHelper::TrialPlan[:id])
645
1107
  end
646
1108
 
647
1109
  collection = Braintree::Subscription.search
@@ -650,14 +1112,15 @@ describe Braintree::Subscription do
650
1112
  subscriptions_ids = collection.map {|t| t.id }.uniq.compact
651
1113
  subscriptions_ids.size.should == collection.maximum_size
652
1114
  end
653
-
654
1115
  end
655
1116
 
656
1117
  describe "self.retry_charge" do
657
1118
  it "is successful with only subscription id" do
658
- subscription = Braintree::Subscription.search do |search|
659
- search.status.in Braintree::Subscription::Status::PastDue
660
- end.first
1119
+ subscription = Braintree::Subscription.create(
1120
+ :payment_method_token => @credit_card.token,
1121
+ :plan_id => SpecHelper::TriallessPlan[:id]
1122
+ ).subscription
1123
+ SpecHelper.make_past_due(subscription)
661
1124
 
662
1125
  result = Braintree::Subscription.retry_charge(subscription.id)
663
1126
 
@@ -671,9 +1134,11 @@ describe Braintree::Subscription do
671
1134
  end
672
1135
 
673
1136
  it "is successful with subscription id and amount" do
674
- subscription = Braintree::Subscription.search do |search|
675
- search.status.in Braintree::Subscription::Status::PastDue
676
- end.first
1137
+ subscription = Braintree::Subscription.create(
1138
+ :payment_method_token => @credit_card.token,
1139
+ :plan_id => SpecHelper::TriallessPlan[:id]
1140
+ ).subscription
1141
+ SpecHelper.make_past_due(subscription)
677
1142
 
678
1143
  result = Braintree::Subscription.retry_charge(subscription.id, Braintree::Test::TransactionAmounts::Authorize)
679
1144