card-validator
Version:
A library for validating credit card fields
253 lines (239 loc) • 7.09 kB
text/typescript
import { expirationYear, ExpirationYearVerification } from "../expiration-year";
const currentYear = new Date().getFullYear();
function yearsFromNow(fromNow: number, digits?: number): string {
let result = String(currentYear + fromNow);
if (digits === 2) {
result = result.substr(2, 2);
}
return result;
}
describe("expirationYear", () => {
const FALSE_VALIDATION = {
isValid: false,
isPotentiallyValid: false,
isCurrentYear: false,
};
describe.each([
[
"returns false if not a string",
[
[[], FALSE_VALIDATION],
[{}, FALSE_VALIDATION],
[null, FALSE_VALIDATION],
[undefined, FALSE_VALIDATION], // eslint-disable-line no-undefined
[Infinity, FALSE_VALIDATION],
[0 / 0, FALSE_VALIDATION],
[0, FALSE_VALIDATION],
[1, FALSE_VALIDATION],
[2, FALSE_VALIDATION],
[12, FALSE_VALIDATION],
[-1, FALSE_VALIDATION],
[-12, FALSE_VALIDATION],
],
],
[
"returns false for malformed strings",
[
["foo", FALSE_VALIDATION],
["1.2", FALSE_VALIDATION],
["1/20", FALSE_VALIDATION],
["1 2", FALSE_VALIDATION],
["1 ", FALSE_VALIDATION],
[" 1", FALSE_VALIDATION],
["20015", FALSE_VALIDATION],
],
],
[
"returns the appropriate values for incomplete strings",
[
[
"",
{ isValid: false, isPotentiallyValid: true, isCurrentYear: false },
],
[
"2",
{ isValid: false, isPotentiallyValid: true, isCurrentYear: false },
],
[
"9",
{ isValid: false, isPotentiallyValid: true, isCurrentYear: false },
],
[
"200",
{ isValid: false, isPotentiallyValid: true, isCurrentYear: false },
],
[
"123",
{ isValid: false, isPotentiallyValid: false, isCurrentYear: false },
],
[
"20",
{ isValid: false, isPotentiallyValid: true, isCurrentYear: false },
],
],
],
[
"accepts four-digit years",
[
[
yearsFromNow(0),
{ isValid: true, isPotentiallyValid: true, isCurrentYear: true },
],
[
yearsFromNow(-5),
{ isValid: false, isPotentiallyValid: false, isCurrentYear: false },
],
[
yearsFromNow(5),
{ isValid: true, isPotentiallyValid: true, isCurrentYear: false },
],
[
yearsFromNow(10),
{ isValid: true, isPotentiallyValid: true, isCurrentYear: false },
],
[
yearsFromNow(11),
{ isValid: true, isPotentiallyValid: true, isCurrentYear: false },
],
[
yearsFromNow(12),
{ isValid: true, isPotentiallyValid: true, isCurrentYear: false },
],
[
yearsFromNow(19),
{ isValid: true, isPotentiallyValid: true, isCurrentYear: false },
],
[
yearsFromNow(20),
{ isValid: false, isPotentiallyValid: false, isCurrentYear: false },
],
[
yearsFromNow(25),
{ isValid: false, isPotentiallyValid: false, isCurrentYear: false },
],
[
yearsFromNow(33),
{ isValid: false, isPotentiallyValid: false, isCurrentYear: false },
],
],
],
[
"accepts two-digit years",
[
[
yearsFromNow(0, 2),
{ isValid: true, isPotentiallyValid: true, isCurrentYear: true },
],
[
yearsFromNow(-5, 2),
{ isValid: false, isPotentiallyValid: false, isCurrentYear: false },
],
[
yearsFromNow(5, 2),
{ isValid: true, isPotentiallyValid: true, isCurrentYear: false },
],
[
yearsFromNow(10, 2),
{ isValid: true, isPotentiallyValid: true, isCurrentYear: false },
],
[
yearsFromNow(11, 2),
{ isValid: true, isPotentiallyValid: true, isCurrentYear: false },
],
[
yearsFromNow(12, 2),
{ isValid: true, isPotentiallyValid: true, isCurrentYear: false },
],
[
yearsFromNow(19, 2),
{ isValid: true, isPotentiallyValid: true, isCurrentYear: false },
],
[
yearsFromNow(20, 2),
{ isValid: false, isPotentiallyValid: false, isCurrentYear: false },
],
[
yearsFromNow(25, 2),
{ isValid: false, isPotentiallyValid: false, isCurrentYear: false },
],
[
yearsFromNow(33, 2),
{ isValid: false, isPotentiallyValid: false, isCurrentYear: false },
],
],
],
/*
* This doesn't take 20xx -> 21xx into account, but probably YAGNI
* (with apologies to whoever is possibly looking at this legacy
* code long after we're dead
* */
[
"accepts three-digit years",
[
[
yearsFromNow(-3).slice(0, 3),
{ isValid: false, isPotentiallyValid: true, isCurrentYear: false },
],
[
yearsFromNow(-1).slice(0, 3),
{ isValid: false, isPotentiallyValid: true, isCurrentYear: false },
],
[
yearsFromNow(0).slice(0, 3),
{ isValid: false, isPotentiallyValid: true, isCurrentYear: false },
],
[
yearsFromNow(1).slice(0, 3),
{ isValid: false, isPotentiallyValid: true, isCurrentYear: false },
],
[
yearsFromNow(5).slice(0, 3),
{ isValid: false, isPotentiallyValid: true, isCurrentYear: false },
],
[
yearsFromNow(11).slice(0, 3),
{ isValid: false, isPotentiallyValid: true, isCurrentYear: false },
],
[
yearsFromNow(17).slice(0, 3),
{ isValid: false, isPotentiallyValid: true, isCurrentYear: false },
],
[
yearsFromNow(23).slice(0, 3),
{ isValid: false, isPotentiallyValid: true, isCurrentYear: false },
],
],
],
] as Array<[string, Array<[unknown, ExpirationYearVerification]>]>)(
"%s",
(description, tests) => {
it.each(tests)("parses %s to be %p", (exp, meta) => {
expect(expirationYear(exp)).toEqual(meta);
});
},
);
it("defaults maxElapsedYear is 19", () => {
expect(expirationYear(yearsFromNow(19))).toEqual({
isValid: true,
isPotentiallyValid: true,
isCurrentYear: false,
});
expect(expirationYear(yearsFromNow(20))).toEqual({
isValid: false,
isPotentiallyValid: false,
isCurrentYear: false,
});
});
it("accepts maxElapsedYear", () => {
expect(expirationYear(yearsFromNow(20), 20)).toEqual({
isValid: true,
isPotentiallyValid: true,
isCurrentYear: false,
});
expect(expirationYear(yearsFromNow(21), 20)).toEqual({
isValid: false,
isPotentiallyValid: false,
isCurrentYear: false,
});
});
});