Skip to content

Commit

Permalink
Added unit tests, put IBAN in a separate class.
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcelvLaar committed Feb 4, 2025
1 parent 643605a commit 810a1f2
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 27 deletions.
9 changes: 6 additions & 3 deletions frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
"name": "digidecs",
"type": "module",
"version": "0.1.0",
"version": "0.1.1",
"private": true,
"scripts": {
"dev": "vite",
"test": "vitest --config './src/tests/vitest.config.ts'",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview",
"lint": "eslint . --fix --ignore-path .gitignore"
Expand All @@ -14,7 +15,7 @@
"base64-arraybuffer": "^1.0.2",
"core-js": "^3.29.0",
"roboto-fontface": "*",
"vue": "^3.2.0",
"vue": "^3.5.13",
"vue-i18n": "9",
"vue-router": "^4.0.0",
"vuetify": "^3.0.0"
Expand All @@ -26,7 +27,7 @@
"@typescript-eslint/eslint-plugin": "^8.4.0",
"@typescript-eslint/parser": "^8.4.0",
"@vitejs/plugin-vue": "^4.0.0",
"@vue/eslint-config-typescript": "^11.0.0",
"@vue/test-utils": "^2.4.6",
"eslint": "^9.9.1",
"eslint-plugin-vue": "^9.28.0",
"sass": "^1.60.0",
Expand All @@ -35,6 +36,8 @@
"unplugin-fonts": "^1.0.3",
"vite": "^4.2.0",
"vite-plugin-vuetify": "^1.0.0",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.0.5",
"vue-tsc": "^2.1.8"
}
}
26 changes: 26 additions & 0 deletions frontend/src/scripts/iban.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export abstract class IBAN{

static checkIBAN(iban: string): boolean {
// Tested with:
// GB33BUKB20201555555555 (correct)
// GB94BARC10201530093459 (correct)
// gB94BARC10201530093459 (correct, evaluates to its uppercase equivalent)
// GB94BARC20201530093459 (incorrect checksum)
iban = iban.toUpperCase();
const ibanRegex = /^[A-Z]{2}[0-9]{2}[A-Z0-9]{1,30}$/;
if (!ibanRegex.test(iban)) {
return false;
}

// ISO/IEC 7064:2003
// Convert IBAN to numeric representation (rearrange and replace letter with corresponding numeric value)
const numericIban = (iban.slice(4) + iban.slice(0,4))
.replace(/[A-Z]/g, char => (parseInt(char, 36)).toString());
// Match only sequences of 1-7 digits, convert each to number and add, then take result mod 97.
const remainder = numericIban
.match(/\d{1,7}/g)?.reduce((acc, block) => Number(acc + block) % 97, 0);
return remainder===1;
}


}
32 changes: 32 additions & 0 deletions frontend/src/tests/IBAN.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { describe, it, expect } from 'vitest';
import { mount } from '@vue/test-utils';
import { checkIBAN } from '../views/HomeView.vue';
import {IBAN} from "../scripts/iban";


describe('checkIBAN', () => {
it('should return true for a valid IBAN', () => {
const validIBAN = 'DE89370400440532013000';
expect(IBAN.checkIBAN(validIBAN)).toBe(true);
});

it('should return false for an invalid IBAN', () => {
const invalidIBAN = 'DE89370400440532013001';
expect(IBAN.checkIBAN(invalidIBAN)).toBe(false);
});

it('should return false for an IBAN with incorrect length', () => {
const shortIBAN = 'DE8937040044053201300';
expect(IBAN.checkIBAN(shortIBAN)).toBe(false);
});

it('should return false for an IBAN with invalid characters', () => {
const invalidCharIBAN = 'DE89$70400440532013000';
expect(IBAN.checkIBAN(invalidCharIBAN)).toBe(false);
});

it('should return false for an empty IBAN', () => {
const emptyIBAN = '';
expect(IBAN.checkIBAN(emptyIBAN)).toBe(false);
});
});
15 changes: 15 additions & 0 deletions frontend/src/tests/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { defineConfig } from 'vitest/config';
import vue from "@vitejs/plugin-vue";
import viteTsconfigPaths from 'vite-tsconfig-paths';

export default defineConfig({
test: {
globals: true,
environment: 'jsdom',
coverage: {
reporter: ['text', 'json', 'html'],
},
include: ["src/tests/*.test.js"],
},
plugins: [vue(),viteTsconfigPaths()],
});
25 changes: 2 additions & 23 deletions frontend/src/views/HomeView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ import {defineComponent} from "vue";
import {InputValidationRules} from "@/main";
import {Digidecs} from "@/scripts/digidecs";
import MaterialBanner from "@/views/components/MaterialBanner.vue";
import {IBAN} from "@/scripts/iban";
interface Data {
error: string | undefined,
Expand All @@ -145,28 +146,6 @@ interface Data {
}
}
function checkIBAN(iban: string): boolean {
// Tested with:
// GB33BUKB20201555555555 (correct)
// GB94BARC10201530093459 (correct)
// gB94BARC10201530093459 (correct, evaluates to its uppercase equivalent)
// GB94BARC20201530093459 (incorrect checksum)
iban = iban.toUpperCase();
const ibanRegex = /^[A-Z]{2}[0-9]{2}[A-Z0-9]{1,30}$/;
if (!ibanRegex.test(iban)) {
return false;
}
// ISO/IEC 7064:2003
// Convert IBAN to numeric representation (rearrange and replace letter with corresponding numeric value)
const numericIban = (iban.slice(4) + iban.slice(0,4))
.replace(/[A-Z]/g, char => (parseInt(char, 36)).toString());
// Match only sequences of 1-7 digits, convert each to number and add, then take result mod 97.
const remainder = numericIban
.match(/\d{1,7}/g)?.reduce((acc, block) => Number(acc + block) % 97, 0);
return remainder===1;
}
export default defineComponent({
components: {MaterialBanner},
data(): Data {
Expand All @@ -180,7 +159,7 @@ export default defineComponent({
],
iban: [
v => !!v || this.$t("home.form.rules.required"),
v => checkIBAN(v) || this.$t("home.form.rules.ibanInvalid")
v => IBAN.checkIBAN(v) || this.$t("home.form.rules.ibanInvalid")
],
email: [
v => !!v || this.$t("home.form.rules.required"),
Expand Down
3 changes: 2 additions & 1 deletion frontend/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"@/*": [
"src/*"
]
}
},
"allowJs": true, // Necessary for vitest to work
},
"include": [
"src/**/*.ts",
Expand Down

0 comments on commit 810a1f2

Please sign in to comment.