mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-04-24 00:36:14 -04:00
feat(new tool): iban validation and parser (#591)
This commit is contained in:
parent
81bfe57cb8
commit
3a63837d3d
14 changed files with 278 additions and 1 deletions
|
@ -0,0 +1,51 @@
|
|||
import { type Page, expect, test } from '@playwright/test';
|
||||
import _ from 'lodash';
|
||||
|
||||
async function extractIbanInfo({ page }: { page: Page }) {
|
||||
const tdHandles = await page.locator('table tr td').elementHandles();
|
||||
const tdTextContents = await Promise.all(tdHandles.map(el => el.textContent()));
|
||||
|
||||
return _.chain(tdTextContents)
|
||||
.map(tdTextContent => tdTextContent?.trim().replace(' Copy to clipboard', ''))
|
||||
.chunk(2)
|
||||
.value();
|
||||
}
|
||||
|
||||
test.describe('Tool - Iban validator and parser', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/iban-validator-and-parser');
|
||||
});
|
||||
|
||||
test('Has correct title', async ({ page }) => {
|
||||
await expect(page).toHaveTitle('IBAN validator and parser - IT Tools');
|
||||
});
|
||||
|
||||
test('iban info are extracted from a valid iban', async ({ page }) => {
|
||||
await page.getByTestId('iban-input').fill('DE89370400440532013000');
|
||||
|
||||
const ibanInfo = await extractIbanInfo({ page });
|
||||
|
||||
expect(ibanInfo).toEqual([
|
||||
['Is IBAN valid ?', 'Yes'],
|
||||
['Is IBAN a QR-IBAN ?', 'No'],
|
||||
['Country code', 'DE'],
|
||||
['BBAN', '370400440532013000'],
|
||||
['IBAN friendly format', 'DE89 3704 0044 0532 0130 00'],
|
||||
]);
|
||||
});
|
||||
|
||||
test('invalid iban errors are displayed', async ({ page }) => {
|
||||
await page.getByTestId('iban-input').fill('FR7630006060011234567890189');
|
||||
|
||||
const ibanInfo = await extractIbanInfo({ page });
|
||||
|
||||
expect(ibanInfo).toEqual([
|
||||
['Is IBAN valid ?', 'No'],
|
||||
['IBAN errors', 'Wrong account bank branch checksumWrong IBAN checksum Copy to clipboard'],
|
||||
['Is IBAN a QR-IBAN ?', 'No'],
|
||||
['Country code', 'N/A'],
|
||||
['BBAN', 'N/A'],
|
||||
['IBAN friendly format', 'FR76 3000 6060 0112 3456 7890 189'],
|
||||
]);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,18 @@
|
|||
import { ValidationErrorsIBAN } from 'ibantools';
|
||||
|
||||
export { getFriendlyErrors };
|
||||
|
||||
const ibanErrorToMessage = {
|
||||
[ValidationErrorsIBAN.NoIBANProvided]: 'No IBAN provided',
|
||||
[ValidationErrorsIBAN.NoIBANCountry]: 'No IBAN country',
|
||||
[ValidationErrorsIBAN.WrongBBANLength]: 'Wrong BBAN length',
|
||||
[ValidationErrorsIBAN.WrongBBANFormat]: 'Wrong BBAN format',
|
||||
[ValidationErrorsIBAN.ChecksumNotNumber]: 'Checksum is not a number',
|
||||
[ValidationErrorsIBAN.WrongIBANChecksum]: 'Wrong IBAN checksum',
|
||||
[ValidationErrorsIBAN.WrongAccountBankBranchChecksum]: 'Wrong account bank branch checksum',
|
||||
[ValidationErrorsIBAN.QRIBANNotAllowed]: 'QR-IBAN not allowed',
|
||||
};
|
||||
|
||||
function getFriendlyErrors(errorCodes: ValidationErrorsIBAN[]) {
|
||||
return errorCodes.map(errorCode => ibanErrorToMessage[errorCode]).filter(Boolean);
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
<script setup lang="ts">
|
||||
import { extractIBAN, friendlyFormatIBAN, isQRIBAN, validateIBAN } from 'ibantools';
|
||||
import { getFriendlyErrors } from './iban-validator-and-parser.service';
|
||||
import type { CKeyValueListItems } from '@/ui/c-key-value-list/c-key-value-list.types';
|
||||
|
||||
const rawIban = ref('');
|
||||
|
||||
const ibanInfo = computed<CKeyValueListItems>(() => {
|
||||
const iban = rawIban.value.toUpperCase().replace(/\s/g, '').replace(/-/g, '');
|
||||
|
||||
if (iban === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { valid: isIbanValid, errorCodes } = validateIBAN(iban);
|
||||
const { countryCode, bban } = extractIBAN(iban);
|
||||
const errors = getFriendlyErrors(errorCodes);
|
||||
|
||||
return [
|
||||
|
||||
{
|
||||
label: 'Is IBAN valid ?',
|
||||
value: isIbanValid,
|
||||
showCopyButton: false,
|
||||
},
|
||||
{
|
||||
label: 'IBAN errors',
|
||||
value: errors.length === 0 ? undefined : errors,
|
||||
hideOnNil: true,
|
||||
showCopyButton: false,
|
||||
},
|
||||
{
|
||||
label: 'Is IBAN a QR-IBAN ?',
|
||||
value: isQRIBAN(iban),
|
||||
showCopyButton: false,
|
||||
},
|
||||
{
|
||||
label: 'Country code',
|
||||
value: countryCode,
|
||||
},
|
||||
{
|
||||
label: 'BBAN',
|
||||
value: bban,
|
||||
},
|
||||
{
|
||||
label: 'IBAN friendly format',
|
||||
value: friendlyFormatIBAN(iban),
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
const ibanExamples = [
|
||||
'FR7630006000011234567890189',
|
||||
'DE89370400440532013000',
|
||||
'GB29NWBK60161331926819',
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<c-input-text v-model:value="rawIban" placeholder="Enter an IBAN to check for validity..." test-id="iban-input" />
|
||||
|
||||
<c-key-value-list :items="ibanInfo" my-5 />
|
||||
|
||||
<c-card title="Valid IBAN examples">
|
||||
<div v-for="iban in ibanExamples" :key="iban">
|
||||
<c-text-copyable :value="iban" font-mono :displayed-value="friendlyFormatIBAN(iban)" />
|
||||
</div>
|
||||
</c-card>
|
||||
</div>
|
||||
</template>
|
12
src/tools/iban-validator-and-parser/index.ts
Normal file
12
src/tools/iban-validator-and-parser/index.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { defineTool } from '../tool';
|
||||
import Bank from '~icons/mdi/bank';
|
||||
|
||||
export const tool = defineTool({
|
||||
name: 'IBAN validator and parser',
|
||||
path: '/iban-validator-and-parser',
|
||||
description: 'Validate and parse IBAN numbers. Check if IBAN is valid and get the country, BBAN, if it is a QR-IBAN and the IBAN friendly format.',
|
||||
keywords: ['iban', 'validator', 'and', 'parser', 'bic', 'bank'],
|
||||
component: () => import('./iban-validator-and-parser.vue'),
|
||||
icon: Bank,
|
||||
createdAt: new Date('2023-08-26'),
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue