gocardless_pro 2.20.0 → 2.24.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +25 -43
  3. data/Gemfile +7 -0
  4. data/gocardless_pro.gemspec +2 -2
  5. data/lib/gocardless_pro.rb +3 -0
  6. data/lib/gocardless_pro/api_service.rb +1 -1
  7. data/lib/gocardless_pro/client.rb +6 -1
  8. data/lib/gocardless_pro/resources/event.rb +12 -0
  9. data/lib/gocardless_pro/resources/payout.rb +2 -0
  10. data/lib/gocardless_pro/resources/payout_item.rb +2 -0
  11. data/lib/gocardless_pro/resources/tax_rate.rb +51 -0
  12. data/lib/gocardless_pro/services/bank_details_lookups_service.rb +0 -10
  13. data/lib/gocardless_pro/services/base_service.rb +11 -0
  14. data/lib/gocardless_pro/services/creditor_bank_accounts_service.rb +0 -10
  15. data/lib/gocardless_pro/services/creditors_service.rb +0 -10
  16. data/lib/gocardless_pro/services/currency_exchange_rates_service.rb +0 -10
  17. data/lib/gocardless_pro/services/customer_bank_accounts_service.rb +0 -10
  18. data/lib/gocardless_pro/services/customer_notifications_service.rb +0 -10
  19. data/lib/gocardless_pro/services/customers_service.rb +0 -10
  20. data/lib/gocardless_pro/services/events_service.rb +0 -10
  21. data/lib/gocardless_pro/services/instalment_schedules_service.rb +0 -10
  22. data/lib/gocardless_pro/services/mandate_import_entries_service.rb +0 -10
  23. data/lib/gocardless_pro/services/mandate_imports_service.rb +0 -10
  24. data/lib/gocardless_pro/services/mandate_pdfs_service.rb +0 -10
  25. data/lib/gocardless_pro/services/mandates_service.rb +0 -10
  26. data/lib/gocardless_pro/services/payments_service.rb +0 -10
  27. data/lib/gocardless_pro/services/payout_items_service.rb +0 -10
  28. data/lib/gocardless_pro/services/payouts_service.rb +0 -10
  29. data/lib/gocardless_pro/services/redirect_flows_service.rb +0 -10
  30. data/lib/gocardless_pro/services/refunds_service.rb +6 -11
  31. data/lib/gocardless_pro/services/subscriptions_service.rb +1 -11
  32. data/lib/gocardless_pro/services/tax_rates_service.rb +74 -0
  33. data/lib/gocardless_pro/version.rb +1 -1
  34. data/spec/resources/payout_item_spec.rb +5 -0
  35. data/spec/resources/payout_spec.rb +8 -0
  36. data/spec/resources/tax_rate_spec.rb +198 -0
  37. data/spec/services/creditor_bank_accounts_service_spec.rb +1 -1
  38. data/spec/services/customer_bank_accounts_service_spec.rb +1 -1
  39. data/spec/services/customer_notifications_service_spec.rb +1 -1
  40. data/spec/services/customers_service_spec.rb +1 -1
  41. data/spec/services/instalment_schedules_service_spec.rb +1 -1
  42. data/spec/services/mandate_imports_service_spec.rb +2 -2
  43. data/spec/services/mandates_service_spec.rb +2 -2
  44. data/spec/services/payments_service_spec.rb +2 -2
  45. data/spec/services/payout_items_service_spec.rb +9 -0
  46. data/spec/services/payouts_service_spec.rb +12 -0
  47. data/spec/services/redirect_flows_service_spec.rb +1 -1
  48. data/spec/services/subscriptions_service_spec.rb +3 -3
  49. data/spec/services/tax_rates_service_spec.rb +381 -0
  50. metadata +13 -7
@@ -692,7 +692,7 @@ describe GoCardlessPro::Services::CreditorBankAccountsService do
692
692
  stub = stub_request(:post, /.*api.gocardless.com#{stub_url}/).
693
693
  to_timeout
694
694
 
695
- expect { post_response }.to raise_error(Faraday::TimeoutError)
695
+ expect { post_response }.to raise_error(Faraday::ConnectionFailed)
696
696
  expect(stub).to have_been_requested
697
697
  end
698
698
  end
@@ -754,7 +754,7 @@ describe GoCardlessPro::Services::CustomerBankAccountsService do
754
754
  stub = stub_request(:post, /.*api.gocardless.com#{stub_url}/).
755
755
  to_timeout
756
756
 
757
- expect { post_response }.to raise_error(Faraday::TimeoutError)
757
+ expect { post_response }.to raise_error(Faraday::ConnectionFailed)
758
758
  expect(stub).to have_been_requested
759
759
  end
760
760
  end
@@ -45,7 +45,7 @@ describe GoCardlessPro::Services::CustomerNotificationsService do
45
45
  stub = stub_request(:post, /.*api.gocardless.com#{stub_url}/).
46
46
  to_timeout
47
47
 
48
- expect { post_response }.to raise_error(Faraday::TimeoutError)
48
+ expect { post_response }.to raise_error(Faraday::ConnectionFailed)
49
49
  expect(stub).to have_been_requested
50
50
  end
51
51
  end
@@ -882,7 +882,7 @@ describe GoCardlessPro::Services::CustomersService do
882
882
  stub = stub_request(:delete, /.*api.gocardless.com#{stub_url}/).
883
883
  to_timeout
884
884
 
885
- expect { delete_response }.to raise_error(Faraday::TimeoutError)
885
+ expect { delete_response }.to raise_error(Faraday::ConnectionFailed)
886
886
  expect(stub).to have_been_requested
887
887
  end
888
888
  end
@@ -927,7 +927,7 @@ describe GoCardlessPro::Services::InstalmentSchedulesService do
927
927
  stub = stub_request(:post, /.*api.gocardless.com#{stub_url}/).
928
928
  to_timeout
929
929
 
930
- expect { post_response }.to raise_error(Faraday::TimeoutError)
930
+ expect { post_response }.to raise_error(Faraday::ConnectionFailed)
931
931
  expect(stub).to have_been_requested
932
932
  end
933
933
  end
@@ -363,7 +363,7 @@ describe GoCardlessPro::Services::MandateImportsService do
363
363
  stub = stub_request(:post, /.*api.gocardless.com#{stub_url}/).
364
364
  to_timeout
365
365
 
366
- expect { post_response }.to raise_error(Faraday::TimeoutError)
366
+ expect { post_response }.to raise_error(Faraday::ConnectionFailed)
367
367
  expect(stub).to have_been_requested
368
368
  end
369
369
  end
@@ -432,7 +432,7 @@ describe GoCardlessPro::Services::MandateImportsService do
432
432
  stub = stub_request(:post, /.*api.gocardless.com#{stub_url}/).
433
433
  to_timeout
434
434
 
435
- expect { post_response }.to raise_error(Faraday::TimeoutError)
435
+ expect { post_response }.to raise_error(Faraday::ConnectionFailed)
436
436
  expect(stub).to have_been_requested
437
437
  end
438
438
  end
@@ -718,7 +718,7 @@ describe GoCardlessPro::Services::MandatesService do
718
718
  stub = stub_request(:post, /.*api.gocardless.com#{stub_url}/).
719
719
  to_timeout
720
720
 
721
- expect { post_response }.to raise_error(Faraday::TimeoutError)
721
+ expect { post_response }.to raise_error(Faraday::ConnectionFailed)
722
722
  expect(stub).to have_been_requested
723
723
  end
724
724
  end
@@ -797,7 +797,7 @@ describe GoCardlessPro::Services::MandatesService do
797
797
  stub = stub_request(:post, /.*api.gocardless.com#{stub_url}/).
798
798
  to_timeout
799
799
 
800
- expect { post_response }.to raise_error(Faraday::TimeoutError)
800
+ expect { post_response }.to raise_error(Faraday::ConnectionFailed)
801
801
  expect(stub).to have_been_requested
802
802
  end
803
803
  end
@@ -790,7 +790,7 @@ describe GoCardlessPro::Services::PaymentsService do
790
790
  stub = stub_request(:post, /.*api.gocardless.com#{stub_url}/).
791
791
  to_timeout
792
792
 
793
- expect { post_response }.to raise_error(Faraday::TimeoutError)
793
+ expect { post_response }.to raise_error(Faraday::ConnectionFailed)
794
794
  expect(stub).to have_been_requested
795
795
  end
796
796
  end
@@ -877,7 +877,7 @@ describe GoCardlessPro::Services::PaymentsService do
877
877
  stub = stub_request(:post, /.*api.gocardless.com#{stub_url}/).
878
878
  to_timeout
879
879
 
880
- expect { post_response }.to raise_error(Faraday::TimeoutError)
880
+ expect { post_response }.to raise_error(Faraday::ConnectionFailed)
881
881
  expect(stub).to have_been_requested
882
882
  end
883
883
  end
@@ -19,6 +19,7 @@ describe GoCardlessPro::Services::PayoutItemsService do
19
19
 
20
20
  'amount' => 'amount-input',
21
21
  'links' => 'links-input',
22
+ 'taxes' => 'taxes-input',
22
23
  'type' => 'type-input',
23
24
  }],
24
25
  meta: {
@@ -42,6 +43,8 @@ describe GoCardlessPro::Services::PayoutItemsService do
42
43
 
43
44
  expect(get_list_response.records.first.amount).to eq('amount-input')
44
45
 
46
+ expect(get_list_response.records.first.taxes).to eq('taxes-input')
47
+
45
48
  expect(get_list_response.records.first.type).to eq('type-input')
46
49
  end
47
50
 
@@ -85,6 +88,7 @@ describe GoCardlessPro::Services::PayoutItemsService do
85
88
 
86
89
  'amount' => 'amount-input',
87
90
  'links' => 'links-input',
91
+ 'taxes' => 'taxes-input',
88
92
  'type' => 'type-input',
89
93
  }],
90
94
  meta: {
@@ -103,6 +107,7 @@ describe GoCardlessPro::Services::PayoutItemsService do
103
107
 
104
108
  'amount' => 'amount-input',
105
109
  'links' => 'links-input',
110
+ 'taxes' => 'taxes-input',
106
111
  'type' => 'type-input',
107
112
  }],
108
113
  meta: {
@@ -130,6 +135,7 @@ describe GoCardlessPro::Services::PayoutItemsService do
130
135
 
131
136
  'amount' => 'amount-input',
132
137
  'links' => 'links-input',
138
+ 'taxes' => 'taxes-input',
133
139
  'type' => 'type-input',
134
140
  }],
135
141
  meta: {
@@ -148,6 +154,7 @@ describe GoCardlessPro::Services::PayoutItemsService do
148
154
 
149
155
  'amount' => 'amount-input',
150
156
  'links' => 'links-input',
157
+ 'taxes' => 'taxes-input',
151
158
  'type' => 'type-input',
152
159
  }],
153
160
  meta: {
@@ -171,6 +178,7 @@ describe GoCardlessPro::Services::PayoutItemsService do
171
178
 
172
179
  'amount' => 'amount-input',
173
180
  'links' => 'links-input',
181
+ 'taxes' => 'taxes-input',
174
182
  'type' => 'type-input',
175
183
  }],
176
184
  meta: {
@@ -192,6 +200,7 @@ describe GoCardlessPro::Services::PayoutItemsService do
192
200
 
193
201
  'amount' => 'amount-input',
194
202
  'links' => 'links-input',
203
+ 'taxes' => 'taxes-input',
195
204
  'type' => 'type-input',
196
205
  }],
197
206
  meta: {
@@ -29,6 +29,7 @@ describe GoCardlessPro::Services::PayoutsService do
29
29
  'payout_type' => 'payout_type-input',
30
30
  'reference' => 'reference-input',
31
31
  'status' => 'status-input',
32
+ 'tax_currency' => 'tax_currency-input',
32
33
  }],
33
34
  meta: {
34
35
  cursors: {
@@ -70,6 +71,8 @@ describe GoCardlessPro::Services::PayoutsService do
70
71
  expect(get_list_response.records.first.reference).to eq('reference-input')
71
72
 
72
73
  expect(get_list_response.records.first.status).to eq('status-input')
74
+
75
+ expect(get_list_response.records.first.tax_currency).to eq('tax_currency-input')
73
76
  end
74
77
 
75
78
  it 'exposes the cursors for before and after' do
@@ -122,6 +125,7 @@ describe GoCardlessPro::Services::PayoutsService do
122
125
  'payout_type' => 'payout_type-input',
123
126
  'reference' => 'reference-input',
124
127
  'status' => 'status-input',
128
+ 'tax_currency' => 'tax_currency-input',
125
129
  }],
126
130
  meta: {
127
131
  cursors: { after: 'AB345' },
@@ -149,6 +153,7 @@ describe GoCardlessPro::Services::PayoutsService do
149
153
  'payout_type' => 'payout_type-input',
150
154
  'reference' => 'reference-input',
151
155
  'status' => 'status-input',
156
+ 'tax_currency' => 'tax_currency-input',
152
157
  }],
153
158
  meta: {
154
159
  limit: 2,
@@ -185,6 +190,7 @@ describe GoCardlessPro::Services::PayoutsService do
185
190
  'payout_type' => 'payout_type-input',
186
191
  'reference' => 'reference-input',
187
192
  'status' => 'status-input',
193
+ 'tax_currency' => 'tax_currency-input',
188
194
  }],
189
195
  meta: {
190
196
  cursors: { after: 'AB345' },
@@ -212,6 +218,7 @@ describe GoCardlessPro::Services::PayoutsService do
212
218
  'payout_type' => 'payout_type-input',
213
219
  'reference' => 'reference-input',
214
220
  'status' => 'status-input',
221
+ 'tax_currency' => 'tax_currency-input',
215
222
  }],
216
223
  meta: {
217
224
  limit: 2,
@@ -244,6 +251,7 @@ describe GoCardlessPro::Services::PayoutsService do
244
251
  'payout_type' => 'payout_type-input',
245
252
  'reference' => 'reference-input',
246
253
  'status' => 'status-input',
254
+ 'tax_currency' => 'tax_currency-input',
247
255
  }],
248
256
  meta: {
249
257
  cursors: { after: 'AB345' },
@@ -274,6 +282,7 @@ describe GoCardlessPro::Services::PayoutsService do
274
282
  'payout_type' => 'payout_type-input',
275
283
  'reference' => 'reference-input',
276
284
  'status' => 'status-input',
285
+ 'tax_currency' => 'tax_currency-input',
277
286
  }],
278
287
  meta: {
279
288
  limit: 2,
@@ -317,6 +326,7 @@ describe GoCardlessPro::Services::PayoutsService do
317
326
  'payout_type' => 'payout_type-input',
318
327
  'reference' => 'reference-input',
319
328
  'status' => 'status-input',
329
+ 'tax_currency' => 'tax_currency-input',
320
330
  },
321
331
  }.to_json,
322
332
  headers: response_headers
@@ -354,6 +364,7 @@ describe GoCardlessPro::Services::PayoutsService do
354
364
  'payout_type' => 'payout_type-input',
355
365
  'reference' => 'reference-input',
356
366
  'status' => 'status-input',
367
+ 'tax_currency' => 'tax_currency-input',
357
368
  },
358
369
  }.to_json,
359
370
  headers: response_headers
@@ -468,6 +479,7 @@ describe GoCardlessPro::Services::PayoutsService do
468
479
  'payout_type' => 'payout_type-input',
469
480
  'reference' => 'reference-input',
470
481
  'status' => 'status-input',
482
+ 'tax_currency' => 'tax_currency-input',
471
483
  },
472
484
  }.to_json,
473
485
  headers: response_headers
@@ -411,7 +411,7 @@ describe GoCardlessPro::Services::RedirectFlowsService do
411
411
  stub = stub_request(:post, /.*api.gocardless.com#{stub_url}/).
412
412
  to_timeout
413
413
 
414
- expect { post_response }.to raise_error(Faraday::TimeoutError)
414
+ expect { post_response }.to raise_error(Faraday::ConnectionFailed)
415
415
  expect(stub).to have_been_requested
416
416
  end
417
417
  end
@@ -916,7 +916,7 @@ describe GoCardlessPro::Services::SubscriptionsService do
916
916
  stub = stub_request(:post, /.*api.gocardless.com#{stub_url}/).
917
917
  to_timeout
918
918
 
919
- expect { post_response }.to raise_error(Faraday::TimeoutError)
919
+ expect { post_response }.to raise_error(Faraday::ConnectionFailed)
920
920
  expect(stub).to have_been_requested
921
921
  end
922
922
  end
@@ -1017,7 +1017,7 @@ describe GoCardlessPro::Services::SubscriptionsService do
1017
1017
  stub = stub_request(:post, /.*api.gocardless.com#{stub_url}/).
1018
1018
  to_timeout
1019
1019
 
1020
- expect { post_response }.to raise_error(Faraday::TimeoutError)
1020
+ expect { post_response }.to raise_error(Faraday::ConnectionFailed)
1021
1021
  expect(stub).to have_been_requested
1022
1022
  end
1023
1023
  end
@@ -1118,7 +1118,7 @@ describe GoCardlessPro::Services::SubscriptionsService do
1118
1118
  stub = stub_request(:post, /.*api.gocardless.com#{stub_url}/).
1119
1119
  to_timeout
1120
1120
 
1121
- expect { post_response }.to raise_error(Faraday::TimeoutError)
1121
+ expect { post_response }.to raise_error(Faraday::ConnectionFailed)
1122
1122
  expect(stub).to have_been_requested
1123
1123
  end
1124
1124
  end
@@ -0,0 +1,381 @@
1
+ require 'spec_helper'
2
+
3
+ describe GoCardlessPro::Services::TaxRatesService 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.tax_rates.list }
15
+
16
+ let(:body) do
17
+ {
18
+ 'tax_rates' => [{
19
+
20
+ 'end_date' => 'end_date-input',
21
+ 'id' => 'id-input',
22
+ 'jurisdiction' => 'jurisdiction-input',
23
+ 'percentage' => 'percentage-input',
24
+ 'start_date' => 'start_date-input',
25
+ 'type' => 'type-input',
26
+ }],
27
+ meta: {
28
+ cursors: {
29
+ before: nil,
30
+ after: 'ABC123',
31
+ },
32
+ },
33
+ }.to_json
34
+ end
35
+
36
+ before do
37
+ stub_request(:get, %r{.*api.gocardless.com/tax_rates}).to_return(
38
+ body: body,
39
+ headers: response_headers
40
+ )
41
+ end
42
+
43
+ it 'wraps each item in the resource class' do
44
+ expect(get_list_response.records.map(&:class).uniq.first).to eq(GoCardlessPro::Resources::TaxRate)
45
+
46
+ expect(get_list_response.records.first.end_date).to eq('end_date-input')
47
+
48
+ expect(get_list_response.records.first.id).to eq('id-input')
49
+
50
+ expect(get_list_response.records.first.jurisdiction).to eq('jurisdiction-input')
51
+
52
+ expect(get_list_response.records.first.percentage).to eq('percentage-input')
53
+
54
+ expect(get_list_response.records.first.start_date).to eq('start_date-input')
55
+
56
+ expect(get_list_response.records.first.type).to eq('type-input')
57
+ end
58
+
59
+ it 'exposes the cursors for before and after' do
60
+ expect(get_list_response.before).to eq(nil)
61
+ expect(get_list_response.after).to eq('ABC123')
62
+ end
63
+
64
+ specify { expect(get_list_response.api_response.headers).to eql('content-type' => 'application/json') }
65
+
66
+ describe 'retry behaviour' do
67
+ before { allow_any_instance_of(GoCardlessPro::Request).to receive(:sleep) }
68
+
69
+ it 'retries timeouts' do
70
+ stub = stub_request(:get, %r{.*api.gocardless.com/tax_rates}).
71
+ to_timeout.then.to_return(status: 200, headers: response_headers, body: body)
72
+
73
+ get_list_response
74
+ expect(stub).to have_been_requested.twice
75
+ end
76
+
77
+ it 'retries 5XX errors' do
78
+ stub = stub_request(:get, %r{.*api.gocardless.com/tax_rates}).
79
+ to_return(status: 502,
80
+ headers: { 'Content-Type' => 'text/html' },
81
+ body: '<html><body>Response from Cloudflare</body></html>').
82
+ then.to_return(status: 200, headers: response_headers, body: body)
83
+
84
+ get_list_response
85
+ expect(stub).to have_been_requested.twice
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ describe '#all' do
92
+ let!(:first_response_stub) do
93
+ stub_request(:get, %r{.*api.gocardless.com/tax_rates$}).to_return(
94
+ body: {
95
+ 'tax_rates' => [{
96
+
97
+ 'end_date' => 'end_date-input',
98
+ 'id' => 'id-input',
99
+ 'jurisdiction' => 'jurisdiction-input',
100
+ 'percentage' => 'percentage-input',
101
+ 'start_date' => 'start_date-input',
102
+ 'type' => 'type-input',
103
+ }],
104
+ meta: {
105
+ cursors: { after: 'AB345' },
106
+ limit: 1,
107
+ },
108
+ }.to_json,
109
+ headers: response_headers
110
+ )
111
+ end
112
+
113
+ let!(:second_response_stub) do
114
+ stub_request(:get, %r{.*api.gocardless.com/tax_rates\?after=AB345}).to_return(
115
+ body: {
116
+ 'tax_rates' => [{
117
+
118
+ 'end_date' => 'end_date-input',
119
+ 'id' => 'id-input',
120
+ 'jurisdiction' => 'jurisdiction-input',
121
+ 'percentage' => 'percentage-input',
122
+ 'start_date' => 'start_date-input',
123
+ 'type' => 'type-input',
124
+ }],
125
+ meta: {
126
+ limit: 2,
127
+ cursors: {},
128
+ },
129
+ }.to_json,
130
+ headers: response_headers
131
+ )
132
+ end
133
+
134
+ it 'automatically makes the extra requests' do
135
+ expect(client.tax_rates.all.to_a.length).to eq(2)
136
+ expect(first_response_stub).to have_been_requested
137
+ expect(second_response_stub).to have_been_requested
138
+ end
139
+
140
+ describe 'retry behaviour' do
141
+ before { allow_any_instance_of(GoCardlessPro::Request).to receive(:sleep) }
142
+
143
+ it 'retries timeouts' do
144
+ first_response_stub = stub_request(:get, %r{.*api.gocardless.com/tax_rates$}).to_return(
145
+ body: {
146
+ 'tax_rates' => [{
147
+
148
+ 'end_date' => 'end_date-input',
149
+ 'id' => 'id-input',
150
+ 'jurisdiction' => 'jurisdiction-input',
151
+ 'percentage' => 'percentage-input',
152
+ 'start_date' => 'start_date-input',
153
+ 'type' => 'type-input',
154
+ }],
155
+ meta: {
156
+ cursors: { after: 'AB345' },
157
+ limit: 1,
158
+ },
159
+ }.to_json,
160
+ headers: response_headers
161
+ )
162
+
163
+ second_response_stub = stub_request(:get, %r{.*api.gocardless.com/tax_rates\?after=AB345}).
164
+ to_timeout.then.
165
+ to_return(
166
+ body: {
167
+ 'tax_rates' => [{
168
+
169
+ 'end_date' => 'end_date-input',
170
+ 'id' => 'id-input',
171
+ 'jurisdiction' => 'jurisdiction-input',
172
+ 'percentage' => 'percentage-input',
173
+ 'start_date' => 'start_date-input',
174
+ 'type' => 'type-input',
175
+ }],
176
+ meta: {
177
+ limit: 2,
178
+ cursors: {},
179
+ },
180
+ }.to_json,
181
+ headers: response_headers
182
+ )
183
+
184
+ client.tax_rates.all.to_a
185
+
186
+ expect(first_response_stub).to have_been_requested
187
+ expect(second_response_stub).to have_been_requested.twice
188
+ end
189
+
190
+ it 'retries 5XX errors' do
191
+ first_response_stub = stub_request(:get, %r{.*api.gocardless.com/tax_rates$}).to_return(
192
+ body: {
193
+ 'tax_rates' => [{
194
+
195
+ 'end_date' => 'end_date-input',
196
+ 'id' => 'id-input',
197
+ 'jurisdiction' => 'jurisdiction-input',
198
+ 'percentage' => 'percentage-input',
199
+ 'start_date' => 'start_date-input',
200
+ 'type' => 'type-input',
201
+ }],
202
+ meta: {
203
+ cursors: { after: 'AB345' },
204
+ limit: 1,
205
+ },
206
+ }.to_json,
207
+ headers: response_headers
208
+ )
209
+
210
+ second_response_stub = stub_request(:get, %r{.*api.gocardless.com/tax_rates\?after=AB345}).
211
+ to_return(
212
+ status: 502,
213
+ body: '<html><body>Response from Cloudflare</body></html>',
214
+ headers: { 'Content-Type' => 'text/html' }
215
+ ).then.to_return(
216
+ body: {
217
+ 'tax_rates' => [{
218
+
219
+ 'end_date' => 'end_date-input',
220
+ 'id' => 'id-input',
221
+ 'jurisdiction' => 'jurisdiction-input',
222
+ 'percentage' => 'percentage-input',
223
+ 'start_date' => 'start_date-input',
224
+ 'type' => 'type-input',
225
+ }],
226
+ meta: {
227
+ limit: 2,
228
+ cursors: {},
229
+ },
230
+ }.to_json,
231
+ headers: response_headers
232
+ )
233
+
234
+ client.tax_rates.all.to_a
235
+
236
+ expect(first_response_stub).to have_been_requested
237
+ expect(second_response_stub).to have_been_requested.twice
238
+ end
239
+ end
240
+ end
241
+
242
+ describe '#get' do
243
+ let(:id) { 'ID123' }
244
+
245
+ subject(:get_response) { client.tax_rates.get(id) }
246
+
247
+ context 'passing in a custom header' do
248
+ let!(:stub) do
249
+ stub_url = '/tax_rates/:identity'.gsub(':identity', id)
250
+ stub_request(:get, /.*api.gocardless.com#{stub_url}/).
251
+ with(headers: { 'Foo' => 'Bar' }).
252
+ to_return(
253
+ body: {
254
+ 'tax_rates' => {
255
+
256
+ 'end_date' => 'end_date-input',
257
+ 'id' => 'id-input',
258
+ 'jurisdiction' => 'jurisdiction-input',
259
+ 'percentage' => 'percentage-input',
260
+ 'start_date' => 'start_date-input',
261
+ 'type' => 'type-input',
262
+ },
263
+ }.to_json,
264
+ headers: response_headers
265
+ )
266
+ end
267
+
268
+ subject(:get_response) do
269
+ client.tax_rates.get(id, headers: {
270
+ 'Foo' => 'Bar',
271
+ })
272
+ end
273
+
274
+ it 'includes the header' do
275
+ get_response
276
+ expect(stub).to have_been_requested
277
+ end
278
+ end
279
+
280
+ context 'when there is a tax_rate to return' do
281
+ before do
282
+ stub_url = '/tax_rates/:identity'.gsub(':identity', id)
283
+ stub_request(:get, /.*api.gocardless.com#{stub_url}/).to_return(
284
+ body: {
285
+ 'tax_rates' => {
286
+
287
+ 'end_date' => 'end_date-input',
288
+ 'id' => 'id-input',
289
+ 'jurisdiction' => 'jurisdiction-input',
290
+ 'percentage' => 'percentage-input',
291
+ 'start_date' => 'start_date-input',
292
+ 'type' => 'type-input',
293
+ },
294
+ }.to_json,
295
+ headers: response_headers
296
+ )
297
+ end
298
+
299
+ it 'wraps the response in a resource' do
300
+ expect(get_response).to be_a(GoCardlessPro::Resources::TaxRate)
301
+ end
302
+ end
303
+
304
+ context 'when nothing is returned' do
305
+ before do
306
+ stub_url = '/tax_rates/:identity'.gsub(':identity', id)
307
+ stub_request(:get, /.*api.gocardless.com#{stub_url}/).to_return(
308
+ body: '',
309
+ headers: response_headers
310
+ )
311
+ end
312
+
313
+ it 'returns nil' do
314
+ expect(get_response).to be_nil
315
+ end
316
+ end
317
+
318
+ context "when an ID is specified which can't be included in a valid URI" do
319
+ let(:id) { '`' }
320
+
321
+ it "doesn't raise an error" do
322
+ expect { get_response }.to_not raise_error(/bad URI/)
323
+ end
324
+ end
325
+
326
+ describe 'retry behaviour' do
327
+ before { allow_any_instance_of(GoCardlessPro::Request).to receive(:sleep) }
328
+
329
+ it 'retries timeouts' do
330
+ stub_url = '/tax_rates/:identity'.gsub(':identity', id)
331
+
332
+ stub = stub_request(:get, /.*api.gocardless.com#{stub_url}/).
333
+ to_timeout.then.to_return(status: 200, headers: response_headers)
334
+
335
+ get_response
336
+ expect(stub).to have_been_requested.twice
337
+ end
338
+
339
+ it 'retries 5XX errors, other than 500s' do
340
+ stub_url = '/tax_rates/:identity'.gsub(':identity', id)
341
+
342
+ stub = stub_request(:get, /.*api.gocardless.com#{stub_url}/).
343
+ to_return(status: 502,
344
+ headers: { 'Content-Type' => 'text/html' },
345
+ body: '<html><body>Response from Cloudflare</body></html>').
346
+ then.to_return(status: 200, headers: response_headers)
347
+
348
+ get_response
349
+ expect(stub).to have_been_requested.twice
350
+ end
351
+
352
+ it 'retries 500 errors returned by the API' do
353
+ stub_url = '/tax_rates/:identity'.gsub(':identity', id)
354
+
355
+ gocardless_error = {
356
+ 'error' => {
357
+ 'message' => 'Internal server error',
358
+ 'documentation_url' => 'https://developer.gocardless.com/#gocardless',
359
+ 'errors' => [{
360
+ 'message' => 'Internal server error',
361
+ 'reason' => 'internal_server_error',
362
+ }],
363
+ 'type' => 'gocardless',
364
+ 'code' => 500,
365
+ 'request_id' => 'dummy_request_id',
366
+ 'id' => 'dummy_exception_id',
367
+ },
368
+ }
369
+
370
+ stub = stub_request(:get, /.*api.gocardless.com#{stub_url}/).
371
+ to_return(status: 500,
372
+ headers: response_headers,
373
+ body: gocardless_error.to_json).
374
+ then.to_return(status: 200, headers: response_headers)
375
+
376
+ get_response
377
+ expect(stub).to have_been_requested.twice
378
+ end
379
+ end
380
+ end
381
+ end