gocardless_pro 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -4
  3. data/lib/gocardless_pro.rb +1 -0
  4. data/lib/gocardless_pro/api_service.rb +2 -0
  5. data/lib/gocardless_pro/client.rb +4 -3
  6. data/lib/gocardless_pro/error/invalid_state_error.rb +17 -0
  7. data/lib/gocardless_pro/middlewares/raise_gocardless_errors.rb +50 -0
  8. data/lib/gocardless_pro/request.rb +38 -1
  9. data/lib/gocardless_pro/resources/creditor.rb +2 -2
  10. data/lib/gocardless_pro/resources/creditor_bank_account.rb +11 -11
  11. data/lib/gocardless_pro/resources/customer_bank_account.rb +2 -2
  12. data/lib/gocardless_pro/resources/event.rb +2 -2
  13. data/lib/gocardless_pro/resources/mandate.rb +2 -2
  14. data/lib/gocardless_pro/resources/payment.rb +7 -7
  15. data/lib/gocardless_pro/resources/payout.rb +7 -6
  16. data/lib/gocardless_pro/resources/redirect_flow.rb +2 -2
  17. data/lib/gocardless_pro/resources/refund.rb +2 -2
  18. data/lib/gocardless_pro/resources/subscription.rb +2 -2
  19. data/lib/gocardless_pro/response.rb +2 -54
  20. data/lib/gocardless_pro/services/bank_details_lookups_service.rb +3 -0
  21. data/lib/gocardless_pro/services/creditor_bank_accounts_service.rb +31 -2
  22. data/lib/gocardless_pro/services/creditors_service.rb +21 -1
  23. data/lib/gocardless_pro/services/customer_bank_accounts_service.rb +34 -2
  24. data/lib/gocardless_pro/services/customers_service.rb +21 -1
  25. data/lib/gocardless_pro/services/events_service.rb +5 -0
  26. data/lib/gocardless_pro/services/mandate_pdfs_service.rb +3 -0
  27. data/lib/gocardless_pro/services/mandates_service.rb +47 -3
  28. data/lib/gocardless_pro/services/payments_service.rb +47 -3
  29. data/lib/gocardless_pro/services/payouts_service.rb +5 -0
  30. data/lib/gocardless_pro/services/redirect_flows_service.rb +28 -2
  31. data/lib/gocardless_pro/services/refunds_service.rb +21 -1
  32. data/lib/gocardless_pro/services/subscriptions_service.rb +34 -2
  33. data/lib/gocardless_pro/version.rb +1 -1
  34. data/spec/api_service_spec.rb +106 -0
  35. data/spec/middlewares/raise_gocardless_errors_spec.rb +98 -0
  36. data/spec/resources/bank_details_lookup_spec.rb +102 -19
  37. data/spec/resources/creditor_bank_account_spec.rb +416 -40
  38. data/spec/resources/creditor_spec.rb +414 -53
  39. data/spec/resources/customer_bank_account_spec.rb +452 -40
  40. data/spec/resources/customer_spec.rb +457 -45
  41. data/spec/resources/event_spec.rb +171 -72
  42. data/spec/resources/mandate_pdf_spec.rb +100 -17
  43. data/spec/resources/mandate_spec.rb +501 -44
  44. data/spec/resources/payment_spec.rb +531 -48
  45. data/spec/resources/payout_spec.rb +189 -45
  46. data/spec/resources/redirect_flow_spec.rb +277 -43
  47. data/spec/resources/refund_spec.rb +349 -34
  48. data/spec/resources/subscription_spec.rb +531 -53
  49. data/spec/response_spec.rb +12 -79
  50. data/spec/services/bank_details_lookups_service_spec.rb +67 -2
  51. data/spec/services/creditor_bank_accounts_service_spec.rb +309 -31
  52. data/spec/services/creditors_service_spec.rb +343 -33
  53. data/spec/services/customer_bank_accounts_service_spec.rb +335 -32
  54. data/spec/services/customers_service_spec.rb +364 -36
  55. data/spec/services/events_service_spec.rb +185 -24
  56. data/spec/services/mandate_pdfs_service_spec.rb +66 -2
  57. data/spec/services/mandates_service_spec.rb +341 -33
  58. data/spec/services/payments_service_spec.rb +355 -35
  59. data/spec/services/payouts_service_spec.rb +206 -26
  60. data/spec/services/redirect_flows_service_spec.rb +137 -7
  61. data/spec/services/refunds_service_spec.rb +301 -27
  62. data/spec/services/subscriptions_service_spec.rb +377 -38
  63. metadata +6 -3
@@ -1,95 +1,578 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe GoCardlessPro::Resources::Payment do
4
- describe 'initialising' do
5
- let(:data) do
6
- {
4
+ let(:client) do
5
+ GoCardlessPro::Client.new(
6
+ access_token: 'SECRET_TOKEN'
7
+ )
8
+ end
9
+
10
+ let(:response_headers) { { 'Content-Type' => 'application/json' } }
11
+
12
+ describe '#create' do
13
+ subject(:post_create_response) { client.payments.create(params: new_resource) }
14
+ context 'with a valid request' do
15
+ let(:new_resource) do
16
+ {
17
+
18
+ 'amount' => 'amount-input',
19
+ 'amount_refunded' => 'amount_refunded-input',
20
+ 'charge_date' => 'charge_date-input',
21
+ 'created_at' => 'created_at-input',
22
+ 'currency' => 'currency-input',
23
+ 'description' => 'description-input',
24
+ 'id' => 'id-input',
25
+ 'links' => 'links-input',
26
+ 'metadata' => 'metadata-input',
27
+ 'reference' => 'reference-input',
28
+ 'status' => 'status-input'
29
+ }
30
+ end
31
+
32
+ before do
33
+ stub_request(:post, %r{.*api.gocardless.com/payments})
34
+ .with(
35
+ body: {
36
+ 'payments' => {
37
+
38
+ 'amount' => 'amount-input',
39
+ 'amount_refunded' => 'amount_refunded-input',
40
+ 'charge_date' => 'charge_date-input',
41
+ 'created_at' => 'created_at-input',
42
+ 'currency' => 'currency-input',
43
+ 'description' => 'description-input',
44
+ 'id' => 'id-input',
45
+ 'links' => 'links-input',
46
+ 'metadata' => 'metadata-input',
47
+ 'reference' => 'reference-input',
48
+ 'status' => 'status-input'
49
+ }
50
+ }
51
+ )
52
+ .to_return(
53
+ body: {
54
+ 'payments' =>
55
+
56
+ {
57
+
58
+ 'amount' => 'amount-input',
59
+ 'amount_refunded' => 'amount_refunded-input',
60
+ 'charge_date' => 'charge_date-input',
61
+ 'created_at' => 'created_at-input',
62
+ 'currency' => 'currency-input',
63
+ 'description' => 'description-input',
64
+ 'id' => 'id-input',
65
+ 'links' => 'links-input',
66
+ 'metadata' => 'metadata-input',
67
+ 'reference' => 'reference-input',
68
+ 'status' => 'status-input'
69
+ }
70
+
71
+ }.to_json,
72
+ headers: response_headers
73
+ )
74
+ end
75
+
76
+ it 'creates and returns the resource' do
77
+ expect(post_create_response).to be_a(GoCardlessPro::Resources::Payment)
78
+ end
79
+ end
80
+
81
+ context 'with a request that returns a validation error' do
82
+ let(:new_resource) { {} }
83
+
84
+ before do
85
+ stub_request(:post, %r{.*api.gocardless.com/payments}).to_return(
86
+ body: {
87
+ error: {
88
+ type: 'validation_failed',
89
+ code: 422,
90
+ errors: [
91
+ { message: 'test error message', field: 'test_field' }
92
+ ]
93
+ }
94
+ }.to_json,
95
+ headers: response_headers,
96
+ status: 422
97
+ )
98
+ end
99
+
100
+ it 'throws the correct error' do
101
+ expect { post_create_response }.to raise_error(GoCardlessPro::ValidationError)
102
+ end
103
+ end
7
104
 
8
- 'amount' => 'amount-input',
105
+ context 'with a request that returns an idempotent creation conflict error' do
106
+ let(:id) { 'ID123' }
107
+
108
+ let(:new_resource) do
109
+ {
110
+
111
+ 'amount' => 'amount-input',
112
+ 'amount_refunded' => 'amount_refunded-input',
113
+ 'charge_date' => 'charge_date-input',
114
+ 'created_at' => 'created_at-input',
115
+ 'currency' => 'currency-input',
116
+ 'description' => 'description-input',
117
+ 'id' => 'id-input',
118
+ 'links' => 'links-input',
119
+ 'metadata' => 'metadata-input',
120
+ 'reference' => 'reference-input',
121
+ 'status' => 'status-input'
122
+ }
123
+ end
9
124
 
10
- 'amount_refunded' => 'amount_refunded-input',
125
+ let!(:post_stub) do
126
+ stub_request(:post, %r{.*api.gocardless.com/payments}).to_return(
127
+ body: {
128
+ error: {
129
+ type: 'invalid_state',
130
+ code: 409,
131
+ errors: [
132
+ {
133
+ message: 'A resource has already been created with this idempotency key',
134
+ reason: 'idempotent_creation_conflict',
135
+ links: {
136
+ conflicting_resource_id: id
137
+ }
138
+ }
139
+ ]
140
+ }
141
+ }.to_json,
142
+ headers: response_headers,
143
+ status: 409
144
+ )
145
+ end
11
146
 
12
- 'charge_date' => 'charge_date-input',
147
+ let!(:get_stub) do
148
+ stub_url = "/payments/#{id}"
149
+ stub_request(:get, /.*api.gocardless.com#{stub_url}/)
150
+ .to_return(
151
+ body: {
152
+ 'payments' => {
153
+
154
+ 'amount' => 'amount-input',
155
+ 'amount_refunded' => 'amount_refunded-input',
156
+ 'charge_date' => 'charge_date-input',
157
+ 'created_at' => 'created_at-input',
158
+ 'currency' => 'currency-input',
159
+ 'description' => 'description-input',
160
+ 'id' => 'id-input',
161
+ 'links' => 'links-input',
162
+ 'metadata' => 'metadata-input',
163
+ 'reference' => 'reference-input',
164
+ 'status' => 'status-input'
165
+ }
166
+ }.to_json,
167
+ headers: response_headers
168
+ )
169
+ end
13
170
 
14
- 'created_at' => 'created_at-input',
171
+ it 'fetches the already-created resource' do
172
+ post_create_response
173
+ expect(post_stub).to have_been_requested
174
+ expect(get_stub).to have_been_requested
175
+ end
176
+ end
177
+ end
15
178
 
16
- 'currency' => 'currency-input',
179
+ describe '#list' do
180
+ describe 'with no filters' do
181
+ subject(:get_list_response) { client.payments.list }
182
+
183
+ before do
184
+ stub_request(:get, %r{.*api.gocardless.com/payments}).to_return(
185
+ body: {
186
+ 'payments' => [{
187
+
188
+ 'amount' => 'amount-input',
189
+ 'amount_refunded' => 'amount_refunded-input',
190
+ 'charge_date' => 'charge_date-input',
191
+ 'created_at' => 'created_at-input',
192
+ 'currency' => 'currency-input',
193
+ 'description' => 'description-input',
194
+ 'id' => 'id-input',
195
+ 'links' => 'links-input',
196
+ 'metadata' => 'metadata-input',
197
+ 'reference' => 'reference-input',
198
+ 'status' => 'status-input'
199
+ }],
200
+ meta: {
201
+ cursors: {
202
+ before: nil,
203
+ after: 'ABC123'
204
+ }
205
+ }
206
+ }.to_json,
207
+ headers: response_headers
208
+ )
209
+ end
17
210
 
18
- 'description' => 'description-input',
211
+ it 'wraps each item in the resource class' do
212
+ expect(get_list_response.records.map(&:class).uniq.first).to eq(GoCardlessPro::Resources::Payment)
19
213
 
20
- 'id' => 'id-input',
214
+ expect(get_list_response.records.first.amount).to eq('amount-input')
21
215
 
22
- 'links' => {
216
+ expect(get_list_response.records.first.amount_refunded).to eq('amount_refunded-input')
23
217
 
24
- 'creditor' => 'creditor-input',
218
+ expect(get_list_response.records.first.charge_date).to eq('charge_date-input')
25
219
 
26
- 'mandate' => 'mandate-input',
220
+ expect(get_list_response.records.first.created_at).to eq('created_at-input')
27
221
 
28
- 'payout' => 'payout-input',
222
+ expect(get_list_response.records.first.currency).to eq('currency-input')
29
223
 
30
- 'subscription' => 'subscription-input'
224
+ expect(get_list_response.records.first.description).to eq('description-input')
31
225
 
32
- },
226
+ expect(get_list_response.records.first.id).to eq('id-input')
33
227
 
34
- 'metadata' => 'metadata-input',
228
+ expect(get_list_response.records.first.metadata).to eq('metadata-input')
35
229
 
36
- 'reference' => 'reference-input',
230
+ expect(get_list_response.records.first.reference).to eq('reference-input')
37
231
 
38
- 'status' => 'status-input'
232
+ expect(get_list_response.records.first.status).to eq('status-input')
233
+ end
234
+
235
+ it 'exposes the cursors for before and after' do
236
+ expect(get_list_response.before).to eq(nil)
237
+ expect(get_list_response.after).to eq('ABC123')
238
+ end
39
239
 
40
- }
240
+ specify { expect(get_list_response.api_response.headers).to eql('content-type' => 'application/json') }
41
241
  end
242
+ end
42
243
 
43
- it 'can be initialized from an unenveloped response' do
44
- resource = described_class.new(data)
244
+ describe '#all' do
245
+ let!(:first_response_stub) do
246
+ stub_request(:get, %r{.*api.gocardless.com/payments$}).to_return(
247
+ body: {
248
+ 'payments' => [{
249
+
250
+ 'amount' => 'amount-input',
251
+ 'amount_refunded' => 'amount_refunded-input',
252
+ 'charge_date' => 'charge_date-input',
253
+ 'created_at' => 'created_at-input',
254
+ 'currency' => 'currency-input',
255
+ 'description' => 'description-input',
256
+ 'id' => 'id-input',
257
+ 'links' => 'links-input',
258
+ 'metadata' => 'metadata-input',
259
+ 'reference' => 'reference-input',
260
+ 'status' => 'status-input'
261
+ }],
262
+ meta: {
263
+ cursors: { after: 'AB345' },
264
+ limit: 1
265
+ }
266
+ }.to_json,
267
+ headers: response_headers
268
+ )
269
+ end
45
270
 
46
- expect(resource.amount).to eq('amount-input')
271
+ let!(:second_response_stub) do
272
+ stub_request(:get, %r{.*api.gocardless.com/payments\?after=AB345}).to_return(
273
+ body: {
274
+ 'payments' => [{
275
+
276
+ 'amount' => 'amount-input',
277
+ 'amount_refunded' => 'amount_refunded-input',
278
+ 'charge_date' => 'charge_date-input',
279
+ 'created_at' => 'created_at-input',
280
+ 'currency' => 'currency-input',
281
+ 'description' => 'description-input',
282
+ 'id' => 'id-input',
283
+ 'links' => 'links-input',
284
+ 'metadata' => 'metadata-input',
285
+ 'reference' => 'reference-input',
286
+ 'status' => 'status-input'
287
+ }],
288
+ meta: {
289
+ limit: 2,
290
+ cursors: {}
291
+ }
292
+ }.to_json,
293
+ headers: response_headers
294
+ )
295
+ end
47
296
 
48
- expect(resource.amount_refunded).to eq('amount_refunded-input')
297
+ it 'automatically makes the extra requests' do
298
+ expect(client.payments.all.to_a.length).to eq(2)
299
+ expect(first_response_stub).to have_been_requested
300
+ expect(second_response_stub).to have_been_requested
301
+ end
302
+ end
49
303
 
50
- expect(resource.charge_date).to eq('charge_date-input')
304
+ describe '#get' do
305
+ let(:id) { 'ID123' }
306
+
307
+ subject(:get_response) { client.payments.get(id) }
308
+
309
+ context 'passing in a custom header' do
310
+ let!(:stub) do
311
+ stub_url = '/payments/:identity'.gsub(':identity', id)
312
+ stub_request(:get, /.*api.gocardless.com#{stub_url}/)
313
+ .with(headers: { 'Foo' => 'Bar' })
314
+ .to_return(
315
+ body: {
316
+ 'payments' => {
317
+
318
+ 'amount' => 'amount-input',
319
+ 'amount_refunded' => 'amount_refunded-input',
320
+ 'charge_date' => 'charge_date-input',
321
+ 'created_at' => 'created_at-input',
322
+ 'currency' => 'currency-input',
323
+ 'description' => 'description-input',
324
+ 'id' => 'id-input',
325
+ 'links' => 'links-input',
326
+ 'metadata' => 'metadata-input',
327
+ 'reference' => 'reference-input',
328
+ 'status' => 'status-input'
329
+ }
330
+ }.to_json,
331
+ headers: response_headers
332
+ )
333
+ end
51
334
 
52
- expect(resource.created_at).to eq('created_at-input')
335
+ subject(:get_response) do
336
+ client.payments.get(id, headers: {
337
+ 'Foo' => 'Bar'
338
+ })
339
+ end
53
340
 
54
- expect(resource.currency).to eq('currency-input')
341
+ it 'includes the header' do
342
+ get_response
343
+ expect(stub).to have_been_requested
344
+ end
345
+ end
55
346
 
56
- expect(resource.description).to eq('description-input')
347
+ context 'when there is a payment to return' do
348
+ before do
349
+ stub_url = '/payments/:identity'.gsub(':identity', id)
350
+ stub_request(:get, /.*api.gocardless.com#{stub_url}/).to_return(
351
+ body: {
352
+ 'payments' => {
353
+
354
+ 'amount' => 'amount-input',
355
+ 'amount_refunded' => 'amount_refunded-input',
356
+ 'charge_date' => 'charge_date-input',
357
+ 'created_at' => 'created_at-input',
358
+ 'currency' => 'currency-input',
359
+ 'description' => 'description-input',
360
+ 'id' => 'id-input',
361
+ 'links' => 'links-input',
362
+ 'metadata' => 'metadata-input',
363
+ 'reference' => 'reference-input',
364
+ 'status' => 'status-input'
365
+ }
366
+ }.to_json,
367
+ headers: response_headers
368
+ )
369
+ end
57
370
 
58
- expect(resource.id).to eq('id-input')
371
+ it 'wraps the response in a resource' do
372
+ expect(get_response).to be_a(GoCardlessPro::Resources::Payment)
373
+ end
374
+ end
59
375
 
60
- expect(resource.links.creditor).to eq('creditor-input')
376
+ context 'when nothing is returned' do
377
+ before do
378
+ stub_url = '/payments/:identity'.gsub(':identity', id)
379
+ stub_request(:get, /.*api.gocardless.com#{stub_url}/).to_return(
380
+ body: '',
381
+ headers: response_headers
382
+ )
383
+ end
61
384
 
62
- expect(resource.links.mandate).to eq('mandate-input')
385
+ it 'returns nil' do
386
+ expect(get_response).to be_nil
387
+ end
388
+ end
63
389
 
64
- expect(resource.links.payout).to eq('payout-input')
390
+ context "when an ID is specified which can't be included in a valid URI" do
391
+ let(:id) { '`' }
65
392
 
66
- expect(resource.links.subscription).to eq('subscription-input')
393
+ it "doesn't raise an error" do
394
+ expect { get_response }.to_not raise_error(/bad URI/)
395
+ end
396
+ end
397
+ end
398
+
399
+ describe '#update' do
400
+ subject(:put_update_response) { client.payments.update(id, params: update_params) }
401
+ let(:id) { 'ABC123' }
402
+
403
+ context 'with a valid request' do
404
+ let(:update_params) { { 'hello' => 'world' } }
405
+
406
+ let!(:stub) do
407
+ stub_url = '/payments/:identity'.gsub(':identity', id)
408
+ stub_request(:put, /.*api.gocardless.com#{stub_url}/).to_return(
409
+ body: {
410
+ 'payments' => {
411
+
412
+ 'amount' => 'amount-input',
413
+ 'amount_refunded' => 'amount_refunded-input',
414
+ 'charge_date' => 'charge_date-input',
415
+ 'created_at' => 'created_at-input',
416
+ 'currency' => 'currency-input',
417
+ 'description' => 'description-input',
418
+ 'id' => 'id-input',
419
+ 'links' => 'links-input',
420
+ 'metadata' => 'metadata-input',
421
+ 'reference' => 'reference-input',
422
+ 'status' => 'status-input'
423
+ }
424
+ }.to_json,
425
+ headers: response_headers
426
+ )
427
+ end
428
+
429
+ it 'updates and returns the resource' do
430
+ expect(put_update_response).to be_a(GoCardlessPro::Resources::Payment)
431
+ expect(stub).to have_been_requested
432
+ end
433
+ end
434
+ end
67
435
 
68
- expect(resource.metadata).to eq('metadata-input')
436
+ describe '#cancel' do
437
+ subject(:post_response) { client.payments.cancel(resource_id) }
438
+
439
+ let(:resource_id) { 'ABC123' }
440
+
441
+ let!(:stub) do
442
+ # /payments/%v/actions/cancel
443
+ stub_url = '/payments/:identity/actions/cancel'.gsub(':identity', resource_id)
444
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).to_return(
445
+ body: {
446
+ 'payments' => {
447
+
448
+ 'amount' => 'amount-input',
449
+ 'amount_refunded' => 'amount_refunded-input',
450
+ 'charge_date' => 'charge_date-input',
451
+ 'created_at' => 'created_at-input',
452
+ 'currency' => 'currency-input',
453
+ 'description' => 'description-input',
454
+ 'id' => 'id-input',
455
+ 'links' => 'links-input',
456
+ 'metadata' => 'metadata-input',
457
+ 'reference' => 'reference-input',
458
+ 'status' => 'status-input'
459
+ }
460
+ }.to_json,
461
+ headers: response_headers
462
+ )
463
+ end
69
464
 
70
- expect(resource.reference).to eq('reference-input')
465
+ it 'wraps the response and calls the right endpoint' do
466
+ expect(post_response).to be_a(GoCardlessPro::Resources::Payment)
71
467
 
72
- expect(resource.status).to eq('status-input')
468
+ expect(stub).to have_been_requested
73
469
  end
74
470
 
75
- it 'can handle new attributes without erroring' do
76
- data['foo'] = 'bar'
77
- expect { described_class.new(data) }.to_not raise_error
471
+ context 'when the request needs a body and custom header' do
472
+ let(:body) { { foo: 'bar' } }
473
+ let(:headers) { { 'Foo' => 'Bar' } }
474
+ subject(:post_response) { client.payments.cancel(resource_id, body, headers) }
475
+
476
+ let(:resource_id) { 'ABC123' }
477
+
478
+ let!(:stub) do
479
+ # /payments/%v/actions/cancel
480
+ stub_url = '/payments/:identity/actions/cancel'.gsub(':identity', resource_id)
481
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/)
482
+ .with(
483
+ body: { foo: 'bar' },
484
+ headers: { 'Foo' => 'Bar' }
485
+ ).to_return(
486
+ body: {
487
+ 'payments' => {
488
+
489
+ 'amount' => 'amount-input',
490
+ 'amount_refunded' => 'amount_refunded-input',
491
+ 'charge_date' => 'charge_date-input',
492
+ 'created_at' => 'created_at-input',
493
+ 'currency' => 'currency-input',
494
+ 'description' => 'description-input',
495
+ 'id' => 'id-input',
496
+ 'links' => 'links-input',
497
+ 'metadata' => 'metadata-input',
498
+ 'reference' => 'reference-input',
499
+ 'status' => 'status-input'
500
+ }
501
+ }.to_json,
502
+ headers: response_headers
503
+ )
504
+ end
78
505
  end
506
+ end
79
507
 
80
- it 'can handle new link attributes without erroring' do
81
- data['links']['foo'] = 'bar'
82
- expect { described_class.new(data) }.to_not raise_error
508
+ describe '#retry' do
509
+ subject(:post_response) { client.payments.retry(resource_id) }
510
+
511
+ let(:resource_id) { 'ABC123' }
512
+
513
+ let!(:stub) do
514
+ # /payments/%v/actions/retry
515
+ stub_url = '/payments/:identity/actions/retry'.gsub(':identity', resource_id)
516
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).to_return(
517
+ body: {
518
+ 'payments' => {
519
+
520
+ 'amount' => 'amount-input',
521
+ 'amount_refunded' => 'amount_refunded-input',
522
+ 'charge_date' => 'charge_date-input',
523
+ 'created_at' => 'created_at-input',
524
+ 'currency' => 'currency-input',
525
+ 'description' => 'description-input',
526
+ 'id' => 'id-input',
527
+ 'links' => 'links-input',
528
+ 'metadata' => 'metadata-input',
529
+ 'reference' => 'reference-input',
530
+ 'status' => 'status-input'
531
+ }
532
+ }.to_json,
533
+ headers: response_headers
534
+ )
83
535
  end
84
536
 
85
- it 'can handle a nil links value' do
86
- data['links'] = nil
87
- expect { described_class.new(data).links }.to_not raise_error
537
+ it 'wraps the response and calls the right endpoint' do
538
+ expect(post_response).to be_a(GoCardlessPro::Resources::Payment)
539
+
540
+ expect(stub).to have_been_requested
88
541
  end
89
542
 
90
- describe '#to_h' do
91
- it 'returns a hash representing the resource' do
92
- expect(described_class.new(data).to_h).to eq(data)
543
+ context 'when the request needs a body and custom header' do
544
+ let(:body) { { foo: 'bar' } }
545
+ let(:headers) { { 'Foo' => 'Bar' } }
546
+ subject(:post_response) { client.payments.retry(resource_id, body, headers) }
547
+
548
+ let(:resource_id) { 'ABC123' }
549
+
550
+ let!(:stub) do
551
+ # /payments/%v/actions/retry
552
+ stub_url = '/payments/:identity/actions/retry'.gsub(':identity', resource_id)
553
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/)
554
+ .with(
555
+ body: { foo: 'bar' },
556
+ headers: { 'Foo' => 'Bar' }
557
+ ).to_return(
558
+ body: {
559
+ 'payments' => {
560
+
561
+ 'amount' => 'amount-input',
562
+ 'amount_refunded' => 'amount_refunded-input',
563
+ 'charge_date' => 'charge_date-input',
564
+ 'created_at' => 'created_at-input',
565
+ 'currency' => 'currency-input',
566
+ 'description' => 'description-input',
567
+ 'id' => 'id-input',
568
+ 'links' => 'links-input',
569
+ 'metadata' => 'metadata-input',
570
+ 'reference' => 'reference-input',
571
+ 'status' => 'status-input'
572
+ }
573
+ }.to_json,
574
+ headers: response_headers
575
+ )
93
576
  end
94
577
  end
95
578
  end