paid 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +8 -0
  3. data/Gemfile.lock +54 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.rdoc +35 -0
  6. data/Rakefile +34 -0
  7. data/lib/data/ca-certificates.crt +0 -0
  8. data/lib/paid/account.rb +4 -0
  9. data/lib/paid/api_operations/create.rb +17 -0
  10. data/lib/paid/api_operations/delete.rb +11 -0
  11. data/lib/paid/api_operations/list.rb +17 -0
  12. data/lib/paid/api_operations/update.rb +57 -0
  13. data/lib/paid/api_resource.rb +32 -0
  14. data/lib/paid/certificate_blacklist.rb +55 -0
  15. data/lib/paid/customer.rb +16 -0
  16. data/lib/paid/errors/api_connection_error.rb +4 -0
  17. data/lib/paid/errors/api_error.rb +4 -0
  18. data/lib/paid/errors/authentication_error.rb +4 -0
  19. data/lib/paid/errors/invalid_request_error.rb +10 -0
  20. data/lib/paid/errors/paid_error.rb +20 -0
  21. data/lib/paid/event.rb +5 -0
  22. data/lib/paid/invoice.rb +7 -0
  23. data/lib/paid/list_object.rb +37 -0
  24. data/lib/paid/paid_object.rb +187 -0
  25. data/lib/paid/singleton_api_resource.rb +20 -0
  26. data/lib/paid/transaction.rb +7 -0
  27. data/lib/paid/util.rb +127 -0
  28. data/lib/paid/version.rb +3 -0
  29. data/lib/paid.rb +280 -0
  30. data/lib/tasks/paid_tasks.rake +4 -0
  31. data/paid.gemspec +30 -0
  32. data/test/paid/account_test.rb +12 -0
  33. data/test/paid/api_resource_test.rb +361 -0
  34. data/test/paid/certificate_blacklist_test.rb +18 -0
  35. data/test/paid/customer_test.rb +35 -0
  36. data/test/paid/invoice_test.rb +26 -0
  37. data/test/paid/list_object_test.rb +16 -0
  38. data/test/paid/metadata_test.rb +104 -0
  39. data/test/paid/paid_object_test.rb +27 -0
  40. data/test/paid/transaction_test.rb +49 -0
  41. data/test/paid/util_test.rb +59 -0
  42. data/test/test_data.rb +106 -0
  43. data/test/test_helper.rb +41 -0
  44. metadata +203 -0
@@ -0,0 +1,361 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.expand_path('../../test_helper', __FILE__)
3
+
4
+ module Paid
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
+ Paid::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
+ Paid::Customer.construct_from({
14
+ :id => "somecustomer",
15
+ :object => "customer",
16
+ :email => 'someone@example.com',
17
+ :name => 'Some Business',
18
+ :account_id => 'acct_1234'
19
+ })
20
+ end
21
+
22
+ should "setting an attribute should not cause a network request" do
23
+ @mock.expects(:get).never
24
+ @mock.expects(:post).never
25
+ c = Paid::Customer.new("test_customer");
26
+ c.name = 'Another Name'
27
+ end
28
+
29
+ should "accessing id should not issue a fetch" do
30
+ @mock.expects(:get).never
31
+ c = Paid::Customer.new("test_customer")
32
+ c.id
33
+ end
34
+
35
+ should "not specifying api credentials should raise an exception" do
36
+ Paid.api_key = nil
37
+ assert_raises Paid::AuthenticationError do
38
+ Paid::Customer.new("test_customer").refresh
39
+ end
40
+ end
41
+
42
+ should "specifying api credentials containing whitespace should raise an exception" do
43
+ Paid.api_key = "key "
44
+ assert_raises Paid::AuthenticationError do
45
+ Paid::Customer.new("test_customer").refresh
46
+ end
47
+ end
48
+
49
+ should "specifying invalid api credentials should raise an exception" do
50
+ Paid.api_key = "invalid"
51
+ response = test_response(test_invalid_api_key_error, 401)
52
+ assert_raises Paid::AuthenticationError do
53
+ @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 401))
54
+ Paid::Customer.retrieve("failing_customer")
55
+ end
56
+ end
57
+
58
+ should "AuthenticationErrors should have an http status, http body, and JSON body" do
59
+ Paid.api_key = "invalid"
60
+ response = test_response(test_invalid_api_key_error, 401)
61
+ begin
62
+ @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 401))
63
+ Paid::Customer.retrieve("failing_customer")
64
+ rescue Paid::AuthenticationError => e
65
+ assert_equal(401, e.http_status)
66
+ assert_equal(true, !!e.http_body)
67
+ assert_equal(true, !!e.json_body[:error][:message])
68
+ assert_equal(test_invalid_api_key_error[:error][:message], e.json_body[:error][:message])
69
+ end
70
+ end
71
+
72
+ should "send paid account as header when set" do
73
+ paid_account = "acct_0000"
74
+ Paid.expects(:execute_request).with do |opts|
75
+ opts[:headers][:paid_account] == paid_account
76
+ end.returns(test_response(test_transaction))
77
+
78
+ Paid::Transaction.create({:amount => 100},
79
+ {:paid_account => paid_account, :api_key => 'sk_test_local'})
80
+ end
81
+
82
+ should "not send paid account as header when not set" do
83
+ Paid.expects(:execute_request).with do |opts|
84
+ opts[:headers][:paid_account].nil?
85
+ end.returns(test_response(test_transaction))
86
+
87
+ Paid::Transaction.create(
88
+ {
89
+ :amount => 200,
90
+ :description => 'This is a description.',
91
+ :customer => 'somecustomer'
92
+
93
+ },
94
+ 'sk_test_local'
95
+ )
96
+ end
97
+
98
+ context "when specifying per-object credentials" do
99
+ context "with no global API key set" do
100
+ should "use the per-object credential when creating" do
101
+ Paid.expects(:execute_request).with do |opts|
102
+ opts[:headers][:authorization] == 'Bearer sk_test_local'
103
+ end.returns(test_response(test_transaction))
104
+
105
+ Paid::Transaction.create(
106
+ {
107
+ :amount => 200,
108
+ :description => 'This is a description.',
109
+ :customer => 'somecustomer'
110
+ },
111
+ 'sk_test_local'
112
+ )
113
+ end
114
+ end
115
+
116
+ context "with a global API key set" do
117
+ setup do
118
+ Paid.api_key = "global"
119
+ end
120
+
121
+ teardown do
122
+ Paid.api_key = nil
123
+ end
124
+
125
+ should "use the per-object credential when creating" do
126
+ Paid.expects(:execute_request).with do |opts|
127
+ opts[:headers][:authorization] == 'Bearer local'
128
+ end.returns(test_response(test_transaction))
129
+
130
+ Paid::Transaction.create(
131
+ {
132
+ :amount => 200,
133
+ :description => 'This is a description.',
134
+ :customer => 'somecustomer'
135
+ },
136
+ 'local'
137
+ )
138
+ end
139
+
140
+ should "use the per-object credential when retrieving and making other calls" do
141
+ Paid.expects(:execute_request).with do |opts|
142
+ opts[:url] == "#{Paid.api_base}/v0/transactions/tr_test_transaction" &&
143
+ opts[:headers][:authorization] == 'Bearer local'
144
+ end.returns(test_response(test_transaction))
145
+
146
+ ch = Paid::Transaction.retrieve('tr_test_transaction', 'local')
147
+ end
148
+ end
149
+ end
150
+
151
+ context "with valid credentials" do
152
+ should "send along the idempotency-key header" do
153
+ Paid.expects(:execute_request).with do |opts|
154
+ opts[:headers][:idempotency_key] == 'bar'
155
+ end.returns(test_response(test_transaction))
156
+
157
+ Paid::Transaction.create(
158
+ {
159
+ :amount => 200,
160
+ :description => 'This is a description.',
161
+ :customer => 'somecustomer'
162
+ },
163
+ {
164
+ :idempotency_key => 'bar',
165
+ :api_key => 'local',
166
+ }
167
+ )
168
+ end
169
+
170
+ should "urlencode values in GET params" do
171
+ response = test_response(test_transaction_array)
172
+ @mock.expects(:get).with("#{Paid.api_base}/v0/transactions?customer=test%20customer", nil, nil).returns(response)
173
+ transactions = Paid::Transaction.all(:customer => 'test customer').data
174
+ assert transactions.kind_of? Array
175
+ end
176
+
177
+ should "a 400 should give an InvalidRequestError with http status, body, and JSON body" do
178
+ response = test_response(test_missing_id_error, 400)
179
+ @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
180
+ begin
181
+ Paid::Customer.retrieve("foo")
182
+ rescue Paid::InvalidRequestError => e
183
+ assert_equal(400, e.http_status)
184
+ assert_equal(true, !!e.http_body)
185
+ assert_equal(true, e.json_body.kind_of?(Hash))
186
+ end
187
+ end
188
+
189
+ should "a 401 should give an AuthenticationError with http status, body, and JSON body" do
190
+ response = test_response(test_missing_id_error, 401)
191
+ @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
192
+ begin
193
+ Paid::Customer.retrieve("foo")
194
+ rescue Paid::AuthenticationError => e
195
+ assert_equal(401, e.http_status)
196
+ assert_equal(true, !!e.http_body)
197
+ assert_equal(true, e.json_body.kind_of?(Hash))
198
+ end
199
+ end
200
+
201
+ should "a 404 should give an InvalidRequestError with http status, body, and JSON body" do
202
+ response = test_response(test_missing_id_error, 404)
203
+ @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
204
+ begin
205
+ Paid::Customer.retrieve("foo")
206
+ rescue Paid::InvalidRequestError => e
207
+ assert_equal(404, e.http_status)
208
+ assert_equal(true, !!e.http_body)
209
+ assert_equal(true, e.json_body.kind_of?(Hash))
210
+ end
211
+ end
212
+
213
+ should "setting a nil value for a param should exclude that param from the request" do
214
+ @mock.expects(:get).with do |url, api_key, params|
215
+ uri = URI(url)
216
+ query = CGI.parse(uri.query)
217
+ (url =~ %r{^#{Paid.api_base}/v0/transactions?} &&
218
+ query.keys.sort == ['offset', 'sad'])
219
+ end.returns(test_response({ :count => 1, :data => [test_transaction] }))
220
+ Paid::Transaction.all(:count => nil, :offset => 5, :sad => false)
221
+
222
+ @mock.expects(:post).with do |url, api_key, params|
223
+ url == "#{Paid.api_base}/v0/transactions" &&
224
+ api_key.nil? &&
225
+ CGI.parse(params) == { 'amount' => ['100'] }
226
+ end.returns(test_response({ :count => 1, :data => [test_transaction] }))
227
+ Paid::Transaction.create(:amount => 100)
228
+ end
229
+
230
+ should "requesting with a unicode ID should result in a request" do
231
+ response = test_response(test_missing_id_error, 404)
232
+ @mock.expects(:get).once.with("#{Paid.api_base}/v0/customers/%E2%98%83", nil, nil).raises(RestClient::ExceptionWithResponse.new(response, 404))
233
+ c = Paid::Customer.new("☃")
234
+ assert_raises(Paid::InvalidRequestError) { c.refresh }
235
+ end
236
+
237
+ should "requesting with no ID should result in an InvalidRequestError with no request" do
238
+ c = Paid::Customer.new
239
+ assert_raises(Paid::InvalidRequestError) { c.refresh }
240
+ end
241
+
242
+ should "making a GET request with parameters should have a query string and no body" do
243
+ params = { :limit => 1 }
244
+ @mock.expects(:get).once.with("#{Paid.api_base}/v0/transactions?limit=1", nil, nil).returns(test_response([test_transaction]))
245
+ Paid::Transaction.all(params)
246
+ end
247
+
248
+ should "making a POST request with parameters should have a body and no query string" do
249
+ params = { :amount => 100, :alias => 'test_alias' }
250
+ @mock.expects(:post).once.with do |url, get, post|
251
+ get.nil? && CGI.parse(post) == {'amount' => ['100'], 'alias' => ['test_alias']}
252
+ end.returns(test_response(test_transaction))
253
+ Paid::Transaction.create(params)
254
+ end
255
+
256
+ should "loading an object should issue a GET request" do
257
+ @mock.expects(:get).once.returns(test_response(test_customer))
258
+ c = Paid::Customer.new("test_customer")
259
+ c.refresh
260
+ end
261
+
262
+ should "using array accessors should be the same as the method interface" do
263
+ @mock.expects(:get).once.returns(test_response(test_customer))
264
+ c = Paid::Customer.new("test_customer")
265
+ c.refresh
266
+ assert_equal c.created, c[:created]
267
+ assert_equal c.created, c['created']
268
+ c['created'] = 12345
269
+ assert_equal c.created, 12345
270
+ end
271
+
272
+ should "accessing a property other than id or parent on an unfetched object should fetch it" do
273
+ @mock.expects(:get).once.returns(test_response(test_customer))
274
+ c = Paid::Customer.new("test_customer")
275
+ c.transactions
276
+ end
277
+
278
+ should "updating an object should issue a POST request with only the changed properties" do
279
+ @mock.expects(:post).with do |url, api_key, params|
280
+ url == "#{Paid.api_base}/v0/customers/c_test_customer" && api_key.nil? && CGI.parse(params) == {'description' => ['another_mn']}
281
+ end.once.returns(test_response(test_customer))
282
+ c = Paid::Customer.construct_from(test_customer)
283
+ c.description = "another_mn"
284
+ c.save
285
+ end
286
+
287
+ should "updating should merge in returned properties" do
288
+ @mock.expects(:post).once.returns(test_response(test_customer))
289
+ c = Paid::Customer.new("c_test_customer")
290
+ c.description = "another_mn"
291
+ c.save
292
+ # assert_equal false, c.livemode
293
+ end
294
+
295
+ should "deleting should send no props and result in an object that has no props other deleted" do
296
+ @mock.expects(:get).never
297
+ @mock.expects(:post).never
298
+ @mock.expects(:delete).with("#{Paid.api_base}/v0/customers/c_test_customer", nil, nil).once.returns(test_response({ "id" => "test_customer", "deleted" => true }))
299
+
300
+ c = Paid::Customer.construct_from(test_customer)
301
+ c.delete
302
+ assert_equal true, c.deleted
303
+
304
+ assert_raises NoMethodError do
305
+ c.livemode
306
+ end
307
+ end
308
+
309
+ should "loading an object with properties that have specific types should instantiate those classes" do
310
+ @mock.expects(:get).once.returns(test_response(test_transaction))
311
+ t = Paid::Transaction.retrieve("test_transaction")
312
+ assert t.kind_of?(Paid::PaidObject) && t.object == 'transaction'
313
+ end
314
+
315
+ should "loading all of an APIResource should return an array of recursively instantiated objects" do
316
+ @mock.expects(:get).once.returns(test_response(test_transaction_array))
317
+ t = Paid::Transaction.all.data
318
+ assert t.kind_of? Array
319
+ assert t[0].kind_of? Paid::Transaction
320
+ assert t[0].kind_of?(Paid::PaidObject) && t[0].object == 'transaction'
321
+ end
322
+
323
+ context "error checking" do
324
+
325
+ should "404s should raise an InvalidRequestError" do
326
+ response = test_response(test_missing_id_error, 404)
327
+ @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
328
+
329
+ rescued = false
330
+ begin
331
+ Paid::Customer.new("test_customer").refresh
332
+ assert false #shouldn't get here either
333
+ rescue Paid::InvalidRequestError => e # we don't use assert_raises because we want to examine e
334
+ rescued = true
335
+ assert e.kind_of? Paid::InvalidRequestError
336
+ assert_equal "id", e.param
337
+ assert_equal "Missing id", e.message
338
+ end
339
+
340
+ assert_equal true, rescued
341
+ end
342
+
343
+ should "5XXs should raise an APIError" do
344
+ response = test_response(test_api_error, 500)
345
+ @mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 500))
346
+
347
+ rescued = false
348
+ begin
349
+ Paid::Customer.new("test_customer").refresh
350
+ assert false #shouldn't get here either
351
+ rescue Paid::APIError => e # we don't use assert_raises because we want to examine e
352
+ rescued = true
353
+ assert e.kind_of? Paid::APIError
354
+ end
355
+
356
+ assert_equal true, rescued
357
+ end
358
+ end
359
+ end
360
+ end
361
+ end
@@ -0,0 +1,18 @@
1
+ # require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ # module Paid
4
+
5
+ # class CertificateBlacklistTest < Test::Unit::TestCase
6
+ # should "not trust revoked certificates" do
7
+ # assert_raises(Paid::APIConnectionError) {
8
+ # Paid::CertificateBlacklist.check_ssl_cert("https://revoked.paidapi.com:444",
9
+ # Paid::DEFAULT_CA_BUNDLE_PATH)
10
+ # }
11
+ # end
12
+
13
+ # should "trust api.paidapi.com" do
14
+ # assert_true Paid::CertificateBlacklist.check_ssl_cert("https://api.paidapi.com",
15
+ # Paid::DEFAULT_CA_BUNDLE_PATH)
16
+ # end
17
+ # end
18
+ # end
@@ -0,0 +1,35 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Paid
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 = Paid::Customer.all.data
8
+ assert c.kind_of? Array
9
+ assert c[0].kind_of? Paid::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 = Paid::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 = Paid::Customer.new("test_customer").refresh
23
+ assert_equal "foo", c.mnemonic
24
+ c.mnemonic = "bar"
25
+ c.save
26
+ assert_equal "bar", c.mnemonic
27
+ end
28
+
29
+ should "create should return a new customer" do
30
+ @mock.expects(:post).once.returns(test_response(test_customer))
31
+ c = Paid::Customer.create
32
+ assert_equal "c_test_customer", c.id
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,26 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Paid
4
+ class InvoiceTest < Test::Unit::TestCase
5
+ should "retrieve should retrieve invoices" do
6
+ @mock.expects(:get).once.returns(test_response(test_invoice))
7
+ i = Paid::Invoice.retrieve('in_test_invoice')
8
+ assert_equal 'inv_test_invoice', i.id
9
+ end
10
+
11
+ should "create should create a new invoice" do
12
+ @mock.expects(:post).once.returns(test_response(test_invoice))
13
+ i = Paid::Invoice.create
14
+ assert_equal "inv_test_invoice", i.id
15
+ end
16
+
17
+ # should "pay should pay an invoice" do
18
+ # @mock.expects(:get).once.returns(test_response(test_invoice))
19
+ # i = Paid::Invoice.retrieve('in_test_invoice')
20
+
21
+ # @mock.expects(:post).once.with('https://api.paidapi.com/v0/invoices/in_test_invoice/pay', nil, '').returns(test_response(test_paid_invoice))
22
+ # i.pay
23
+ # assert_equal nil, i.next_payment_attempt
24
+ # end
25
+ end
26
+ end
@@ -0,0 +1,16 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Paid
4
+ class ListObjectTest < Test::Unit::TestCase
5
+ should "be able to retrieve full lists given a listobject" do
6
+ @mock.expects(:get).twice.returns(test_response(test_transaction_array))
7
+ c = Paid::Transaction.all
8
+ assert c.kind_of?(Paid::ListObject)
9
+ assert_equal('/v0/transactions', c.url)
10
+ all = c.all
11
+ assert all.kind_of?(Paid::ListObject)
12
+ assert_equal('/v0/transactions', all.url)
13
+ assert all.data.kind_of?(Array)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,104 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Paid
4
+ class MetadataTest < Test::Unit::TestCase
5
+ setup do
6
+ @metadata_supported = {
7
+ :transaction => {
8
+ :new => Paid::Transaction.method(:new),
9
+ :test => method(:test_transaction),
10
+ :url => "/v0/transactions/#{test_transaction()[:id]}"
11
+ },
12
+ :customer => {
13
+ :new => Paid::Customer.method(:new),
14
+ :test => method(:test_customer),
15
+ :url => "/v0/customers/#{test_customer()[:id]}"
16
+ }
17
+ }
18
+
19
+ @base_url = 'https://api.paidapi.com'
20
+ end
21
+
22
+ should "not touch metadata" do
23
+ update_actions = lambda {|obj| obj.description = 'test'}
24
+ check_metadata({:metadata => {'initial' => 'true'}},
25
+ 'description=test',
26
+ update_actions)
27
+ end
28
+
29
+
30
+ should "update metadata as a whole" do
31
+ update_actions = lambda {|obj| obj.metadata = {'uuid' => '6735'}}
32
+ check_metadata({:metadata => {}},
33
+ 'metadata[uuid]=6735',
34
+ update_actions)
35
+
36
+ if is_greater_than_ruby_1_9?
37
+ check_metadata({:metadata => {:initial => 'true'}},
38
+ 'metadata[uuid]=6735&metadata[initial]=',
39
+ update_actions)
40
+ end
41
+ end
42
+
43
+ should "update metadata keys individually" do
44
+ update_actions = lambda {|obj| obj.metadata['txn_id'] = '134a13'}
45
+ check_metadata({:metadata => {'initial' => 'true'}},
46
+ 'metadata[txn_id]=134a13',
47
+ update_actions)
48
+ end
49
+
50
+ should "clear metadata as a whole" do
51
+ update_actions = lambda {|obj| obj.metadata = nil}
52
+ check_metadata({:metadata => {'initial' => 'true'}},
53
+ 'metadata=',
54
+ update_actions)
55
+ end
56
+
57
+ should "clear metadata keys individually" do
58
+ update_actions = lambda {|obj| obj.metadata['initial'] = nil}
59
+ check_metadata({:metadata => {'initial' => 'true'}},
60
+ 'metadata[initial]=',
61
+ update_actions)
62
+ end
63
+
64
+ should "handle combinations of whole and partial metadata updates" do
65
+ if is_greater_than_ruby_1_9?
66
+ update_actions = lambda do |obj|
67
+ obj.metadata = {'type' => 'summer'}
68
+ obj.metadata['uuid'] = '6735'
69
+ end
70
+ params = {:metadata => {'type' => 'summer', 'uuid' => '6735'}}
71
+ curl_args = Paid.uri_encode(params)
72
+ check_metadata({:metadata => {'type' => 'christmas'}},
73
+ curl_args,
74
+ update_actions)
75
+ end
76
+ end
77
+
78
+ def check_metadata (initial_params, curl_args, metadata_update)
79
+ @metadata_supported.each do |name, methods|
80
+ neu = methods[:new]
81
+ test = methods[:test]
82
+ url = @base_url + methods[:url]
83
+
84
+ initial_test_obj = test.call(initial_params)
85
+ @mock.expects(:get).once.returns(test_response(initial_test_obj))
86
+
87
+ final_test_obj = test.call()
88
+ @mock.expects(:post).once.
89
+ returns(test_response(final_test_obj)).
90
+ with(url, nil, curl_args)
91
+
92
+ obj = neu.call("test")
93
+ obj.refresh()
94
+ metadata_update.call(obj)
95
+ obj.save
96
+ end
97
+ end
98
+
99
+ def is_greater_than_ruby_1_9?
100
+ version = RUBY_VERSION.dup # clone preserves frozen state
101
+ Gem::Version.new(version) >= Gem::Version.new('1.9')
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,27 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Paid
4
+ class PaidObjectTest < Test::Unit::TestCase
5
+ should "implement #respond_to correctly" do
6
+ obj = Paid::PaidObject.construct_from({ :id => 1, :foo => 'bar' })
7
+ assert obj.respond_to?(:id)
8
+ assert obj.respond_to?(:foo)
9
+ assert !obj.respond_to?(:baz)
10
+ end
11
+
12
+ should "marshal a paid object correctly" do
13
+ obj = Paid::PaidObject.construct_from({ :id => 1, :name => 'Paid' }, 'apikey')
14
+ m = Marshal.load(Marshal.dump(obj))
15
+ assert_equal 1, m.id
16
+ assert_equal 'Paid', m.name
17
+ assert_equal 'apikey', m.api_key
18
+ end
19
+
20
+ should "recursively call to_hash on its values" do
21
+ nested = Paid::PaidObject.construct_from({ :id => 7, :foo => 'bar' })
22
+ obj = Paid::PaidObject.construct_from({ :id => 1, :nested => nested })
23
+ expected_hash = { :id => 1, :nested => { :id => 7, :foo => 'bar' } }
24
+ assert_equal expected_hash, obj.to_hash
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,49 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Paid
4
+ class TransactionTest < Test::Unit::TestCase
5
+ should "transactions should be listable" do
6
+ @mock.expects(:get).once.returns(test_response(test_transaction_array))
7
+ c = Paid::Transaction.all
8
+ assert c.data.kind_of? Array
9
+ c.each do |transaction|
10
+ assert transaction.kind_of?(Paid::Transaction)
11
+ end
12
+ end
13
+
14
+ should "transactions should not be deletable" do
15
+ assert_raises NoMethodError do
16
+ @mock.expects(:get).once.returns(test_response(test_transaction))
17
+ c = Paid::Transaction.retrieve("test_transaction")
18
+ c.delete
19
+ end
20
+ end
21
+
22
+ should "transactions should be updateable" do
23
+ @mock.expects(:get).once.returns(test_response(test_transaction))
24
+ @mock.expects(:post).once.returns(test_response(test_transaction))
25
+ c = Paid::Transaction.new("test_transaction")
26
+ c.refresh
27
+ c.mnemonic = "New transaction description"
28
+ c.save
29
+ end
30
+
31
+ should "execute should return a new, fully executed transaction when passed correct parameters" do
32
+ @mock.expects(:post).with do |url, api_key, params|
33
+ url == "#{Paid.api_base}/v0/transactions" && api_key.nil? && CGI.parse(params) == {
34
+ 'amount' => ['100'],
35
+ 'description' => ['a description'],
36
+ 'customer' => ['c_test_customer']
37
+ }
38
+ end.once.returns(test_response(test_transaction))
39
+
40
+ c = Paid::Transaction.create({
41
+ :amount => 100,
42
+ :description => 'a description',
43
+ :customer => 'c_test_customer'
44
+ })
45
+
46
+ assert !c.paid
47
+ end
48
+ end
49
+ end