stripe 1.18.0 → 1.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +11 -1
  4. data/History.txt +98 -0
  5. data/README.rdoc +19 -10
  6. data/VERSION +1 -1
  7. data/lib/stripe/account.rb +46 -4
  8. data/lib/stripe/api_operations/create.rb +3 -10
  9. data/lib/stripe/api_operations/delete.rb +4 -4
  10. data/lib/stripe/api_operations/list.rb +17 -9
  11. data/lib/stripe/api_operations/request.rb +41 -0
  12. data/lib/stripe/api_operations/update.rb +41 -40
  13. data/lib/stripe/api_resource.rb +7 -4
  14. data/lib/stripe/application_fee.rb +3 -4
  15. data/lib/stripe/application_fee_refund.rb +1 -1
  16. data/lib/stripe/balance_transaction.rb +1 -1
  17. data/lib/stripe/bank_account.rb +19 -0
  18. data/lib/stripe/bitcoin_receiver.rb +12 -2
  19. data/lib/stripe/bitcoin_transaction.rb +5 -0
  20. data/lib/stripe/card.rb +6 -4
  21. data/lib/stripe/charge.rb +14 -22
  22. data/lib/stripe/coupon.rb +2 -2
  23. data/lib/stripe/customer.rb +24 -26
  24. data/lib/stripe/dispute.rb +16 -0
  25. data/lib/stripe/errors/card_error.rb +3 -2
  26. data/lib/stripe/errors/invalid_request_error.rb +3 -2
  27. data/lib/stripe/errors/rate_limit_error.rb +4 -0
  28. data/lib/stripe/errors/stripe_error.rb +8 -2
  29. data/lib/stripe/event.rb +1 -1
  30. data/lib/stripe/file_upload.rb +12 -22
  31. data/lib/stripe/invoice.rb +8 -8
  32. data/lib/stripe/invoice_item.rb +2 -2
  33. data/lib/stripe/list_object.rb +77 -13
  34. data/lib/stripe/order.rb +19 -0
  35. data/lib/stripe/plan.rb +2 -2
  36. data/lib/stripe/product.rb +16 -0
  37. data/lib/stripe/recipient.rb +2 -2
  38. data/lib/stripe/refund.rb +2 -9
  39. data/lib/stripe/reversal.rb +14 -0
  40. data/lib/stripe/singleton_api_resource.rb +2 -2
  41. data/lib/stripe/sku.rb +8 -0
  42. data/lib/stripe/stripe_object.rb +232 -46
  43. data/lib/stripe/subscription.rb +3 -3
  44. data/lib/stripe/token.rb +1 -1
  45. data/lib/stripe/transfer.rb +3 -3
  46. data/lib/stripe/util.rb +64 -21
  47. data/lib/stripe/version.rb +1 -1
  48. data/lib/stripe.rb +102 -67
  49. data/stripe.gemspec +0 -2
  50. data/test/stripe/account_test.rb +135 -6
  51. data/test/stripe/api_resource_test.rb +326 -42
  52. data/test/stripe/application_fee_refund_test.rb +6 -6
  53. data/test/stripe/application_fee_test.rb +3 -3
  54. data/test/stripe/balance_test.rb +11 -0
  55. data/test/stripe/bitcoin_receiver_test.rb +30 -7
  56. data/test/stripe/bitcoin_transaction_test.rb +29 -0
  57. data/test/stripe/charge_refund_test.rb +55 -0
  58. data/test/stripe/charge_test.rb +32 -13
  59. data/test/stripe/coupon_test.rb +3 -3
  60. data/test/stripe/customer_card_test.rb +20 -14
  61. data/test/stripe/customer_test.rb +15 -15
  62. data/test/stripe/dispute_test.rb +45 -0
  63. data/test/stripe/file_upload_test.rb +17 -6
  64. data/test/stripe/invoice_test.rb +18 -4
  65. data/test/stripe/list_object_test.rb +126 -2
  66. data/test/stripe/metadata_test.rb +28 -13
  67. data/test/stripe/order_test.rb +52 -0
  68. data/test/stripe/product_test.rb +41 -0
  69. data/test/stripe/recipient_card_test.rb +9 -9
  70. data/test/stripe/refund_test.rb +23 -15
  71. data/test/stripe/reversal_test.rb +47 -0
  72. data/test/stripe/sku_test.rb +24 -0
  73. data/test/stripe/stripe_object_test.rb +67 -6
  74. data/test/stripe/subscription_test.rb +13 -13
  75. data/test/stripe/transfer_test.rb +4 -4
  76. data/test/stripe/util_test.rb +45 -29
  77. data/test/stripe_test.rb +16 -0
  78. data/test/test_data.rb +273 -66
  79. metadata +47 -76
  80. data/lib/stripe/certificate_blacklist.rb +0 -55
  81. data/test/stripe/certificate_blacklist_test.rb +0 -18
@@ -37,6 +37,15 @@ module Stripe
37
37
  end
38
38
  end
39
39
 
40
+ should "using a nil api key should raise an exception" do
41
+ assert_raises TypeError do
42
+ Stripe::Customer.list({}, nil)
43
+ end
44
+ assert_raises TypeError do
45
+ Stripe::Customer.list({}, { :api_key => nil })
46
+ end
47
+ end
48
+
40
49
  should "specifying api credentials containing whitespace should raise an exception" do
41
50
  Stripe.api_key = "key "
42
51
  assert_raises Stripe::AuthenticationError do
@@ -46,7 +55,7 @@ module Stripe
46
55
 
47
56
  should "specifying invalid api credentials should raise an exception" do
48
57
  Stripe.api_key = "invalid"
49
- response = test_response(test_invalid_api_key_error, 401)
58
+ response = make_response(make_invalid_api_key_error, 401)
50
59
  assert_raises Stripe::AuthenticationError do
51
60
  @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 401))
52
61
  Stripe::Customer.retrieve("failing_customer")
@@ -55,7 +64,7 @@ module Stripe
55
64
 
56
65
  should "AuthenticationErrors should have an http status, http body, and JSON body" do
57
66
  Stripe.api_key = "invalid"
58
- response = test_response(test_invalid_api_key_error, 401)
67
+ response = make_response(make_invalid_api_key_error, 401)
59
68
  begin
60
69
  @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 401))
61
70
  Stripe::Customer.retrieve("failing_customer")
@@ -63,15 +72,45 @@ module Stripe
63
72
  assert_equal(401, e.http_status)
64
73
  assert_equal(true, !!e.http_body)
65
74
  assert_equal(true, !!e.json_body[:error][:message])
66
- assert_equal(test_invalid_api_key_error[:error][:message], e.json_body[:error][:message])
75
+ assert_equal(make_invalid_api_key_error[:error][:message], e.json_body[:error][:message])
67
76
  end
68
77
  end
69
78
 
79
+ should "send expand on fetch properly" do
80
+ @mock.expects(:get).once.
81
+ with("#{Stripe.api_base}/v1/charges/ch_test_charge?expand[]=customer", nil, nil).
82
+ returns(make_response(make_charge))
83
+
84
+ Stripe::Charge.retrieve({:id => 'ch_test_charge', :expand => [:customer]})
85
+ end
86
+
87
+ should "preserve expand across refreshes" do
88
+ @mock.expects(:get).twice.
89
+ with("#{Stripe.api_base}/v1/charges/ch_test_charge?expand[]=customer", nil, nil).
90
+ returns(make_response(make_charge))
91
+
92
+ ch = Stripe::Charge.retrieve({:id => 'ch_test_charge', :expand => [:customer]})
93
+ ch.refresh
94
+ end
95
+
96
+ should "send expand when fetching through ListObject" do
97
+ @mock.expects(:get).once.
98
+ with("#{Stripe.api_base}/v1/customers/c_test_customer", nil, nil).
99
+ returns(make_response(make_customer))
100
+
101
+ @mock.expects(:get).once.
102
+ with("#{Stripe.api_base}/v1/customers/c_test_customer/sources/cc_test_card?expand[]=customer", nil, nil).
103
+ returns(make_response(make_card))
104
+
105
+ customer = Stripe::Customer.retrieve('c_test_customer')
106
+ customer.sources.retrieve({:id => 'cc_test_card', :expand => [:customer]})
107
+ end
108
+
70
109
  should "send stripe account as header when set" do
71
110
  stripe_account = "acct_0000"
72
111
  Stripe.expects(:execute_request).with do |opts|
73
112
  opts[:headers][:stripe_account] == stripe_account
74
- end.returns(test_response(test_charge))
113
+ end.returns(make_response(make_charge))
75
114
 
76
115
  Stripe::Charge.create({:card => {:number => '4242424242424242'}},
77
116
  {:stripe_account => stripe_account, :api_key => 'sk_test_local'})
@@ -80,18 +119,63 @@ module Stripe
80
119
  should "not send stripe account as header when not set" do
81
120
  Stripe.expects(:execute_request).with do |opts|
82
121
  opts[:headers][:stripe_account].nil?
83
- end.returns(test_response(test_charge))
122
+ end.returns(make_response(make_charge))
84
123
 
85
124
  Stripe::Charge.create({:card => {:number => '4242424242424242'}},
86
125
  'sk_test_local')
87
126
  end
88
127
 
128
+ should "handle error response with empty body" do
129
+ response = make_response('', 500)
130
+ @mock.expects(:post).once.raises(RestClient::ExceptionWithResponse.new(response, 500))
131
+
132
+ e = assert_raises Stripe::APIError do
133
+ Stripe::Charge.create
134
+ end
135
+
136
+ assert_equal 'Invalid response object from API: "" (HTTP response code was 500)', e.message
137
+ end
138
+
139
+ should "handle error response with non-object error value" do
140
+ response = make_response('{"error": "foo"}', 500)
141
+ @mock.expects(:post).once.raises(RestClient::ExceptionWithResponse.new(response, 500))
142
+
143
+ e = assert_raises Stripe::APIError do
144
+ Stripe::Charge.create
145
+ end
146
+
147
+ assert_equal 'Invalid response object from API: "{\"error\": \"foo\"}" (HTTP response code was 500)', e.message
148
+ end
149
+
150
+ should "have default open and read timeouts" do
151
+ assert_equal Stripe.open_timeout, 30
152
+ assert_equal Stripe.read_timeout, 80
153
+ end
154
+
155
+ should "allow configurable open and read timeouts" do
156
+ original_timeouts = Stripe.open_timeout, Stripe.read_timeout
157
+
158
+ begin
159
+ Stripe.open_timeout = 999
160
+ Stripe.read_timeout = 998
161
+
162
+ Stripe.expects(:execute_request).with do |opts|
163
+ opts[:open_timeout] == 999 && opts[:timeout] == 998
164
+ end.returns(make_response(make_charge))
165
+
166
+ Stripe::Charge.create({:card => {:number => '4242424242424242'}},
167
+ 'sk_test_local')
168
+ ensure
169
+ Stripe.open_timeout, Stripe.read_timeout = original_timeouts
170
+ end
171
+ end
172
+
89
173
  context "when specifying per-object credentials" do
90
174
  context "with no global API key set" do
91
175
  should "use the per-object credential when creating" do
92
176
  Stripe.expects(:execute_request).with do |opts|
93
177
  opts[:headers][:authorization] == 'Bearer sk_test_local'
94
- end.returns(test_response(test_charge))
178
+ end.returns(make_response(make_charge))
95
179
 
96
180
  Stripe::Charge.create({:card => {:number => '4242424242424242'}},
97
181
  'sk_test_local')
@@ -110,7 +194,7 @@ module Stripe
110
194
  should "use the per-object credential when creating" do
111
195
  Stripe.expects(:execute_request).with do |opts|
112
196
  opts[:headers][:authorization] == 'Bearer local'
113
- end.returns(test_response(test_charge))
197
+ end.returns(make_response(make_charge))
114
198
 
115
199
  Stripe::Charge.create({:card => {:number => '4242424242424242'}},
116
200
  'local')
@@ -120,11 +204,11 @@ module Stripe
120
204
  Stripe.expects(:execute_request).with do |opts|
121
205
  opts[:url] == "#{Stripe.api_base}/v1/charges/ch_test_charge" &&
122
206
  opts[:headers][:authorization] == 'Bearer local'
123
- end.returns(test_response(test_charge))
207
+ end.returns(make_response(make_charge))
124
208
  Stripe.expects(:execute_request).with do |opts|
125
209
  opts[:url] == "#{Stripe.api_base}/v1/charges/ch_test_charge/refund" &&
126
210
  opts[:headers][:authorization] == 'Bearer local'
127
- end.returns(test_response(test_charge))
211
+ end.returns(make_response(make_charge))
128
212
 
129
213
  ch = Stripe::Charge.retrieve('ch_test_charge', 'local')
130
214
  ch.refund
@@ -136,7 +220,7 @@ module Stripe
136
220
  should "send along the idempotency-key header" do
137
221
  Stripe.expects(:execute_request).with do |opts|
138
222
  opts[:headers][:idempotency_key] == 'bar'
139
- end.returns(test_response(test_charge))
223
+ end.returns(make_response(make_charge))
140
224
 
141
225
  Stripe::Charge.create({:card => {:number => '4242424242424242'}}, {
142
226
  :idempotency_key => 'bar',
@@ -145,23 +229,23 @@ module Stripe
145
229
  end
146
230
 
147
231
  should "urlencode values in GET params" do
148
- response = test_response(test_charge_array)
149
- @mock.expects(:get).with("#{Stripe.api_base}/v1/charges?customer=test%20customer", nil, nil).returns(response)
150
- charges = Stripe::Charge.all(:customer => 'test customer').data
232
+ response = make_response(make_charge_array)
233
+ @mock.expects(:get).with("#{Stripe.api_base}/v1/charges?customer=test+customer", nil, nil).returns(response)
234
+ charges = Stripe::Charge.list(:customer => 'test customer').data
151
235
  assert charges.kind_of? Array
152
236
  end
153
237
 
154
238
  should "construct URL properly with base query parameters" do
155
- response = test_response(test_invoice_customer_array)
239
+ response = make_response(make_invoice_customer_array)
156
240
  @mock.expects(:get).with("#{Stripe.api_base}/v1/invoices?customer=test_customer", nil, nil).returns(response)
157
- invoices = Stripe::Invoice.all(:customer => 'test_customer')
241
+ invoices = Stripe::Invoice.list(:customer => 'test_customer')
158
242
 
159
243
  @mock.expects(:get).with("#{Stripe.api_base}/v1/invoices?customer=test_customer&paid=true", nil, nil).returns(response)
160
- invoices.all(:paid => true)
244
+ invoices.list(:paid => true)
161
245
  end
162
246
 
163
247
  should "a 400 should give an InvalidRequestError with http status, body, and JSON body" do
164
- response = test_response(test_missing_id_error, 400)
248
+ response = make_response(make_missing_id_error, 400)
165
249
  @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
166
250
  begin
167
251
  Stripe::Customer.retrieve("foo")
@@ -173,7 +257,7 @@ module Stripe
173
257
  end
174
258
 
175
259
  should "a 401 should give an AuthenticationError with http status, body, and JSON body" do
176
- response = test_response(test_missing_id_error, 401)
260
+ response = make_response(make_missing_id_error, 401)
177
261
  @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
178
262
  begin
179
263
  Stripe::Customer.retrieve("foo")
@@ -185,7 +269,7 @@ module Stripe
185
269
  end
186
270
 
187
271
  should "a 402 should give a CardError with http status, body, and JSON body" do
188
- response = test_response(test_missing_id_error, 402)
272
+ response = make_response(make_missing_id_error, 402)
189
273
  @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
190
274
  begin
191
275
  Stripe::Customer.retrieve("foo")
@@ -197,7 +281,7 @@ module Stripe
197
281
  end
198
282
 
199
283
  should "a 404 should give an InvalidRequestError with http status, body, and JSON body" do
200
- response = test_response(test_missing_id_error, 404)
284
+ response = make_response(make_missing_id_error, 404)
201
285
  @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
202
286
  begin
203
287
  Stripe::Customer.retrieve("foo")
@@ -208,25 +292,37 @@ module Stripe
208
292
  end
209
293
  end
210
294
 
295
+ should "a 429 should give a RateLimitError with http status, body, and JSON body" do
296
+ response = make_response(make_rate_limit_error, 429)
297
+ @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 429))
298
+ begin
299
+ Stripe::Customer.retrieve("foo")
300
+ rescue Stripe::RateLimitError => e
301
+ assert_equal(429, e.http_status)
302
+ assert_equal(true, !!e.http_body)
303
+ assert_equal(true, e.json_body.kind_of?(Hash))
304
+ end
305
+ end
306
+
211
307
  should "setting a nil value for a param should exclude that param from the request" do
212
308
  @mock.expects(:get).with do |url, api_key, params|
213
309
  uri = URI(url)
214
310
  query = CGI.parse(uri.query)
215
311
  (url =~ %r{^#{Stripe.api_base}/v1/charges?} &&
216
312
  query.keys.sort == ['offset', 'sad'])
217
- end.returns(test_response({ :count => 1, :data => [test_charge] }))
218
- Stripe::Charge.all(:count => nil, :offset => 5, :sad => false)
313
+ end.returns(make_response({ :count => 1, :data => [make_charge] }))
314
+ Stripe::Charge.list(:count => nil, :offset => 5, :sad => false)
219
315
 
220
316
  @mock.expects(:post).with do |url, api_key, params|
221
317
  url == "#{Stripe.api_base}/v1/charges" &&
222
318
  api_key.nil? &&
223
319
  CGI.parse(params) == { 'amount' => ['50'], 'currency' => ['usd'] }
224
- end.returns(test_response({ :count => 1, :data => [test_charge] }))
320
+ end.returns(make_response({ :count => 1, :data => [make_charge] }))
225
321
  Stripe::Charge.create(:amount => 50, :currency => 'usd', :card => { :number => nil })
226
322
  end
227
323
 
228
324
  should "requesting with a unicode ID should result in a request" do
229
- response = test_response(test_missing_id_error, 404)
325
+ response = make_response(make_missing_id_error, 404)
230
326
  @mock.expects(:get).once.with("#{Stripe.api_base}/v1/customers/%E2%98%83", nil, nil).raises(RestClient::ExceptionWithResponse.new(response, 404))
231
327
  c = Stripe::Customer.new("☃")
232
328
  assert_raises(Stripe::InvalidRequestError) { c.refresh }
@@ -239,26 +335,27 @@ module Stripe
239
335
 
240
336
  should "making a GET request with parameters should have a query string and no body" do
241
337
  params = { :limit => 1 }
242
- @mock.expects(:get).once.with("#{Stripe.api_base}/v1/charges?limit=1", nil, nil).returns(test_response([test_charge]))
243
- Stripe::Charge.all(params)
338
+ @mock.expects(:get).once.with("#{Stripe.api_base}/v1/charges?limit=1", nil, nil).
339
+ returns(make_response({ :data => [make_charge] }))
340
+ Stripe::Charge.list(params)
244
341
  end
245
342
 
246
343
  should "making a POST request with parameters should have a body and no query string" do
247
344
  params = { :amount => 100, :currency => 'usd', :card => 'sc_token' }
248
345
  @mock.expects(:post).once.with do |url, get, post|
249
346
  get.nil? && CGI.parse(post) == {'amount' => ['100'], 'currency' => ['usd'], 'card' => ['sc_token']}
250
- end.returns(test_response(test_charge))
347
+ end.returns(make_response(make_charge))
251
348
  Stripe::Charge.create(params)
252
349
  end
253
350
 
254
351
  should "loading an object should issue a GET request" do
255
- @mock.expects(:get).once.returns(test_response(test_customer))
352
+ @mock.expects(:get).once.returns(make_response(make_customer))
256
353
  c = Stripe::Customer.new("test_customer")
257
354
  c.refresh
258
355
  end
259
356
 
260
357
  should "using array accessors should be the same as the method interface" do
261
- @mock.expects(:get).once.returns(test_response(test_customer))
358
+ @mock.expects(:get).once.returns(make_response(make_customer))
262
359
  c = Stripe::Customer.new("test_customer")
263
360
  c.refresh
264
361
  assert_equal c.created, c[:created]
@@ -268,7 +365,7 @@ module Stripe
268
365
  end
269
366
 
270
367
  should "accessing a property other than id or parent on an unfetched object should fetch it" do
271
- @mock.expects(:get).once.returns(test_response(test_customer))
368
+ @mock.expects(:get).once.returns(make_response(make_customer))
272
369
  c = Stripe::Customer.new("test_customer")
273
370
  c.charges
274
371
  end
@@ -276,14 +373,14 @@ module Stripe
276
373
  should "updating an object should issue a POST request with only the changed properties" do
277
374
  @mock.expects(:post).with do |url, api_key, params|
278
375
  url == "#{Stripe.api_base}/v1/customers/c_test_customer" && api_key.nil? && CGI.parse(params) == {'description' => ['another_mn']}
279
- end.once.returns(test_response(test_customer))
280
- c = Stripe::Customer.construct_from(test_customer)
376
+ end.once.returns(make_response(make_customer))
377
+ c = Stripe::Customer.construct_from(make_customer)
281
378
  c.description = "another_mn"
282
379
  c.save
283
380
  end
284
381
 
285
382
  should "updating should merge in returned properties" do
286
- @mock.expects(:post).once.returns(test_response(test_customer))
383
+ @mock.expects(:post).once.returns(make_response(make_customer))
287
384
  c = Stripe::Customer.new("c_test_customer")
288
385
  c.description = "another_mn"
289
386
  c.save
@@ -293,9 +390,8 @@ module Stripe
293
390
  should "deleting should send no props and result in an object that has no props other deleted" do
294
391
  @mock.expects(:get).never
295
392
  @mock.expects(:post).never
296
- @mock.expects(:delete).with("#{Stripe.api_base}/v1/customers/c_test_customer", nil, nil).once.returns(test_response({ "id" => "test_customer", "deleted" => true }))
297
-
298
- c = Stripe::Customer.construct_from(test_customer)
393
+ @mock.expects(:delete).with("#{Stripe.api_base}/v1/customers/c_test_customer", nil, nil).once.returns(make_response({ "id" => "test_customer", "deleted" => true }))
394
+ c = Stripe::Customer.construct_from(make_customer)
299
395
  c.delete
300
396
  assert_equal true, c.deleted
301
397
 
@@ -305,23 +401,50 @@ module Stripe
305
401
  end
306
402
 
307
403
  should "loading an object with properties that have specific types should instantiate those classes" do
308
- @mock.expects(:get).once.returns(test_response(test_charge))
404
+ @mock.expects(:get).once.returns(make_response(make_charge))
309
405
  c = Stripe::Charge.retrieve("test_charge")
310
406
  assert c.card.kind_of?(Stripe::StripeObject) && c.card.object == 'card'
311
407
  end
312
408
 
313
409
  should "loading all of an APIResource should return an array of recursively instantiated objects" do
314
- @mock.expects(:get).once.returns(test_response(test_charge_array))
315
- c = Stripe::Charge.all.data
410
+ @mock.expects(:get).once.returns(make_response(make_charge_array))
411
+ c = Stripe::Charge.list.data
316
412
  assert c.kind_of? Array
317
413
  assert c[0].kind_of? Stripe::Charge
318
414
  assert c[0].card.kind_of?(Stripe::StripeObject) && c[0].card.object == 'card'
319
415
  end
320
416
 
417
+ should "passing in a stripe_account header should pass it through on call" do
418
+ Stripe.expects(:execute_request).with do |opts|
419
+ opts[:method] == :get &&
420
+ opts[:url] == "#{Stripe.api_base}/v1/customers/c_test_customer" &&
421
+ opts[:headers][:stripe_account] == 'acct_abc'
422
+ end.once.returns(make_response(make_customer))
423
+ c = Stripe::Customer.retrieve("c_test_customer", {:stripe_account => 'acct_abc'})
424
+ end
425
+
426
+ should "passing in a stripe_account header should pass it through on save" do
427
+ Stripe.expects(:execute_request).with do |opts|
428
+ opts[:method] == :get &&
429
+ opts[:url] == "#{Stripe.api_base}/v1/customers/c_test_customer" &&
430
+ opts[:headers][:stripe_account] == 'acct_abc'
431
+ end.once.returns(make_response(make_customer))
432
+ c = Stripe::Customer.retrieve("c_test_customer", {:stripe_account => 'acct_abc'})
433
+
434
+ Stripe.expects(:execute_request).with do |opts|
435
+ opts[:method] == :post &&
436
+ opts[:url] == "#{Stripe.api_base}/v1/customers/c_test_customer" &&
437
+ opts[:headers][:stripe_account] == 'acct_abc' &&
438
+ opts[:payload] == 'description=FOO'
439
+ end.once.returns(make_response(make_customer))
440
+ c.description = 'FOO'
441
+ c.save
442
+ end
443
+
321
444
  context "error checking" do
322
445
 
323
446
  should "404s should raise an InvalidRequestError" do
324
- response = test_response(test_missing_id_error, 404)
447
+ response = make_response(make_missing_id_error, 404)
325
448
  @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
326
449
 
327
450
  rescued = false
@@ -339,7 +462,7 @@ module Stripe
339
462
  end
340
463
 
341
464
  should "5XXs should raise an APIError" do
342
- response = test_response(test_api_error, 500)
465
+ response = make_response(make_api_error, 500)
343
466
  @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 500))
344
467
 
345
468
  rescued = false
@@ -355,7 +478,7 @@ module Stripe
355
478
  end
356
479
 
357
480
  should "402s should raise a CardError" do
358
- response = test_response(test_invalid_exp_year_error, 402)
481
+ response = make_response(make_invalid_exp_year_error, 402)
359
482
  @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 402))
360
483
 
361
484
  rescued = false
@@ -373,6 +496,167 @@ module Stripe
373
496
  assert_equal true, rescued
374
497
  end
375
498
  end
499
+
500
+ should 'add key to nested objects' do
501
+ acct = Stripe::Account.construct_from({
502
+ :id => 'myid',
503
+ :legal_entity => {
504
+ :size => 'l',
505
+ :score => 4,
506
+ :height => 10
507
+ }
508
+ })
509
+
510
+ @mock.expects(:post).once.with("#{Stripe.api_base}/v1/accounts/myid", nil, 'legal_entity[first_name]=Bob').returns(make_response({"id" => "myid"}))
511
+
512
+ acct.legal_entity.first_name = 'Bob'
513
+ acct.save
514
+ end
515
+
516
+ should 'save nothing if nothing changes' do
517
+ acct = Stripe::Account.construct_from({
518
+ :id => 'myid',
519
+ :metadata => {
520
+ :key => 'value'
521
+ }
522
+ })
523
+
524
+ @mock.expects(:post).once.with("#{Stripe.api_base}/v1/accounts/myid", nil, '').returns(make_response({"id" => "myid"}))
525
+
526
+ acct.save
527
+ end
528
+
529
+ should 'not save nested API resources' do
530
+ ch = Stripe::Charge.construct_from({
531
+ :id => 'charge_id',
532
+ :customer => {
533
+ :object => 'customer',
534
+ :id => 'customer_id'
535
+ }
536
+ })
537
+
538
+ @mock.expects(:post).once.with("#{Stripe.api_base}/v1/charges/charge_id", nil, '').returns(make_response({"id" => "charge_id"}))
539
+
540
+ ch.customer.description = 'Bob'
541
+ ch.save
542
+ end
543
+
544
+ should 'correctly handle replaced nested objects' do
545
+ acct = Stripe::Account.construct_from({
546
+ :id => 'myid',
547
+ :legal_entity => {
548
+ :last_name => 'Smith',
549
+ :address => {
550
+ :line1 => "test",
551
+ :city => "San Francisco"
552
+ }
553
+ }
554
+ })
555
+
556
+ @mock.expects(:post).once.with(
557
+ "#{Stripe.api_base}/v1/accounts/myid",
558
+ nil,
559
+ any_of(
560
+ 'legal_entity[address][line1]=Test2&legal_entity[address][city]=',
561
+ 'legal_entity[address][city]=&legal_entity[address][line1]=Test2'
562
+ )
563
+ ).returns(make_response({"id" => "myid"}))
564
+
565
+ acct.legal_entity.address = {:line1 => 'Test2'}
566
+ acct.save
567
+ end
568
+
569
+ should 'correctly handle array setting' do
570
+ acct = Stripe::Account.construct_from({
571
+ :id => 'myid',
572
+ :legal_entity => {}
573
+ })
574
+
575
+ @mock.expects(:post).once.with("#{Stripe.api_base}/v1/accounts/myid", nil, 'legal_entity[additional_owners][0][first_name]=Bob').returns(make_response({"id" => "myid"}))
576
+
577
+ acct.legal_entity.additional_owners = [{:first_name => 'Bob'}]
578
+ acct.save
579
+ end
580
+
581
+ should 'correctly handle array insertion' do
582
+ acct = Stripe::Account.construct_from({
583
+ :id => 'myid',
584
+ :legal_entity => {
585
+ :additional_owners => []
586
+ }
587
+ })
588
+
589
+ @mock.expects(:post).once.with("#{Stripe.api_base}/v1/accounts/myid", nil, 'legal_entity[additional_owners][0][first_name]=Bob').returns(make_response({"id" => "myid"}))
590
+
591
+ acct.legal_entity.additional_owners << {:first_name => 'Bob'}
592
+ acct.save
593
+ end
594
+
595
+ should 'correctly handle array updates' do
596
+ acct = Stripe::Account.construct_from({
597
+ :id => 'myid',
598
+ :legal_entity => {
599
+ :additional_owners => [{:first_name => 'Bob'}, {:first_name => 'Jane'}]
600
+ }
601
+ })
602
+
603
+ @mock.expects(:post).once.with("#{Stripe.api_base}/v1/accounts/myid", nil, 'legal_entity[additional_owners][1][first_name]=Janet').returns(make_response({"id" => "myid"}))
604
+
605
+ acct.legal_entity.additional_owners[1].first_name = 'Janet'
606
+ acct.save
607
+ end
608
+
609
+ should 'correctly handle array noops' do
610
+ acct = Stripe::Account.construct_from({
611
+ :id => 'myid',
612
+ :legal_entity => {
613
+ :additional_owners => [{:first_name => 'Bob'}]
614
+ },
615
+ :currencies_supported => ['usd', 'cad']
616
+ })
617
+
618
+ @mock.expects(:post).once.with("#{Stripe.api_base}/v1/accounts/myid", nil, '').returns(make_response({"id" => "myid"}))
619
+
620
+ acct.save
621
+ end
622
+
623
+ should 'correctly handle hash noops' do
624
+ acct = Stripe::Account.construct_from({
625
+ :id => 'myid',
626
+ :legal_entity => {
627
+ :address => {:line1 => '1 Two Three'}
628
+ }
629
+ })
630
+
631
+ @mock.expects(:post).once.with("#{Stripe.api_base}/v1/accounts/myid", nil, '').returns(make_response({"id" => "myid"}))
632
+
633
+ acct.save
634
+ end
635
+
636
+ should 'should create a new resource when an object without an id is saved' do
637
+ account = Stripe::Account.construct_from({
638
+ :id => nil,
639
+ :display_name => nil,
640
+ })
641
+
642
+ @mock.expects(:post).once.with("#{Stripe.api_base}/v1/accounts", nil, 'display_name=stripe').
643
+ returns(make_response({"id" => "charge_id"}))
644
+
645
+ account.display_name = 'stripe'
646
+ account.save
647
+ end
648
+
649
+ should 'set attributes as part of save' do
650
+ account = Stripe::Account.construct_from({
651
+ :id => nil,
652
+ :display_name => nil,
653
+ })
654
+
655
+ @mock.expects(:post).once.with("#{Stripe.api_base}/v1/accounts", nil, 'display_name=stripe').
656
+ returns(make_response({"id" => "charge_id"}))
657
+
658
+ account.save(:display_name => 'stripe')
659
+ end
376
660
  end
377
661
  end
378
662
  end
@@ -3,7 +3,7 @@ require File.expand_path('../../test_helper', __FILE__)
3
3
  module Stripe
4
4
  class ApplicationFeeRefundTest < Test::Unit::TestCase
5
5
  should "refunds should be listable" do
6
- @mock.expects(:get).once.returns(test_response(test_application_fee))
6
+ @mock.expects(:get).once.returns(make_response(make_application_fee))
7
7
 
8
8
  application_fee = Stripe::ApplicationFee.retrieve('test_application_fee')
9
9
 
@@ -11,7 +11,7 @@ module Stripe
11
11
  end
12
12
 
13
13
  should "refunds should be refreshable" do
14
- @mock.expects(:get).twice.returns(test_response(test_application_fee), test_response(test_application_fee_refund(:id => 'refreshed_refund')))
14
+ @mock.expects(:get).twice.returns(make_response(make_application_fee), make_response(make_application_fee_refund(:id => 'refreshed_refund')))
15
15
 
16
16
  application_fee = Stripe::ApplicationFee.retrieve('test_application_fee')
17
17
  refund = application_fee.refunds.first
@@ -21,8 +21,8 @@ module Stripe
21
21
  end
22
22
 
23
23
  should "refunds should be updateable" do
24
- @mock.expects(:get).once.returns(test_response(test_application_fee))
25
- @mock.expects(:post).once.returns(test_response(test_application_fee_refund(:metadata => {'key' => 'value'})))
24
+ @mock.expects(:get).once.returns(make_response(make_application_fee))
25
+ @mock.expects(:post).once.returns(make_response(make_application_fee_refund(:metadata => {'key' => 'value'})))
26
26
 
27
27
  application_fee = Stripe::ApplicationFee.retrieve('test_application_fee')
28
28
  refund = application_fee.refunds.first
@@ -36,8 +36,8 @@ module Stripe
36
36
  end
37
37
 
38
38
  should "create should return a new refund" do
39
- @mock.expects(:get).once.returns(test_response(test_application_fee))
40
- @mock.expects(:post).once.returns(test_response(test_application_fee_refund(:id => 'test_new_refund')))
39
+ @mock.expects(:get).once.returns(make_response(make_application_fee))
40
+ @mock.expects(:post).once.returns(make_response(make_application_fee_refund(:id => 'test_new_refund')))
41
41
 
42
42
  application_fee = Stripe::ApplicationFee.retrieve('test_application_fee')
43
43
  refund = application_fee.refunds.create(:amount => 20)
@@ -3,8 +3,8 @@ require File.expand_path('../../test_helper', __FILE__)
3
3
  module Stripe
4
4
  class ApplicationFeeTest < Test::Unit::TestCase
5
5
  should "application fees should be listable" do
6
- @mock.expects(:get).once.returns(test_response(test_application_fee_array))
7
- fees = Stripe::ApplicationFee.all
6
+ @mock.expects(:get).once.returns(make_response(make_application_fee_array))
7
+ fees = Stripe::ApplicationFee.list
8
8
  assert fees.data.kind_of? Array
9
9
  fees.each do |fee|
10
10
  assert fee.kind_of?(Stripe::ApplicationFee)
@@ -13,7 +13,7 @@ module Stripe
13
13
 
14
14
  should "application fees should be refundable" do
15
15
  @mock.expects(:get).never
16
- @mock.expects(:post).once.returns(test_response({:id => "fee_test_fee", :refunded => true}))
16
+ @mock.expects(:post).once.returns(make_response({:id => "fee_test_fee", :refunded => true}))
17
17
  fee = Stripe::ApplicationFee.new("test_application_fee")
18
18
  fee.refund
19
19
  assert fee.refunded
@@ -0,0 +1,11 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Stripe
4
+ class BalanceTest < Test::Unit::TestCase
5
+ should "balance should be retrievable" do
6
+ @mock.expects(:get).once.returns(make_response(make_balance))
7
+ balance = Stripe::Balance.retrieve
8
+ assert_equal('balance', balance['object'])
9
+ end
10
+ end
11
+ end