@hy_ong/zod-kit 0.0.6 → 0.1.0
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.
- package/.claude/settings.local.json +4 -1
- package/dist/index.cjs +93 -89
- package/dist/index.d.cts +235 -169
- package/dist/index.d.ts +235 -169
- package/dist/index.js +93 -89
- package/package.json +2 -1
- package/src/validators/common/boolean.ts +17 -14
- package/src/validators/common/date.ts +21 -14
- package/src/validators/common/datetime.ts +21 -14
- package/src/validators/common/email.ts +18 -15
- package/src/validators/common/file.ts +20 -13
- package/src/validators/common/id.ts +14 -14
- package/src/validators/common/number.ts +18 -15
- package/src/validators/common/password.ts +21 -14
- package/src/validators/common/text.ts +21 -17
- package/src/validators/common/time.ts +21 -14
- package/src/validators/common/url.ts +22 -15
- package/src/validators/taiwan/business-id.ts +18 -11
- package/src/validators/taiwan/fax.ts +23 -14
- package/src/validators/taiwan/mobile.ts +23 -14
- package/src/validators/taiwan/national-id.ts +11 -12
- package/src/validators/taiwan/postal-code.ts +16 -17
- package/src/validators/taiwan/tel.ts +23 -14
- package/tests/common/boolean.test.ts +38 -38
- package/tests/common/date.test.ts +65 -65
- package/tests/common/datetime.test.ts +100 -118
- package/tests/common/email.test.ts +24 -28
- package/tests/common/file.test.ts +47 -51
- package/tests/common/id.test.ts +80 -113
- package/tests/common/number.test.ts +24 -25
- package/tests/common/password.test.ts +28 -35
- package/tests/common/text.test.ts +36 -37
- package/tests/common/time.test.ts +64 -82
- package/tests/common/url.test.ts +67 -67
- package/tests/taiwan/business-id.test.ts +22 -22
- package/tests/taiwan/fax.test.ts +33 -42
- package/tests/taiwan/mobile.test.ts +32 -41
- package/tests/taiwan/national-id.test.ts +31 -31
- package/tests/taiwan/postal-code.test.ts +142 -96
- package/tests/taiwan/tel.test.ts +33 -42
- package/debug.js +0 -21
- package/debug.ts +0 -16
|
@@ -2,16 +2,16 @@ import { describe, it, expect, beforeEach } from "vitest"
|
|
|
2
2
|
import { datetime, setLocale, validateDateTimeFormat, parseDateTimeValue, normalizeDateTimeValue } from "../../src"
|
|
3
3
|
import dayjs from "dayjs"
|
|
4
4
|
|
|
5
|
-
describe("Taiwan datetime() validator", () => {
|
|
5
|
+
describe("Taiwan datetime(true) validator", () => {
|
|
6
6
|
beforeEach(() => setLocale("en"))
|
|
7
7
|
|
|
8
8
|
describe("basic functionality", () => {
|
|
9
9
|
it("should validate correct datetime formats", () => {
|
|
10
|
-
const schemaISO = datetime({ format: "YYYY-MM-DD HH:mm" })
|
|
11
|
-
const schemaUS = datetime({ format: "MM/DD/YYYY HH:mm" })
|
|
12
|
-
const schemaEU = datetime({ format: "DD/MM/YYYY HH:mm" })
|
|
13
|
-
const schemaWithSeconds = datetime({ format: "YYYY-MM-DD HH:mm:ss" })
|
|
14
|
-
const schema12Hour = datetime({ format: "YYYY-MM-DD hh:mm A" })
|
|
10
|
+
const schemaISO = datetime(true, { format: "YYYY-MM-DD HH:mm" })
|
|
11
|
+
const schemaUS = datetime(true, { format: "MM/DD/YYYY HH:mm" })
|
|
12
|
+
const schemaEU = datetime(true, { format: "DD/MM/YYYY HH:mm" })
|
|
13
|
+
const schemaWithSeconds = datetime(true, { format: "YYYY-MM-DD HH:mm:ss" })
|
|
14
|
+
const schema12Hour = datetime(true, { format: "YYYY-MM-DD hh:mm A" })
|
|
15
15
|
|
|
16
16
|
// ISO format
|
|
17
17
|
expect(schemaISO.parse("2024-03-15 14:30")).toBe("2024-03-15 14:30")
|
|
@@ -37,9 +37,9 @@ describe("Taiwan datetime() validator", () => {
|
|
|
37
37
|
})
|
|
38
38
|
|
|
39
39
|
it("should validate special formats", () => {
|
|
40
|
-
const isoSchema = datetime({ format: "ISO" })
|
|
41
|
-
const rfcSchema = datetime({ format: "RFC" })
|
|
42
|
-
const unixSchema = datetime({ format: "UNIX" })
|
|
40
|
+
const isoSchema = datetime(true, { format: "ISO" })
|
|
41
|
+
const rfcSchema = datetime(true, { format: "RFC" })
|
|
42
|
+
const unixSchema = datetime(true, { format: "UNIX" })
|
|
43
43
|
|
|
44
44
|
// ISO 8601
|
|
45
45
|
expect(isoSchema.parse("2024-03-15T14:30:45.000Z")).toBe("2024-03-15T14:30:45.000Z")
|
|
@@ -53,7 +53,7 @@ describe("Taiwan datetime() validator", () => {
|
|
|
53
53
|
})
|
|
54
54
|
|
|
55
55
|
it("should reject invalid datetime formats", () => {
|
|
56
|
-
const schema = datetime({ format: "YYYY-MM-DD HH:mm" })
|
|
56
|
+
const schema = datetime(true, { format: "YYYY-MM-DD HH:mm" })
|
|
57
57
|
|
|
58
58
|
// Invalid date formats
|
|
59
59
|
expect(() => schema.parse("2024-13-15 14:30")).toThrow("Must be in YYYY-MM-DD HH:mm format")
|
|
@@ -65,7 +65,7 @@ describe("Taiwan datetime() validator", () => {
|
|
|
65
65
|
})
|
|
66
66
|
|
|
67
67
|
it("should handle whitespace trimming", () => {
|
|
68
|
-
const schema = datetime({ format: "YYYY-MM-DD HH:mm" })
|
|
68
|
+
const schema = datetime(true, { format: "YYYY-MM-DD HH:mm" })
|
|
69
69
|
|
|
70
70
|
expect(schema.parse(" 2024-03-15 14:30 ")).toBe("2024-03-15 14:30")
|
|
71
71
|
expect(schema.parse("\t2024-03-15 09:15\n")).toBe("2024-03-15 09:15")
|
|
@@ -74,9 +74,9 @@ describe("Taiwan datetime() validator", () => {
|
|
|
74
74
|
|
|
75
75
|
describe("whitelist functionality", () => {
|
|
76
76
|
it("should accept any string in whitelist regardless of format", () => {
|
|
77
|
-
const schema = datetime({
|
|
77
|
+
const schema = datetime(true, {
|
|
78
78
|
format: "YYYY-MM-DD HH:mm",
|
|
79
|
-
whitelist: ["now", "tomorrow", "TBD"]
|
|
79
|
+
whitelist: ["now", "tomorrow", "TBD"],
|
|
80
80
|
})
|
|
81
81
|
|
|
82
82
|
expect(schema.parse("now")).toBe("now")
|
|
@@ -86,10 +86,10 @@ describe("Taiwan datetime() validator", () => {
|
|
|
86
86
|
})
|
|
87
87
|
|
|
88
88
|
it("should reject values not in whitelist when whitelistOnly is true", () => {
|
|
89
|
-
const schema = datetime({
|
|
89
|
+
const schema = datetime(true, {
|
|
90
90
|
format: "YYYY-MM-DD HH:mm",
|
|
91
91
|
whitelist: ["now", "2024-03-15 14:30"],
|
|
92
|
-
whitelistOnly: true
|
|
92
|
+
whitelistOnly: true,
|
|
93
93
|
})
|
|
94
94
|
|
|
95
95
|
expect(schema.parse("now")).toBe("now")
|
|
@@ -101,9 +101,9 @@ describe("Taiwan datetime() validator", () => {
|
|
|
101
101
|
})
|
|
102
102
|
|
|
103
103
|
it("should work with empty whitelist", () => {
|
|
104
|
-
const schema = datetime({
|
|
104
|
+
const schema = datetime(true, {
|
|
105
105
|
format: "YYYY-MM-DD HH:mm",
|
|
106
|
-
whitelist: []
|
|
106
|
+
whitelist: [],
|
|
107
107
|
})
|
|
108
108
|
|
|
109
109
|
// With empty whitelist, should still validate datetime format
|
|
@@ -112,9 +112,9 @@ describe("Taiwan datetime() validator", () => {
|
|
|
112
112
|
})
|
|
113
113
|
|
|
114
114
|
it("should prioritize whitelist over format validation", () => {
|
|
115
|
-
const schema = datetime({
|
|
115
|
+
const schema = datetime(true, {
|
|
116
116
|
format: "YYYY-MM-DD HH:mm",
|
|
117
|
-
whitelist: ["anytime", "flexible", "TBD"]
|
|
117
|
+
whitelist: ["anytime", "flexible", "TBD"],
|
|
118
118
|
})
|
|
119
119
|
|
|
120
120
|
expect(schema.parse("anytime")).toBe("anytime")
|
|
@@ -126,7 +126,7 @@ describe("Taiwan datetime() validator", () => {
|
|
|
126
126
|
|
|
127
127
|
describe("required/optional behavior", () => {
|
|
128
128
|
it("should handle required=true (default)", () => {
|
|
129
|
-
const schema = datetime({ format: "YYYY-MM-DD HH:mm" })
|
|
129
|
+
const schema = datetime(true, { format: "YYYY-MM-DD HH:mm" })
|
|
130
130
|
|
|
131
131
|
expect(() => schema.parse("")).toThrow("Required")
|
|
132
132
|
expect(() => schema.parse(null)).toThrow("Required")
|
|
@@ -134,7 +134,7 @@ describe("Taiwan datetime() validator", () => {
|
|
|
134
134
|
})
|
|
135
135
|
|
|
136
136
|
it("should handle required=false", () => {
|
|
137
|
-
const schema = datetime({ format: "YYYY-MM-DD HH:mm"
|
|
137
|
+
const schema = datetime(false, { format: "YYYY-MM-DD HH:mm" })
|
|
138
138
|
|
|
139
139
|
expect(schema.parse("")).toBe(null)
|
|
140
140
|
expect(schema.parse(null)).toBe(null)
|
|
@@ -143,15 +143,11 @@ describe("Taiwan datetime() validator", () => {
|
|
|
143
143
|
})
|
|
144
144
|
|
|
145
145
|
it("should use default values", () => {
|
|
146
|
-
const requiredSchema = datetime({
|
|
147
|
-
format: "YYYY-MM-DD HH:mm",
|
|
148
|
-
defaultValue: "2024-01-01 12:00"
|
|
149
|
-
})
|
|
150
|
-
const optionalSchema = datetime({
|
|
146
|
+
const requiredSchema = datetime(true, {
|
|
151
147
|
format: "YYYY-MM-DD HH:mm",
|
|
152
|
-
|
|
153
|
-
defaultValue: "2024-01-01 12:00"
|
|
148
|
+
defaultValue: "2024-01-01 12:00",
|
|
154
149
|
})
|
|
150
|
+
const optionalSchema = datetime(false, { format: "YYYY-MM-DD HH:mm", defaultValue: "2024-01-01 12:00" })
|
|
155
151
|
|
|
156
152
|
expect(requiredSchema.parse("")).toBe("2024-01-01 12:00")
|
|
157
153
|
expect(requiredSchema.parse(null)).toBe("2024-01-01 12:00")
|
|
@@ -161,12 +157,7 @@ describe("Taiwan datetime() validator", () => {
|
|
|
161
157
|
})
|
|
162
158
|
|
|
163
159
|
it("should handle whitelist with optional fields", () => {
|
|
164
|
-
const schema = datetime({
|
|
165
|
-
format: "YYYY-MM-DD HH:mm",
|
|
166
|
-
required: false,
|
|
167
|
-
whitelist: ["flexible", "2024-03-15 14:30"],
|
|
168
|
-
whitelistOnly: true
|
|
169
|
-
})
|
|
160
|
+
const schema = datetime(false, { format: "YYYY-MM-DD HH:mm", whitelist: ["flexible", "2024-03-15 14:30"], whitelistOnly: true })
|
|
170
161
|
|
|
171
162
|
expect(schema.parse("")).toBe(null)
|
|
172
163
|
expect(schema.parse("flexible")).toBe("flexible")
|
|
@@ -177,10 +168,10 @@ describe("Taiwan datetime() validator", () => {
|
|
|
177
168
|
|
|
178
169
|
describe("datetime range validation", () => {
|
|
179
170
|
it("should validate minimum and maximum datetimes", () => {
|
|
180
|
-
const schema = datetime({
|
|
171
|
+
const schema = datetime(true, {
|
|
181
172
|
format: "YYYY-MM-DD HH:mm",
|
|
182
173
|
min: "2024-03-15 09:00",
|
|
183
|
-
max: "2024-03-15 17:00"
|
|
174
|
+
max: "2024-03-15 17:00",
|
|
184
175
|
})
|
|
185
176
|
|
|
186
177
|
// Valid datetimes within range
|
|
@@ -194,10 +185,10 @@ describe("Taiwan datetime() validator", () => {
|
|
|
194
185
|
})
|
|
195
186
|
|
|
196
187
|
it("should validate hour ranges", () => {
|
|
197
|
-
const schema = datetime({
|
|
188
|
+
const schema = datetime(true, {
|
|
198
189
|
format: "YYYY-MM-DD HH:mm",
|
|
199
190
|
minHour: 9,
|
|
200
|
-
maxHour: 17
|
|
191
|
+
maxHour: 17,
|
|
201
192
|
})
|
|
202
193
|
|
|
203
194
|
expect(schema.parse("2024-03-15 09:30")).toBe("2024-03-15 09:30")
|
|
@@ -208,9 +199,9 @@ describe("Taiwan datetime() validator", () => {
|
|
|
208
199
|
})
|
|
209
200
|
|
|
210
201
|
it("should validate allowed hours", () => {
|
|
211
|
-
const schema = datetime({
|
|
202
|
+
const schema = datetime(true, {
|
|
212
203
|
format: "YYYY-MM-DD HH:mm",
|
|
213
|
-
allowedHours: [9, 10, 14, 15, 16]
|
|
204
|
+
allowedHours: [9, 10, 14, 15, 16],
|
|
214
205
|
})
|
|
215
206
|
|
|
216
207
|
expect(schema.parse("2024-03-15 09:30")).toBe("2024-03-15 09:30")
|
|
@@ -222,9 +213,9 @@ describe("Taiwan datetime() validator", () => {
|
|
|
222
213
|
})
|
|
223
214
|
|
|
224
215
|
it("should validate minute steps", () => {
|
|
225
|
-
const schema = datetime({
|
|
216
|
+
const schema = datetime(true, {
|
|
226
217
|
format: "YYYY-MM-DD HH:mm",
|
|
227
|
-
minuteStep: 15
|
|
218
|
+
minuteStep: 15,
|
|
228
219
|
})
|
|
229
220
|
|
|
230
221
|
expect(schema.parse("2024-03-15 14:00")).toBe("2024-03-15 14:00")
|
|
@@ -239,9 +230,9 @@ describe("Taiwan datetime() validator", () => {
|
|
|
239
230
|
|
|
240
231
|
describe("temporal validation", () => {
|
|
241
232
|
it("should validate past dates", () => {
|
|
242
|
-
const schema = datetime({
|
|
233
|
+
const schema = datetime(true, {
|
|
243
234
|
format: "YYYY-MM-DD HH:mm",
|
|
244
|
-
mustBePast: true
|
|
235
|
+
mustBePast: true,
|
|
245
236
|
})
|
|
246
237
|
|
|
247
238
|
const pastDate = dayjs().subtract(1, "day").format("YYYY-MM-DD HH:mm")
|
|
@@ -252,9 +243,9 @@ describe("Taiwan datetime() validator", () => {
|
|
|
252
243
|
})
|
|
253
244
|
|
|
254
245
|
it("should validate future dates", () => {
|
|
255
|
-
const schema = datetime({
|
|
246
|
+
const schema = datetime(true, {
|
|
256
247
|
format: "YYYY-MM-DD HH:mm",
|
|
257
|
-
mustBeFuture: true
|
|
248
|
+
mustBeFuture: true,
|
|
258
249
|
})
|
|
259
250
|
|
|
260
251
|
const pastDate = dayjs().subtract(1, "day").format("YYYY-MM-DD HH:mm")
|
|
@@ -265,9 +256,9 @@ describe("Taiwan datetime() validator", () => {
|
|
|
265
256
|
})
|
|
266
257
|
|
|
267
258
|
it("should validate today", () => {
|
|
268
|
-
const schema = datetime({
|
|
259
|
+
const schema = datetime(true, {
|
|
269
260
|
format: "YYYY-MM-DD HH:mm",
|
|
270
|
-
mustBeToday: true
|
|
261
|
+
mustBeToday: true,
|
|
271
262
|
})
|
|
272
263
|
|
|
273
264
|
const todayDate = dayjs().format("YYYY-MM-DD") + " 14:30"
|
|
@@ -278,14 +269,14 @@ describe("Taiwan datetime() validator", () => {
|
|
|
278
269
|
})
|
|
279
270
|
|
|
280
271
|
it("should validate weekdays and weekends", () => {
|
|
281
|
-
const weekdaySchema = datetime({
|
|
272
|
+
const weekdaySchema = datetime(true, {
|
|
282
273
|
format: "YYYY-MM-DD HH:mm",
|
|
283
|
-
weekdaysOnly: true
|
|
274
|
+
weekdaysOnly: true,
|
|
284
275
|
})
|
|
285
276
|
|
|
286
|
-
const weekendSchema = datetime({
|
|
277
|
+
const weekendSchema = datetime(true, {
|
|
287
278
|
format: "YYYY-MM-DD HH:mm",
|
|
288
|
-
weekendsOnly: true
|
|
279
|
+
weekendsOnly: true,
|
|
289
280
|
})
|
|
290
281
|
|
|
291
282
|
// Find a Monday and a Saturday
|
|
@@ -302,20 +293,20 @@ describe("Taiwan datetime() validator", () => {
|
|
|
302
293
|
|
|
303
294
|
describe("timezone support", () => {
|
|
304
295
|
it("should handle timezone parsing", () => {
|
|
305
|
-
const schema = datetime({
|
|
296
|
+
const schema = datetime(true, {
|
|
306
297
|
format: "YYYY-MM-DD HH:mm",
|
|
307
|
-
timezone: "Asia/Taipei"
|
|
298
|
+
timezone: "Asia/Taipei",
|
|
308
299
|
})
|
|
309
300
|
|
|
310
301
|
expect(schema.parse("2024-03-15 14:30")).toBe("2024-03-15 14:30")
|
|
311
302
|
})
|
|
312
303
|
|
|
313
304
|
it("should validate with timezone-aware ranges", () => {
|
|
314
|
-
const schema = datetime({
|
|
305
|
+
const schema = datetime(true, {
|
|
315
306
|
format: "YYYY-MM-DD HH:mm",
|
|
316
307
|
timezone: "Asia/Taipei",
|
|
317
308
|
min: "2024-03-15 09:00",
|
|
318
|
-
max: "2024-03-15 17:00"
|
|
309
|
+
max: "2024-03-15 17:00",
|
|
319
310
|
})
|
|
320
311
|
|
|
321
312
|
expect(schema.parse("2024-03-15 12:30")).toBe("2024-03-15 12:30")
|
|
@@ -325,28 +316,28 @@ describe("Taiwan datetime() validator", () => {
|
|
|
325
316
|
|
|
326
317
|
describe("transform function", () => {
|
|
327
318
|
it("should apply custom transform", () => {
|
|
328
|
-
const schema = datetime({
|
|
319
|
+
const schema = datetime(true, {
|
|
329
320
|
format: "YYYY-MM-DD HH:mm",
|
|
330
|
-
transform: (val) => val.replace(/\//g, "-")
|
|
321
|
+
transform: (val) => val.replace(/\//g, "-"),
|
|
331
322
|
})
|
|
332
323
|
|
|
333
324
|
expect(schema.parse("2024/03/15 14:30")).toBe("2024-03-15 14:30")
|
|
334
325
|
})
|
|
335
326
|
|
|
336
327
|
it("should apply transform before validation", () => {
|
|
337
|
-
const schema = datetime({
|
|
328
|
+
const schema = datetime(true, {
|
|
338
329
|
format: "YYYY-MM-DD HH:mm",
|
|
339
|
-
transform: (val) => val.replace(/T/g, " ").replace(/Z$/, "")
|
|
330
|
+
transform: (val) => val.replace(/T/g, " ").replace(/Z$/, ""),
|
|
340
331
|
})
|
|
341
332
|
|
|
342
333
|
expect(schema.parse("2024-03-15T14:30Z")).toBe("2024-03-15 14:30")
|
|
343
334
|
})
|
|
344
335
|
|
|
345
336
|
it("should work with whitelist after transform", () => {
|
|
346
|
-
const schema = datetime({
|
|
337
|
+
const schema = datetime(true, {
|
|
347
338
|
format: "YYYY-MM-DD HH:mm",
|
|
348
339
|
whitelist: ["NOW", "2024-03-15 14:30"],
|
|
349
|
-
transform: (val) => val.toUpperCase()
|
|
340
|
+
transform: (val) => val.toUpperCase(),
|
|
350
341
|
})
|
|
351
342
|
|
|
352
343
|
expect(schema.parse("now")).toBe("NOW")
|
|
@@ -356,31 +347,31 @@ describe("Taiwan datetime() validator", () => {
|
|
|
356
347
|
|
|
357
348
|
describe("input preprocessing", () => {
|
|
358
349
|
it("should handle string conversion", () => {
|
|
359
|
-
const schema = datetime({ format: "UNIX" })
|
|
350
|
+
const schema = datetime(true, { format: "UNIX" })
|
|
360
351
|
|
|
361
352
|
// Test string conversion of numbers
|
|
362
353
|
expect(schema.parse(1710508245)).toBe("1710508245")
|
|
363
354
|
})
|
|
364
355
|
|
|
365
356
|
it("should trim whitespace", () => {
|
|
366
|
-
const schema = datetime({ format: "YYYY-MM-DD HH:mm" })
|
|
357
|
+
const schema = datetime(true, { format: "YYYY-MM-DD HH:mm" })
|
|
367
358
|
|
|
368
359
|
expect(schema.parse(" 2024-03-15 14:30 ")).toBe("2024-03-15 14:30")
|
|
369
360
|
expect(schema.parse("\t2024-03-15 09:15\n")).toBe("2024-03-15 09:15")
|
|
370
361
|
})
|
|
371
362
|
|
|
372
363
|
it("should handle different trim modes", () => {
|
|
373
|
-
const trimStartSchema = datetime({
|
|
364
|
+
const trimStartSchema = datetime(true, {
|
|
374
365
|
format: "YYYY-MM-DD HH:mm",
|
|
375
|
-
trimMode: "trimStart"
|
|
366
|
+
trimMode: "trimStart",
|
|
376
367
|
})
|
|
377
|
-
const trimEndSchema = datetime({
|
|
368
|
+
const trimEndSchema = datetime(true, {
|
|
378
369
|
format: "YYYY-MM-DD HH:mm",
|
|
379
|
-
trimMode: "trimEnd"
|
|
370
|
+
trimMode: "trimEnd",
|
|
380
371
|
})
|
|
381
|
-
const noTrimSchema = datetime({
|
|
372
|
+
const noTrimSchema = datetime(true, {
|
|
382
373
|
format: "YYYY-MM-DD HH:mm",
|
|
383
|
-
trimMode: "none"
|
|
374
|
+
trimMode: "none",
|
|
384
375
|
})
|
|
385
376
|
|
|
386
377
|
expect(trimStartSchema.parse(" 2024-03-15 14:30 ")).toBe("2024-03-15 14:30 ")
|
|
@@ -389,10 +380,10 @@ describe("Taiwan datetime() validator", () => {
|
|
|
389
380
|
})
|
|
390
381
|
|
|
391
382
|
it("should handle case transformations", () => {
|
|
392
|
-
const upperSchema = datetime({
|
|
383
|
+
const upperSchema = datetime(true, {
|
|
393
384
|
format: "YYYY-MM-DD HH:mm",
|
|
394
385
|
whitelist: ["NOW", "TOMORROW"],
|
|
395
|
-
casing: "upper"
|
|
386
|
+
casing: "upper",
|
|
396
387
|
})
|
|
397
388
|
|
|
398
389
|
expect(upperSchema.parse("now")).toBe("NOW")
|
|
@@ -402,8 +393,8 @@ describe("Taiwan datetime() validator", () => {
|
|
|
402
393
|
|
|
403
394
|
describe("custom regex validation", () => {
|
|
404
395
|
it("should use custom regex instead of format validation", () => {
|
|
405
|
-
const schema = datetime({
|
|
406
|
-
regex: /^(morning|afternoon|evening|night)
|
|
396
|
+
const schema = datetime(true, {
|
|
397
|
+
regex: /^(morning|afternoon|evening|night)$/,
|
|
407
398
|
})
|
|
408
399
|
|
|
409
400
|
expect(schema.parse("morning")).toBe("morning")
|
|
@@ -412,9 +403,9 @@ describe("Taiwan datetime() validator", () => {
|
|
|
412
403
|
})
|
|
413
404
|
|
|
414
405
|
it("should skip datetime parsing with custom regex", () => {
|
|
415
|
-
const schema = datetime({
|
|
406
|
+
const schema = datetime(true, {
|
|
416
407
|
regex: /^(now|later|asap)$/,
|
|
417
|
-
mustBePast: true // This should be ignored when using regex
|
|
408
|
+
mustBePast: true, // This should be ignored when using regex
|
|
418
409
|
})
|
|
419
410
|
|
|
420
411
|
expect(schema.parse("now")).toBe("now")
|
|
@@ -425,9 +416,9 @@ describe("Taiwan datetime() validator", () => {
|
|
|
425
416
|
|
|
426
417
|
describe("includes/excludes validation", () => {
|
|
427
418
|
it("should validate includes", () => {
|
|
428
|
-
const schema = datetime({
|
|
419
|
+
const schema = datetime(true, {
|
|
429
420
|
format: "YYYY-MM-DD HH:mm",
|
|
430
|
-
includes: "2024"
|
|
421
|
+
includes: "2024",
|
|
431
422
|
})
|
|
432
423
|
|
|
433
424
|
expect(schema.parse("2024-03-15 14:30")).toBe("2024-03-15 14:30")
|
|
@@ -435,9 +426,9 @@ describe("Taiwan datetime() validator", () => {
|
|
|
435
426
|
})
|
|
436
427
|
|
|
437
428
|
it("should validate excludes", () => {
|
|
438
|
-
const schema = datetime({
|
|
429
|
+
const schema = datetime(true, {
|
|
439
430
|
regex: /^[\d\-\s:test]+$/, // Custom regex to allow "test" in the string
|
|
440
|
-
excludes: ["test", "invalid"]
|
|
431
|
+
excludes: ["test", "invalid"],
|
|
441
432
|
})
|
|
442
433
|
|
|
443
434
|
expect(schema.parse("2024-03-15 14:30")).toBe("2024-03-15 14:30")
|
|
@@ -513,13 +504,13 @@ describe("Taiwan datetime() validator", () => {
|
|
|
513
504
|
describe("i18n support", () => {
|
|
514
505
|
it("should use English messages by default", () => {
|
|
515
506
|
setLocale("en")
|
|
516
|
-
expect(() => datetime().parse("")).toThrow("Required")
|
|
517
|
-
expect(() => datetime().parse("invalid")).toThrow("Must be in YYYY-MM-DD HH:mm format")
|
|
507
|
+
expect(() => datetime(true).parse("")).toThrow("Required")
|
|
508
|
+
expect(() => datetime(true).parse("invalid")).toThrow("Must be in YYYY-MM-DD HH:mm format")
|
|
518
509
|
})
|
|
519
510
|
|
|
520
511
|
it("should use Chinese messages when locale is zh-TW", () => {
|
|
521
512
|
setLocale("zh-TW")
|
|
522
|
-
const schema = datetime({ format: "YYYY-MM-DD HH:mm" })
|
|
513
|
+
const schema = datetime(true, { format: "YYYY-MM-DD HH:mm" })
|
|
523
514
|
|
|
524
515
|
expect(() => schema.parse("")).toThrow("必填")
|
|
525
516
|
expect(() => schema.parse("invalid")).toThrow("必須為 YYYY-MM-DD HH:mm 格式")
|
|
@@ -527,28 +518,28 @@ describe("Taiwan datetime() validator", () => {
|
|
|
527
518
|
|
|
528
519
|
it("should support whitelist error messages", () => {
|
|
529
520
|
setLocale("en")
|
|
530
|
-
const schema = datetime({
|
|
521
|
+
const schema = datetime(true, {
|
|
531
522
|
format: "YYYY-MM-DD HH:mm",
|
|
532
523
|
whitelist: ["now"],
|
|
533
|
-
whitelistOnly: true
|
|
524
|
+
whitelistOnly: true,
|
|
534
525
|
})
|
|
535
526
|
|
|
536
527
|
expect(() => schema.parse("2024-03-15 14:30")).toThrow("DateTime is not in the allowed list")
|
|
537
528
|
})
|
|
538
529
|
|
|
539
530
|
it("should support custom i18n messages", () => {
|
|
540
|
-
const schema = datetime({
|
|
531
|
+
const schema = datetime(true, {
|
|
541
532
|
format: "YYYY-MM-DD HH:mm",
|
|
542
533
|
i18n: {
|
|
543
534
|
en: {
|
|
544
535
|
required: "DateTime is required",
|
|
545
|
-
invalid: "Invalid datetime value"
|
|
536
|
+
invalid: "Invalid datetime value",
|
|
546
537
|
},
|
|
547
538
|
"zh-TW": {
|
|
548
539
|
required: "請輸入日期時間",
|
|
549
|
-
invalid: "無效的日期時間值"
|
|
550
|
-
}
|
|
551
|
-
}
|
|
540
|
+
invalid: "無效的日期時間值",
|
|
541
|
+
},
|
|
542
|
+
},
|
|
552
543
|
})
|
|
553
544
|
|
|
554
545
|
setLocale("en")
|
|
@@ -559,18 +550,18 @@ describe("Taiwan datetime() validator", () => {
|
|
|
559
550
|
})
|
|
560
551
|
|
|
561
552
|
it("should support custom whitelist messages", () => {
|
|
562
|
-
const schema = datetime({
|
|
553
|
+
const schema = datetime(true, {
|
|
563
554
|
format: "YYYY-MM-DD HH:mm",
|
|
564
555
|
whitelist: ["now"],
|
|
565
556
|
whitelistOnly: true,
|
|
566
557
|
i18n: {
|
|
567
558
|
en: {
|
|
568
|
-
notInWhitelist: "This datetime is not allowed"
|
|
559
|
+
notInWhitelist: "This datetime is not allowed",
|
|
569
560
|
},
|
|
570
561
|
"zh-TW": {
|
|
571
|
-
notInWhitelist: "此日期時間不被允許"
|
|
572
|
-
}
|
|
573
|
-
}
|
|
562
|
+
notInWhitelist: "此日期時間不被允許",
|
|
563
|
+
},
|
|
564
|
+
},
|
|
574
565
|
})
|
|
575
566
|
|
|
576
567
|
setLocale("en")
|
|
@@ -583,12 +574,12 @@ describe("Taiwan datetime() validator", () => {
|
|
|
583
574
|
|
|
584
575
|
describe("real world datetime scenarios", () => {
|
|
585
576
|
it("should validate business hours", () => {
|
|
586
|
-
const businessHours = datetime({
|
|
577
|
+
const businessHours = datetime(true, {
|
|
587
578
|
format: "YYYY-MM-DD HH:mm",
|
|
588
579
|
minHour: 9,
|
|
589
580
|
maxHour: 17,
|
|
590
581
|
weekdaysOnly: true,
|
|
591
|
-
minuteStep: 30
|
|
582
|
+
minuteStep: 30,
|
|
592
583
|
})
|
|
593
584
|
|
|
594
585
|
expect(businessHours.parse("2024-03-18 09:00")).toBe("2024-03-18 09:00") // Monday
|
|
@@ -599,11 +590,11 @@ describe("Taiwan datetime() validator", () => {
|
|
|
599
590
|
})
|
|
600
591
|
|
|
601
592
|
it("should validate appointment slots", () => {
|
|
602
|
-
const appointmentSlots = datetime({
|
|
593
|
+
const appointmentSlots = datetime(true, {
|
|
603
594
|
format: "YYYY-MM-DD HH:mm",
|
|
604
595
|
allowedHours: [9, 10, 11, 14, 15, 16],
|
|
605
596
|
minuteStep: 30,
|
|
606
|
-
weekdaysOnly: true
|
|
597
|
+
weekdaysOnly: true,
|
|
607
598
|
})
|
|
608
599
|
|
|
609
600
|
expect(appointmentSlots.parse("2024-03-18 09:00")).toBe("2024-03-18 09:00")
|
|
@@ -614,11 +605,7 @@ describe("Taiwan datetime() validator", () => {
|
|
|
614
605
|
})
|
|
615
606
|
|
|
616
607
|
it("should handle flexible datetime input", () => {
|
|
617
|
-
const flexibleDateTime = datetime({
|
|
618
|
-
format: "YYYY-MM-DD HH:mm",
|
|
619
|
-
whitelist: ["now", "tomorrow", "next week", "asap"],
|
|
620
|
-
required: false
|
|
621
|
-
})
|
|
608
|
+
const flexibleDateTime = datetime(false, { format: "YYYY-MM-DD HH:mm", whitelist: ["now", "tomorrow", "next week", "asap"] })
|
|
622
609
|
|
|
623
610
|
expect(flexibleDateTime.parse("now")).toBe("now")
|
|
624
611
|
expect(flexibleDateTime.parse("2024-03-15 14:30")).toBe("2024-03-15 14:30")
|
|
@@ -629,15 +616,15 @@ describe("Taiwan datetime() validator", () => {
|
|
|
629
616
|
|
|
630
617
|
describe("edge cases", () => {
|
|
631
618
|
it("should handle various input types", () => {
|
|
632
|
-
const schema = datetime({ format: "UNIX" })
|
|
619
|
+
const schema = datetime(true, { format: "UNIX" })
|
|
633
620
|
|
|
634
621
|
expect(schema.parse("1710508245")).toBe("1710508245")
|
|
635
622
|
expect(schema.parse(1710508245)).toBe("1710508245")
|
|
636
623
|
})
|
|
637
624
|
|
|
638
625
|
it("should handle empty and whitespace inputs", () => {
|
|
639
|
-
const requiredSchema = datetime({ format: "YYYY-MM-DD HH:mm"
|
|
640
|
-
const optionalSchema = datetime({ format: "YYYY-MM-DD HH:mm"
|
|
626
|
+
const requiredSchema = datetime(true, { format: "YYYY-MM-DD HH:mm" })
|
|
627
|
+
const optionalSchema = datetime(false, { format: "YYYY-MM-DD HH:mm" })
|
|
641
628
|
|
|
642
629
|
expect(() => requiredSchema.parse("")).toThrow("Required")
|
|
643
630
|
expect(() => requiredSchema.parse(" ")).toThrow("Required")
|
|
@@ -647,21 +634,16 @@ describe("Taiwan datetime() validator", () => {
|
|
|
647
634
|
})
|
|
648
635
|
|
|
649
636
|
it("should preserve valid format after transformation", () => {
|
|
650
|
-
const schema = datetime({
|
|
637
|
+
const schema = datetime(true, {
|
|
651
638
|
format: "YYYY-MM-DD HH:mm",
|
|
652
|
-
transform: (val) => val.replace(/[^0-9:\-\s]/g, "")
|
|
639
|
+
transform: (val) => val.replace(/[^0-9:\-\s]/g, ""),
|
|
653
640
|
})
|
|
654
641
|
|
|
655
642
|
expect(schema.parse("2024abc-03def-15 14:30")).toBe("2024-03-15 14:30")
|
|
656
643
|
})
|
|
657
644
|
|
|
658
645
|
it("should work with complex whitelist scenarios", () => {
|
|
659
|
-
const schema = datetime({
|
|
660
|
-
format: "YYYY-MM-DD HH:mm",
|
|
661
|
-
whitelist: ["2024-03-15 14:30", "TBD", "flexible", ""],
|
|
662
|
-
whitelistOnly: true,
|
|
663
|
-
required: false
|
|
664
|
-
})
|
|
646
|
+
const schema = datetime(false, { format: "YYYY-MM-DD HH:mm", whitelist: ["2024-03-15 14:30", "TBD", "flexible", ""], whitelistOnly: true })
|
|
665
647
|
|
|
666
648
|
// Whitelist scenarios
|
|
667
649
|
expect(schema.parse("2024-03-15 14:30")).toBe("2024-03-15 14:30")
|
|
@@ -674,8 +656,8 @@ describe("Taiwan datetime() validator", () => {
|
|
|
674
656
|
})
|
|
675
657
|
|
|
676
658
|
it("should handle boundary cases for different formats", () => {
|
|
677
|
-
const schema24 = datetime({ format: "YYYY-MM-DD HH:mm" })
|
|
678
|
-
const schema12 = datetime({ format: "YYYY-MM-DD hh:mm A" })
|
|
659
|
+
const schema24 = datetime(true, { format: "YYYY-MM-DD HH:mm" })
|
|
660
|
+
const schema12 = datetime(true, { format: "YYYY-MM-DD hh:mm A" })
|
|
679
661
|
|
|
680
662
|
// Valid boundary cases
|
|
681
663
|
expect(schema24.parse("2024-01-01 00:00")).toBe("2024-01-01 00:00")
|
|
@@ -690,4 +672,4 @@ describe("Taiwan datetime() validator", () => {
|
|
|
690
672
|
expect(() => schema12.parse("2024-01-01 13:00 PM")).toThrow("Must be in YYYY-MM-DD hh:mm A format")
|
|
691
673
|
})
|
|
692
674
|
})
|
|
693
|
-
})
|
|
675
|
+
})
|