gocardless 0.1.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.
- data/.gitignore +10 -0
- data/.rspec +1 -0
- data/Gemfile +12 -0
- data/Guardfile +6 -0
- data/LICENSE +22 -0
- data/README.md +15 -0
- data/Rakefile +6 -0
- data/gocardless.gemspec +22 -0
- data/lib/gocardless.rb +32 -0
- data/lib/gocardless/bill.rb +44 -0
- data/lib/gocardless/client.rb +352 -0
- data/lib/gocardless/errors.rb +30 -0
- data/lib/gocardless/merchant.rb +47 -0
- data/lib/gocardless/payment.rb +9 -0
- data/lib/gocardless/pre_authorization.rb +21 -0
- data/lib/gocardless/resource.rb +191 -0
- data/lib/gocardless/subscription.rb +15 -0
- data/lib/gocardless/user.rb +8 -0
- data/lib/gocardless/utils.rb +36 -0
- data/lib/gocardless/version.rb +3 -0
- data/spec/bill_spec.rb +27 -0
- data/spec/client_spec.rb +376 -0
- data/spec/gocardless_spec.rb +41 -0
- data/spec/merchant_spec.rb +31 -0
- data/spec/resource_spec.rb +395 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/utils_spec.rb +67 -0
- metadata +195 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GoCardless do
|
4
|
+
before do
|
5
|
+
unset_ivar GoCardless, :client
|
6
|
+
unset_ivar GoCardless, :account_details
|
7
|
+
@details = {:app_id => 'X', :app_secret => 'X', :token => 'X manage_merchant:1'}
|
8
|
+
end
|
9
|
+
|
10
|
+
describe ".account_details=" do
|
11
|
+
it "creates a Client instance" do
|
12
|
+
GoCardless::Client.expects :new
|
13
|
+
subject.account_details = @details
|
14
|
+
end
|
15
|
+
|
16
|
+
it "gets upset if the token is missing" do
|
17
|
+
expect {
|
18
|
+
subject.account_details = @details.merge(:token => nil)
|
19
|
+
}.to raise_exception GoCardless::ClientError
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
describe "delegated methods" do
|
25
|
+
%w(new_subscription_url new_pre_authorization_url new_bill_url confirm_resource).each do |name|
|
26
|
+
it "#{name} delegates to @client" do
|
27
|
+
subject.account_details = @details
|
28
|
+
subject.instance_variable_get(:@client).expects(name.to_sym)
|
29
|
+
subject.send(name)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "raises an exception if the account details aren't set" do
|
33
|
+
expect {
|
34
|
+
subject.send(name)
|
35
|
+
}.to raise_exception GoCardless::ClientError
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GoCardless::Merchant do
|
4
|
+
before :each do
|
5
|
+
@app_id = 'abc'
|
6
|
+
@app_secret = 'xyz'
|
7
|
+
@client = GoCardless::Client.new(:app_id => @app_id, :app_secret => @app_secret)
|
8
|
+
@client.access_token = 'TOKEN123 manage_merchant:123'
|
9
|
+
@redirect_uri = 'http://test.com/cb'
|
10
|
+
end
|
11
|
+
|
12
|
+
index_methods = [:subscriptions, :pre_authorizations, :users, :payments, :bills]
|
13
|
+
|
14
|
+
index_methods.each do |method|
|
15
|
+
it "##{method} works correctly" do
|
16
|
+
merchant = GoCardless::Merchant.new_with_client(@client)
|
17
|
+
|
18
|
+
data = [{:id => 1}, {:id => 2}]
|
19
|
+
stub_get(@client, data)
|
20
|
+
|
21
|
+
merchant.send(method).should be_a Array
|
22
|
+
merchant.send(method).length.should == 2
|
23
|
+
merchant.send(method).zip(data).each do |obj,attrs|
|
24
|
+
class_name = GoCardless::Utils.camelize(method.to_s).sub(/s$/, '')
|
25
|
+
obj.class.to_s.should == "GoCardless::#{class_name}"
|
26
|
+
attrs.each { |k,v| obj.send(k).should == v }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,395 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GoCardless::Resource do
|
4
|
+
it "initializes from hash" do
|
5
|
+
test_resource = Class.new(GoCardless::Resource) do
|
6
|
+
attr_accessor :id, :name, :uri
|
7
|
+
end
|
8
|
+
props = {:id => 1, :name => 'test', :uri => 'http://test'}
|
9
|
+
resource = test_resource.new(props)
|
10
|
+
props.each { |k,v| resource.send(k).should == v }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#date_writer" do
|
14
|
+
it "creates date writers properly" do
|
15
|
+
test_resource = Class.new(GoCardless::Resource) do
|
16
|
+
date_writer :created_at, :modified_at
|
17
|
+
end
|
18
|
+
|
19
|
+
test_resource.instance_methods.map(&:to_s).should include 'created_at='
|
20
|
+
test_resource.instance_methods.map(&:to_s).should include 'modified_at='
|
21
|
+
end
|
22
|
+
|
23
|
+
it "date writers work properly" do
|
24
|
+
test_resource = Class.new(GoCardless::Resource) do
|
25
|
+
date_writer :created_at
|
26
|
+
end
|
27
|
+
|
28
|
+
resource = test_resource.new
|
29
|
+
time = '2011-12-12T12:00:00Z'
|
30
|
+
resource.created_at = time
|
31
|
+
date_time = resource.instance_variable_get(:@created_at)
|
32
|
+
date_time.should be_instance_of DateTime
|
33
|
+
date_time.strftime('%Y-%m-%dT%H:%M:%SZ').should == time
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#date_accessor" do
|
38
|
+
it "creates date readers and writers properly" do
|
39
|
+
test_resource = Class.new(GoCardless::Resource) do
|
40
|
+
date_accessor :created_at, :modified_at
|
41
|
+
end
|
42
|
+
|
43
|
+
test_resource.instance_methods.map(&:to_s).should include 'created_at='
|
44
|
+
test_resource.instance_methods.map(&:to_s).should include 'created_at'
|
45
|
+
test_resource.instance_methods.map(&:to_s).should include 'modified_at='
|
46
|
+
test_resource.instance_methods.map(&:to_s).should include 'modified_at'
|
47
|
+
end
|
48
|
+
|
49
|
+
it "date readers work properly" do
|
50
|
+
test_resource = Class.new(GoCardless::Resource) do
|
51
|
+
date_accessor :created_at
|
52
|
+
end
|
53
|
+
|
54
|
+
resource = test_resource.new
|
55
|
+
date = DateTime.now
|
56
|
+
resource.instance_variable_set(:@created_at, date)
|
57
|
+
resource.created_at.should == date
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe ".find_with_client" do
|
62
|
+
it "instantiates the correct object" do
|
63
|
+
test_resource = Class.new(GoCardless::Resource) do
|
64
|
+
self.endpoint = '/test/:id'
|
65
|
+
end
|
66
|
+
mock_client = mock
|
67
|
+
mock_client.expects(:api_get).returns({:id => 123})
|
68
|
+
resource = test_resource.find_with_client(mock_client, 123)
|
69
|
+
resource.should be_a test_resource
|
70
|
+
resource.id.should == 123
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe ".find" do
|
75
|
+
it "calls find with the default client" do
|
76
|
+
test_resource = Class.new(GoCardless::Resource) do
|
77
|
+
self.endpoint = '/test/:id'
|
78
|
+
end
|
79
|
+
GoCardless.stubs(:client => mock)
|
80
|
+
test_resource.expects(:find_with_client).with(GoCardless.client, 1)
|
81
|
+
test_resource.find(1)
|
82
|
+
unset_ivar GoCardless, :client
|
83
|
+
end
|
84
|
+
|
85
|
+
it "raises a helpful error when there is no default client" do
|
86
|
+
test_resource = Class.new(GoCardless::Resource) do
|
87
|
+
self.endpoint = '/test/:id'
|
88
|
+
end
|
89
|
+
expect { test_resource.find(1) }.to raise_error
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "#reference_writer" do
|
94
|
+
it "creates reference writers properly" do
|
95
|
+
test_resource = Class.new(GoCardless::Resource) do
|
96
|
+
reference_writer :merchant_id, :user_id
|
97
|
+
end
|
98
|
+
|
99
|
+
test_resource.instance_methods.map(&:to_s).should include 'merchant='
|
100
|
+
test_resource.instance_methods.map(&:to_s).should include 'merchant_id='
|
101
|
+
test_resource.instance_methods.map(&:to_s).should include 'user='
|
102
|
+
test_resource.instance_methods.map(&:to_s).should include 'user_id='
|
103
|
+
end
|
104
|
+
|
105
|
+
it "direct assignment methods work properly" do
|
106
|
+
test_resource = Class.new(GoCardless::Resource) do
|
107
|
+
reference_writer :user_id
|
108
|
+
end
|
109
|
+
|
110
|
+
resource = test_resource.new
|
111
|
+
resource.user = GoCardless::User.new(:id => 123)
|
112
|
+
resource.instance_variable_get(:@user_id).should == 123
|
113
|
+
end
|
114
|
+
|
115
|
+
it "requires args to end with _id" do
|
116
|
+
expect do
|
117
|
+
test_resource = Class.new(GoCardless::Resource) do
|
118
|
+
reference_writer :user
|
119
|
+
end
|
120
|
+
end.to raise_exception ArgumentError
|
121
|
+
end
|
122
|
+
|
123
|
+
it "fails with the wrong object type" do
|
124
|
+
test_resource = Class.new(GoCardless::Resource) do
|
125
|
+
reference_writer :user_id
|
126
|
+
end
|
127
|
+
expect do
|
128
|
+
test_resource.new.user = 'asdf'
|
129
|
+
end.to raise_exception ArgumentError
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "#reference_reader" do
|
134
|
+
before :each do
|
135
|
+
@app_id = 'abc'
|
136
|
+
@app_secret = 'xyz'
|
137
|
+
@client = GoCardless::Client.new(:app_id => @app_id, :app_secret => @app_secret)
|
138
|
+
@redirect_uri = 'http://test.com/cb'
|
139
|
+
end
|
140
|
+
|
141
|
+
it "creates reference writers properly" do
|
142
|
+
test_resource = Class.new(GoCardless::Resource) do
|
143
|
+
reference_reader :merchant_id, :user_id
|
144
|
+
end
|
145
|
+
|
146
|
+
test_resource.instance_methods.map(&:to_s).should include 'merchant'
|
147
|
+
test_resource.instance_methods.map(&:to_s).should include 'merchant_id'
|
148
|
+
test_resource.instance_methods.map(&:to_s).should include 'user'
|
149
|
+
test_resource.instance_methods.map(&:to_s).should include 'user_id'
|
150
|
+
end
|
151
|
+
|
152
|
+
it "lookup methods work properly" do
|
153
|
+
test_resource = Class.new(GoCardless::Resource) do
|
154
|
+
reference_reader :user_id
|
155
|
+
end
|
156
|
+
|
157
|
+
resource = test_resource.new_with_client(@client)
|
158
|
+
resource.instance_variable_set(:@user_id, 123)
|
159
|
+
@client.access_token = 'TOKEN manage_merchant:123'
|
160
|
+
stub_get(@client, {:id => 123})
|
161
|
+
user = resource.user
|
162
|
+
user.should be_a GoCardless::User
|
163
|
+
user.id.should == 123
|
164
|
+
end
|
165
|
+
|
166
|
+
it "requires args to end with _id" do
|
167
|
+
expect do
|
168
|
+
test_resource = Class.new(GoCardless::Resource) do
|
169
|
+
reference_reader :user
|
170
|
+
end
|
171
|
+
end.to raise_exception ArgumentError
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe "#reference_accessor" do
|
176
|
+
it "creates reference readers and writers" do
|
177
|
+
test_resource = Class.new(GoCardless::Resource) do
|
178
|
+
reference_accessor :merchant_id, :user_id
|
179
|
+
end
|
180
|
+
|
181
|
+
test_resource.instance_methods.map(&:to_s).should include 'merchant'
|
182
|
+
test_resource.instance_methods.map(&:to_s).should include 'merchant_id'
|
183
|
+
test_resource.instance_methods.map(&:to_s).should include 'user'
|
184
|
+
test_resource.instance_methods.map(&:to_s).should include 'user_id'
|
185
|
+
test_resource.instance_methods.map(&:to_s).should include 'merchant='
|
186
|
+
test_resource.instance_methods.map(&:to_s).should include 'merchant_id='
|
187
|
+
test_resource.instance_methods.map(&:to_s).should include 'user='
|
188
|
+
test_resource.instance_methods.map(&:to_s).should include 'user_id='
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
it "#persisted? works" do
|
193
|
+
GoCardless::Resource.new.persisted?.should be_false
|
194
|
+
GoCardless::Resource.new(:id => 1).persisted?.should be_true
|
195
|
+
end
|
196
|
+
|
197
|
+
describe "#save" do
|
198
|
+
describe "succeeds and" do
|
199
|
+
before :each do
|
200
|
+
@test_resource = Class.new(GoCardless::Resource) do
|
201
|
+
self.endpoint = '/test'
|
202
|
+
attr_accessor :x, :y
|
203
|
+
creatable
|
204
|
+
updatable
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
after :each do
|
209
|
+
@test_resource = nil
|
210
|
+
end
|
211
|
+
|
212
|
+
it "sends the correct data parameters" do
|
213
|
+
client = mock
|
214
|
+
data = {:x => 1, :y => 2}
|
215
|
+
resource = @test_resource.new_with_client(client, data)
|
216
|
+
client.expects(:api_post).with(anything, data)
|
217
|
+
resource.save
|
218
|
+
end
|
219
|
+
|
220
|
+
it "sends the correct path" do
|
221
|
+
client = mock
|
222
|
+
resource = @test_resource.new_with_client(client)
|
223
|
+
client.expects(:api_post).with('/test', anything)
|
224
|
+
resource.save
|
225
|
+
end
|
226
|
+
|
227
|
+
it "POSTs when not persisted" do
|
228
|
+
client = mock
|
229
|
+
resource = @test_resource.new_with_client(client)
|
230
|
+
client.expects(:api_post)
|
231
|
+
resource.save
|
232
|
+
end
|
233
|
+
|
234
|
+
it "PUTs when already persisted" do
|
235
|
+
client = mock
|
236
|
+
resource = @test_resource.new_with_client(client, :id => 1)
|
237
|
+
client.expects(:api_put)
|
238
|
+
resource.save
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
it "succeeds when not persisted and create allowed" do
|
243
|
+
test_resource = Class.new(GoCardless::Resource) do
|
244
|
+
self.endpoint = '/test'
|
245
|
+
creatable
|
246
|
+
end
|
247
|
+
|
248
|
+
client = mock('client') { stubs :api_post }
|
249
|
+
test_resource.new_with_client(client).save
|
250
|
+
end
|
251
|
+
|
252
|
+
it "succeeds when persisted and update allowed" do
|
253
|
+
test_resource = Class.new(GoCardless::Resource) do
|
254
|
+
self.endpoint = '/test'
|
255
|
+
updatable
|
256
|
+
end
|
257
|
+
|
258
|
+
client = mock('client') { stubs :api_put }
|
259
|
+
test_resource.new_with_client(client, :id => 1).save
|
260
|
+
end
|
261
|
+
|
262
|
+
it "fails when not persisted and create not allowed" do
|
263
|
+
test_resource = Class.new(GoCardless::Resource) do
|
264
|
+
updatable
|
265
|
+
end
|
266
|
+
|
267
|
+
expect { test_resource.new.save }.to raise_error
|
268
|
+
end
|
269
|
+
|
270
|
+
it "fails when persisted and update not allowed" do
|
271
|
+
test_resource = Class.new(GoCardless::Resource) do
|
272
|
+
creatable
|
273
|
+
end
|
274
|
+
|
275
|
+
expect { test_resource.new(:id => 1).save }.to raise_error
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
it "#to_hash pulls out the correct attributes" do
|
280
|
+
test_resource = Class.new(GoCardless::Resource) do
|
281
|
+
attr_accessor :x
|
282
|
+
end
|
283
|
+
|
284
|
+
attrs = {:id => 1, :uri => 'http:', :x => 'y'}
|
285
|
+
resource = test_resource.new_with_client(mock, attrs)
|
286
|
+
resource.to_hash.should == attrs
|
287
|
+
end
|
288
|
+
|
289
|
+
it "#to_json converts to the correct JSON format" do
|
290
|
+
test_resource = Class.new(GoCardless::Resource) do
|
291
|
+
attr_accessor :amount
|
292
|
+
date_accessor :when
|
293
|
+
reference_accessor :person_id
|
294
|
+
end
|
295
|
+
|
296
|
+
bill = test_resource.new({
|
297
|
+
:amount => '10',
|
298
|
+
:when => DateTime.now,
|
299
|
+
:person_id => 15
|
300
|
+
})
|
301
|
+
|
302
|
+
result = JSON.parse(bill.to_json)
|
303
|
+
result['amount'].should == bill.amount
|
304
|
+
result['when'].should == bill.when.to_s
|
305
|
+
result['person_id'].should == 15
|
306
|
+
end
|
307
|
+
|
308
|
+
describe "resource permissions" do
|
309
|
+
it "are not given by default" do
|
310
|
+
GoCardless::Resource.creatable?.should be_false
|
311
|
+
GoCardless::Resource.updatable?.should be_false
|
312
|
+
end
|
313
|
+
|
314
|
+
it "are present when specified" do
|
315
|
+
class CreatableResource < GoCardless::Resource
|
316
|
+
creatable
|
317
|
+
end
|
318
|
+
|
319
|
+
class UpdatableResource < GoCardless::Resource
|
320
|
+
updatable
|
321
|
+
end
|
322
|
+
|
323
|
+
CreatableResource.creatable?.should be_true
|
324
|
+
CreatableResource.updatable?.should be_false
|
325
|
+
|
326
|
+
UpdatableResource.creatable?.should be_false
|
327
|
+
UpdatableResource.updatable?.should be_true
|
328
|
+
|
329
|
+
GoCardless::Resource.creatable?.should be_false
|
330
|
+
GoCardless::Resource.updatable?.should be_false
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
describe "sub_resource_uri methods" do
|
335
|
+
before :each do
|
336
|
+
@test_resource = Class.new(GoCardless::Resource) do
|
337
|
+
end
|
338
|
+
@attrs = {
|
339
|
+
'sub_resource_uris' => {
|
340
|
+
'bills' => 'https://test.com/api/bills/?merchant_id=1'
|
341
|
+
}
|
342
|
+
}
|
343
|
+
end
|
344
|
+
|
345
|
+
it "are defined on instances" do
|
346
|
+
r = @test_resource.new(@attrs)
|
347
|
+
r.should respond_to :bills
|
348
|
+
end
|
349
|
+
|
350
|
+
it "aren't defined for other instances of the class" do
|
351
|
+
@test_resource.new(@attrs)
|
352
|
+
resource = @test_resource.new
|
353
|
+
resource.should_not respond_to :bills
|
354
|
+
end
|
355
|
+
|
356
|
+
it "use the correct uri path" do
|
357
|
+
client = mock()
|
358
|
+
client.expects(:api_get).with('/api/bills/', anything).returns([])
|
359
|
+
r = @test_resource.new_with_client(client, @attrs)
|
360
|
+
r.bills
|
361
|
+
end
|
362
|
+
|
363
|
+
it "strips the api prefix from the path" do
|
364
|
+
client = mock()
|
365
|
+
client.expects(:api_get).with('/bills/', anything).returns([])
|
366
|
+
uris = {'bills' => 'https://test.com/api/v123/bills/'}
|
367
|
+
r = @test_resource.new_with_client(client, 'sub_resource_uris' => uris)
|
368
|
+
r.bills
|
369
|
+
end
|
370
|
+
|
371
|
+
it "use the correct query string params" do
|
372
|
+
client = mock()
|
373
|
+
client.expects(:api_get).with(anything, 'merchant_id' => '1').returns([])
|
374
|
+
r = @test_resource.new_with_client(client, @attrs)
|
375
|
+
r.bills
|
376
|
+
end
|
377
|
+
|
378
|
+
it "adds provided params to query string params" do
|
379
|
+
client = mock()
|
380
|
+
params = { 'merchant_id' => '1', :amount => '10.00' }
|
381
|
+
client.expects(:api_get).with(anything, params).returns([])
|
382
|
+
r = @test_resource.new_with_client(client, @attrs)
|
383
|
+
r.bills(:amount => '10.00')
|
384
|
+
end
|
385
|
+
|
386
|
+
it "return instances of the correct resource class" do
|
387
|
+
client = stub(:api_get => [{:id => 1}])
|
388
|
+
r = @test_resource.new_with_client(client, @attrs)
|
389
|
+
ret = r.bills
|
390
|
+
ret.should be_a Array
|
391
|
+
ret.first.should be_a GoCardless::Bill
|
392
|
+
end
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|