Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.eslintcache
.git
dist
node_modules
6 changes: 0 additions & 6 deletions .eslintrc.yml

This file was deleted.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.eslintcache
node_modules
4 changes: 0 additions & 4 deletions .jscsrc

This file was deleted.

34 changes: 34 additions & 0 deletions eslint.config.mjs
Comment thread
pedropiloto marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Module dependencies.
*/

import { defineConfig } from 'eslint/config';
import uphold, { mocha as upholdMochaConfig } from 'eslint-config-uphold';

/**
* `ESLint` configuration.
*/

export default defineConfig([
uphold,
{ ignores: ['dist/**'] },
{
files: ['**/*.js'],
name: 'uk-modulus-checking/config',
rules: {
// Weight table columns are named after single letters in the VocaLink specification.
'id-length': 'off',
// Data sets are read from disk once, on instantiation.
'n/no-sync': 'off'
}
},
{
extends: [upholdMochaConfig],
files: ['test/**/*.js'],
name: 'uk-modulus-checking/tests',
rules: {
// Test cases are generated from the VocaLink account number fixtures.
'mocha/no-setup-in-describe': 'off'
}
}
]);
12 changes: 5 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
},
"scripts": {
"changelog": "github_changelog_generator --no-issues --header-label='# Changelog'",
"lint": "eslint src test && jscs src test",
"lint": "eslint --cache src test",
"prepublish": "npm run transpile",
"testdocker": "docker-compose run --rm sut",
"test": "mocha $npm_package_options_mocha",
Expand All @@ -28,18 +28,16 @@
},
"devDependencies": {
Comment thread
pedropiloto marked this conversation as resolved.
"babel-cli": "^6.4.0",
"babel-eslint": "^4.1.6",
"babel-plugin-add-module-exports": "^0.1.2",
"babel-plugin-static-fs": "^1.2.0",
"babel-preset-es2015": "6.5.0",
"babel-register": "^6.3.13",
"eslint": "^1.10.3",
"eslint-config-seegno": "2.0.0",
"eslint-plugin-babel": "^3.0.0",
"jscs": "^2.7.0",
"jscs-config-seegno": "^1.0.0",
"eslint": "~10.6.0",
Comment thread
pedropiloto marked this conversation as resolved.
"eslint-config-uphold": "^7.0.0",
Comment thread
pedropiloto marked this conversation as resolved.
"eslint-plugin-mocha": "^11.3.0",
"mocha": "^2.3.4",
"pre-commit": "^1.1.2",
"prettier": "^3.9.4",
"should": "^8.0.0"
},
"pre-commit": [
Expand Down
7 changes: 5 additions & 2 deletions src/constants.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
/**
* Exports.
*/

/* jscs:disable validateOrderInObjectKeys */
/* eslint-disable sort-keys-fix/sort-keys-fix */
export const positions = {
u: 0,
v: 1,
Expand All @@ -16,4 +19,4 @@ export const positions = {
g: 12,
h: 13
};
/* jscs:enable validateOrderInObjectKeys */
/* eslint-enable sort-keys-fix/sort-keys-fix */
106 changes: 62 additions & 44 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

/**
* Module dependencies.
*/
Expand All @@ -12,7 +11,6 @@ import path from 'path';
*/

export default class UkModulusChecking {

/**
* Constructor.
*/
Expand Down Expand Up @@ -48,20 +46,35 @@ export default class UkModulusChecking {
if (check.exception === 10) {
const ab = number.charAt(positions.a) + number.charAt(positions.b);

if (ab === '09' || ab === '99' && this.pickPosition(number, 'b') === 9) {
if (ab === '09' || (ab === '99' && this.pickPosition(number, 'b') === 9)) {
return [0, 0, 0, 0, 0, 0, 0, 0, check.c, check.d, check.e, check.f, check.g, check.h];
}
}

return [check.u, check.v, check.w, check.x, check.y, check.z, check.a, check.b, check.c, check.d, check.e, check.f, check.g, check.h];
return [
check.u,
check.v,
check.w,
check.x,
check.y,
check.z,
check.a,
check.b,
check.c,
check.d,
check.e,
check.f,
check.g,
check.h
];
}

/**
* Get number to be used in validation process. (sorting code + account number).
*/

getNumber(check, number) {
let sortCode = this.sortCode;
let { sortCode } = this;

number = number || this.accountNumber;

Expand Down Expand Up @@ -123,7 +136,12 @@ export default class UkModulusChecking {
return true;
}

if (check.exception === 6 && this.pickPosition(number, 'a') >= 4 && this.pickPosition(number, 'a') <= 8 && this.pickPosition(number, 'g') === this.pickPosition(number, 'h')) {
if (
check.exception === 6 &&
this.pickPosition(number, 'a') >= 4 &&
this.pickPosition(number, 'a') <= 8 &&
this.pickPosition(number, 'g') === this.pickPosition(number, 'h')
) {
return true;
}

Expand Down Expand Up @@ -199,46 +217,46 @@ export default class UkModulusChecking {
* Is valid.
*/

isValid() {
if (this.accountNumber.length < 6 || this.accountNumber.length > 10 || this.sortCode.length !== 6) {
return false;
}
isValid() {
if (this.accountNumber.length < 6 || this.accountNumber.length > 10 || this.sortCode.length !== 6) {
return false;
}

const checks = this.getSortCodeChecks();
const checks = this.getSortCodeChecks();

// If no range is found that contains the sorting code, there is no modulus check that can be performed.
// The sorting code and account number should be presumed valid unless other evidence implies otherwise.
if (checks.length === 0) {
return true;
}
// If no range is found that contains the sorting code, there is no modulus check that can be performed.
// The sorting code and account number should be presumed valid unless other evidence implies otherwise.
if (checks.length === 0) {
return true;
}

const firstCheck = checks[0];
const [firstCheck] = checks;

if (this.isCheckValid(firstCheck)) {
if (checks.length === 1 || [2, 9, 10, 11, 12, 13, 14].indexOf(firstCheck.exception) !== -1) {
return true;
}
if (this.isCheckValid(firstCheck)) {
if (checks.length === 1 || [2, 9, 10, 11, 12, 13, 14].indexOf(firstCheck.exception) !== -1) {
return true;
}

// Verify second check.
return this.isCheckValid(checks[1]);
}
// Verify second check.
return this.isCheckValid(checks[1]);
}

if (firstCheck.exception === 14) {
if ([0, 1, 9].indexOf(parseInt(this.accountNumber.charAt(7), 10)) === -1) {
return false;
}
if (firstCheck.exception === 14) {
if ([0, 1, 9].indexOf(parseInt(this.accountNumber.charAt(7), 10)) === -1) {
return false;
}

// If the 8th digit is 0, 1 or 9, then remove the digit from the account number and insert a 0 as the 1st digit for check purposes only
return this.isCheckValid(checks[0], `0${this.accountNumber.substring(7, 0)}`);
}
// If the 8th digit is 0, 1 or 9, then remove the digit from the account number and insert a 0 as the 1st digit for check purposes only.
return this.isCheckValid(checks[0], `0${this.accountNumber.substring(7, 0)}`);
Comment thread
pedropiloto marked this conversation as resolved.
}

if (checks.length === 1 || [2, 9, 10, 11, 12, 13, 14].indexOf(firstCheck.exception) === -1) {
return false;
}
if (checks.length === 1 || [2, 9, 10, 11, 12, 13, 14].indexOf(firstCheck.exception) === -1) {
return false;
}

// Verify second check.
return this.isCheckValid(checks[1]);
}
// Verify second check.
return this.isCheckValid(checks[1]);
}

/**
* Load scsubtab file.
Expand All @@ -248,7 +266,7 @@ export default class UkModulusChecking {
const content = fs.readFileSync(path.join(__dirname, 'data', 'scsubtab.txt'), 'utf8');
const scsubtab = [];

content.split('\r\n').forEach((line) => {
content.split('\r\n').forEach(line => {
const data = line.split(/\s+/);

scsubtab.push({
Expand All @@ -268,10 +286,10 @@ export default class UkModulusChecking {
const content = fs.readFileSync(path.join(__dirname, 'data', 'valacdos-v900.txt'), 'utf8');
const valacdos = [];

content.split('\r\n').forEach((line) => {
content.split('\r\n').forEach(line => {
const data = line.split(/\s+/);

/* jscs:disable validateOrderInObjectKeys */
/* eslint-disable sort-keys-fix/sort-keys-fix */
valacdos.push({
start: parseInt(data[0], 10),
end: parseInt(data[1], 10),
Expand All @@ -292,7 +310,7 @@ export default class UkModulusChecking {
h: parseInt(data[16], 10),
exception: parseInt(data[17], 10) || null
});
/* jscs:enable validateOrderInObjectKeys */
/* eslint-enable sort-keys-fix/sort-keys-fix */
});

return valacdos;
Expand All @@ -302,9 +320,9 @@ export default class UkModulusChecking {
* Pick position in number.
*/

pickPosition(number, position) {
return parseInt(number.charAt(positions[position]), 10);
}
pickPosition(number, position) {
return parseInt(number.charAt(positions[position]), 10);
}

/**
* Sanitize.
Expand Down
27 changes: 15 additions & 12 deletions test/index_test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

/**
* Module dependencies.
*/
Expand Down Expand Up @@ -50,29 +49,33 @@ const accounts = {
* Test `UkModulusChecking`.
*/

describe('UkModulusChecking', () => {
describe('isValid()', () => {
it('should return false if account number length is less than 6', () => {
describe('UkModulusChecking', function () {
describe('isValid()', function () {
it('should return false if account number length is less than 6', function () {
new UkModulusChecking({ accountNumber: '12345', sortCode: '123456' }).isValid().should.be.false();
});

it('should return false if account number length is greater than 10', () => {
it('should return false if account number length is greater than 10', function () {
new UkModulusChecking({ accountNumber: '12345678901', sortCode: '123456' }).isValid().should.be.false();
});

it('should return false if sort code length is not 6', () => {
it('should return false if sort code length is not 6', function () {
new UkModulusChecking({ accountNumber: '12345789', sortCode: '12345' }).isValid().should.be.false();
});

accounts.invalid.forEach((account) => {
it(`should return false if sort code is ${account.sortCode} and account number is ${account.accountNumber}`, () => {
new UkModulusChecking({ accountNumber: account.accountNumber, sortCode: account.sortCode }).isValid().should.be.false();
accounts.invalid.forEach(account => {
it(`should return false if sort code is ${account.sortCode} and account number is ${account.accountNumber}`, function () {
new UkModulusChecking({ accountNumber: account.accountNumber, sortCode: account.sortCode })
.isValid()
.should.be.false();
});
});

accounts.valid.forEach((account) => {
it(`should return true if sort code is ${account.sortCode} and account number is ${account.accountNumber}`, () => {
new UkModulusChecking({ accountNumber: account.accountNumber, sortCode: account.sortCode }).isValid().should.be.true();
accounts.valid.forEach(account => {
it(`should return true if sort code is ${account.sortCode} and account number is ${account.accountNumber}`, function () {
new UkModulusChecking({ accountNumber: account.accountNumber, sortCode: account.sortCode })
.isValid()
.should.be.true();
});
});
});
Expand Down