gocardless_pro 2.27.0 → 2.28.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +20 -1
  3. data/lib/gocardless_pro.rb +6 -0
  4. data/lib/gocardless_pro/api_service.rb +4 -0
  5. data/lib/gocardless_pro/client.rb +6 -1
  6. data/lib/gocardless_pro/error/authentication_error.rb +4 -0
  7. data/lib/gocardless_pro/error/permission_error.rb +4 -0
  8. data/lib/gocardless_pro/error/rate_limit_error.rb +4 -0
  9. data/lib/gocardless_pro/middlewares/raise_gocardless_errors.rb +12 -1
  10. data/lib/gocardless_pro/resources/bank_authorisation.rb +3 -5
  11. data/lib/gocardless_pro/resources/billing_request.rb +29 -7
  12. data/lib/gocardless_pro/resources/billing_request_flow.rb +10 -0
  13. data/lib/gocardless_pro/resources/billing_request_template.rb +68 -0
  14. data/lib/gocardless_pro/resources/payer_authorisation.rb +9 -0
  15. data/lib/gocardless_pro/services/bank_authorisations_service.rb +0 -2
  16. data/lib/gocardless_pro/services/billing_request_flows_service.rb +23 -0
  17. data/lib/gocardless_pro/services/billing_request_templates_service.rb +131 -0
  18. data/lib/gocardless_pro/services/billing_requests_service.rb +49 -22
  19. data/lib/gocardless_pro/services/creditor_bank_accounts_service.rb +0 -4
  20. data/lib/gocardless_pro/services/creditors_service.rb +0 -2
  21. data/lib/gocardless_pro/services/customer_bank_accounts_service.rb +0 -4
  22. data/lib/gocardless_pro/services/customers_service.rb +0 -2
  23. data/lib/gocardless_pro/services/instalment_schedules_service.rb +0 -6
  24. data/lib/gocardless_pro/services/mandate_imports_service.rb +0 -6
  25. data/lib/gocardless_pro/services/mandates_service.rb +0 -6
  26. data/lib/gocardless_pro/services/payer_authorisations_service.rb +0 -6
  27. data/lib/gocardless_pro/services/payments_service.rb +0 -6
  28. data/lib/gocardless_pro/services/redirect_flows_service.rb +0 -4
  29. data/lib/gocardless_pro/services/refunds_service.rb +0 -2
  30. data/lib/gocardless_pro/services/scenario_simulators_service.rb +28 -6
  31. data/lib/gocardless_pro/services/subscriptions_service.rb +2 -10
  32. data/lib/gocardless_pro/services/webhooks_service.rb +0 -2
  33. data/lib/gocardless_pro/version.rb +1 -1
  34. data/spec/api_service_spec.rb +12 -1
  35. data/spec/middlewares/raise_gocardless_errors_spec.rb +30 -0
  36. data/spec/resources/bank_authorisation_spec.rb +7 -7
  37. data/spec/resources/billing_request_flow_spec.rb +90 -0
  38. data/spec/resources/billing_request_spec.rb +75 -29
  39. data/spec/resources/billing_request_template_spec.rb +502 -0
  40. data/spec/services/bank_authorisations_service_spec.rb +7 -20
  41. data/spec/services/billing_request_flows_service_spec.rb +101 -0
  42. data/spec/services/billing_request_templates_service_spec.rb +789 -0
  43. data/spec/services/billing_requests_service_spec.rb +87 -47
  44. data/spec/services/creditor_bank_accounts_service_spec.rb +0 -13
  45. data/spec/services/creditors_service_spec.rb +0 -13
  46. data/spec/services/customer_bank_accounts_service_spec.rb +0 -13
  47. data/spec/services/customers_service_spec.rb +0 -13
  48. data/spec/services/instalment_schedules_service_spec.rb +0 -26
  49. data/spec/services/mandate_imports_service_spec.rb +0 -13
  50. data/spec/services/mandates_service_spec.rb +0 -13
  51. data/spec/services/payer_authorisations_service_spec.rb +0 -13
  52. data/spec/services/payments_service_spec.rb +0 -13
  53. data/spec/services/redirect_flows_service_spec.rb +0 -13
  54. data/spec/services/refunds_service_spec.rb +0 -13
  55. data/spec/services/subscriptions_service_spec.rb +0 -13
  56. metadata +16 -7
@@ -24,13 +24,13 @@ describe GoCardlessPro::Services::BankAuthorisationsService do
24
24
  'bank_authorisations' => {
25
25
 
26
26
  'authorisation_type' => 'authorisation_type-input',
27
+ 'authorised_at' => 'authorised_at-input',
27
28
  'created_at' => 'created_at-input',
28
29
  'expires_at' => 'expires_at-input',
29
30
  'id' => 'id-input',
30
31
  'last_visited_at' => 'last_visited_at-input',
31
32
  'links' => 'links-input',
32
33
  'redirect_uri' => 'redirect_uri-input',
33
- 'short_url' => 'short_url-input',
34
34
  'url' => 'url-input',
35
35
  },
36
36
  }.to_json,
@@ -58,13 +58,13 @@ describe GoCardlessPro::Services::BankAuthorisationsService do
58
58
  'bank_authorisations' => {
59
59
 
60
60
  'authorisation_type' => 'authorisation_type-input',
61
+ 'authorised_at' => 'authorised_at-input',
61
62
  'created_at' => 'created_at-input',
62
63
  'expires_at' => 'expires_at-input',
63
64
  'id' => 'id-input',
64
65
  'last_visited_at' => 'last_visited_at-input',
65
66
  'links' => 'links-input',
66
67
  'redirect_uri' => 'redirect_uri-input',
67
- 'short_url' => 'short_url-input',
68
68
  'url' => 'url-input',
69
69
  },
70
70
  }.to_json,
@@ -162,13 +162,13 @@ describe GoCardlessPro::Services::BankAuthorisationsService do
162
162
  {
163
163
 
164
164
  'authorisation_type' => 'authorisation_type-input',
165
+ 'authorised_at' => 'authorised_at-input',
165
166
  'created_at' => 'created_at-input',
166
167
  'expires_at' => 'expires_at-input',
167
168
  'id' => 'id-input',
168
169
  'last_visited_at' => 'last_visited_at-input',
169
170
  'links' => 'links-input',
170
171
  'redirect_uri' => 'redirect_uri-input',
171
- 'short_url' => 'short_url-input',
172
172
  'url' => 'url-input',
173
173
  }
174
174
  end
@@ -180,13 +180,13 @@ describe GoCardlessPro::Services::BankAuthorisationsService do
180
180
  'bank_authorisations' => {
181
181
 
182
182
  'authorisation_type' => 'authorisation_type-input',
183
+ 'authorised_at' => 'authorised_at-input',
183
184
  'created_at' => 'created_at-input',
184
185
  'expires_at' => 'expires_at-input',
185
186
  'id' => 'id-input',
186
187
  'last_visited_at' => 'last_visited_at-input',
187
188
  'links' => 'links-input',
188
189
  'redirect_uri' => 'redirect_uri-input',
189
- 'short_url' => 'short_url-input',
190
190
  'url' => 'url-input',
191
191
  },
192
192
  }
@@ -198,13 +198,13 @@ describe GoCardlessPro::Services::BankAuthorisationsService do
198
198
  {
199
199
 
200
200
  'authorisation_type' => 'authorisation_type-input',
201
+ 'authorised_at' => 'authorised_at-input',
201
202
  'created_at' => 'created_at-input',
202
203
  'expires_at' => 'expires_at-input',
203
204
  'id' => 'id-input',
204
205
  'last_visited_at' => 'last_visited_at-input',
205
206
  'links' => 'links-input',
206
207
  'redirect_uri' => 'redirect_uri-input',
207
- 'short_url' => 'short_url-input',
208
208
  'url' => 'url-input',
209
209
  },
210
210
 
@@ -272,13 +272,13 @@ describe GoCardlessPro::Services::BankAuthorisationsService do
272
272
  {
273
273
 
274
274
  'authorisation_type' => 'authorisation_type-input',
275
+ 'authorised_at' => 'authorised_at-input',
275
276
  'created_at' => 'created_at-input',
276
277
  'expires_at' => 'expires_at-input',
277
278
  'id' => 'id-input',
278
279
  'last_visited_at' => 'last_visited_at-input',
279
280
  'links' => 'links-input',
280
281
  'redirect_uri' => 'redirect_uri-input',
281
- 'short_url' => 'short_url-input',
282
282
  'url' => 'url-input',
283
283
  }
284
284
  end
@@ -313,13 +313,13 @@ describe GoCardlessPro::Services::BankAuthorisationsService do
313
313
  'bank_authorisations' => {
314
314
 
315
315
  'authorisation_type' => 'authorisation_type-input',
316
+ 'authorised_at' => 'authorised_at-input',
316
317
  'created_at' => 'created_at-input',
317
318
  'expires_at' => 'expires_at-input',
318
319
  'id' => 'id-input',
319
320
  'last_visited_at' => 'last_visited_at-input',
320
321
  'links' => 'links-input',
321
322
  'redirect_uri' => 'redirect_uri-input',
322
- 'short_url' => 'short_url-input',
323
323
  'url' => 'url-input',
324
324
  },
325
325
  }.to_json,
@@ -348,19 +348,6 @@ describe GoCardlessPro::Services::BankAuthorisationsService do
348
348
  to raise_error(GoCardlessPro::IdempotencyConflict)
349
349
  end
350
350
  end
351
-
352
- context 'with on_idempotency_conflict: :unknown' do
353
- let(:client) do
354
- GoCardlessPro::Client.new(
355
- access_token: 'SECRET_TOKEN',
356
- on_idempotency_conflict: :unknown
357
- )
358
- end
359
-
360
- it 'raises an ArgumentError' do
361
- expect { post_create_response }.to raise_error(ArgumentError)
362
- end
363
- end
364
351
  end
365
352
  end
366
353
  end
@@ -16,10 +16,15 @@ describe GoCardlessPro::Services::BillingRequestFlowsService do
16
16
  {
17
17
 
18
18
  'authorisation_url' => 'authorisation_url-input',
19
+ 'auto_fulfil' => 'auto_fulfil-input',
19
20
  'created_at' => 'created_at-input',
20
21
  'expires_at' => 'expires_at-input',
22
+ 'id' => 'id-input',
21
23
  'links' => 'links-input',
24
+ 'lock_bank_account' => 'lock_bank_account-input',
25
+ 'lock_customer_details' => 'lock_customer_details-input',
22
26
  'redirect_uri' => 'redirect_uri-input',
27
+ 'session_token' => 'session_token-input',
23
28
  }
24
29
  end
25
30
 
@@ -30,10 +35,15 @@ describe GoCardlessPro::Services::BillingRequestFlowsService do
30
35
  'billing_request_flows' => {
31
36
 
32
37
  'authorisation_url' => 'authorisation_url-input',
38
+ 'auto_fulfil' => 'auto_fulfil-input',
33
39
  'created_at' => 'created_at-input',
34
40
  'expires_at' => 'expires_at-input',
41
+ 'id' => 'id-input',
35
42
  'links' => 'links-input',
43
+ 'lock_bank_account' => 'lock_bank_account-input',
44
+ 'lock_customer_details' => 'lock_customer_details-input',
36
45
  'redirect_uri' => 'redirect_uri-input',
46
+ 'session_token' => 'session_token-input',
37
47
  },
38
48
  }
39
49
  ).
@@ -44,10 +54,15 @@ describe GoCardlessPro::Services::BillingRequestFlowsService do
44
54
  {
45
55
 
46
56
  'authorisation_url' => 'authorisation_url-input',
57
+ 'auto_fulfil' => 'auto_fulfil-input',
47
58
  'created_at' => 'created_at-input',
48
59
  'expires_at' => 'expires_at-input',
60
+ 'id' => 'id-input',
49
61
  'links' => 'links-input',
62
+ 'lock_bank_account' => 'lock_bank_account-input',
63
+ 'lock_customer_details' => 'lock_customer_details-input',
50
64
  'redirect_uri' => 'redirect_uri-input',
65
+ 'session_token' => 'session_token-input',
51
66
  },
52
67
 
53
68
  }.to_json,
@@ -114,10 +129,15 @@ describe GoCardlessPro::Services::BillingRequestFlowsService do
114
129
  {
115
130
 
116
131
  'authorisation_url' => 'authorisation_url-input',
132
+ 'auto_fulfil' => 'auto_fulfil-input',
117
133
  'created_at' => 'created_at-input',
118
134
  'expires_at' => 'expires_at-input',
135
+ 'id' => 'id-input',
119
136
  'links' => 'links-input',
137
+ 'lock_bank_account' => 'lock_bank_account-input',
138
+ 'lock_customer_details' => 'lock_customer_details-input',
120
139
  'redirect_uri' => 'redirect_uri-input',
140
+ 'session_token' => 'session_token-input',
121
141
  }
122
142
  end
123
143
 
@@ -149,4 +169,85 @@ describe GoCardlessPro::Services::BillingRequestFlowsService do
149
169
  end
150
170
  end
151
171
  end
172
+
173
+ describe '#initialise' do
174
+ subject(:post_response) { client.billing_request_flows.initialise(resource_id) }
175
+
176
+ let(:resource_id) { 'ABC123' }
177
+
178
+ let!(:stub) do
179
+ # /billing_request_flows/%v/actions/initialise
180
+ stub_url = '/billing_request_flows/:identity/actions/initialise'.gsub(':identity', resource_id)
181
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).to_return(
182
+ body: {
183
+ 'billing_request_flows' => {
184
+
185
+ 'authorisation_url' => 'authorisation_url-input',
186
+ 'auto_fulfil' => 'auto_fulfil-input',
187
+ 'created_at' => 'created_at-input',
188
+ 'expires_at' => 'expires_at-input',
189
+ 'id' => 'id-input',
190
+ 'links' => 'links-input',
191
+ 'lock_bank_account' => 'lock_bank_account-input',
192
+ 'lock_customer_details' => 'lock_customer_details-input',
193
+ 'redirect_uri' => 'redirect_uri-input',
194
+ 'session_token' => 'session_token-input',
195
+ },
196
+ }.to_json,
197
+ headers: response_headers
198
+ )
199
+ end
200
+
201
+ it 'wraps the response and calls the right endpoint' do
202
+ expect(post_response).to be_a(GoCardlessPro::Resources::BillingRequestFlow)
203
+
204
+ expect(stub).to have_been_requested
205
+ end
206
+
207
+ describe 'retry behaviour' do
208
+ it "doesn't retry errors" do
209
+ stub_url = '/billing_request_flows/:identity/actions/initialise'.gsub(':identity', resource_id)
210
+ stub = stub_request(:post, /.*api.gocardless.com#{stub_url}/).
211
+ to_timeout
212
+
213
+ expect { post_response }.to raise_error(Faraday::ConnectionFailed)
214
+ expect(stub).to have_been_requested
215
+ end
216
+ end
217
+
218
+ context 'when the request needs a body and custom header' do
219
+ let(:body) { { foo: 'bar' } }
220
+ let(:headers) { { 'Foo' => 'Bar' } }
221
+ subject(:post_response) { client.billing_request_flows.initialise(resource_id, body, headers) }
222
+
223
+ let(:resource_id) { 'ABC123' }
224
+
225
+ let!(:stub) do
226
+ # /billing_request_flows/%v/actions/initialise
227
+ stub_url = '/billing_request_flows/:identity/actions/initialise'.gsub(':identity', resource_id)
228
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).
229
+ with(
230
+ body: { foo: 'bar' },
231
+ headers: { 'Foo' => 'Bar' }
232
+ ).to_return(
233
+ body: {
234
+ 'billing_request_flows' => {
235
+
236
+ 'authorisation_url' => 'authorisation_url-input',
237
+ 'auto_fulfil' => 'auto_fulfil-input',
238
+ 'created_at' => 'created_at-input',
239
+ 'expires_at' => 'expires_at-input',
240
+ 'id' => 'id-input',
241
+ 'links' => 'links-input',
242
+ 'lock_bank_account' => 'lock_bank_account-input',
243
+ 'lock_customer_details' => 'lock_customer_details-input',
244
+ 'redirect_uri' => 'redirect_uri-input',
245
+ 'session_token' => 'session_token-input',
246
+ },
247
+ }.to_json,
248
+ headers: response_headers
249
+ )
250
+ end
251
+ end
252
+ end
152
253
  end
@@ -0,0 +1,789 @@
1
+ require 'spec_helper'
2
+
3
+ describe GoCardlessPro::Services::BillingRequestTemplatesService do
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 '#list' do
13
+ describe 'with no filters' do
14
+ subject(:get_list_response) { client.billing_request_templates.list }
15
+
16
+ let(:body) do
17
+ {
18
+ 'billing_request_templates' => [{
19
+
20
+ 'authorisation_url' => 'authorisation_url-input',
21
+ 'created_at' => 'created_at-input',
22
+ 'id' => 'id-input',
23
+ 'mandate_request_currency' => 'mandate_request_currency-input',
24
+ 'mandate_request_metadata' => 'mandate_request_metadata-input',
25
+ 'mandate_request_scheme' => 'mandate_request_scheme-input',
26
+ 'mandate_request_verify' => 'mandate_request_verify-input',
27
+ 'metadata' => 'metadata-input',
28
+ 'name' => 'name-input',
29
+ 'payment_request_amount' => 'payment_request_amount-input',
30
+ 'payment_request_currency' => 'payment_request_currency-input',
31
+ 'payment_request_description' => 'payment_request_description-input',
32
+ 'payment_request_metadata' => 'payment_request_metadata-input',
33
+ 'payment_request_scheme' => 'payment_request_scheme-input',
34
+ 'redirect_uri' => 'redirect_uri-input',
35
+ 'updated_at' => 'updated_at-input',
36
+ }],
37
+ meta: {
38
+ cursors: {
39
+ before: nil,
40
+ after: 'ABC123',
41
+ },
42
+ },
43
+ }.to_json
44
+ end
45
+
46
+ before do
47
+ stub_request(:get, %r{.*api.gocardless.com/billing_request_templates}).to_return(
48
+ body: body,
49
+ headers: response_headers
50
+ )
51
+ end
52
+
53
+ it 'wraps each item in the resource class' do
54
+ expect(get_list_response.records.map(&:class).uniq.first).to eq(GoCardlessPro::Resources::BillingRequestTemplate)
55
+
56
+ expect(get_list_response.records.first.authorisation_url).to eq('authorisation_url-input')
57
+
58
+ expect(get_list_response.records.first.created_at).to eq('created_at-input')
59
+
60
+ expect(get_list_response.records.first.id).to eq('id-input')
61
+
62
+ expect(get_list_response.records.first.mandate_request_currency).to eq('mandate_request_currency-input')
63
+
64
+ expect(get_list_response.records.first.mandate_request_metadata).to eq('mandate_request_metadata-input')
65
+
66
+ expect(get_list_response.records.first.mandate_request_scheme).to eq('mandate_request_scheme-input')
67
+
68
+ expect(get_list_response.records.first.mandate_request_verify).to eq('mandate_request_verify-input')
69
+
70
+ expect(get_list_response.records.first.metadata).to eq('metadata-input')
71
+
72
+ expect(get_list_response.records.first.name).to eq('name-input')
73
+
74
+ expect(get_list_response.records.first.payment_request_amount).to eq('payment_request_amount-input')
75
+
76
+ expect(get_list_response.records.first.payment_request_currency).to eq('payment_request_currency-input')
77
+
78
+ expect(get_list_response.records.first.payment_request_description).to eq('payment_request_description-input')
79
+
80
+ expect(get_list_response.records.first.payment_request_metadata).to eq('payment_request_metadata-input')
81
+
82
+ expect(get_list_response.records.first.payment_request_scheme).to eq('payment_request_scheme-input')
83
+
84
+ expect(get_list_response.records.first.redirect_uri).to eq('redirect_uri-input')
85
+
86
+ expect(get_list_response.records.first.updated_at).to eq('updated_at-input')
87
+ end
88
+
89
+ it 'exposes the cursors for before and after' do
90
+ expect(get_list_response.before).to eq(nil)
91
+ expect(get_list_response.after).to eq('ABC123')
92
+ end
93
+
94
+ specify { expect(get_list_response.api_response.headers).to eql('content-type' => 'application/json') }
95
+
96
+ describe 'retry behaviour' do
97
+ before { allow_any_instance_of(GoCardlessPro::Request).to receive(:sleep) }
98
+
99
+ it 'retries timeouts' do
100
+ stub = stub_request(:get, %r{.*api.gocardless.com/billing_request_templates}).
101
+ to_timeout.then.to_return(status: 200, headers: response_headers, body: body)
102
+
103
+ get_list_response
104
+ expect(stub).to have_been_requested.twice
105
+ end
106
+
107
+ it 'retries 5XX errors' do
108
+ stub = stub_request(:get, %r{.*api.gocardless.com/billing_request_templates}).
109
+ to_return(status: 502,
110
+ headers: { 'Content-Type' => 'text/html' },
111
+ body: '<html><body>Response from Cloudflare</body></html>').
112
+ then.to_return(status: 200, headers: response_headers, body: body)
113
+
114
+ get_list_response
115
+ expect(stub).to have_been_requested.twice
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ describe '#all' do
122
+ let!(:first_response_stub) do
123
+ stub_request(:get, %r{.*api.gocardless.com/billing_request_templates$}).to_return(
124
+ body: {
125
+ 'billing_request_templates' => [{
126
+
127
+ 'authorisation_url' => 'authorisation_url-input',
128
+ 'created_at' => 'created_at-input',
129
+ 'id' => 'id-input',
130
+ 'mandate_request_currency' => 'mandate_request_currency-input',
131
+ 'mandate_request_metadata' => 'mandate_request_metadata-input',
132
+ 'mandate_request_scheme' => 'mandate_request_scheme-input',
133
+ 'mandate_request_verify' => 'mandate_request_verify-input',
134
+ 'metadata' => 'metadata-input',
135
+ 'name' => 'name-input',
136
+ 'payment_request_amount' => 'payment_request_amount-input',
137
+ 'payment_request_currency' => 'payment_request_currency-input',
138
+ 'payment_request_description' => 'payment_request_description-input',
139
+ 'payment_request_metadata' => 'payment_request_metadata-input',
140
+ 'payment_request_scheme' => 'payment_request_scheme-input',
141
+ 'redirect_uri' => 'redirect_uri-input',
142
+ 'updated_at' => 'updated_at-input',
143
+ }],
144
+ meta: {
145
+ cursors: { after: 'AB345' },
146
+ limit: 1,
147
+ },
148
+ }.to_json,
149
+ headers: response_headers
150
+ )
151
+ end
152
+
153
+ let!(:second_response_stub) do
154
+ stub_request(:get, %r{.*api.gocardless.com/billing_request_templates\?after=AB345}).to_return(
155
+ body: {
156
+ 'billing_request_templates' => [{
157
+
158
+ 'authorisation_url' => 'authorisation_url-input',
159
+ 'created_at' => 'created_at-input',
160
+ 'id' => 'id-input',
161
+ 'mandate_request_currency' => 'mandate_request_currency-input',
162
+ 'mandate_request_metadata' => 'mandate_request_metadata-input',
163
+ 'mandate_request_scheme' => 'mandate_request_scheme-input',
164
+ 'mandate_request_verify' => 'mandate_request_verify-input',
165
+ 'metadata' => 'metadata-input',
166
+ 'name' => 'name-input',
167
+ 'payment_request_amount' => 'payment_request_amount-input',
168
+ 'payment_request_currency' => 'payment_request_currency-input',
169
+ 'payment_request_description' => 'payment_request_description-input',
170
+ 'payment_request_metadata' => 'payment_request_metadata-input',
171
+ 'payment_request_scheme' => 'payment_request_scheme-input',
172
+ 'redirect_uri' => 'redirect_uri-input',
173
+ 'updated_at' => 'updated_at-input',
174
+ }],
175
+ meta: {
176
+ limit: 2,
177
+ cursors: {},
178
+ },
179
+ }.to_json,
180
+ headers: response_headers
181
+ )
182
+ end
183
+
184
+ it 'automatically makes the extra requests' do
185
+ expect(client.billing_request_templates.all.to_a.length).to eq(2)
186
+ expect(first_response_stub).to have_been_requested
187
+ expect(second_response_stub).to have_been_requested
188
+ end
189
+
190
+ describe 'retry behaviour' do
191
+ before { allow_any_instance_of(GoCardlessPro::Request).to receive(:sleep) }
192
+
193
+ it 'retries timeouts' do
194
+ first_response_stub = stub_request(:get, %r{.*api.gocardless.com/billing_request_templates$}).to_return(
195
+ body: {
196
+ 'billing_request_templates' => [{
197
+
198
+ 'authorisation_url' => 'authorisation_url-input',
199
+ 'created_at' => 'created_at-input',
200
+ 'id' => 'id-input',
201
+ 'mandate_request_currency' => 'mandate_request_currency-input',
202
+ 'mandate_request_metadata' => 'mandate_request_metadata-input',
203
+ 'mandate_request_scheme' => 'mandate_request_scheme-input',
204
+ 'mandate_request_verify' => 'mandate_request_verify-input',
205
+ 'metadata' => 'metadata-input',
206
+ 'name' => 'name-input',
207
+ 'payment_request_amount' => 'payment_request_amount-input',
208
+ 'payment_request_currency' => 'payment_request_currency-input',
209
+ 'payment_request_description' => 'payment_request_description-input',
210
+ 'payment_request_metadata' => 'payment_request_metadata-input',
211
+ 'payment_request_scheme' => 'payment_request_scheme-input',
212
+ 'redirect_uri' => 'redirect_uri-input',
213
+ 'updated_at' => 'updated_at-input',
214
+ }],
215
+ meta: {
216
+ cursors: { after: 'AB345' },
217
+ limit: 1,
218
+ },
219
+ }.to_json,
220
+ headers: response_headers
221
+ )
222
+
223
+ second_response_stub = stub_request(:get, %r{.*api.gocardless.com/billing_request_templates\?after=AB345}).
224
+ to_timeout.then.
225
+ to_return(
226
+ body: {
227
+ 'billing_request_templates' => [{
228
+
229
+ 'authorisation_url' => 'authorisation_url-input',
230
+ 'created_at' => 'created_at-input',
231
+ 'id' => 'id-input',
232
+ 'mandate_request_currency' => 'mandate_request_currency-input',
233
+ 'mandate_request_metadata' => 'mandate_request_metadata-input',
234
+ 'mandate_request_scheme' => 'mandate_request_scheme-input',
235
+ 'mandate_request_verify' => 'mandate_request_verify-input',
236
+ 'metadata' => 'metadata-input',
237
+ 'name' => 'name-input',
238
+ 'payment_request_amount' => 'payment_request_amount-input',
239
+ 'payment_request_currency' => 'payment_request_currency-input',
240
+ 'payment_request_description' => 'payment_request_description-input',
241
+ 'payment_request_metadata' => 'payment_request_metadata-input',
242
+ 'payment_request_scheme' => 'payment_request_scheme-input',
243
+ 'redirect_uri' => 'redirect_uri-input',
244
+ 'updated_at' => 'updated_at-input',
245
+ }],
246
+ meta: {
247
+ limit: 2,
248
+ cursors: {},
249
+ },
250
+ }.to_json,
251
+ headers: response_headers
252
+ )
253
+
254
+ client.billing_request_templates.all.to_a
255
+
256
+ expect(first_response_stub).to have_been_requested
257
+ expect(second_response_stub).to have_been_requested.twice
258
+ end
259
+
260
+ it 'retries 5XX errors' do
261
+ first_response_stub = stub_request(:get, %r{.*api.gocardless.com/billing_request_templates$}).to_return(
262
+ body: {
263
+ 'billing_request_templates' => [{
264
+
265
+ 'authorisation_url' => 'authorisation_url-input',
266
+ 'created_at' => 'created_at-input',
267
+ 'id' => 'id-input',
268
+ 'mandate_request_currency' => 'mandate_request_currency-input',
269
+ 'mandate_request_metadata' => 'mandate_request_metadata-input',
270
+ 'mandate_request_scheme' => 'mandate_request_scheme-input',
271
+ 'mandate_request_verify' => 'mandate_request_verify-input',
272
+ 'metadata' => 'metadata-input',
273
+ 'name' => 'name-input',
274
+ 'payment_request_amount' => 'payment_request_amount-input',
275
+ 'payment_request_currency' => 'payment_request_currency-input',
276
+ 'payment_request_description' => 'payment_request_description-input',
277
+ 'payment_request_metadata' => 'payment_request_metadata-input',
278
+ 'payment_request_scheme' => 'payment_request_scheme-input',
279
+ 'redirect_uri' => 'redirect_uri-input',
280
+ 'updated_at' => 'updated_at-input',
281
+ }],
282
+ meta: {
283
+ cursors: { after: 'AB345' },
284
+ limit: 1,
285
+ },
286
+ }.to_json,
287
+ headers: response_headers
288
+ )
289
+
290
+ second_response_stub = stub_request(:get, %r{.*api.gocardless.com/billing_request_templates\?after=AB345}).
291
+ to_return(
292
+ status: 502,
293
+ body: '<html><body>Response from Cloudflare</body></html>',
294
+ headers: { 'Content-Type' => 'text/html' }
295
+ ).then.to_return(
296
+ body: {
297
+ 'billing_request_templates' => [{
298
+
299
+ 'authorisation_url' => 'authorisation_url-input',
300
+ 'created_at' => 'created_at-input',
301
+ 'id' => 'id-input',
302
+ 'mandate_request_currency' => 'mandate_request_currency-input',
303
+ 'mandate_request_metadata' => 'mandate_request_metadata-input',
304
+ 'mandate_request_scheme' => 'mandate_request_scheme-input',
305
+ 'mandate_request_verify' => 'mandate_request_verify-input',
306
+ 'metadata' => 'metadata-input',
307
+ 'name' => 'name-input',
308
+ 'payment_request_amount' => 'payment_request_amount-input',
309
+ 'payment_request_currency' => 'payment_request_currency-input',
310
+ 'payment_request_description' => 'payment_request_description-input',
311
+ 'payment_request_metadata' => 'payment_request_metadata-input',
312
+ 'payment_request_scheme' => 'payment_request_scheme-input',
313
+ 'redirect_uri' => 'redirect_uri-input',
314
+ 'updated_at' => 'updated_at-input',
315
+ }],
316
+ meta: {
317
+ limit: 2,
318
+ cursors: {},
319
+ },
320
+ }.to_json,
321
+ headers: response_headers
322
+ )
323
+
324
+ client.billing_request_templates.all.to_a
325
+
326
+ expect(first_response_stub).to have_been_requested
327
+ expect(second_response_stub).to have_been_requested.twice
328
+ end
329
+ end
330
+ end
331
+
332
+ describe '#get' do
333
+ let(:id) { 'ID123' }
334
+
335
+ subject(:get_response) { client.billing_request_templates.get(id) }
336
+
337
+ context 'passing in a custom header' do
338
+ let!(:stub) do
339
+ stub_url = '/billing_request_templates/:identity'.gsub(':identity', id)
340
+ stub_request(:get, /.*api.gocardless.com#{stub_url}/).
341
+ with(headers: { 'Foo' => 'Bar' }).
342
+ to_return(
343
+ body: {
344
+ 'billing_request_templates' => {
345
+
346
+ 'authorisation_url' => 'authorisation_url-input',
347
+ 'created_at' => 'created_at-input',
348
+ 'id' => 'id-input',
349
+ 'mandate_request_currency' => 'mandate_request_currency-input',
350
+ 'mandate_request_metadata' => 'mandate_request_metadata-input',
351
+ 'mandate_request_scheme' => 'mandate_request_scheme-input',
352
+ 'mandate_request_verify' => 'mandate_request_verify-input',
353
+ 'metadata' => 'metadata-input',
354
+ 'name' => 'name-input',
355
+ 'payment_request_amount' => 'payment_request_amount-input',
356
+ 'payment_request_currency' => 'payment_request_currency-input',
357
+ 'payment_request_description' => 'payment_request_description-input',
358
+ 'payment_request_metadata' => 'payment_request_metadata-input',
359
+ 'payment_request_scheme' => 'payment_request_scheme-input',
360
+ 'redirect_uri' => 'redirect_uri-input',
361
+ 'updated_at' => 'updated_at-input',
362
+ },
363
+ }.to_json,
364
+ headers: response_headers
365
+ )
366
+ end
367
+
368
+ subject(:get_response) do
369
+ client.billing_request_templates.get(id, headers: {
370
+ 'Foo' => 'Bar',
371
+ })
372
+ end
373
+
374
+ it 'includes the header' do
375
+ get_response
376
+ expect(stub).to have_been_requested
377
+ end
378
+ end
379
+
380
+ context 'when there is a billing_request_template to return' do
381
+ before do
382
+ stub_url = '/billing_request_templates/:identity'.gsub(':identity', id)
383
+ stub_request(:get, /.*api.gocardless.com#{stub_url}/).to_return(
384
+ body: {
385
+ 'billing_request_templates' => {
386
+
387
+ 'authorisation_url' => 'authorisation_url-input',
388
+ 'created_at' => 'created_at-input',
389
+ 'id' => 'id-input',
390
+ 'mandate_request_currency' => 'mandate_request_currency-input',
391
+ 'mandate_request_metadata' => 'mandate_request_metadata-input',
392
+ 'mandate_request_scheme' => 'mandate_request_scheme-input',
393
+ 'mandate_request_verify' => 'mandate_request_verify-input',
394
+ 'metadata' => 'metadata-input',
395
+ 'name' => 'name-input',
396
+ 'payment_request_amount' => 'payment_request_amount-input',
397
+ 'payment_request_currency' => 'payment_request_currency-input',
398
+ 'payment_request_description' => 'payment_request_description-input',
399
+ 'payment_request_metadata' => 'payment_request_metadata-input',
400
+ 'payment_request_scheme' => 'payment_request_scheme-input',
401
+ 'redirect_uri' => 'redirect_uri-input',
402
+ 'updated_at' => 'updated_at-input',
403
+ },
404
+ }.to_json,
405
+ headers: response_headers
406
+ )
407
+ end
408
+
409
+ it 'wraps the response in a resource' do
410
+ expect(get_response).to be_a(GoCardlessPro::Resources::BillingRequestTemplate)
411
+ end
412
+ end
413
+
414
+ context 'when nothing is returned' do
415
+ before do
416
+ stub_url = '/billing_request_templates/:identity'.gsub(':identity', id)
417
+ stub_request(:get, /.*api.gocardless.com#{stub_url}/).to_return(
418
+ body: '',
419
+ headers: response_headers
420
+ )
421
+ end
422
+
423
+ it 'returns nil' do
424
+ expect(get_response).to be_nil
425
+ end
426
+ end
427
+
428
+ context "when an ID is specified which can't be included in a valid URI" do
429
+ let(:id) { '`' }
430
+
431
+ it "doesn't raise an error" do
432
+ expect { get_response }.to_not raise_error(/bad URI/)
433
+ end
434
+ end
435
+
436
+ describe 'retry behaviour' do
437
+ before { allow_any_instance_of(GoCardlessPro::Request).to receive(:sleep) }
438
+
439
+ it 'retries timeouts' do
440
+ stub_url = '/billing_request_templates/:identity'.gsub(':identity', id)
441
+
442
+ stub = stub_request(:get, /.*api.gocardless.com#{stub_url}/).
443
+ to_timeout.then.to_return(status: 200, headers: response_headers)
444
+
445
+ get_response
446
+ expect(stub).to have_been_requested.twice
447
+ end
448
+
449
+ it 'retries 5XX errors, other than 500s' do
450
+ stub_url = '/billing_request_templates/:identity'.gsub(':identity', id)
451
+
452
+ stub = stub_request(:get, /.*api.gocardless.com#{stub_url}/).
453
+ to_return(status: 502,
454
+ headers: { 'Content-Type' => 'text/html' },
455
+ body: '<html><body>Response from Cloudflare</body></html>').
456
+ then.to_return(status: 200, headers: response_headers)
457
+
458
+ get_response
459
+ expect(stub).to have_been_requested.twice
460
+ end
461
+
462
+ it 'retries 500 errors returned by the API' do
463
+ stub_url = '/billing_request_templates/:identity'.gsub(':identity', id)
464
+
465
+ gocardless_error = {
466
+ 'error' => {
467
+ 'message' => 'Internal server error',
468
+ 'documentation_url' => 'https://developer.gocardless.com/#gocardless',
469
+ 'errors' => [{
470
+ 'message' => 'Internal server error',
471
+ 'reason' => 'internal_server_error',
472
+ }],
473
+ 'type' => 'gocardless',
474
+ 'code' => 500,
475
+ 'request_id' => 'dummy_request_id',
476
+ 'id' => 'dummy_exception_id',
477
+ },
478
+ }
479
+
480
+ stub = stub_request(:get, /.*api.gocardless.com#{stub_url}/).
481
+ to_return(status: 500,
482
+ headers: response_headers,
483
+ body: gocardless_error.to_json).
484
+ then.to_return(status: 200, headers: response_headers)
485
+
486
+ get_response
487
+ expect(stub).to have_been_requested.twice
488
+ end
489
+ end
490
+ end
491
+
492
+ describe '#create' do
493
+ subject(:post_create_response) { client.billing_request_templates.create(params: new_resource) }
494
+ context 'with a valid request' do
495
+ let(:new_resource) do
496
+ {
497
+
498
+ 'authorisation_url' => 'authorisation_url-input',
499
+ 'created_at' => 'created_at-input',
500
+ 'id' => 'id-input',
501
+ 'mandate_request_currency' => 'mandate_request_currency-input',
502
+ 'mandate_request_metadata' => 'mandate_request_metadata-input',
503
+ 'mandate_request_scheme' => 'mandate_request_scheme-input',
504
+ 'mandate_request_verify' => 'mandate_request_verify-input',
505
+ 'metadata' => 'metadata-input',
506
+ 'name' => 'name-input',
507
+ 'payment_request_amount' => 'payment_request_amount-input',
508
+ 'payment_request_currency' => 'payment_request_currency-input',
509
+ 'payment_request_description' => 'payment_request_description-input',
510
+ 'payment_request_metadata' => 'payment_request_metadata-input',
511
+ 'payment_request_scheme' => 'payment_request_scheme-input',
512
+ 'redirect_uri' => 'redirect_uri-input',
513
+ 'updated_at' => 'updated_at-input',
514
+ }
515
+ end
516
+
517
+ before do
518
+ stub_request(:post, %r{.*api.gocardless.com/billing_request_templates}).
519
+ with(
520
+ body: {
521
+ 'billing_request_templates' => {
522
+
523
+ 'authorisation_url' => 'authorisation_url-input',
524
+ 'created_at' => 'created_at-input',
525
+ 'id' => 'id-input',
526
+ 'mandate_request_currency' => 'mandate_request_currency-input',
527
+ 'mandate_request_metadata' => 'mandate_request_metadata-input',
528
+ 'mandate_request_scheme' => 'mandate_request_scheme-input',
529
+ 'mandate_request_verify' => 'mandate_request_verify-input',
530
+ 'metadata' => 'metadata-input',
531
+ 'name' => 'name-input',
532
+ 'payment_request_amount' => 'payment_request_amount-input',
533
+ 'payment_request_currency' => 'payment_request_currency-input',
534
+ 'payment_request_description' => 'payment_request_description-input',
535
+ 'payment_request_metadata' => 'payment_request_metadata-input',
536
+ 'payment_request_scheme' => 'payment_request_scheme-input',
537
+ 'redirect_uri' => 'redirect_uri-input',
538
+ 'updated_at' => 'updated_at-input',
539
+ },
540
+ }
541
+ ).
542
+ to_return(
543
+ body: {
544
+ 'billing_request_templates' =>
545
+
546
+ {
547
+
548
+ 'authorisation_url' => 'authorisation_url-input',
549
+ 'created_at' => 'created_at-input',
550
+ 'id' => 'id-input',
551
+ 'mandate_request_currency' => 'mandate_request_currency-input',
552
+ 'mandate_request_metadata' => 'mandate_request_metadata-input',
553
+ 'mandate_request_scheme' => 'mandate_request_scheme-input',
554
+ 'mandate_request_verify' => 'mandate_request_verify-input',
555
+ 'metadata' => 'metadata-input',
556
+ 'name' => 'name-input',
557
+ 'payment_request_amount' => 'payment_request_amount-input',
558
+ 'payment_request_currency' => 'payment_request_currency-input',
559
+ 'payment_request_description' => 'payment_request_description-input',
560
+ 'payment_request_metadata' => 'payment_request_metadata-input',
561
+ 'payment_request_scheme' => 'payment_request_scheme-input',
562
+ 'redirect_uri' => 'redirect_uri-input',
563
+ 'updated_at' => 'updated_at-input',
564
+ },
565
+
566
+ }.to_json,
567
+ headers: response_headers
568
+ )
569
+ end
570
+
571
+ it 'creates and returns the resource' do
572
+ expect(post_create_response).to be_a(GoCardlessPro::Resources::BillingRequestTemplate)
573
+ end
574
+
575
+ describe 'retry behaviour' do
576
+ before { allow_any_instance_of(GoCardlessPro::Request).to receive(:sleep) }
577
+
578
+ it 'retries timeouts' do
579
+ stub = stub_request(:post, %r{.*api.gocardless.com/billing_request_templates}).
580
+ to_timeout.then.to_return(status: 200, headers: response_headers)
581
+
582
+ post_create_response
583
+ expect(stub).to have_been_requested.twice
584
+ end
585
+
586
+ it 'retries 5XX errors' do
587
+ stub = stub_request(:post, %r{.*api.gocardless.com/billing_request_templates}).
588
+ to_return(status: 502,
589
+ headers: { 'Content-Type' => 'text/html' },
590
+ body: '<html><body>Response from Cloudflare</body></html>').
591
+ then.to_return(status: 200, headers: response_headers)
592
+
593
+ post_create_response
594
+ expect(stub).to have_been_requested.twice
595
+ end
596
+ end
597
+ end
598
+
599
+ context 'with a request that returns a validation error' do
600
+ let(:new_resource) { {} }
601
+
602
+ before do
603
+ stub_request(:post, %r{.*api.gocardless.com/billing_request_templates}).to_return(
604
+ body: {
605
+ error: {
606
+ type: 'validation_failed',
607
+ code: 422,
608
+ errors: [
609
+ { message: 'test error message', field: 'test_field' },
610
+ ],
611
+ },
612
+ }.to_json,
613
+ headers: response_headers,
614
+ status: 422
615
+ )
616
+ end
617
+
618
+ it 'throws the correct error' do
619
+ expect { post_create_response }.to raise_error(GoCardlessPro::ValidationError)
620
+ end
621
+ end
622
+
623
+ context 'with a request that returns an idempotent creation conflict error' do
624
+ let(:id) { 'ID123' }
625
+
626
+ let(:new_resource) do
627
+ {
628
+
629
+ 'authorisation_url' => 'authorisation_url-input',
630
+ 'created_at' => 'created_at-input',
631
+ 'id' => 'id-input',
632
+ 'mandate_request_currency' => 'mandate_request_currency-input',
633
+ 'mandate_request_metadata' => 'mandate_request_metadata-input',
634
+ 'mandate_request_scheme' => 'mandate_request_scheme-input',
635
+ 'mandate_request_verify' => 'mandate_request_verify-input',
636
+ 'metadata' => 'metadata-input',
637
+ 'name' => 'name-input',
638
+ 'payment_request_amount' => 'payment_request_amount-input',
639
+ 'payment_request_currency' => 'payment_request_currency-input',
640
+ 'payment_request_description' => 'payment_request_description-input',
641
+ 'payment_request_metadata' => 'payment_request_metadata-input',
642
+ 'payment_request_scheme' => 'payment_request_scheme-input',
643
+ 'redirect_uri' => 'redirect_uri-input',
644
+ 'updated_at' => 'updated_at-input',
645
+ }
646
+ end
647
+
648
+ let!(:post_stub) do
649
+ stub_request(:post, %r{.*api.gocardless.com/billing_request_templates}).to_return(
650
+ body: {
651
+ error: {
652
+ type: 'invalid_state',
653
+ code: 409,
654
+ errors: [
655
+ {
656
+ message: 'A resource has already been created with this idempotency key',
657
+ reason: 'idempotent_creation_conflict',
658
+ links: {
659
+ conflicting_resource_id: id,
660
+ },
661
+ },
662
+ ],
663
+ },
664
+ }.to_json,
665
+ headers: response_headers,
666
+ status: 409
667
+ )
668
+ end
669
+
670
+ let!(:get_stub) do
671
+ stub_url = "/billing_request_templates/#{id}"
672
+ stub_request(:get, /.*api.gocardless.com#{stub_url}/).
673
+ to_return(
674
+ body: {
675
+ 'billing_request_templates' => {
676
+
677
+ 'authorisation_url' => 'authorisation_url-input',
678
+ 'created_at' => 'created_at-input',
679
+ 'id' => 'id-input',
680
+ 'mandate_request_currency' => 'mandate_request_currency-input',
681
+ 'mandate_request_metadata' => 'mandate_request_metadata-input',
682
+ 'mandate_request_scheme' => 'mandate_request_scheme-input',
683
+ 'mandate_request_verify' => 'mandate_request_verify-input',
684
+ 'metadata' => 'metadata-input',
685
+ 'name' => 'name-input',
686
+ 'payment_request_amount' => 'payment_request_amount-input',
687
+ 'payment_request_currency' => 'payment_request_currency-input',
688
+ 'payment_request_description' => 'payment_request_description-input',
689
+ 'payment_request_metadata' => 'payment_request_metadata-input',
690
+ 'payment_request_scheme' => 'payment_request_scheme-input',
691
+ 'redirect_uri' => 'redirect_uri-input',
692
+ 'updated_at' => 'updated_at-input',
693
+ },
694
+ }.to_json,
695
+ headers: response_headers
696
+ )
697
+ end
698
+
699
+ context 'with default behaviour' do
700
+ it 'fetches the already-created resource' do
701
+ post_create_response
702
+ expect(post_stub).to have_been_requested
703
+ expect(get_stub).to have_been_requested
704
+ end
705
+ end
706
+
707
+ context 'with on_idempotency_conflict: :raise' do
708
+ let(:client) do
709
+ GoCardlessPro::Client.new(
710
+ access_token: 'SECRET_TOKEN',
711
+ on_idempotency_conflict: :raise
712
+ )
713
+ end
714
+
715
+ it 'raises an IdempotencyConflict error' do
716
+ expect { post_create_response }.
717
+ to raise_error(GoCardlessPro::IdempotencyConflict)
718
+ end
719
+ end
720
+ end
721
+ end
722
+
723
+ describe '#update' do
724
+ subject(:put_update_response) { client.billing_request_templates.update(id, params: update_params) }
725
+ let(:id) { 'ABC123' }
726
+
727
+ context 'with a valid request' do
728
+ let(:update_params) { { 'hello' => 'world' } }
729
+
730
+ let!(:stub) do
731
+ stub_url = '/billing_requests/:identity'.gsub(':identity', id)
732
+ stub_request(:put, /.*api.gocardless.com#{stub_url}/).to_return(
733
+ body: {
734
+ 'billing_request_templates' => {
735
+
736
+ 'authorisation_url' => 'authorisation_url-input',
737
+ 'created_at' => 'created_at-input',
738
+ 'id' => 'id-input',
739
+ 'mandate_request_currency' => 'mandate_request_currency-input',
740
+ 'mandate_request_metadata' => 'mandate_request_metadata-input',
741
+ 'mandate_request_scheme' => 'mandate_request_scheme-input',
742
+ 'mandate_request_verify' => 'mandate_request_verify-input',
743
+ 'metadata' => 'metadata-input',
744
+ 'name' => 'name-input',
745
+ 'payment_request_amount' => 'payment_request_amount-input',
746
+ 'payment_request_currency' => 'payment_request_currency-input',
747
+ 'payment_request_description' => 'payment_request_description-input',
748
+ 'payment_request_metadata' => 'payment_request_metadata-input',
749
+ 'payment_request_scheme' => 'payment_request_scheme-input',
750
+ 'redirect_uri' => 'redirect_uri-input',
751
+ 'updated_at' => 'updated_at-input',
752
+ },
753
+ }.to_json,
754
+ headers: response_headers
755
+ )
756
+ end
757
+
758
+ it 'updates and returns the resource' do
759
+ expect(put_update_response).to be_a(GoCardlessPro::Resources::BillingRequestTemplate)
760
+ expect(stub).to have_been_requested
761
+ end
762
+
763
+ describe 'retry behaviour' do
764
+ before { allow_any_instance_of(GoCardlessPro::Request).to receive(:sleep) }
765
+
766
+ it 'retries timeouts' do
767
+ stub_url = '/billing_requests/:identity'.gsub(':identity', id)
768
+ stub = stub_request(:put, /.*api.gocardless.com#{stub_url}/).
769
+ to_timeout.then.to_return(status: 200, headers: response_headers)
770
+
771
+ put_update_response
772
+ expect(stub).to have_been_requested.twice
773
+ end
774
+
775
+ it 'retries 5XX errors' do
776
+ stub_url = '/billing_requests/:identity'.gsub(':identity', id)
777
+ stub = stub_request(:put, /.*api.gocardless.com#{stub_url}/).
778
+ to_return(status: 502,
779
+ headers: { 'Content-Type' => 'text/html' },
780
+ body: '<html><body>Response from Cloudflare</body></html>').
781
+ then.to_return(status: 200, headers: response_headers)
782
+
783
+ put_update_response
784
+ expect(stub).to have_been_requested.twice
785
+ end
786
+ end
787
+ end
788
+ end
789
+ end