gocardless_pro 1.1.0 → 2.0.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 (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