rainforest 1.0.1

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 (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.travis.yml +10 -0
  4. data/CONTRIBUTORS +1 -0
  5. data/Gemfile +2 -0
  6. data/History.txt +4 -0
  7. data/LICENSE +21 -0
  8. data/README.md +50 -0
  9. data/Rakefile +15 -0
  10. data/VERSION +1 -0
  11. data/bin/rainforest-console +7 -0
  12. data/gemfiles/default-with-activesupport.gemfile +3 -0
  13. data/gemfiles/json.gemfile +4 -0
  14. data/gemfiles/yajl.gemfile +4 -0
  15. data/lib/.DS_Store +0 -0
  16. data/lib/data/ca-certificates.crt +3918 -0
  17. data/lib/rainforest.rb +271 -0
  18. data/lib/rainforest/api_operations/create.rb +16 -0
  19. data/lib/rainforest/api_operations/delete.rb +11 -0
  20. data/lib/rainforest/api_operations/list.rb +18 -0
  21. data/lib/rainforest/api_operations/update.rb +61 -0
  22. data/lib/rainforest/api_resource.rb +33 -0
  23. data/lib/rainforest/errors/api_connection_error.rb +4 -0
  24. data/lib/rainforest/errors/api_error.rb +4 -0
  25. data/lib/rainforest/errors/authentication_error.rb +4 -0
  26. data/lib/rainforest/errors/invalid_request_error.rb +10 -0
  27. data/lib/rainforest/errors/rainforest_error.rb +20 -0
  28. data/lib/rainforest/json.rb +21 -0
  29. data/lib/rainforest/list_object.rb +35 -0
  30. data/lib/rainforest/rainforest_object.rb +168 -0
  31. data/lib/rainforest/run.rb +8 -0
  32. data/lib/rainforest/singleton_api_resource.rb +20 -0
  33. data/lib/rainforest/test.rb +14 -0
  34. data/lib/rainforest/util.rb +101 -0
  35. data/lib/rainforest/version.rb +3 -0
  36. data/rainforest.gemspec +26 -0
  37. data/test/stripe/account_test.rb +14 -0
  38. data/test/stripe/api_resource_test.rb +345 -0
  39. data/test/stripe/charge_test.rb +67 -0
  40. data/test/stripe/coupon_test.rb +11 -0
  41. data/test/stripe/customer_test.rb +70 -0
  42. data/test/stripe/invoice_test.rb +20 -0
  43. data/test/stripe/list_object_test.rb +16 -0
  44. data/test/stripe/metadata_test.rb +114 -0
  45. data/test/stripe/util_test.rb +29 -0
  46. data/test/test_helper.rb +356 -0
  47. metadata +191 -0
@@ -0,0 +1,345 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.expand_path('../../test_helper', __FILE__)
3
+
4
+ module Rainforest
5
+ class ApiResourceTest < Test::Unit::TestCase
6
+ should "creating a new APIResource should not fetch over the network" do
7
+ @mock.expects(:get).never
8
+ c = Rainforest::Customer.new("someid")
9
+ end
10
+
11
+ should "creating a new APIResource from a hash should not fetch over the network" do
12
+ @mock.expects(:get).never
13
+ c = Rainforest::Customer.construct_from({
14
+ :id => "somecustomer",
15
+ :card => {:id => "somecard", :object => "card"},
16
+ :object => "customer"
17
+ })
18
+ end
19
+
20
+ should "setting an attribute should not cause a network request" do
21
+ @mock.expects(:get).never
22
+ @mock.expects(:post).never
23
+ c = Rainforest::Customer.new("test_customer");
24
+ c.card = {:id => "somecard", :object => "card"}
25
+ end
26
+
27
+ should "accessing id should not issue a fetch" do
28
+ @mock.expects(:get).never
29
+ c = Rainforest::Customer.new("test_customer");
30
+ c.id
31
+ end
32
+
33
+ should "not specifying api credentials should raise an exception" do
34
+ Rainforest.api_key = nil
35
+ assert_raises Rainforest::AuthenticationError do
36
+ Rainforest::Customer.new("test_customer").refresh
37
+ end
38
+ end
39
+
40
+ should "specifying api credentials containing whitespace should raise an exception" do
41
+ Rainforest.api_key = "key "
42
+ assert_raises Rainforest::AuthenticationError do
43
+ Rainforest::Customer.new("test_customer").refresh
44
+ end
45
+ end
46
+
47
+ should "specifying invalid api credentials should raise an exception" do
48
+ Rainforest.api_key = "invalid"
49
+ response = test_response(test_invalid_api_key_error, 401)
50
+ assert_raises Rainforest::AuthenticationError do
51
+ @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 401))
52
+ Rainforest::Customer.retrieve("failing_customer")
53
+ end
54
+ end
55
+
56
+ should "AuthenticationErrors should have an http status, http body, and JSON body" do
57
+ Rainforest.api_key = "invalid"
58
+ response = test_response(test_invalid_api_key_error, 401)
59
+ begin
60
+ @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 401))
61
+ Rainforest::Customer.retrieve("failing_customer")
62
+ rescue Rainforest::AuthenticationError => e
63
+ assert_equal(401, e.http_status)
64
+ assert_equal(true, !!e.http_body)
65
+ assert_equal(true, !!e.json_body[:error][:message])
66
+ assert_equal(test_invalid_api_key_error['error']['message'], e.json_body[:error][:message])
67
+ end
68
+ end
69
+
70
+ context "when specifying per-object credentials" do
71
+ context "with no global API key set" do
72
+ should "use the per-object credential when creating" do
73
+ Rainforest.expects(:execute_request).with do |opts|
74
+ opts[:headers][:authorization] == 'Bearer sk_test_local'
75
+ end.returns(test_response(test_charge))
76
+
77
+ Rainforest::Charge.create({:card => {:number => '4242424242424242'}},
78
+ 'sk_test_local')
79
+ end
80
+ end
81
+
82
+ context "with a global API key set" do
83
+ setup do
84
+ Rainforest.api_key = "global"
85
+ end
86
+
87
+ teardown do
88
+ Rainforest.api_key = nil
89
+ end
90
+
91
+ should "use the per-object credential when creating" do
92
+ Rainforest.expects(:execute_request).with do |opts|
93
+ opts[:headers][:authorization] == 'Bearer local'
94
+ end.returns(test_response(test_charge))
95
+
96
+ Rainforest::Charge.create({:card => {:number => '4242424242424242'}},
97
+ 'local')
98
+ end
99
+
100
+ should "use the per-object credential when retrieving and making other calls" do
101
+ Rainforest.expects(:execute_request).with do |opts|
102
+ opts[:url] == "#{Rainforest.api_base}/v1/charges/ch_test_charge" &&
103
+ opts[:headers][:authorization] == 'Bearer local'
104
+ end.returns(test_response(test_charge))
105
+ Rainforest.expects(:execute_request).with do |opts|
106
+ opts[:url] == "#{Rainforest.api_base}/v1/charges/ch_test_charge/refund" &&
107
+ opts[:headers][:authorization] == 'Bearer local'
108
+ end.returns(test_response(test_charge))
109
+
110
+ ch = Rainforest::Charge.retrieve('ch_test_charge', 'local')
111
+ ch.refund
112
+ end
113
+ end
114
+ end
115
+
116
+ context "with valid credentials" do
117
+ should "urlencode values in GET params" do
118
+ response = test_response(test_charge_array)
119
+ @mock.expects(:get).with("#{Rainforest.api_base}/v1/charges?customer=test%20customer", nil, nil).returns(response)
120
+ charges = Rainforest::Charge.all(:customer => 'test customer').data
121
+ assert charges.kind_of? Array
122
+ end
123
+
124
+ should "construct URL properly with base query parameters" do
125
+ response = test_response(test_invoice_customer_array)
126
+ @mock.expects(:get).with("#{Rainforest.api_base}/v1/invoices?customer=test_customer", nil, nil).returns(response)
127
+ invoices = Rainforest::Invoice.all(:customer => 'test_customer')
128
+
129
+ @mock.expects(:get).with("#{Rainforest.api_base}/v1/invoices?customer=test_customer&paid=true", nil, nil).returns(response)
130
+ invoices.all(:paid => true)
131
+ end
132
+
133
+ should "a 400 should give an InvalidRequestError with http status, body, and JSON body" do
134
+ response = test_response(test_missing_id_error, 400)
135
+ @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
136
+ begin
137
+ Rainforest::Customer.retrieve("foo")
138
+ rescue Rainforest::InvalidRequestError => e
139
+ assert_equal(400, e.http_status)
140
+ assert_equal(true, !!e.http_body)
141
+ assert_equal(true, e.json_body.kind_of?(Hash))
142
+ end
143
+ end
144
+
145
+ should "a 401 should give an AuthenticationError with http status, body, and JSON body" do
146
+ response = test_response(test_missing_id_error, 401)
147
+ @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
148
+ begin
149
+ Rainforest::Customer.retrieve("foo")
150
+ rescue Rainforest::AuthenticationError => e
151
+ assert_equal(401, e.http_status)
152
+ assert_equal(true, !!e.http_body)
153
+ assert_equal(true, e.json_body.kind_of?(Hash))
154
+ end
155
+ end
156
+
157
+ should "a 402 should give a CardError with http status, body, and JSON body" do
158
+ response = test_response(test_missing_id_error, 402)
159
+ @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
160
+ begin
161
+ Rainforest::Customer.retrieve("foo")
162
+ rescue Rainforest::CardError => e
163
+ assert_equal(402, e.http_status)
164
+ assert_equal(true, !!e.http_body)
165
+ assert_equal(true, e.json_body.kind_of?(Hash))
166
+ end
167
+ end
168
+
169
+ should "a 404 should give an InvalidRequestError with http status, body, and JSON body" do
170
+ response = test_response(test_missing_id_error, 404)
171
+ @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
172
+ begin
173
+ Rainforest::Customer.retrieve("foo")
174
+ rescue Rainforest::InvalidRequestError => e
175
+ assert_equal(404, e.http_status)
176
+ assert_equal(true, !!e.http_body)
177
+ assert_equal(true, e.json_body.kind_of?(Hash))
178
+ end
179
+ end
180
+
181
+ should "setting a nil value for a param should exclude that param from the request" do
182
+ @mock.expects(:get).with do |url, api_key, params|
183
+ uri = URI(url)
184
+ query = CGI.parse(uri.query)
185
+ (url =~ %r{^#{Rainforest.api_base}/v1/charges?} &&
186
+ query.keys.sort == ['offset', 'sad'])
187
+ end.returns(test_response({ :count => 1, :data => [test_charge] }))
188
+ c = Rainforest::Charge.all(:count => nil, :offset => 5, :sad => false)
189
+
190
+ @mock.expects(:post).with do |url, api_key, params|
191
+ url == "#{Rainforest.api_base}/v1/charges" &&
192
+ api_key.nil? &&
193
+ CGI.parse(params) == { 'amount' => ['50'], 'currency' => ['usd'] }
194
+ end.returns(test_response({ :count => 1, :data => [test_charge] }))
195
+ c = Rainforest::Charge.create(:amount => 50, :currency => 'usd', :card => { :number => nil })
196
+ end
197
+
198
+ should "requesting with a unicode ID should result in a request" do
199
+ response = test_response(test_missing_id_error, 404)
200
+ @mock.expects(:get).once.with("#{Rainforest.api_base}/v1/customers/%E2%98%83", nil, nil).raises(RestClient::ExceptionWithResponse.new(response, 404))
201
+ c = Rainforest::Customer.new("☃")
202
+ assert_raises(Rainforest::InvalidRequestError) { c.refresh }
203
+ end
204
+
205
+ should "requesting with no ID should result in an InvalidRequestError with no request" do
206
+ c = Rainforest::Customer.new
207
+ assert_raises(Rainforest::InvalidRequestError) { c.refresh }
208
+ end
209
+
210
+ should "making a GET request with parameters should have a query string and no body" do
211
+ params = { :limit => 1 }
212
+ @mock.expects(:get).once.with("#{Rainforest.api_base}/v1/charges?limit=1", nil, nil).returns(test_response([test_charge]))
213
+ c = Rainforest::Charge.all(params)
214
+ end
215
+
216
+ should "making a POST request with parameters should have a body and no query string" do
217
+ params = { :amount => 100, :currency => 'usd', :card => 'sc_token' }
218
+ @mock.expects(:post).once.with do |url, get, post|
219
+ get.nil? && CGI.parse(post) == {'amount' => ['100'], 'currency' => ['usd'], 'card' => ['sc_token']}
220
+ end.returns(test_response(test_charge))
221
+ c = Rainforest::Charge.create(params)
222
+ end
223
+
224
+ should "loading an object should issue a GET request" do
225
+ @mock.expects(:get).once.returns(test_response(test_customer))
226
+ c = Rainforest::Customer.new("test_customer")
227
+ c.refresh
228
+ end
229
+
230
+ should "using array accessors should be the same as the method interface" do
231
+ @mock.expects(:get).once.returns(test_response(test_customer))
232
+ c = Rainforest::Customer.new("test_customer")
233
+ c.refresh
234
+ assert_equal c.created, c[:created]
235
+ assert_equal c.created, c['created']
236
+ c['created'] = 12345
237
+ assert_equal c.created, 12345
238
+ end
239
+
240
+ should "accessing a property other than id or parent on an unfetched object should fetch it" do
241
+ @mock.expects(:get).once.returns(test_response(test_customer))
242
+ c = Rainforest::Customer.new("test_customer")
243
+ c.charges
244
+ end
245
+
246
+ should "updating an object should issue a POST request with only the changed properties" do
247
+ @mock.expects(:post).with do |url, api_key, params|
248
+ url == "#{Rainforest.api_base}/v1/customers/c_test_customer" && api_key.nil? && CGI.parse(params) == {'description' => ['another_mn']}
249
+ end.once.returns(test_response(test_customer))
250
+ c = Rainforest::Customer.construct_from(test_customer)
251
+ c.description = "another_mn"
252
+ c.save
253
+ end
254
+
255
+ should "updating should merge in returned properties" do
256
+ @mock.expects(:post).once.returns(test_response(test_customer))
257
+ c = Rainforest::Customer.new("c_test_customer")
258
+ c.description = "another_mn"
259
+ c.save
260
+ assert_equal false, c.livemode
261
+ end
262
+
263
+ should "deleting should send no props and result in an object that has no props other deleted" do
264
+ @mock.expects(:get).never
265
+ @mock.expects(:post).never
266
+ @mock.expects(:delete).with("#{Rainforest.api_base}/v1/customers/c_test_customer", nil, nil).once.returns(test_response({ "id" => "test_customer", "deleted" => true }))
267
+
268
+ c = Rainforest::Customer.construct_from(test_customer)
269
+ c.delete
270
+ assert_equal true, c.deleted
271
+
272
+ assert_raises NoMethodError do
273
+ c.livemode
274
+ end
275
+ end
276
+
277
+ should "loading an object with properties that have specific types should instantiate those classes" do
278
+ @mock.expects(:get).once.returns(test_response(test_charge))
279
+ c = Rainforest::Charge.retrieve("test_charge")
280
+ assert c.card.kind_of?(Rainforest::RainforestObject) && c.card.object == 'card'
281
+ end
282
+
283
+ should "loading all of an APIResource should return an array of recursively instantiated objects" do
284
+ @mock.expects(:get).once.returns(test_response(test_charge_array))
285
+ c = Rainforest::Charge.all.data
286
+ assert c.kind_of? Array
287
+ assert c[0].kind_of? Rainforest::Charge
288
+ assert c[0].card.kind_of?(Rainforest::RainforestObject) && c[0].card.object == 'card'
289
+ end
290
+
291
+ context "error checking" do
292
+
293
+ should "404s should raise an InvalidRequestError" do
294
+ response = test_response(test_missing_id_error, 404)
295
+ @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
296
+
297
+ begin
298
+ Rainforest::Customer.new("test_customer").refresh
299
+ assert false #shouldn't get here either
300
+ rescue Rainforest::InvalidRequestError => e # we don't use assert_raises because we want to examine e
301
+ assert e.kind_of? Rainforest::InvalidRequestError
302
+ assert_equal "id", e.param
303
+ assert_equal "Missing id", e.message
304
+ return
305
+ end
306
+
307
+ assert false #shouldn't get here
308
+ end
309
+
310
+ should "5XXs should raise an APIError" do
311
+ response = test_response(test_api_error, 500)
312
+ @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 500))
313
+
314
+ begin
315
+ Rainforest::Customer.new("test_customer").refresh
316
+ assert false #shouldn't get here either
317
+ rescue Rainforest::APIError => e # we don't use assert_raises because we want to examine e
318
+ assert e.kind_of? Rainforest::APIError
319
+ return
320
+ end
321
+
322
+ assert false #shouldn't get here
323
+ end
324
+
325
+ should "402s should raise a CardError" do
326
+ response = test_response(test_invalid_exp_year_error, 402)
327
+ @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 402))
328
+
329
+ begin
330
+ Rainforest::Customer.new("test_customer").refresh
331
+ assert false #shouldn't get here either
332
+ rescue Rainforest::CardError => e # we don't use assert_raises because we want to examine e
333
+ assert e.kind_of? Rainforest::CardError
334
+ assert_equal "invalid_expiry_year", e.code
335
+ assert_equal "exp_year", e.param
336
+ assert_equal "Your card's expiration year is invalid", e.message
337
+ return
338
+ end
339
+
340
+ assert false #shouldn't get here
341
+ end
342
+ end
343
+ end
344
+ end
345
+ end
@@ -0,0 +1,67 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Rainforest
4
+ class ChargeTest < Test::Unit::TestCase
5
+ should "charges should be listable" do
6
+ @mock.expects(:get).once.returns(test_response(test_charge_array))
7
+ c = Rainforest::Charge.all
8
+ assert c.data.kind_of? Array
9
+ c.each do |charge|
10
+ assert charge.kind_of?(Rainforest::Charge)
11
+ end
12
+ end
13
+
14
+ should "charges should be refundable" do
15
+ @mock.expects(:get).never
16
+ @mock.expects(:post).once.returns(test_response({:id => "ch_test_charge", :refunded => true}))
17
+ c = Rainforest::Charge.new("test_charge")
18
+ c.refund
19
+ assert c.refunded
20
+ end
21
+
22
+ should "charges should not be deletable" do
23
+ assert_raises NoMethodError do
24
+ @mock.expects(:get).once.returns(test_response(test_charge))
25
+ c = Rainforest::Charge.retrieve("test_charge")
26
+ c.delete
27
+ end
28
+ end
29
+
30
+ should "charges should be updateable" do
31
+ @mock.expects(:get).once.returns(test_response(test_charge))
32
+ @mock.expects(:post).once.returns(test_response(test_charge))
33
+ c = Rainforest::Charge.new("test_charge")
34
+ c.refresh
35
+ c.mnemonic = "New charge description"
36
+ c.save
37
+ end
38
+
39
+ should "charges should have Card objects associated with their Card property" do
40
+ @mock.expects(:get).once.returns(test_response(test_charge))
41
+ c = Rainforest::Charge.retrieve("test_charge")
42
+ assert c.card.kind_of?(Rainforest::RainforestObject) && c.card.object == 'card'
43
+ end
44
+
45
+ should "execute should return a new, fully executed charge when passed correct parameters" do
46
+ @mock.expects(:post).with do |url, api_key, params|
47
+ url == "#{Rainforest.api_base}/v1/charges" && api_key.nil? && CGI.parse(params) == {
48
+ 'currency' => ['usd'], 'amount' => ['100'],
49
+ 'card[exp_year]' => ['2012'],
50
+ 'card[number]' => ['4242424242424242'],
51
+ 'card[exp_month]' => ['11']
52
+ }
53
+ end.once.returns(test_response(test_charge))
54
+
55
+ c = Rainforest::Charge.create({
56
+ :amount => 100,
57
+ :card => {
58
+ :number => "4242424242424242",
59
+ :exp_month => 11,
60
+ :exp_year => 2012,
61
+ },
62
+ :currency => "usd"
63
+ })
64
+ assert c.paid
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,11 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Rainforest
4
+ class CouponTest < Test::Unit::TestCase
5
+ should "create should return a new coupon" do
6
+ @mock.expects(:post).once.returns(test_response(test_coupon))
7
+ c = Rainforest::Coupon.create
8
+ assert_equal "co_test_coupon", c.id
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,70 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Rainforest
4
+ class CustomerTest < Test::Unit::TestCase
5
+ should "customers should be listable" do
6
+ @mock.expects(:get).once.returns(test_response(test_customer_array))
7
+ c = Rainforest::Customer.all.data
8
+ assert c.kind_of? Array
9
+ assert c[0].kind_of? Rainforest::Customer
10
+ end
11
+
12
+ should "customers should be deletable" do
13
+ @mock.expects(:delete).once.returns(test_response(test_customer({:deleted => true})))
14
+ c = Rainforest::Customer.new("test_customer")
15
+ c.delete
16
+ assert c.deleted
17
+ end
18
+
19
+ should "customers should be updateable" do
20
+ @mock.expects(:get).once.returns(test_response(test_customer({:mnemonic => "foo"})))
21
+ @mock.expects(:post).once.returns(test_response(test_customer({:mnemonic => "bar"})))
22
+ c = Rainforest::Customer.new("test_customer").refresh
23
+ assert_equal c.mnemonic, "foo"
24
+ c.mnemonic = "bar"
25
+ c.save
26
+ assert_equal c.mnemonic, "bar"
27
+ end
28
+
29
+ should "create should return a new customer" do
30
+ @mock.expects(:post).once.returns(test_response(test_customer))
31
+ c = Rainforest::Customer.create
32
+ assert_equal "c_test_customer", c.id
33
+ end
34
+
35
+ should "be able to update a customer's subscription" do
36
+ @mock.expects(:get).once.returns(test_response(test_customer))
37
+ c = Rainforest::Customer.retrieve("test_customer")
38
+
39
+ @mock.expects(:post).once.with do |url, api_key, params|
40
+ url == "#{Rainforest.api_base}/v1/customers/c_test_customer/subscription" && api_key.nil? && CGI.parse(params) == {'plan' => ['silver']}
41
+ end.returns(test_response(test_subscription('silver')))
42
+ s = c.update_subscription({:plan => 'silver'})
43
+
44
+ assert_equal 'subscription', s.object
45
+ assert_equal 'silver', s.plan.identifier
46
+ end
47
+
48
+ should "be able to cancel a customer's subscription" do
49
+ @mock.expects(:get).once.returns(test_response(test_customer))
50
+ c = Rainforest::Customer.retrieve("test_customer")
51
+
52
+ # Not an accurate response, but whatever
53
+
54
+ @mock.expects(:delete).once.with("#{Rainforest.api_base}/v1/customers/c_test_customer/subscription?at_period_end=true", nil, nil).returns(test_response(test_subscription('silver')))
55
+ s = c.cancel_subscription({:at_period_end => 'true'})
56
+
57
+ @mock.expects(:delete).once.with("#{Rainforest.api_base}/v1/customers/c_test_customer/subscription", nil, nil).returns(test_response(test_subscription('silver')))
58
+ s = c.cancel_subscription
59
+ end
60
+
61
+ should "be able to delete a customer's discount" do
62
+ @mock.expects(:get).once.returns(test_response(test_customer))
63
+ c = Rainforest::Customer.retrieve("test_customer")
64
+
65
+ @mock.expects(:delete).once.with("#{Rainforest.api_base}/v1/customers/c_test_customer/discount", nil, nil).returns(test_response(test_delete_discount_response))
66
+ s = c.delete_discount
67
+ assert_equal nil, c.discount
68
+ end
69
+ end
70
+ end