Skip to content

Commit

Permalink
Feature luhn (#3)
Browse files Browse the repository at this point in the history
* luhn constraint

* luhn constraint
  • Loading branch information
OxCom authored Jan 10, 2020
1 parent e872a32 commit c0a077f
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 732 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ console.log(result);
Financial and other Number Constraints:
- [Currency](docs/Constraints/Currency.md)
- [Issn](docs/Constraints/Issn.md)
- [Luhn](docs/Constraints/Luhn.md)

Other constraints:
- [Count](docs/Constraints/Count.md)
Expand All @@ -113,7 +114,6 @@ console.log(result);
Investigate and add financial and other number constraints
- Bic
- CardScheme
- Luhn
- Iban
- Isbn
- Callback
Expand Down
731 changes: 1 addition & 730 deletions dist/validator.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion docs/Constraints.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,11 @@ Choice constraints:

Financial and other Number Constraints:
- [Currency](./Constraints/Currency.md)
- [Luhn](./Constraints/Luhn.md)
- [Issn](./Constraints/Issn.md)

Other constraints:
- [Count](./Constraints/Count.md)
- [Issn](./Constraints/Issn.md)

## Create custom constraint

Expand Down
16 changes: 16 additions & 0 deletions docs/Constraints/Luhn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Luhn
This constraint is used to ensure that a credit card number passes the [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm). It is useful as a first step to validating a credit card: before communicating with a payment gateway.

## Options

##### message
type: `string` default: `Invalid card number.`
The default message supplied when the value does not pass the Luhn check.

| Parameter | Description |
|---|---|
| {{ value }} | The current (invalid) value

##### trim
type: `boolean` default: `true`
Trim provided value.
71 changes: 71 additions & 0 deletions src/Constraints/Luhn.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import AbstractConstraint from './AbstractConstraint';
import { trim } from '../Utils/functions';

const MESSAGE_INVALID = 'Invalid card number.';

export default class Luhn extends AbstractConstraint {
/**
* @param {{message: string, trim: boolean}} [options]
*/
constructor(options) {
super(options);
}

/**
* @return {{message: string, trim: boolean}}
*/
getDefaultOptions() {
return {
'trim': true,
'message': MESSAGE_INVALID,
};
}

/**
* Test provided value and return Error if occurs
*
* @param value
*
* @return {Error|undefined}
*/
validate(value) {
if (this.options.trim) {
value = trim(value);
}

if (this.isEmptyValue(value)) {
return;
}

if (/[^0-9-\s]+/.test(value)) {
return this
.getViolationBuilder()
.setParameter('value', value)
.build(this.options.message);
}

let canonical = value.toString().replace(/\D/g, '');
let checkSum = 0;

for (let i = canonical.length - 1; i >= 0; i -= 2) {
checkSum += parseInt(canonical.charAt(i));
}

for (let i = canonical.length - 2; i >= 0; i -= 2) {
// checkSum += array_sum(str_split((int) $value[$i] * 2));
checkSum += (parseInt(canonical.charAt(i)) * 2)
.toString()
.split('')
.reduce((a, b) => {
return parseInt(a) + parseInt(b);
}, 0);
}

if (0 === checkSum || 0 !== checkSum % 10) {
return this
.getViolationBuilder()
.setParameter('value', value)
.build(this.options.message);
}
}
}
2 changes: 2 additions & 0 deletions src/validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import Regex from './Constraints/Regex';
import Range from './Constraints/Range';
import Locale from './Constraints/Locale';
import Issn from './Constraints/Issn';
import Luhn from './Constraints/Luhn';
import Validator from './Validator/Validator';
import Form from './Validator/Form';

Expand Down Expand Up @@ -72,6 +73,7 @@ export default {
Range: Range,
Locale: Locale,
Issn: Issn,
Luhn: Luhn,
Validator: Validator,
Form: Form,
};
67 changes: 67 additions & 0 deletions tests/Constraints/Luhn.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Luhn } from '../../src/validator';

const assert = require('assert');

describe('Luhn', function () {
describe('#constructor()', function () {
it('empty configuration', function () {
new Luhn();
});
});

describe('#validate()', function () {
it('Valid', function () {
const object = new Luhn();

[
'42424242424242424242',
'378282246310005',
'371449635398431',
'378734493671000',
'5610591081018250',
'30569309025904',
'38520000023237',
'6011111111111117',
'6011000990139424',
'3530111333300000',
'3566002020360505',
'5555555555554444',
'3530-1113-3330-0000',
'3566002020360505',
'3566 0020 2036 0505',
'5555555555554444',
'5105105105105100',
'4111111111111111',
'4012888888881881',
'4222222222222',
'5019717010103742',
'6331101999990016',
].forEach((code) => {
const e = object.validate(code);

assert.ok(typeof e === 'undefined', e);
});
});

it('Invalid', function () {
const object = new Luhn();

[
'foobar', 1, 100, 804, '804',
0,
'0',
'0000000000',
'00',
'1234567812345678',
'4222222222222222',
'0000000000000000',
'42-22222222222222'
]
.forEach((code) => {
const e = object.validate(code);

assert.strictEqual(e.message, 'Invalid card number.');
});
});
});
});

0 comments on commit c0a077f

Please sign in to comment.