card-validator 10.0.1 → 10.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.postalCode = void 0;
4
- var DEFAULT_MIN_POSTAL_CODE_LENGTH = 3;
4
+ var DEFAULT_MIN_POSTAL_CODE_LENGTH = 2;
5
5
  var ALPHANUM = new RegExp(/^[a-z0-9]+$/i);
6
6
  function verification(isValid, isPotentiallyValid) {
7
7
  return { isValid: isValid, isPotentiallyValid: isPotentiallyValid };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "card-validator",
3
- "version": "10.0.1",
3
+ "version": "10.0.3",
4
4
  "description": "A library for validating credit card fields",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -33,7 +33,7 @@
33
33
  "typescript": "^5.1.6"
34
34
  },
35
35
  "dependencies": {
36
- "credit-card-type": "^10.0.1"
36
+ "credit-card-type": "^10.0.2"
37
37
  },
38
38
  "jest": {
39
39
  "testEnvironment": "jsdom",
@@ -1,252 +1,163 @@
1
1
  import { expirationYear, ExpirationYearVerification } from "../expiration-year";
2
2
 
3
- const currentYear = new Date().getFullYear();
3
+ const INVALID: ExpirationYearVerification = {
4
+ isValid: false,
5
+ isPotentiallyValid: false,
6
+ isCurrentYear: false,
7
+ };
4
8
 
5
- function yearsFromNow(fromNow: number, digits?: number): string {
6
- let result = String(currentYear + fromNow);
9
+ const POTENTIALLY_VALID: ExpirationYearVerification = {
10
+ isValid: false,
11
+ isPotentiallyValid: true,
12
+ isCurrentYear: false,
13
+ };
7
14
 
8
- if (digits === 2) {
9
- result = result.substr(2, 2);
10
- }
15
+ const VALID: ExpirationYearVerification = {
16
+ isValid: true,
17
+ isPotentiallyValid: true,
18
+ isCurrentYear: false,
19
+ };
11
20
 
12
- return result;
13
- }
21
+ const CURRENT_YEAR: ExpirationYearVerification = {
22
+ isValid: true,
23
+ isPotentiallyValid: true,
24
+ isCurrentYear: true,
25
+ };
14
26
 
15
27
  describe("expirationYear", () => {
16
- const FALSE_VALIDATION = {
17
- isValid: false,
18
- isPotentiallyValid: false,
19
- isCurrentYear: false,
20
- };
21
-
22
- describe.each([
23
- [
24
- "returns false if not a string",
25
- [
26
- [[], FALSE_VALIDATION],
27
- [{}, FALSE_VALIDATION],
28
- [null, FALSE_VALIDATION],
29
- [undefined, FALSE_VALIDATION], // eslint-disable-line no-undefined
30
- [Infinity, FALSE_VALIDATION],
31
- [0 / 0, FALSE_VALIDATION],
32
- [0, FALSE_VALIDATION],
33
- [1, FALSE_VALIDATION],
34
- [2, FALSE_VALIDATION],
35
- [12, FALSE_VALIDATION],
36
- [-1, FALSE_VALIDATION],
37
- [-12, FALSE_VALIDATION],
38
- ],
39
- ],
40
-
41
- [
42
- "returns false for malformed strings",
43
- [
44
- ["foo", FALSE_VALIDATION],
45
- ["1.2", FALSE_VALIDATION],
46
- ["1/20", FALSE_VALIDATION],
47
- ["1 2", FALSE_VALIDATION],
48
- ["1 ", FALSE_VALIDATION],
49
- [" 1", FALSE_VALIDATION],
50
- ["20015", FALSE_VALIDATION],
51
- ],
52
- ],
53
-
54
- [
55
- "returns the appropriate values for incomplete strings",
56
- [
57
- [
58
- "",
59
- { isValid: false, isPotentiallyValid: true, isCurrentYear: false },
60
- ],
61
- [
62
- "2",
63
- { isValid: false, isPotentiallyValid: true, isCurrentYear: false },
64
- ],
65
- [
66
- "9",
67
- { isValid: false, isPotentiallyValid: true, isCurrentYear: false },
68
- ],
69
- [
70
- "200",
71
- { isValid: false, isPotentiallyValid: true, isCurrentYear: false },
72
- ],
73
- [
74
- "123",
75
- { isValid: false, isPotentiallyValid: false, isCurrentYear: false },
76
- ],
77
- [
78
- "20",
79
- { isValid: false, isPotentiallyValid: true, isCurrentYear: false },
80
- ],
81
- ],
82
- ],
83
-
84
- [
85
- "accepts four-digit years",
86
- [
87
- [
88
- yearsFromNow(0),
89
- { isValid: true, isPotentiallyValid: true, isCurrentYear: true },
90
- ],
91
- [
92
- yearsFromNow(-5),
93
- { isValid: false, isPotentiallyValid: false, isCurrentYear: false },
94
- ],
95
- [
96
- yearsFromNow(5),
97
- { isValid: true, isPotentiallyValid: true, isCurrentYear: false },
98
- ],
99
- [
100
- yearsFromNow(10),
101
- { isValid: true, isPotentiallyValid: true, isCurrentYear: false },
102
- ],
103
- [
104
- yearsFromNow(11),
105
- { isValid: true, isPotentiallyValid: true, isCurrentYear: false },
106
- ],
107
- [
108
- yearsFromNow(12),
109
- { isValid: true, isPotentiallyValid: true, isCurrentYear: false },
110
- ],
111
- [
112
- yearsFromNow(19),
113
- { isValid: true, isPotentiallyValid: true, isCurrentYear: false },
114
- ],
115
- [
116
- yearsFromNow(20),
117
- { isValid: false, isPotentiallyValid: false, isCurrentYear: false },
118
- ],
119
- [
120
- yearsFromNow(25),
121
- { isValid: false, isPotentiallyValid: false, isCurrentYear: false },
122
- ],
123
- [
124
- yearsFromNow(33),
125
- { isValid: false, isPotentiallyValid: false, isCurrentYear: false },
126
- ],
127
- ],
128
- ],
129
-
130
- [
131
- "accepts two-digit years",
132
- [
133
- [
134
- yearsFromNow(0, 2),
135
- { isValid: true, isPotentiallyValid: true, isCurrentYear: true },
136
- ],
137
- [
138
- yearsFromNow(-5, 2),
139
- { isValid: false, isPotentiallyValid: false, isCurrentYear: false },
140
- ],
141
- [
142
- yearsFromNow(5, 2),
143
- { isValid: true, isPotentiallyValid: true, isCurrentYear: false },
144
- ],
145
- [
146
- yearsFromNow(10, 2),
147
- { isValid: true, isPotentiallyValid: true, isCurrentYear: false },
148
- ],
149
- [
150
- yearsFromNow(11, 2),
151
- { isValid: true, isPotentiallyValid: true, isCurrentYear: false },
152
- ],
153
- [
154
- yearsFromNow(12, 2),
155
- { isValid: true, isPotentiallyValid: true, isCurrentYear: false },
156
- ],
157
- [
158
- yearsFromNow(19, 2),
159
- { isValid: true, isPotentiallyValid: true, isCurrentYear: false },
160
- ],
161
- [
162
- yearsFromNow(20, 2),
163
- { isValid: false, isPotentiallyValid: false, isCurrentYear: false },
164
- ],
165
- [
166
- yearsFromNow(25, 2),
167
- { isValid: false, isPotentiallyValid: false, isCurrentYear: false },
168
- ],
169
- [
170
- yearsFromNow(33, 2),
171
- { isValid: false, isPotentiallyValid: false, isCurrentYear: false },
172
- ],
173
- ],
174
- ],
175
-
176
- /*
177
- * This doesn't take 20xx -> 21xx into account, but probably YAGNI
178
- * (with apologies to whoever is possibly looking at this legacy
179
- * code long after we're dead
180
- * */
181
- [
182
- "accepts three-digit years",
183
- [
184
- [
185
- yearsFromNow(-3).slice(0, 3),
186
- { isValid: false, isPotentiallyValid: true, isCurrentYear: false },
187
- ],
188
- [
189
- yearsFromNow(-1).slice(0, 3),
190
- { isValid: false, isPotentiallyValid: true, isCurrentYear: false },
191
- ],
192
- [
193
- yearsFromNow(0).slice(0, 3),
194
- { isValid: false, isPotentiallyValid: true, isCurrentYear: false },
195
- ],
196
- [
197
- yearsFromNow(1).slice(0, 3),
198
- { isValid: false, isPotentiallyValid: true, isCurrentYear: false },
199
- ],
200
- [
201
- yearsFromNow(5).slice(0, 3),
202
- { isValid: false, isPotentiallyValid: true, isCurrentYear: false },
203
- ],
204
- [
205
- yearsFromNow(11).slice(0, 3),
206
- { isValid: false, isPotentiallyValid: true, isCurrentYear: false },
207
- ],
208
- [
209
- yearsFromNow(17).slice(0, 3),
210
- { isValid: false, isPotentiallyValid: true, isCurrentYear: false },
211
- ],
212
- [
213
- yearsFromNow(23).slice(0, 3),
214
- { isValid: false, isPotentiallyValid: true, isCurrentYear: false },
215
- ],
216
- ],
217
- ],
218
- ] as Array<[string, Array<[unknown, ExpirationYearVerification]>]>)(
219
- "%s",
220
- (description, tests) => {
221
- it.each(tests)("parses %s to be %p", (exp, meta) => {
222
- expect(expirationYear(exp)).toEqual(meta);
28
+ // Date picked at random from the past 5 years
29
+ const mockToday = new Date(2021, 5, 9);
30
+ jest.useFakeTimers().setSystemTime(mockToday);
31
+
32
+ describe("given a non-string value", () => {
33
+ test.each([
34
+ [[], INVALID],
35
+ [{}, INVALID],
36
+ [null, INVALID],
37
+ [undefined, INVALID], // eslint-disable-line no-undefined
38
+ [Infinity, INVALID],
39
+ [0 / 0, INVALID],
40
+ [0, INVALID],
41
+ [1, INVALID],
42
+ [2, INVALID],
43
+ [12, INVALID],
44
+ [-1, INVALID],
45
+ [-12, INVALID],
46
+ ])("%p is invalid", (value, output) => {
47
+ expect(expirationYear(value)).toEqual(output);
48
+ });
49
+ });
50
+
51
+ describe("given an empty string", () => {
52
+ it("returns as potentially valid", () => {
53
+ expect(expirationYear("")).toEqual(POTENTIALLY_VALID);
54
+ });
55
+ });
56
+
57
+ describe("given only whitespace", () => {
58
+ it("returns as potentially valid", () => {
59
+ expect(expirationYear(" ")).toEqual(POTENTIALLY_VALID);
60
+ });
61
+ });
62
+
63
+ describe("given a malformed string value", () => {
64
+ test.each([
65
+ ["foo", INVALID],
66
+ ["1.2", INVALID],
67
+ ["1/20", INVALID],
68
+ ["1 2", INVALID],
69
+ ["1 ", INVALID],
70
+ [" 1", INVALID],
71
+ ["20015", INVALID],
72
+ ])("%p is invalid", (value, output) => {
73
+ expect(expirationYear(value)).toEqual(output);
74
+ });
75
+ });
76
+
77
+ describe("given a 1 digit string", () => {
78
+ describe("that's not a number", () => {
79
+ test.each(["a", "#", ";", "\\", "+"])("%p is invalid", (value) => {
80
+ expect(expirationYear(value)).toEqual(INVALID);
223
81
  });
224
- },
225
- );
226
-
227
- it("defaults maxElapsedYear is 19", () => {
228
- expect(expirationYear(yearsFromNow(19))).toEqual({
229
- isValid: true,
230
- isPotentiallyValid: true,
231
- isCurrentYear: false,
232
82
  });
233
- expect(expirationYear(yearsFromNow(20))).toEqual({
234
- isValid: false,
235
- isPotentiallyValid: false,
236
- isCurrentYear: false,
83
+
84
+ describe("that is a number", () => {
85
+ test.each(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"])(
86
+ "%p is potentially valid",
87
+ (value) => {
88
+ expect(expirationYear(value)).toEqual(POTENTIALLY_VALID);
89
+ },
90
+ );
91
+ });
92
+ });
93
+
94
+ describe("given a 2 digit string", () => {
95
+ test.each([
96
+ ["19", INVALID],
97
+ ["20", POTENTIALLY_VALID],
98
+ ["21", CURRENT_YEAR],
99
+ ["22", VALID],
100
+ ["40", VALID],
101
+ ["41", INVALID],
102
+ ])("%p gives expected output", (value, output) => {
103
+ expect(expirationYear(value)).toEqual(output);
104
+ });
105
+ });
106
+
107
+ describe("given a 3 digit string", () => {
108
+ test.each([
109
+ ["000", INVALID],
110
+ ["123", INVALID],
111
+ ["200", POTENTIALLY_VALID],
112
+ ["201", POTENTIALLY_VALID],
113
+ ["202", POTENTIALLY_VALID],
114
+ ["203", POTENTIALLY_VALID],
115
+ ["204", POTENTIALLY_VALID],
116
+ ["205", POTENTIALLY_VALID],
117
+ ["206", POTENTIALLY_VALID],
118
+ ["207", POTENTIALLY_VALID],
119
+ ["208", POTENTIALLY_VALID],
120
+ ["209", POTENTIALLY_VALID],
121
+ ["210", INVALID],
122
+ ["300", INVALID],
123
+ ["999", INVALID],
124
+ ])("%p gives expected output", (value, output) => {
125
+ expect(expirationYear(value)).toEqual(output);
237
126
  });
238
127
  });
239
128
 
240
- it("accepts maxElapsedYear", () => {
241
- expect(expirationYear(yearsFromNow(20), 20)).toEqual({
242
- isValid: true,
243
- isPotentiallyValid: true,
244
- isCurrentYear: false,
129
+ describe("given a 4 digit string", () => {
130
+ test.each([
131
+ ["0000", INVALID],
132
+ ["1234", INVALID],
133
+ ["2020", INVALID],
134
+ ["2021", CURRENT_YEAR],
135
+ ["2022", VALID],
136
+ ["2040", VALID],
137
+ ["2041", INVALID],
138
+ ["3000", INVALID],
139
+ ["9999", INVALID],
140
+ ])("%p gives expected output", (value, output) => {
141
+ expect(expirationYear(value)).toEqual(output);
245
142
  });
246
- expect(expirationYear(yearsFromNow(21), 20)).toEqual({
247
- isValid: false,
248
- isPotentiallyValid: false,
249
- isCurrentYear: false,
143
+ });
144
+
145
+ describe("given a more than 4 digit string", () => {
146
+ test.each(["00000", "12345", "20021", "20202", "20211", "30000", "99999"])(
147
+ "%p is invalid",
148
+ (value) => {
149
+ expect(expirationYear(value)).toEqual(INVALID);
150
+ },
151
+ );
152
+ });
153
+
154
+ describe("given a custom max elapsed year", () => {
155
+ it("uses it correctly", () => {
156
+ expect(expirationYear("2020", 5)).toEqual(INVALID);
157
+ expect(expirationYear("2021", 5)).toEqual(CURRENT_YEAR);
158
+ expect(expirationYear("2022", 5)).toEqual(VALID);
159
+ expect(expirationYear("2026", 5)).toEqual(VALID);
160
+ expect(expirationYear("2027", 5)).toEqual(INVALID);
250
161
  });
251
162
  });
252
163
  });
@@ -32,6 +32,8 @@ describe("postalCode", () => {
32
32
  ["557016", { isValid: true, isPotentiallyValid: true }], // Romania
33
33
  ["110001", { isValid: true, isPotentiallyValid: true }], // India
34
34
  ["SE1 2LN", { isValid: true, isPotentiallyValid: true }], // UK
35
+ ["S9 1DF", { isValid: true, isPotentiallyValid: true }], // UK
36
+ ["AA9A 9AA", { isValid: true, isPotentiallyValid: true }], // UK
35
37
  ["01234567890123456789", { isValid: true, isPotentiallyValid: true }], // some hypothetical country
36
38
  ],
37
39
  ],
@@ -52,11 +54,11 @@ describe("postalCode", () => {
52
54
  ],
53
55
 
54
56
  [
55
- "returns isPotentiallyValid for shorter-than-3 strings",
57
+ "returns isPotentiallyValid for shorter-than-2 strings",
56
58
  [
57
59
  ["", { isValid: false, isPotentiallyValid: true }],
58
60
  ["1", { isValid: false, isPotentiallyValid: true }],
59
- ["12", { isValid: false, isPotentiallyValid: true }],
61
+ ["12", { isValid: true, isPotentiallyValid: true }],
60
62
  ],
61
63
  ],
62
64
  ] as Array<[string, Array<[string, Verification]>]>)(
@@ -79,10 +81,18 @@ describe("postalCode", () => {
79
81
  isPotentiallyValid: true,
80
82
  });
81
83
  expect(postalCode("12")).toEqual({
82
- isValid: false,
84
+ isValid: true,
83
85
  isPotentiallyValid: true,
84
86
  });
85
87
  expect(postalCode("12", {})).toEqual({
88
+ isValid: true,
89
+ isPotentiallyValid: true,
90
+ });
91
+ expect(postalCode("1")).toEqual({
92
+ isValid: false,
93
+ isPotentiallyValid: true,
94
+ });
95
+ expect(postalCode("1", {})).toEqual({
86
96
  isValid: false,
87
97
  isPotentiallyValid: true,
88
98
  });
@@ -4,7 +4,7 @@ type PostalCodeOptions = {
4
4
  minLength?: number;
5
5
  };
6
6
 
7
- const DEFAULT_MIN_POSTAL_CODE_LENGTH = 3;
7
+ const DEFAULT_MIN_POSTAL_CODE_LENGTH = 2;
8
8
  const ALPHANUM = new RegExp(/^[a-z0-9]+$/i);
9
9
 
10
10
  function verification(