ibandit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.rubocop.yml +43 -0
- data/.rubocop_todo.yml +23 -0
- data/CHANGELOG.md +48 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +303 -0
- data/TODO.md +5 -0
- data/bin/build_structure_file.rb +101 -0
- data/circle.yml +19 -0
- data/data/IBANSTRUCTURE.xml +1184 -0
- data/data/IBAN_Registry.txt +70 -0
- data/data/structure_additions.yml +43 -0
- data/ibandit.gemspec +24 -0
- data/lib/ibandit.rb +16 -0
- data/lib/ibandit/check_digit.rb +183 -0
- data/lib/ibandit/errors.rb +5 -0
- data/lib/ibandit/iban.rb +168 -0
- data/lib/ibandit/iban_builder.rb +528 -0
- data/lib/ibandit/structures.yml +703 -0
- data/lib/ibandit/version.rb +3 -0
- data/spec/ibandit/check_digit_spec.rb +130 -0
- data/spec/ibandit/iban_builder_spec.rb +853 -0
- data/spec/ibandit/iban_spec.rb +549 -0
- data/spec/spec_helper.rb +7 -0
- metadata +141 -0
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ibandit::CheckDigit do
|
4
|
+
describe '.mod_97_10' do
|
5
|
+
subject { described_class.mod_97_10(account_number) }
|
6
|
+
|
7
|
+
context 'with a non-numeric character' do
|
8
|
+
let(:account_number) { 'hhhh' }
|
9
|
+
specify { expect { subject }.to raise_error(/non-alphanumeric/) }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '.spanish' do
|
14
|
+
subject { described_class.spanish(account_number) }
|
15
|
+
|
16
|
+
context 'sequence that should give a check digit of 0' do
|
17
|
+
let(:account_number) { '12345678' }
|
18
|
+
it { is_expected.to eq('0') }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'sequence that should give a check digit of 8' do
|
22
|
+
let(:account_number) { '0000012345' }
|
23
|
+
it { is_expected.to eq('8') }
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'with a non-numeric character' do
|
27
|
+
let(:account_number) { '000001234A' }
|
28
|
+
it 'raises an error' do
|
29
|
+
expect { subject }.to raise_error(Ibandit::InvalidCharacterError)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '.lund' do
|
35
|
+
subject { described_class.lund(account_number) }
|
36
|
+
|
37
|
+
let(:account_number) { '1200300002088' }
|
38
|
+
it { is_expected.to eq('3') }
|
39
|
+
|
40
|
+
context 'with another account number (double checking!)' do
|
41
|
+
let(:account_number) { '1428350017114' }
|
42
|
+
it { is_expected.to eq('1') }
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'with a non-numeric character' do
|
46
|
+
let(:account_number) { '1BAD2014' }
|
47
|
+
specify { expect { subject }.to raise_error(/non-numeric character/) }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '.estonian' do
|
52
|
+
subject { described_class.estonian(account_number) }
|
53
|
+
|
54
|
+
context "with an account_number that doesn't start with a zero" do
|
55
|
+
let(:account_number) { '22102014568' }
|
56
|
+
it { is_expected.to eq('5') }
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'with leading zeros' do
|
60
|
+
let(:account_number) { '0022102014568' }
|
61
|
+
it { is_expected.to eq('5') }
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'with a non-numeric character' do
|
65
|
+
let(:account_number) { '1BAD2014' }
|
66
|
+
specify { expect { subject }.to raise_error(/non-numeric character/) }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '.dutch' do
|
71
|
+
subject { described_class.dutch(account_number) }
|
72
|
+
|
73
|
+
let(:account_number) { '041716430' }
|
74
|
+
it { is_expected.to eq('0') }
|
75
|
+
|
76
|
+
context 'with another account number (double checking!)' do
|
77
|
+
let(:account_number) { '030006526' }
|
78
|
+
it { is_expected.to eq('4') }
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'with a non-numeric character' do
|
82
|
+
let(:account_number) { '1BAD2014' }
|
83
|
+
specify { expect { subject }.to raise_error(/non-numeric character/) }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '.slovakian_prefix' do
|
88
|
+
subject { described_class.slovakian_prefix(account_number) }
|
89
|
+
|
90
|
+
let(:account_number) { '00001' }
|
91
|
+
it { is_expected.to eq('9') }
|
92
|
+
|
93
|
+
context 'with a non-numeric character' do
|
94
|
+
let(:account_number) { '1BAD2014' }
|
95
|
+
specify { expect { subject }.to raise_error(/non-numeric character/) }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe '.slovakian_basic' do
|
100
|
+
subject { described_class.slovakian_basic(account_number) }
|
101
|
+
|
102
|
+
let(:account_number) { '874263754' }
|
103
|
+
it { is_expected.to eq('1') }
|
104
|
+
|
105
|
+
context 'with a non-numeric character' do
|
106
|
+
let(:account_number) { '1BAD2014' }
|
107
|
+
specify { expect { subject }.to raise_error(/non-numeric character/) }
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe '.rib' do
|
112
|
+
subject { described_class.rib(bank_code, branch_code, account_number) }
|
113
|
+
|
114
|
+
context 'with some non-numeric characters' do
|
115
|
+
let(:bank_code) { '12BD4' }
|
116
|
+
let(:branch_code) { '367WX' }
|
117
|
+
let(:account_number) { '12345678912' }
|
118
|
+
|
119
|
+
it { is_expected.to eq('20') }
|
120
|
+
end
|
121
|
+
|
122
|
+
context 'with numeric characters' do
|
123
|
+
let(:bank_code) { '12244' }
|
124
|
+
let(:branch_code) { '36767' }
|
125
|
+
let(:account_number) { '12345678912' }
|
126
|
+
|
127
|
+
it { is_expected.to eq('20') }
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,853 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ibandit::IBANBuilder do
|
4
|
+
shared_examples_for 'allows round trips' do |iban_code|
|
5
|
+
let(:iban) { Ibandit::IBAN.new(iban_code) }
|
6
|
+
let(:args) do
|
7
|
+
{
|
8
|
+
country_code: iban.country_code,
|
9
|
+
account_number: iban.account_number,
|
10
|
+
branch_code: iban.branch_code,
|
11
|
+
bank_code: iban.bank_code
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'successfully reconstructs the IBAN' do
|
16
|
+
expect(described_class.build(args).iban).to eq(iban.iban)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '.build' do
|
21
|
+
subject(:build) { described_class.build(args) }
|
22
|
+
let(:args) { { country_code: 'ES' } }
|
23
|
+
|
24
|
+
context 'without a country_code' do
|
25
|
+
let(:args) { { bank_code: 1 } }
|
26
|
+
|
27
|
+
it 'raises a helpful error message' do
|
28
|
+
expect { build }.to raise_error(ArgumentError, /provide a country_code/)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'with an unsupported country_code' do
|
33
|
+
let(:args) { { country_code: 'FU' } }
|
34
|
+
|
35
|
+
it 'raises a helpful error message' do
|
36
|
+
expect { build }.to raise_error(Ibandit::UnsupportedCountryError)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'with AT as the country_code' do
|
41
|
+
let(:args) do
|
42
|
+
{
|
43
|
+
country_code: 'AT',
|
44
|
+
account_number: '00234573201',
|
45
|
+
bank_code: '19043'
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
its(:iban) { is_expected.to eq('AT611904300234573201') }
|
50
|
+
|
51
|
+
it_behaves_like 'allows round trips', 'AT61 1904 3002 3457 3201'
|
52
|
+
|
53
|
+
context "with an account number that hasn't been zero-padded" do
|
54
|
+
before { args[:account_number] = '234573201' }
|
55
|
+
its(:iban) { is_expected.to eq('AT611904300234573201') }
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'without an account_number' do
|
59
|
+
before { args.delete(:account_number) }
|
60
|
+
|
61
|
+
it 'raises a helpful error message' do
|
62
|
+
expect { build }.
|
63
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'without an bank_code' do
|
68
|
+
before { args.delete(:bank_code) }
|
69
|
+
|
70
|
+
it 'raises a helpful error message' do
|
71
|
+
expect { build }.
|
72
|
+
to raise_error(ArgumentError, /bank_code is a required field/)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'with BE as the country_code' do
|
78
|
+
let(:args) { { country_code: 'BE', account_number: '510007547061' } }
|
79
|
+
|
80
|
+
its(:iban) { is_expected.to eq('BE62510007547061') }
|
81
|
+
|
82
|
+
it_behaves_like 'allows round trips', 'BE62 5100 0754 7061'
|
83
|
+
|
84
|
+
context 'with dashes' do
|
85
|
+
before { args[:account_number] = '510-0075470-61' }
|
86
|
+
its(:iban) { is_expected.to eq('BE62510007547061') }
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'without an account_number' do
|
90
|
+
before { args.delete(:account_number) }
|
91
|
+
|
92
|
+
it 'raises a helpful error message' do
|
93
|
+
expect { build }.
|
94
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'with CY as the country_code' do
|
100
|
+
let(:args) do
|
101
|
+
{
|
102
|
+
country_code: 'CY',
|
103
|
+
account_number: '0000001200527600',
|
104
|
+
bank_code: '002',
|
105
|
+
branch_code: '00128'
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
its(:iban) { is_expected.to eq('CY17002001280000001200527600') }
|
110
|
+
|
111
|
+
it_behaves_like 'allows round trips', 'CY17 0020 0128 0000 0012 0052 7600'
|
112
|
+
|
113
|
+
context "with an account number that hasn't been zero-padded" do
|
114
|
+
before { args[:account_number] = '1200527600' }
|
115
|
+
its(:iban) { is_expected.to eq('CY17002001280000001200527600') }
|
116
|
+
end
|
117
|
+
|
118
|
+
context 'without an branch_code' do
|
119
|
+
before { args.delete(:branch_code) }
|
120
|
+
its(:iban) { is_expected.to eq('CY040020000001200527600') }
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'without an account_number' do
|
124
|
+
before { args.delete(:account_number) }
|
125
|
+
|
126
|
+
it 'raises a helpful error message' do
|
127
|
+
expect { build }.
|
128
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context 'without an bank_code' do
|
133
|
+
before { args.delete(:bank_code) }
|
134
|
+
|
135
|
+
it 'raises a helpful error message' do
|
136
|
+
expect { build }.
|
137
|
+
to raise_error(ArgumentError, /bank_code is a required field/)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'with DE as the country_code' do
|
143
|
+
let(:args) do
|
144
|
+
{ country_code: 'DE',
|
145
|
+
bank_code: '37040044',
|
146
|
+
account_number: '0532013000' }
|
147
|
+
end
|
148
|
+
|
149
|
+
its(:iban) { is_expected.to eq('DE89370400440532013000') }
|
150
|
+
|
151
|
+
it_behaves_like 'allows round trips', 'DE89 3704 0044 0532 0130 00'
|
152
|
+
|
153
|
+
context 'without a bank_code' do
|
154
|
+
before { args.delete(:bank_code) }
|
155
|
+
|
156
|
+
specify do
|
157
|
+
expect { build }.
|
158
|
+
to raise_error(ArgumentError, /bank_code is a required field/)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context 'without an account_number' do
|
163
|
+
before { args.delete(:account_number) }
|
164
|
+
|
165
|
+
specify do
|
166
|
+
expect { build }.
|
167
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context 'with EE as the country_code' do
|
173
|
+
let(:args) { { country_code: 'EE', account_number: '0221020145685' } }
|
174
|
+
|
175
|
+
its(:iban) { is_expected.to eq('EE382200221020145685') }
|
176
|
+
|
177
|
+
it_behaves_like 'allows round trips', 'EE38 2200 2210 2014 5685'
|
178
|
+
|
179
|
+
context 'with an account number that needs translating' do
|
180
|
+
before { args[:account_number] = '111020145685' }
|
181
|
+
its(:iban) { is_expected.to eq('EE412200111020145685') }
|
182
|
+
end
|
183
|
+
|
184
|
+
context 'without an account_number' do
|
185
|
+
before { args.delete(:account_number) }
|
186
|
+
|
187
|
+
it 'raises a helpful error message' do
|
188
|
+
expect { build }.
|
189
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
context 'with ES as the country_code' do
|
195
|
+
let(:args) do
|
196
|
+
{
|
197
|
+
country_code: 'ES',
|
198
|
+
bank_code: '2310',
|
199
|
+
branch_code: '0001',
|
200
|
+
account_number: '180000012345'
|
201
|
+
}
|
202
|
+
end
|
203
|
+
|
204
|
+
its(:iban) { is_expected.to eq('ES8023100001180000012345') }
|
205
|
+
|
206
|
+
it_behaves_like 'allows round trips', 'ES80 2310 0001 1800 0001 2345'
|
207
|
+
|
208
|
+
context 'without a bank_code or branch code' do
|
209
|
+
before { args.delete(:bank_code) }
|
210
|
+
before { args.delete(:branch_code) }
|
211
|
+
before { args[:account_number] = '23100001180000012345' }
|
212
|
+
|
213
|
+
its(:iban) { is_expected.to eq('ES8023100001180000012345') }
|
214
|
+
end
|
215
|
+
|
216
|
+
context 'without an account_number' do
|
217
|
+
before { args.delete(:account_number) }
|
218
|
+
|
219
|
+
it 'raises a helpful error message' do
|
220
|
+
expect { build }.
|
221
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
context 'with FI as the country_code' do
|
227
|
+
let(:args) do
|
228
|
+
{ country_code: 'FI', bank_code: '123456', account_number: '785' }
|
229
|
+
end
|
230
|
+
|
231
|
+
its(:iban) { is_expected.to eq('FI2112345600000785') }
|
232
|
+
|
233
|
+
it_behaves_like 'allows round trips', 'FI21 1234 5600 0007 85'
|
234
|
+
|
235
|
+
context 'with a savings bank account_number in traditional format' do
|
236
|
+
before { args[:account_number] = '78510' }
|
237
|
+
before { args[:bank_code] = '423456' }
|
238
|
+
|
239
|
+
its(:iban) { is_expected.to eq('FI3442345670008510') }
|
240
|
+
end
|
241
|
+
|
242
|
+
context 'without an account_number' do
|
243
|
+
before { args.delete(:account_number) }
|
244
|
+
|
245
|
+
it 'raises a helpful error message' do
|
246
|
+
expect { build }.
|
247
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
context 'without a bank_code' do
|
252
|
+
before { args.delete(:bank_code) }
|
253
|
+
|
254
|
+
it 'raises a helpful error message' do
|
255
|
+
expect { build }.
|
256
|
+
to raise_error(ArgumentError, /bank_code is a required field/)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
context 'with FR as the country_code' do
|
262
|
+
let(:args) do
|
263
|
+
{
|
264
|
+
country_code: 'FR',
|
265
|
+
bank_code: '20041',
|
266
|
+
branch_code: '01005',
|
267
|
+
account_number: '0500013M02606'
|
268
|
+
}
|
269
|
+
end
|
270
|
+
|
271
|
+
its(:iban) { is_expected.to eq('FR1420041010050500013M02606') }
|
272
|
+
|
273
|
+
it_behaves_like 'allows round trips', 'FR14 2004 1010 0505 0001 3M02 606'
|
274
|
+
|
275
|
+
context 'without the rib key in the account number' do
|
276
|
+
before { args[:account_number] = '0500013M026' }
|
277
|
+
its(:valid?) { is_expected.to be_falsey }
|
278
|
+
end
|
279
|
+
|
280
|
+
context 'without a bank_code' do
|
281
|
+
before { args.delete(:bank_code) }
|
282
|
+
|
283
|
+
it 'raises a helpful error message' do
|
284
|
+
expect { build }.
|
285
|
+
to raise_error(ArgumentError, /bank_code is a required field/)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
context 'without a branch_code' do
|
290
|
+
before { args.delete(:branch_code) }
|
291
|
+
|
292
|
+
it 'raises a helpful error message' do
|
293
|
+
expect { build }.
|
294
|
+
to raise_error(ArgumentError, /branch_code is a required field/)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
context 'without an account_number' do
|
299
|
+
before { args.delete(:account_number) }
|
300
|
+
|
301
|
+
it 'raises a helpful error message' do
|
302
|
+
expect { build }.
|
303
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
context 'with GB as the country_code' do
|
309
|
+
let(:args) do
|
310
|
+
{ country_code: 'GB',
|
311
|
+
bank_code: 'BARC',
|
312
|
+
branch_code: '200000',
|
313
|
+
account_number: '579135' }
|
314
|
+
end
|
315
|
+
|
316
|
+
its(:iban) { is_expected.to eq('GB07BARC20000000579135') }
|
317
|
+
|
318
|
+
it_behaves_like 'allows round trips', 'GB07 BARC 2000 0000 5791 35'
|
319
|
+
|
320
|
+
context 'when the sort code is hyphenated' do
|
321
|
+
before { args[:branch_code] = '20-00-00' }
|
322
|
+
its(:iban) { is_expected.to eq('GB07BARC20000000579135') }
|
323
|
+
end
|
324
|
+
|
325
|
+
context 'when the sort code is spaced' do
|
326
|
+
before { args[:branch_code] = '20 00 00' }
|
327
|
+
its(:iban) { is_expected.to eq('GB07BARC20000000579135') }
|
328
|
+
end
|
329
|
+
|
330
|
+
context 'when the account number is spaced' do
|
331
|
+
before { args[:account_number] = '579 135' }
|
332
|
+
its(:iban) { is_expected.to eq('GB07BARC20000000579135') }
|
333
|
+
end
|
334
|
+
|
335
|
+
context 'when the account number is hyphenated' do
|
336
|
+
before { args[:account_number] = '5577-9911' }
|
337
|
+
its(:iban) { is_expected.to eq('GB60BARC20000055779911') }
|
338
|
+
end
|
339
|
+
|
340
|
+
context 'with the bank_code supplied manually' do
|
341
|
+
before { args.merge!(bank_code: 'BARC') }
|
342
|
+
its(:iban) { is_expected.to eq('GB07BARC20000000579135') }
|
343
|
+
end
|
344
|
+
|
345
|
+
context 'without a branch_code' do
|
346
|
+
before { args.delete(:branch_code) }
|
347
|
+
|
348
|
+
specify do
|
349
|
+
expect { build }.
|
350
|
+
to raise_error(ArgumentError, /branch_code is a required field/)
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
context 'without an account_number' do
|
355
|
+
before { args.delete(:account_number) }
|
356
|
+
|
357
|
+
specify do
|
358
|
+
expect { build }.
|
359
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
context 'without a bank_code' do
|
364
|
+
before { args.delete(:bank_code) }
|
365
|
+
|
366
|
+
context 'when a bic_finder is not defined' do
|
367
|
+
specify do
|
368
|
+
expect { build }.
|
369
|
+
to raise_error(ArgumentError, /bank_code is a required field/)
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
context 'with a bic_finder' do
|
374
|
+
let(:bic_finder) { double }
|
375
|
+
before do
|
376
|
+
allow(bic_finder).to receive(:find).with('GB', '200000').
|
377
|
+
and_return('BARCGB22XXX')
|
378
|
+
Ibandit.bic_finder = ->(cc, id) { bic_finder.find(cc, id) }
|
379
|
+
end
|
380
|
+
after { Ibandit.bic_finder = nil }
|
381
|
+
|
382
|
+
its(:iban) { is_expected.to eq('GB07BARC20000000579135') }
|
383
|
+
|
384
|
+
context "when the BIC can't be found" do
|
385
|
+
before { Ibandit.bic_finder = ->(_cc, _id) { nil } }
|
386
|
+
|
387
|
+
it 'raises an Ibandit::BicNotFoundError' do
|
388
|
+
expect { build }.to raise_error(Ibandit::BicNotFoundError)
|
389
|
+
end
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
context 'with both a bank_code and a bic_finder' do
|
395
|
+
let(:bic_finder) { double }
|
396
|
+
before do
|
397
|
+
allow(bic_finder).to receive(:find).with('GB', '200000').
|
398
|
+
and_return('BANKGB22XXX')
|
399
|
+
Ibandit.bic_finder = ->(cc, id) { bic_finder.find(cc, id) }
|
400
|
+
end
|
401
|
+
after { Ibandit.bic_finder = nil }
|
402
|
+
|
403
|
+
it 'uses the explicitly provided bank_code' do
|
404
|
+
expect(subject.iban).to eq('GB07BARC20000000579135')
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
context 'with IE as the country_code' do
|
410
|
+
let(:args) do
|
411
|
+
{ country_code: 'IE',
|
412
|
+
bank_code: 'AIBK',
|
413
|
+
branch_code: '931152',
|
414
|
+
account_number: '12345678' }
|
415
|
+
end
|
416
|
+
|
417
|
+
its(:iban) { is_expected.to eq('IE29AIBK93115212345678') }
|
418
|
+
|
419
|
+
it_behaves_like 'allows round trips', 'IE29 AIBK 9311 5212 3456 78'
|
420
|
+
|
421
|
+
context 'with hyphens in the sort code' do
|
422
|
+
before { args[:branch_code] = '93-11-52' }
|
423
|
+
its(:iban) { is_expected.to eq('IE29AIBK93115212345678') }
|
424
|
+
end
|
425
|
+
|
426
|
+
context 'without a branch_code' do
|
427
|
+
before { args.delete(:branch_code) }
|
428
|
+
|
429
|
+
it 'raises a helpful error message' do
|
430
|
+
expect { build }.
|
431
|
+
to raise_error(ArgumentError, /branch_code is a required field/)
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
context 'without an account_number' do
|
436
|
+
before { args.delete(:account_number) }
|
437
|
+
|
438
|
+
it 'raises a helpful error message' do
|
439
|
+
expect { build }.
|
440
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
context 'without a bank_code' do
|
445
|
+
before { args.delete(:bank_code) }
|
446
|
+
|
447
|
+
context 'when a bic_finder is not defined' do
|
448
|
+
specify do
|
449
|
+
expect { build }.
|
450
|
+
to raise_error(ArgumentError, /bank_code is a required field/)
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
context 'with a bic_finder' do
|
455
|
+
let(:bic_finder) { double }
|
456
|
+
before do
|
457
|
+
allow(bic_finder).to receive(:find).with('IE', '931152').
|
458
|
+
and_return('AIBK1234XXX')
|
459
|
+
Ibandit.bic_finder = ->(cc, id) { bic_finder.find(cc, id) }
|
460
|
+
end
|
461
|
+
after { Ibandit.bic_finder = nil }
|
462
|
+
|
463
|
+
its(:iban) { is_expected.to eq('IE29AIBK93115212345678') }
|
464
|
+
|
465
|
+
context "when the BIC can't be found" do
|
466
|
+
before { Ibandit.bic_finder = ->(_cc, _id) { nil } }
|
467
|
+
|
468
|
+
it 'raises an Ibandit::BicNotFoundError' do
|
469
|
+
expect { build }.to raise_error(Ibandit::BicNotFoundError)
|
470
|
+
end
|
471
|
+
end
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
context 'with both a bank_code and a bic_finder' do
|
476
|
+
let(:bic_finder) { double }
|
477
|
+
before do
|
478
|
+
allow(bic_finder).to receive(:find).with('IE', '931152').
|
479
|
+
and_return('BANK1234XXX')
|
480
|
+
Ibandit.bic_finder = ->(cc, id) { bic_finder.find(cc, id) }
|
481
|
+
end
|
482
|
+
after { Ibandit.bic_finder = nil }
|
483
|
+
|
484
|
+
it 'uses the explicitly provided bank_code' do
|
485
|
+
expect(subject.iban).to eq('IE29AIBK93115212345678')
|
486
|
+
end
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
context 'with IT as the country_code' do
|
491
|
+
let(:args) do
|
492
|
+
{
|
493
|
+
country_code: 'IT',
|
494
|
+
bank_code: '05428',
|
495
|
+
branch_code: '11101',
|
496
|
+
account_number: '0000123456'
|
497
|
+
}
|
498
|
+
end
|
499
|
+
|
500
|
+
its(:iban) { is_expected.to eq('IT60X0542811101000000123456') }
|
501
|
+
|
502
|
+
it_behaves_like 'allows round trips', 'IT60 X054 2811 1010 0000 0123 456'
|
503
|
+
|
504
|
+
context 'with an explicitly passed check digit' do
|
505
|
+
before { args[:check_digit] = 'Y' }
|
506
|
+
its(:iban) { is_expected.to eq('IT64Y0542811101000000123456') }
|
507
|
+
end
|
508
|
+
|
509
|
+
context 'without a bank_code' do
|
510
|
+
before { args.delete(:bank_code) }
|
511
|
+
|
512
|
+
it 'raises a helpful error message' do
|
513
|
+
expect { build }.
|
514
|
+
to raise_error(ArgumentError, /bank_code is a required field/)
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
context 'without a branch_code' do
|
519
|
+
before { args.delete(:branch_code) }
|
520
|
+
|
521
|
+
it 'raises a helpful error message' do
|
522
|
+
expect { build }.
|
523
|
+
to raise_error(ArgumentError, /branch_code is a required field/)
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
527
|
+
context 'without an account_number' do
|
528
|
+
before { args.delete(:account_number) }
|
529
|
+
|
530
|
+
it 'raises a helpful error message' do
|
531
|
+
expect { build }.
|
532
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
533
|
+
end
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
context 'with LU as the country_code' do
|
538
|
+
let(:args) do
|
539
|
+
{
|
540
|
+
country_code: 'LU',
|
541
|
+
account_number: '9400644750000',
|
542
|
+
bank_code: '001'
|
543
|
+
}
|
544
|
+
end
|
545
|
+
|
546
|
+
its(:iban) { is_expected.to eq('LU280019400644750000') }
|
547
|
+
|
548
|
+
it_behaves_like 'allows round trips', 'LU28 0019 4006 4475 0000'
|
549
|
+
|
550
|
+
context 'without an account_number' do
|
551
|
+
before { args.delete(:account_number) }
|
552
|
+
|
553
|
+
it 'raises a helpful error message' do
|
554
|
+
expect { build }.
|
555
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
556
|
+
end
|
557
|
+
end
|
558
|
+
|
559
|
+
context 'without a bank_code' do
|
560
|
+
before { args.delete(:bank_code) }
|
561
|
+
|
562
|
+
it 'raises a helpful error message' do
|
563
|
+
expect { build }.
|
564
|
+
to raise_error(ArgumentError, /bank_code is a required field/)
|
565
|
+
end
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
569
|
+
context 'with LV as the country_code' do
|
570
|
+
let(:args) do
|
571
|
+
{
|
572
|
+
country_code: 'LV',
|
573
|
+
account_number: '1234567890123',
|
574
|
+
bank_code: 'BANK'
|
575
|
+
}
|
576
|
+
end
|
577
|
+
|
578
|
+
its(:iban) { is_expected.to eq('LV72BANK1234567890123') }
|
579
|
+
|
580
|
+
it_behaves_like 'allows round trips', 'LV72 BANK 1234 5678 9012 3'
|
581
|
+
|
582
|
+
context 'without an account_number' do
|
583
|
+
before { args.delete(:account_number) }
|
584
|
+
|
585
|
+
it 'raises a helpful error message' do
|
586
|
+
expect { build }.
|
587
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
588
|
+
end
|
589
|
+
end
|
590
|
+
|
591
|
+
context 'without a bank_code' do
|
592
|
+
before { args.delete(:bank_code) }
|
593
|
+
|
594
|
+
it 'raises a helpful error message' do
|
595
|
+
expect { build }.
|
596
|
+
to raise_error(ArgumentError, /bank_code is a required field/)
|
597
|
+
end
|
598
|
+
end
|
599
|
+
end
|
600
|
+
|
601
|
+
context 'with MC as the country_code' do
|
602
|
+
let(:args) do
|
603
|
+
{
|
604
|
+
country_code: 'MC',
|
605
|
+
bank_code: '20041',
|
606
|
+
branch_code: '01005',
|
607
|
+
account_number: '0500013M02606'
|
608
|
+
}
|
609
|
+
end
|
610
|
+
|
611
|
+
its(:iban) { is_expected.to eq('MC9320041010050500013M02606') }
|
612
|
+
|
613
|
+
it_behaves_like 'allows round trips', 'MC93 2004 1010 0505 0001 3M02 606'
|
614
|
+
|
615
|
+
context 'without the rib key in the account number' do
|
616
|
+
before { args[:account_number] = '0500013M026' }
|
617
|
+
its(:valid?) { is_expected.to be_falsey }
|
618
|
+
end
|
619
|
+
|
620
|
+
context 'without a bank_code' do
|
621
|
+
before { args.delete(:bank_code) }
|
622
|
+
|
623
|
+
it 'raises a helpful error message' do
|
624
|
+
expect { build }.
|
625
|
+
to raise_error(ArgumentError, /bank_code is a required field/)
|
626
|
+
end
|
627
|
+
end
|
628
|
+
|
629
|
+
context 'without a branch_code' do
|
630
|
+
before { args.delete(:branch_code) }
|
631
|
+
|
632
|
+
it 'raises a helpful error message' do
|
633
|
+
expect { build }.
|
634
|
+
to raise_error(ArgumentError, /branch_code is a required field/)
|
635
|
+
end
|
636
|
+
end
|
637
|
+
|
638
|
+
context 'without an account_number' do
|
639
|
+
before { args.delete(:account_number) }
|
640
|
+
|
641
|
+
it 'raises a helpful error message' do
|
642
|
+
expect { build }.
|
643
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
644
|
+
end
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
648
|
+
context 'with NL as the country_code' do
|
649
|
+
let(:args) do
|
650
|
+
{
|
651
|
+
country_code: 'NL',
|
652
|
+
account_number: '0417164300',
|
653
|
+
bank_code: 'ABNA'
|
654
|
+
}
|
655
|
+
end
|
656
|
+
|
657
|
+
its(:iban) { is_expected.to eq('NL91ABNA0417164300') }
|
658
|
+
|
659
|
+
it_behaves_like 'allows round trips', 'NL91 ABNA 0417 1643 00'
|
660
|
+
|
661
|
+
context "with an account number that hasn't been zero-padded" do
|
662
|
+
before { args[:account_number] = '417164300' }
|
663
|
+
its(:iban) { is_expected.to eq('NL91ABNA0417164300') }
|
664
|
+
end
|
665
|
+
|
666
|
+
context 'without an account_number' do
|
667
|
+
before { args.delete(:account_number) }
|
668
|
+
|
669
|
+
it 'raises a helpful error message' do
|
670
|
+
expect { build }.
|
671
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
672
|
+
end
|
673
|
+
end
|
674
|
+
|
675
|
+
context 'without an bank_code' do
|
676
|
+
before { args.delete(:bank_code) }
|
677
|
+
|
678
|
+
it 'raises a helpful error message' do
|
679
|
+
expect { build }.
|
680
|
+
to raise_error(ArgumentError, /bank_code is a required field/)
|
681
|
+
end
|
682
|
+
end
|
683
|
+
end
|
684
|
+
|
685
|
+
context 'with PT as the country_code' do
|
686
|
+
let(:args) do
|
687
|
+
{
|
688
|
+
country_code: 'PT',
|
689
|
+
bank_code: '0002',
|
690
|
+
branch_code: '0023',
|
691
|
+
account_number: '0023843000578'
|
692
|
+
}
|
693
|
+
end
|
694
|
+
|
695
|
+
its(:iban) { is_expected.to eq('PT50000200230023843000578') }
|
696
|
+
|
697
|
+
it_behaves_like 'allows round trips', 'PT50 0002 0023 0023 8430 0057 8'
|
698
|
+
|
699
|
+
context 'without a bank_code' do
|
700
|
+
before { args.delete(:bank_code) }
|
701
|
+
|
702
|
+
it 'raises a helpful error message' do
|
703
|
+
expect { build }.
|
704
|
+
to raise_error(ArgumentError, /bank_code is a required field/)
|
705
|
+
end
|
706
|
+
end
|
707
|
+
|
708
|
+
context 'without a branch_code' do
|
709
|
+
before { args.delete(:branch_code) }
|
710
|
+
|
711
|
+
it 'raises a helpful error message' do
|
712
|
+
expect { build }.
|
713
|
+
to raise_error(ArgumentError, /branch_code is a required field/)
|
714
|
+
end
|
715
|
+
end
|
716
|
+
|
717
|
+
context 'without an account_number' do
|
718
|
+
before { args.delete(:account_number) }
|
719
|
+
|
720
|
+
it 'raises a helpful error message' do
|
721
|
+
expect { build }.
|
722
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
723
|
+
end
|
724
|
+
end
|
725
|
+
end
|
726
|
+
|
727
|
+
context 'with SI as the country_code' do
|
728
|
+
let(:args) do
|
729
|
+
{
|
730
|
+
country_code: 'SI',
|
731
|
+
bank_code: '19100',
|
732
|
+
account_number: '0000123438'
|
733
|
+
}
|
734
|
+
end
|
735
|
+
|
736
|
+
its(:iban) { is_expected.to eq('SI56191000000123438') }
|
737
|
+
|
738
|
+
it_behaves_like 'allows round trips', 'SI56 1910 0000 0123 438'
|
739
|
+
|
740
|
+
context 'with an account number that needs padding' do
|
741
|
+
before { args[:account_number] = '123438' }
|
742
|
+
its(:iban) { is_expected.to eq('SI56191000000123438') }
|
743
|
+
end
|
744
|
+
|
745
|
+
context 'without a bank_code' do
|
746
|
+
before { args.delete(:bank_code) }
|
747
|
+
|
748
|
+
it 'raises a helpful error message' do
|
749
|
+
expect { build }.
|
750
|
+
to raise_error(ArgumentError, /bank_code is a required field/)
|
751
|
+
end
|
752
|
+
end
|
753
|
+
|
754
|
+
context 'without an account_number' do
|
755
|
+
before { args.delete(:account_number) }
|
756
|
+
|
757
|
+
it 'raises a helpful error message' do
|
758
|
+
expect { build }.
|
759
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
760
|
+
end
|
761
|
+
end
|
762
|
+
end
|
763
|
+
|
764
|
+
context 'with SK as the country_code' do
|
765
|
+
let(:args) do
|
766
|
+
{
|
767
|
+
country_code: 'SK',
|
768
|
+
bank_code: '1200',
|
769
|
+
account_number_prefix: '000019',
|
770
|
+
account_number: '8742637541'
|
771
|
+
}
|
772
|
+
end
|
773
|
+
|
774
|
+
its(:iban) { is_expected.to eq('SK3112000000198742637541') }
|
775
|
+
|
776
|
+
it_behaves_like 'allows round trips', 'SK31 1200 0000 1987 4263 7541'
|
777
|
+
|
778
|
+
context 'with an account number prefix that needs padding' do
|
779
|
+
before { args[:account_number_prefix] = '19' }
|
780
|
+
its(:iban) { is_expected.to eq('SK3112000000198742637541') }
|
781
|
+
end
|
782
|
+
|
783
|
+
context 'without a bank_code' do
|
784
|
+
before { args.delete(:bank_code) }
|
785
|
+
|
786
|
+
it 'raises a helpful error message' do
|
787
|
+
expect { build }.
|
788
|
+
to raise_error(ArgumentError, /bank_code is a required field/)
|
789
|
+
end
|
790
|
+
end
|
791
|
+
|
792
|
+
context 'without an account_number' do
|
793
|
+
before { args.delete(:account_number) }
|
794
|
+
|
795
|
+
it 'raises a helpful error message' do
|
796
|
+
expect { build }.
|
797
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
798
|
+
end
|
799
|
+
end
|
800
|
+
|
801
|
+
context 'without an account_number_prefix' do
|
802
|
+
before { args.delete(:account_number) }
|
803
|
+
|
804
|
+
it 'raises a helpful error message' do
|
805
|
+
expect { build }.
|
806
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
807
|
+
end
|
808
|
+
end
|
809
|
+
end
|
810
|
+
|
811
|
+
context 'with SM as the country_code' do
|
812
|
+
let(:args) do
|
813
|
+
{
|
814
|
+
country_code: 'SM',
|
815
|
+
bank_code: '05428',
|
816
|
+
branch_code: '11101',
|
817
|
+
account_number: '000000123456'
|
818
|
+
}
|
819
|
+
end
|
820
|
+
|
821
|
+
its(:iban) { is_expected.to eq('SM88X0542811101000000123456') }
|
822
|
+
|
823
|
+
it_behaves_like 'allows round trips', 'SM88 X054 2811 1010 0000 0123 456'
|
824
|
+
|
825
|
+
context 'without a bank_code' do
|
826
|
+
before { args.delete(:bank_code) }
|
827
|
+
|
828
|
+
it 'raises a helpful error message' do
|
829
|
+
expect { build }.
|
830
|
+
to raise_error(ArgumentError, /bank_code is a required field/)
|
831
|
+
end
|
832
|
+
end
|
833
|
+
|
834
|
+
context 'without a branch_code' do
|
835
|
+
before { args.delete(:branch_code) }
|
836
|
+
|
837
|
+
it 'raises a helpful error message' do
|
838
|
+
expect { build }.
|
839
|
+
to raise_error(ArgumentError, /branch_code is a required field/)
|
840
|
+
end
|
841
|
+
end
|
842
|
+
|
843
|
+
context 'without an account_number' do
|
844
|
+
before { args.delete(:account_number) }
|
845
|
+
|
846
|
+
it 'raises a helpful error message' do
|
847
|
+
expect { build }.
|
848
|
+
to raise_error(ArgumentError, /account_number is a required field/)
|
849
|
+
end
|
850
|
+
end
|
851
|
+
end
|
852
|
+
end
|
853
|
+
end
|