ibandit 0.2.1 → 0.3.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 +4 -4
- data/CHANGELOG.md +10 -3
- data/README.md +3 -0
- data/bin/build_structure_file.rb +41 -5
- data/data/raw/structure_additions.yml +43 -0
- data/data/structures.yml +157 -0
- data/ibandit.gemspec +1 -1
- data/lib/ibandit/iban.rb +147 -60
- data/lib/ibandit/iban_assembler.rb +117 -0
- data/lib/ibandit/iban_splitter.rb +66 -0
- data/lib/ibandit/local_details_cleaner.rb +298 -0
- data/lib/ibandit/version.rb +1 -1
- data/lib/ibandit.rb +9 -1
- data/spec/ibandit/iban_assembler_spec.rb +567 -0
- data/spec/ibandit/iban_spec.rb +294 -13
- data/spec/ibandit/iban_splitter_spec.rb +41 -0
- data/spec/ibandit/local_details_cleaner_spec.rb +688 -0
- metadata +10 -6
- data/lib/ibandit/iban_builder.rb +0 -539
- data/spec/ibandit/iban_builder_spec.rb +0 -892
@@ -0,0 +1,567 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ibandit::IBANAssembler 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
|
+
}.reject { |_key, value| value.nil? }
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'successfully reconstructs the IBAN' do
|
16
|
+
expect(described_class.assemble(args)).to eq(iban.iban)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '.assemble' do
|
21
|
+
subject(:assemble) { described_class.assemble(args) }
|
22
|
+
let(:args) { { country_code: 'ES' } }
|
23
|
+
|
24
|
+
context 'without a country_code' do
|
25
|
+
let(:args) { { bank_code: 1 } }
|
26
|
+
it { is_expected.to be_nil }
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with an unsupported country_code' do
|
30
|
+
let(:args) { { country_code: 'FU' } }
|
31
|
+
it { is_expected.to be_nil }
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'with AT as the country_code' do
|
35
|
+
let(:args) do
|
36
|
+
{
|
37
|
+
country_code: 'AT',
|
38
|
+
account_number: '00234573201',
|
39
|
+
bank_code: '19043'
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
it { is_expected.to eq('AT611904300234573201') }
|
44
|
+
|
45
|
+
it_behaves_like 'allows round trips', 'AT61 1904 3002 3457 3201'
|
46
|
+
|
47
|
+
context 'without an account_number' do
|
48
|
+
before { args.delete(:account_number) }
|
49
|
+
it { is_expected.to be_nil }
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'without an bank_code' do
|
53
|
+
before { args.delete(:bank_code) }
|
54
|
+
it { is_expected.to be_nil }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'with BE as the country_code' do
|
59
|
+
let(:args) { { country_code: 'BE', account_number: '510007547061' } }
|
60
|
+
|
61
|
+
it { is_expected.to eq('BE62510007547061') }
|
62
|
+
|
63
|
+
it_behaves_like 'allows round trips', 'BE62 5100 0754 7061'
|
64
|
+
|
65
|
+
context 'without an account_number' do
|
66
|
+
before { args.delete(:account_number) }
|
67
|
+
it { is_expected.to be_nil }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'with CY as the country_code' do
|
72
|
+
let(:args) do
|
73
|
+
{
|
74
|
+
country_code: 'CY',
|
75
|
+
account_number: '0000001200527600',
|
76
|
+
bank_code: '002',
|
77
|
+
branch_code: '00128'
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
it { is_expected.to eq('CY17002001280000001200527600') }
|
82
|
+
|
83
|
+
it_behaves_like 'allows round trips', 'CY17 0020 0128 0000 0012 0052 7600'
|
84
|
+
|
85
|
+
context 'without an branch_code' do
|
86
|
+
before { args.delete(:branch_code) }
|
87
|
+
it { is_expected.to eq('CY040020000001200527600') }
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'without an account_number' do
|
91
|
+
before { args.delete(:account_number) }
|
92
|
+
it { is_expected.to be_nil }
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'without an bank_code' do
|
96
|
+
before { args.delete(:bank_code) }
|
97
|
+
it { is_expected.to be_nil }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'with DE as the country_code' do
|
102
|
+
let(:args) do
|
103
|
+
{ country_code: 'DE',
|
104
|
+
bank_code: '37040044',
|
105
|
+
account_number: '0532013000' }
|
106
|
+
end
|
107
|
+
|
108
|
+
it { is_expected.to eq('DE89370400440532013000') }
|
109
|
+
|
110
|
+
it_behaves_like 'allows round trips', 'DE89 3704 0044 0532 0130 00'
|
111
|
+
|
112
|
+
context 'without a bank_code' do
|
113
|
+
before { args.delete(:bank_code) }
|
114
|
+
it { is_expected.to be_nil }
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'without an account_number' do
|
118
|
+
before { args.delete(:account_number) }
|
119
|
+
it { is_expected.to be_nil }
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'with EE as the country_code' do
|
124
|
+
let(:args) do
|
125
|
+
{
|
126
|
+
country_code: 'EE',
|
127
|
+
bank_code: '22',
|
128
|
+
account_number: '00221020145685'
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
it { is_expected.to eq('EE382200221020145685') }
|
133
|
+
|
134
|
+
it_behaves_like 'allows round trips', 'EE38 2200 2210 2014 5685'
|
135
|
+
|
136
|
+
context 'without an account_number' do
|
137
|
+
before { args.delete(:account_number) }
|
138
|
+
it { is_expected.to be_nil }
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'with ES as the country_code' do
|
143
|
+
let(:args) do
|
144
|
+
{
|
145
|
+
country_code: 'ES',
|
146
|
+
bank_code: '2310',
|
147
|
+
branch_code: '0001',
|
148
|
+
account_number: '180000012345'
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
152
|
+
it { is_expected.to eq('ES8023100001180000012345') }
|
153
|
+
|
154
|
+
it_behaves_like 'allows round trips', 'ES80 2310 0001 1800 0001 2345'
|
155
|
+
|
156
|
+
context 'without a bank_code or branch code' do
|
157
|
+
before { args.delete(:bank_code) }
|
158
|
+
before { args.delete(:branch_code) }
|
159
|
+
before { args[:account_number] = '23100001180000012345' }
|
160
|
+
|
161
|
+
it { is_expected.to be_nil }
|
162
|
+
end
|
163
|
+
|
164
|
+
context 'without an account_number' do
|
165
|
+
before { args.delete(:account_number) }
|
166
|
+
it { is_expected.to be_nil }
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context 'with FI as the country_code' do
|
171
|
+
let(:args) do
|
172
|
+
{ country_code: 'FI', bank_code: '123456', account_number: '00000785' }
|
173
|
+
end
|
174
|
+
|
175
|
+
it { is_expected.to eq('FI2112345600000785') }
|
176
|
+
|
177
|
+
it_behaves_like 'allows round trips', 'FI21 1234 5600 0007 85'
|
178
|
+
|
179
|
+
context 'without an account_number' do
|
180
|
+
before { args.delete(:account_number) }
|
181
|
+
it { is_expected.to be_nil }
|
182
|
+
end
|
183
|
+
|
184
|
+
context 'without a bank_code' do
|
185
|
+
before { args.delete(:bank_code) }
|
186
|
+
it { is_expected.to be_nil }
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
context 'with FR as the country_code' do
|
191
|
+
let(:args) do
|
192
|
+
{
|
193
|
+
country_code: 'FR',
|
194
|
+
bank_code: '20041',
|
195
|
+
branch_code: '01005',
|
196
|
+
account_number: '0500013M02606'
|
197
|
+
}
|
198
|
+
end
|
199
|
+
|
200
|
+
it { is_expected.to eq('FR1420041010050500013M02606') }
|
201
|
+
|
202
|
+
it_behaves_like 'allows round trips', 'FR14 2004 1010 0505 0001 3M02 606'
|
203
|
+
|
204
|
+
context 'without the rib key in the account number' do
|
205
|
+
before { args[:account_number] = '0500013M026' }
|
206
|
+
specify { expect(Ibandit::IBAN.new(assemble)).to_not be_valid }
|
207
|
+
end
|
208
|
+
|
209
|
+
context 'without a bank_code' do
|
210
|
+
before { args.delete(:bank_code) }
|
211
|
+
it { is_expected.to be_nil }
|
212
|
+
end
|
213
|
+
|
214
|
+
context 'without a branch_code' do
|
215
|
+
before { args.delete(:branch_code) }
|
216
|
+
it { is_expected.to be_nil }
|
217
|
+
end
|
218
|
+
|
219
|
+
context 'without an account_number' do
|
220
|
+
before { args.delete(:account_number) }
|
221
|
+
it { is_expected.to be_nil }
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
context 'with GB as the country_code' do
|
226
|
+
let(:args) do
|
227
|
+
{
|
228
|
+
country_code: 'GB',
|
229
|
+
bank_code: 'BARC',
|
230
|
+
branch_code: '200000',
|
231
|
+
account_number: '00579135'
|
232
|
+
}
|
233
|
+
end
|
234
|
+
|
235
|
+
it { is_expected.to eq('GB07BARC20000000579135') }
|
236
|
+
|
237
|
+
it_behaves_like 'allows round trips', 'GB07 BARC 2000 0000 5791 35'
|
238
|
+
|
239
|
+
context 'with the bank_code supplied manually' do
|
240
|
+
before { args.merge!(bank_code: 'BARC') }
|
241
|
+
it { is_expected.to eq('GB07BARC20000000579135') }
|
242
|
+
end
|
243
|
+
|
244
|
+
context 'without a branch_code' do
|
245
|
+
before { args.delete(:branch_code) }
|
246
|
+
it { is_expected.to be_nil }
|
247
|
+
end
|
248
|
+
|
249
|
+
context 'without an account_number' do
|
250
|
+
before { args.delete(:account_number) }
|
251
|
+
it { is_expected.to be_nil }
|
252
|
+
end
|
253
|
+
|
254
|
+
context 'without a bank_code' do
|
255
|
+
before { args.delete(:bank_code) }
|
256
|
+
it { is_expected.to be_nil }
|
257
|
+
end
|
258
|
+
|
259
|
+
context 'with a non-numeric branch code' do
|
260
|
+
before { args[:branch_code] = 'abc123' }
|
261
|
+
it { is_expected.to be_nil }
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
context 'with IE as the country_code' do
|
266
|
+
let(:args) do
|
267
|
+
{ country_code: 'IE',
|
268
|
+
bank_code: 'AIBK',
|
269
|
+
branch_code: '931152',
|
270
|
+
account_number: '12345678' }
|
271
|
+
end
|
272
|
+
|
273
|
+
it { is_expected.to eq('IE29AIBK93115212345678') }
|
274
|
+
|
275
|
+
it_behaves_like 'allows round trips', 'IE29 AIBK 9311 5212 3456 78'
|
276
|
+
|
277
|
+
context 'without a branch_code' do
|
278
|
+
before { args.delete(:branch_code) }
|
279
|
+
it { is_expected.to be_nil }
|
280
|
+
end
|
281
|
+
|
282
|
+
context 'without an account_number' do
|
283
|
+
before { args.delete(:account_number) }
|
284
|
+
it { is_expected.to be_nil }
|
285
|
+
end
|
286
|
+
|
287
|
+
context 'without a bank_code' do
|
288
|
+
before { args.delete(:bank_code) }
|
289
|
+
it { is_expected.to be_nil }
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
context 'with IT as the country_code' do
|
294
|
+
let(:args) do
|
295
|
+
{
|
296
|
+
country_code: 'IT',
|
297
|
+
bank_code: '05428',
|
298
|
+
branch_code: '11101',
|
299
|
+
account_number: '000000123456'
|
300
|
+
}
|
301
|
+
end
|
302
|
+
|
303
|
+
it { is_expected.to eq('IT60X0542811101000000123456') }
|
304
|
+
|
305
|
+
it_behaves_like 'allows round trips', 'IT60 X054 2811 1010 0000 0123 456'
|
306
|
+
|
307
|
+
context 'with an explicitly passed check digit' do
|
308
|
+
before { args[:check_digit] = 'Y' }
|
309
|
+
it { is_expected.to eq('IT64Y0542811101000000123456') }
|
310
|
+
end
|
311
|
+
|
312
|
+
context 'without a bank_code' do
|
313
|
+
before { args.delete(:bank_code) }
|
314
|
+
it { is_expected.to be_nil }
|
315
|
+
end
|
316
|
+
|
317
|
+
context 'without a branch_code' do
|
318
|
+
before { args.delete(:branch_code) }
|
319
|
+
it { is_expected.to be_nil }
|
320
|
+
end
|
321
|
+
|
322
|
+
context 'without an account_number' do
|
323
|
+
before { args.delete(:account_number) }
|
324
|
+
it { is_expected.to be_nil }
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
context 'with LT as the country_code' do
|
329
|
+
let(:args) do
|
330
|
+
{
|
331
|
+
country_code: 'LT',
|
332
|
+
account_number: '11101001000',
|
333
|
+
bank_code: '10000'
|
334
|
+
}
|
335
|
+
end
|
336
|
+
|
337
|
+
it { is_expected.to eq('LT121000011101001000') }
|
338
|
+
|
339
|
+
it_behaves_like 'allows round trips', 'LT12 1000 0111 0100 1000'
|
340
|
+
|
341
|
+
context 'without an account_number' do
|
342
|
+
before { args.delete(:account_number) }
|
343
|
+
it { is_expected.to be_nil }
|
344
|
+
end
|
345
|
+
|
346
|
+
context 'without a bank_code' do
|
347
|
+
before { args.delete(:bank_code) }
|
348
|
+
it { is_expected.to be_nil }
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
context 'with LU as the country_code' do
|
353
|
+
let(:args) do
|
354
|
+
{
|
355
|
+
country_code: 'LU',
|
356
|
+
account_number: '9400644750000',
|
357
|
+
bank_code: '001'
|
358
|
+
}
|
359
|
+
end
|
360
|
+
|
361
|
+
it { is_expected.to eq('LU280019400644750000') }
|
362
|
+
|
363
|
+
it_behaves_like 'allows round trips', 'LU28 0019 4006 4475 0000'
|
364
|
+
|
365
|
+
context 'without an account_number' do
|
366
|
+
before { args.delete(:account_number) }
|
367
|
+
it { is_expected.to be_nil }
|
368
|
+
end
|
369
|
+
|
370
|
+
context 'without a bank_code' do
|
371
|
+
before { args.delete(:bank_code) }
|
372
|
+
it { is_expected.to be_nil }
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
context 'with LV as the country_code' do
|
377
|
+
let(:args) do
|
378
|
+
{
|
379
|
+
country_code: 'LV',
|
380
|
+
account_number: '1234567890123',
|
381
|
+
bank_code: 'BANK'
|
382
|
+
}
|
383
|
+
end
|
384
|
+
|
385
|
+
it { is_expected.to eq('LV72BANK1234567890123') }
|
386
|
+
|
387
|
+
it_behaves_like 'allows round trips', 'LV72 BANK 1234 5678 9012 3'
|
388
|
+
|
389
|
+
context 'without an account_number' do
|
390
|
+
before { args.delete(:account_number) }
|
391
|
+
it { is_expected.to be_nil }
|
392
|
+
end
|
393
|
+
|
394
|
+
context 'without a bank_code' do
|
395
|
+
before { args.delete(:bank_code) }
|
396
|
+
it { is_expected.to be_nil }
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
context 'with MC as the country_code' do
|
401
|
+
let(:args) do
|
402
|
+
{
|
403
|
+
country_code: 'MC',
|
404
|
+
bank_code: '20041',
|
405
|
+
branch_code: '01005',
|
406
|
+
account_number: '0500013M02606'
|
407
|
+
}
|
408
|
+
end
|
409
|
+
|
410
|
+
it { is_expected.to eq('MC9320041010050500013M02606') }
|
411
|
+
|
412
|
+
it_behaves_like 'allows round trips', 'MC93 2004 1010 0505 0001 3M02 606'
|
413
|
+
|
414
|
+
context 'without the rib key in the account number' do
|
415
|
+
before { args[:account_number] = '0500013M026' }
|
416
|
+
specify { expect(Ibandit::IBAN.new(assemble)).to_not be_valid }
|
417
|
+
end
|
418
|
+
|
419
|
+
context 'without a bank_code' do
|
420
|
+
before { args.delete(:bank_code) }
|
421
|
+
it { is_expected.to be_nil }
|
422
|
+
end
|
423
|
+
|
424
|
+
context 'without a branch_code' do
|
425
|
+
before { args.delete(:branch_code) }
|
426
|
+
it { is_expected.to be_nil }
|
427
|
+
end
|
428
|
+
|
429
|
+
context 'without an account_number' do
|
430
|
+
before { args.delete(:account_number) }
|
431
|
+
it { is_expected.to be_nil }
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
context 'with NL as the country_code' do
|
436
|
+
let(:args) do
|
437
|
+
{
|
438
|
+
country_code: 'NL',
|
439
|
+
account_number: '0417164300',
|
440
|
+
bank_code: 'ABNA'
|
441
|
+
}
|
442
|
+
end
|
443
|
+
|
444
|
+
it { is_expected.to eq('NL91ABNA0417164300') }
|
445
|
+
|
446
|
+
it_behaves_like 'allows round trips', 'NL91 ABNA 0417 1643 00'
|
447
|
+
|
448
|
+
context 'without an account_number' do
|
449
|
+
before { args.delete(:account_number) }
|
450
|
+
it { is_expected.to be_nil }
|
451
|
+
end
|
452
|
+
|
453
|
+
context 'without an bank_code' do
|
454
|
+
before { args.delete(:bank_code) }
|
455
|
+
it { is_expected.to be_nil }
|
456
|
+
end
|
457
|
+
end
|
458
|
+
|
459
|
+
context 'with PT as the country_code' do
|
460
|
+
let(:args) do
|
461
|
+
{
|
462
|
+
country_code: 'PT',
|
463
|
+
bank_code: '0002',
|
464
|
+
branch_code: '0023',
|
465
|
+
account_number: '0023843000578'
|
466
|
+
}
|
467
|
+
end
|
468
|
+
|
469
|
+
it { is_expected.to eq('PT50000200230023843000578') }
|
470
|
+
|
471
|
+
it_behaves_like 'allows round trips', 'PT50 0002 0023 0023 8430 0057 8'
|
472
|
+
|
473
|
+
context 'without a bank_code' do
|
474
|
+
before { args.delete(:bank_code) }
|
475
|
+
it { is_expected.to be_nil }
|
476
|
+
end
|
477
|
+
|
478
|
+
context 'without a branch_code' do
|
479
|
+
before { args.delete(:branch_code) }
|
480
|
+
it { is_expected.to be_nil }
|
481
|
+
end
|
482
|
+
|
483
|
+
context 'without an account_number' do
|
484
|
+
before { args.delete(:account_number) }
|
485
|
+
it { is_expected.to be_nil }
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
context 'with SI as the country_code' do
|
490
|
+
let(:args) do
|
491
|
+
{
|
492
|
+
country_code: 'SI',
|
493
|
+
bank_code: '19100',
|
494
|
+
account_number: '0000123438'
|
495
|
+
}
|
496
|
+
end
|
497
|
+
|
498
|
+
it { is_expected.to eq('SI56191000000123438') }
|
499
|
+
|
500
|
+
it_behaves_like 'allows round trips', 'SI56 1910 0000 0123 438'
|
501
|
+
|
502
|
+
context 'without a bank_code' do
|
503
|
+
before { args.delete(:bank_code) }
|
504
|
+
it { is_expected.to be_nil }
|
505
|
+
end
|
506
|
+
|
507
|
+
context 'without an account_number' do
|
508
|
+
before { args.delete(:account_number) }
|
509
|
+
it { is_expected.to be_nil }
|
510
|
+
end
|
511
|
+
end
|
512
|
+
|
513
|
+
context 'with SK as the country_code' do
|
514
|
+
let(:args) do
|
515
|
+
{
|
516
|
+
country_code: 'SK',
|
517
|
+
bank_code: '1200',
|
518
|
+
account_number: '0000198742637541'
|
519
|
+
}
|
520
|
+
end
|
521
|
+
|
522
|
+
it { is_expected.to eq('SK3112000000198742637541') }
|
523
|
+
|
524
|
+
it_behaves_like 'allows round trips', 'SK31 1200 0000 1987 4263 7541'
|
525
|
+
|
526
|
+
context 'without a bank_code' do
|
527
|
+
before { args.delete(:bank_code) }
|
528
|
+
it { is_expected.to be_nil }
|
529
|
+
end
|
530
|
+
|
531
|
+
context 'without an account_number' do
|
532
|
+
before { args.delete(:account_number) }
|
533
|
+
it { is_expected.to be_nil }
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
context 'with SM as the country_code' do
|
538
|
+
let(:args) do
|
539
|
+
{
|
540
|
+
country_code: 'SM',
|
541
|
+
bank_code: '05428',
|
542
|
+
branch_code: '11101',
|
543
|
+
account_number: '000000123456'
|
544
|
+
}
|
545
|
+
end
|
546
|
+
|
547
|
+
it { is_expected.to eq('SM88X0542811101000000123456') }
|
548
|
+
|
549
|
+
it_behaves_like 'allows round trips', 'SM88 X054 2811 1010 0000 0123 456'
|
550
|
+
|
551
|
+
context 'without a bank_code' do
|
552
|
+
before { args.delete(:bank_code) }
|
553
|
+
it { is_expected.to be_nil }
|
554
|
+
end
|
555
|
+
|
556
|
+
context 'without a branch_code' do
|
557
|
+
before { args.delete(:branch_code) }
|
558
|
+
it { is_expected.to be_nil }
|
559
|
+
end
|
560
|
+
|
561
|
+
context 'without an account_number' do
|
562
|
+
before { args.delete(:account_number) }
|
563
|
+
it { is_expected.to be_nil }
|
564
|
+
end
|
565
|
+
end
|
566
|
+
end
|
567
|
+
end
|