@wwog/react 1.3.12 → 1.3.13

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,407 +1,403 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { ruleChecker } from './ruleChecker';
3
- import type { RuleDescription } from './ruleChecker';
1
+ import {describe, expect, it} from 'vitest'
2
+ import {ruleChecker} from './ruleChecker'
3
+ import type {RuleDescription} from './ruleChecker'
4
4
 
5
5
  describe('ruleChecker', () => {
6
6
  // ==== 基础功能测试 ====
7
7
  describe('基础功能', () => {
8
8
  it('应该通过空规则验证', () => {
9
- const result = ruleChecker({}, {});
10
- expect(result.valid).toBe(true);
9
+ const result = ruleChecker({}, {})
10
+ expect(result.valid).toBe(true)
11
11
  if (result.valid) {
12
- expect(result.data).toEqual({});
12
+ expect(result.data).toEqual({})
13
13
  }
14
- });
14
+ })
15
15
 
16
16
  it('应该验证 required 规则 - 成功', () => {
17
- const data = { name: 'John' };
17
+ const data = {name: 'John'}
18
18
  const rules: RuleDescription<typeof data> = {
19
- name: { required: true },
20
- };
21
- const result = ruleChecker(data, rules);
22
- expect(result.valid).toBe(true);
19
+ name: {required: true},
20
+ }
21
+ const result = ruleChecker(data, rules)
22
+ expect(result.valid).toBe(true)
23
23
  if (result.valid) {
24
- expect(result.data.name).toBe('John');
24
+ expect(result.data.name).toBe('John')
25
25
  }
26
- });
26
+ })
27
27
 
28
28
  it('应该验证 required 规则 - 失败', () => {
29
- const data = { name: '' };
29
+ const data = {name: ''}
30
30
  const rules: RuleDescription<typeof data> = {
31
- name: { required: true },
32
- };
33
- const result = ruleChecker(data, rules);
34
- expect(result.valid).toBe(false);
31
+ name: {required: true},
32
+ }
33
+ const result = ruleChecker(data, rules)
34
+ expect(result.valid).toBe(false)
35
35
  if (!result.valid) {
36
- expect(result.errors).toContain('name 为必填项');
37
- expect(result.fieldErrors.name).toContain('name 为必填项');
36
+ expect(result.errors).toContain('name 为必填项')
37
+ expect(result.fieldErrors.name).toContain('name 为必填项')
38
38
  }
39
- });
39
+ })
40
40
 
41
41
  it('应该使用自定义错误消息', () => {
42
- const data = { email: '' };
42
+ const data = {email: ''}
43
43
  const rules: RuleDescription<typeof data> = {
44
- email: { required: true, message: '邮箱不能为空' },
45
- };
46
- const result = ruleChecker(data, rules);
47
- expect(result.valid).toBe(false);
44
+ email: {required: true, message: '邮箱不能为空'},
45
+ }
46
+ const result = ruleChecker(data, rules)
47
+ expect(result.valid).toBe(false)
48
48
  if (!result.valid) {
49
- expect(result.errors).toContain('邮箱不能为空');
49
+ expect(result.errors).toContain('邮箱不能为空')
50
50
  }
51
- });
51
+ })
52
52
 
53
53
  it('应该处理 null 和 undefined 值', () => {
54
- type DataType = { name: string | null; age?: number };
55
- const data: Partial<DataType> = { name: null, age: undefined };
54
+ type DataType = {name: string | null; age?: number}
55
+ const data: Partial<DataType> = {name: null, age: undefined}
56
56
  const rules: RuleDescription<DataType> = {
57
- name: { required: true },
58
- age: { required: false },
59
- };
60
- const result = ruleChecker(data, rules);
61
- expect(result.valid).toBe(false);
57
+ name: {required: true},
58
+ age: {required: false},
59
+ }
60
+ const result = ruleChecker(data, rules)
61
+ expect(result.valid).toBe(false)
62
62
  if (!result.valid) {
63
- expect(result.fieldErrors.name).toContain('name 为必填项');
64
- expect(result.fieldErrors.age).toBeUndefined();
63
+ expect(result.fieldErrors.name).toContain('name 为必填项')
64
+ expect(result.fieldErrors.age).toBeUndefined()
65
65
  }
66
- });
66
+ })
67
67
 
68
68
  it('应该验证自定义 validator - 返回 boolean', () => {
69
- const data = { password: '123' };
69
+ const data = {password: '123'}
70
70
  const rules: RuleDescription<typeof data> = {
71
71
  password: {
72
72
  validator: (value) => value.length >= 6,
73
73
  message: '密码至少6位',
74
74
  },
75
- };
76
- const result = ruleChecker(data, rules);
77
- expect(result.valid).toBe(false);
75
+ }
76
+ const result = ruleChecker(data, rules)
77
+ expect(result.valid).toBe(false)
78
78
  if (!result.valid) {
79
- expect(result.errors).toContain('密码至少6位');
79
+ expect(result.errors).toContain('密码至少6位')
80
80
  }
81
- });
81
+ })
82
82
 
83
83
  it('应该验证自定义 validator - 返回 string', () => {
84
- const data = { username: 'admin' };
84
+ const data = {username: 'admin'}
85
85
  const rules: RuleDescription<typeof data> = {
86
86
  username: {
87
- validator: (value) =>
88
- value === 'admin' ? '用户名不能是admin' : true,
87
+ validator: (value) => (value === 'admin' ? '用户名不能是admin' : true),
89
88
  },
90
- };
91
- const result = ruleChecker(data, rules);
92
- expect(result.valid).toBe(false);
89
+ }
90
+ const result = ruleChecker(data, rules)
91
+ expect(result.valid).toBe(false)
93
92
  if (!result.valid) {
94
- expect(result.errors).toContain('用户名不能是admin');
93
+ expect(result.errors).toContain('用户名不能是admin')
95
94
  }
96
- });
97
- });
95
+ })
96
+ })
98
97
 
99
98
  // ==== 字符串规则测试 ====
100
99
  describe('字符串规则', () => {
101
100
  it('应该验证字符串长度 len', () => {
102
- const data = { code: '123' };
101
+ const data = {code: '123'}
103
102
  const rules: RuleDescription<typeof data> = {
104
- code: { len: 4 },
105
- };
106
- const result = ruleChecker(data, rules);
107
- expect(result.valid).toBe(false);
103
+ code: {len: 4},
104
+ }
105
+ const result = ruleChecker(data, rules)
106
+ expect(result.valid).toBe(false)
108
107
  if (!result.valid) {
109
- expect(result.errors).toContain('code 长度必须为 4');
108
+ expect(result.errors).toContain('code 长度必须为 4')
110
109
  }
111
- });
110
+ })
112
111
 
113
112
  it('应该验证字符串最小长度 min', () => {
114
- const data = { username: 'ab' };
113
+ const data = {username: 'ab'}
115
114
  const rules: RuleDescription<typeof data> = {
116
- username: { min: 3 },
117
- };
118
- const result = ruleChecker(data, rules);
119
- expect(result.valid).toBe(false);
115
+ username: {min: 3},
116
+ }
117
+ const result = ruleChecker(data, rules)
118
+ expect(result.valid).toBe(false)
120
119
  if (!result.valid) {
121
- expect(result.errors).toContain('username 长度不能少于 3');
120
+ expect(result.errors).toContain('username 长度不能少于 3')
122
121
  }
123
- });
122
+ })
124
123
 
125
124
  it('应该验证字符串最大长度 max', () => {
126
- const data = { comment: 'a'.repeat(101) };
125
+ const data = {comment: 'a'.repeat(101)}
127
126
  const rules: RuleDescription<typeof data> = {
128
- comment: { max: 100 },
129
- };
130
- const result = ruleChecker(data, rules);
131
- expect(result.valid).toBe(false);
127
+ comment: {max: 100},
128
+ }
129
+ const result = ruleChecker(data, rules)
130
+ expect(result.valid).toBe(false)
132
131
  if (!result.valid) {
133
- expect(result.errors).toContain('comment 长度不能超过 100');
132
+ expect(result.errors).toContain('comment 长度不能超过 100')
134
133
  }
135
- });
134
+ })
136
135
 
137
136
  it('应该验证正则表达式', () => {
138
- const data = { phone: '123456' };
137
+ const data = {phone: '123456'}
139
138
  const rules: RuleDescription<typeof data> = {
140
- phone: { regex: /^\d{11}$/ },
141
- };
142
- const result = ruleChecker(data, rules);
143
- expect(result.valid).toBe(false);
139
+ phone: {regex: /^\d{11}$/},
140
+ }
141
+ const result = ruleChecker(data, rules)
142
+ expect(result.valid).toBe(false)
144
143
  if (!result.valid) {
145
- expect(result.errors).toContain('phone 格式不正确');
144
+ expect(result.errors).toContain('phone 格式不正确')
146
145
  }
147
- });
146
+ })
148
147
 
149
148
  it('应该验证邮箱格式', () => {
150
- const data = { email: 'invalid-email' };
149
+ const data = {email: 'invalid-email'}
151
150
  const rules: RuleDescription<typeof data> = {
152
- email: { email: true },
153
- };
154
- const result = ruleChecker(data, rules);
155
- expect(result.valid).toBe(false);
151
+ email: {email: true},
152
+ }
153
+ const result = ruleChecker(data, rules)
154
+ expect(result.valid).toBe(false)
156
155
  if (!result.valid) {
157
- expect(result.errors).toContain('email 不是有效的邮箱');
156
+ expect(result.errors).toContain('email 不是有效的邮箱')
158
157
  }
159
- });
158
+ })
160
159
 
161
160
  it('应该通过有效的邮箱验证', () => {
162
- const data = { email: 'test@example.com' };
161
+ const data = {email: 'test@example.com'}
163
162
  const rules: RuleDescription<typeof data> = {
164
- email: { email: true },
165
- };
166
- const result = ruleChecker(data, rules);
167
- expect(result.valid).toBe(true);
168
- });
163
+ email: {email: true},
164
+ }
165
+ const result = ruleChecker(data, rules)
166
+ expect(result.valid).toBe(true)
167
+ })
169
168
 
170
169
  it('应该验证URL格式', () => {
171
- const data = { website: 'invalid-url' };
170
+ const data = {website: 'invalid-url'}
172
171
  const rules: RuleDescription<typeof data> = {
173
- website: { url: true },
174
- };
175
- const result = ruleChecker(data, rules);
176
- expect(result.valid).toBe(false);
172
+ website: {url: true},
173
+ }
174
+ const result = ruleChecker(data, rules)
175
+ expect(result.valid).toBe(false)
177
176
  if (!result.valid) {
178
- expect(result.errors).toContain('website 不是有效的URL');
177
+ expect(result.errors).toContain('website 不是有效的URL')
179
178
  }
180
- });
179
+ })
181
180
 
182
181
  it('应该通过有效的URL验证', () => {
183
- const data = { website: 'https://example.com' };
182
+ const data = {website: 'https://example.com'}
184
183
  const rules: RuleDescription<typeof data> = {
185
- website: { url: true },
186
- };
187
- const result = ruleChecker(data, rules);
188
- expect(result.valid).toBe(true);
189
- });
184
+ website: {url: true},
185
+ }
186
+ const result = ruleChecker(data, rules)
187
+ expect(result.valid).toBe(true)
188
+ })
190
189
 
191
190
  it('应该验证手机号格式', () => {
192
- const data = { mobile: '123456789' };
191
+ const data = {mobile: '123456789'}
193
192
  const rules: RuleDescription<typeof data> = {
194
- mobile: { phone: true },
195
- };
196
- const result = ruleChecker(data, rules);
197
- expect(result.valid).toBe(false);
193
+ mobile: {phone: true},
194
+ }
195
+ const result = ruleChecker(data, rules)
196
+ expect(result.valid).toBe(false)
198
197
  if (!result.valid) {
199
- expect(result.errors).toContain('mobile 不是有效的手机号');
198
+ expect(result.errors).toContain('mobile 不是有效的手机号')
200
199
  }
201
- });
200
+ })
202
201
 
203
202
  it('应该通过有效的手机号验证', () => {
204
- const data = { mobile: '13812345678' };
203
+ const data = {mobile: '13812345678'}
205
204
  const rules: RuleDescription<typeof data> = {
206
- mobile: { phone: true },
207
- };
208
- const result = ruleChecker(data, rules);
209
- expect(result.valid).toBe(true);
210
- });
211
- });
205
+ mobile: {phone: true},
206
+ }
207
+ const result = ruleChecker(data, rules)
208
+ expect(result.valid).toBe(true)
209
+ })
210
+ })
212
211
 
213
212
  // ==== 数字规则测试 ====
214
213
  describe('数字规则', () => {
215
214
  it('应该验证数字最小值', () => {
216
- const data = { age: 5 };
215
+ const data = {age: 5}
217
216
  const rules: RuleDescription<typeof data> = {
218
- age: { min: 18 },
219
- };
220
- const result = ruleChecker(data, rules);
221
- expect(result.valid).toBe(false);
217
+ age: {min: 18},
218
+ }
219
+ const result = ruleChecker(data, rules)
220
+ expect(result.valid).toBe(false)
222
221
  if (!result.valid) {
223
- expect(result.errors).toContain('age 不能小于 18');
222
+ expect(result.errors).toContain('age 不能小于 18')
224
223
  }
225
- });
224
+ })
226
225
 
227
226
  it('应该验证数字最大值', () => {
228
- const data = { score: 105 };
227
+ const data = {score: 105}
229
228
  const rules: RuleDescription<typeof data> = {
230
- score: { max: 100 },
231
- };
232
- const result = ruleChecker(data, rules);
233
- expect(result.valid).toBe(false);
229
+ score: {max: 100},
230
+ }
231
+ const result = ruleChecker(data, rules)
232
+ expect(result.valid).toBe(false)
234
233
  if (!result.valid) {
235
- expect(result.errors).toContain('score 不能大于 100');
234
+ expect(result.errors).toContain('score 不能大于 100')
236
235
  }
237
- });
236
+ })
238
237
 
239
238
  it('应该通过数字范围验证', () => {
240
- const data = { percentage: 85 };
239
+ const data = {percentage: 85}
241
240
  const rules: RuleDescription<typeof data> = {
242
- percentage: { min: 0, max: 100 },
243
- };
244
- const result = ruleChecker(data, rules);
245
- expect(result.valid).toBe(true);
246
- });
247
- });
241
+ percentage: {min: 0, max: 100},
242
+ }
243
+ const result = ruleChecker(data, rules)
244
+ expect(result.valid).toBe(true)
245
+ })
246
+ })
248
247
 
249
248
  // ==== 数组规则测试 ====
250
249
  describe('数组规则', () => {
251
250
  it('应该验证数组长度 len', () => {
252
- const data = { items: [1, 2, 3] };
251
+ const data = {items: [1, 2, 3]}
253
252
  const rules: RuleDescription<typeof data> = {
254
- items: { len: 5 },
255
- };
256
- const result = ruleChecker(data, rules);
257
- expect(result.valid).toBe(false);
253
+ items: {len: 5},
254
+ }
255
+ const result = ruleChecker(data, rules)
256
+ expect(result.valid).toBe(false)
258
257
  if (!result.valid) {
259
- expect(result.errors).toContain('items 长度必须为 5');
258
+ expect(result.errors).toContain('items 长度必须为 5')
260
259
  }
261
- });
260
+ })
262
261
 
263
262
  it('应该验证数组最小长度', () => {
264
- const data = { tags: ['one'] };
263
+ const data = {tags: ['one']}
265
264
  const rules: RuleDescription<typeof data> = {
266
- tags: { min: 2 },
267
- };
268
- const result = ruleChecker(data, rules);
269
- expect(result.valid).toBe(false);
265
+ tags: {min: 2},
266
+ }
267
+ const result = ruleChecker(data, rules)
268
+ expect(result.valid).toBe(false)
270
269
  if (!result.valid) {
271
- expect(result.errors).toContain('tags 长度不能小于 2');
270
+ expect(result.errors).toContain('tags 长度不能小于 2')
272
271
  }
273
- });
272
+ })
274
273
 
275
274
  it('应该验证数组最大长度', () => {
276
- const data = { categories: [1, 2, 3, 4, 5, 6] };
275
+ const data = {categories: [1, 2, 3, 4, 5, 6]}
277
276
  const rules: RuleDescription<typeof data> = {
278
- categories: { max: 5 },
279
- };
280
- const result = ruleChecker(data, rules);
281
- expect(result.valid).toBe(false);
277
+ categories: {max: 5},
278
+ }
279
+ const result = ruleChecker(data, rules)
280
+ expect(result.valid).toBe(false)
282
281
  if (!result.valid) {
283
- expect(result.errors).toContain('categories 长度不能大于 5');
282
+ expect(result.errors).toContain('categories 长度不能大于 5')
284
283
  }
285
- });
284
+ })
286
285
 
287
286
  it('应该验证数组元素唯一性', () => {
288
- const data = { ids: [1, 2, 2, 3] };
287
+ const data = {ids: [1, 2, 2, 3]}
289
288
  const rules: RuleDescription<typeof data> = {
290
- ids: { unique: true },
291
- };
292
- const result = ruleChecker(data, rules);
293
- expect(result.valid).toBe(false);
289
+ ids: {unique: true},
290
+ }
291
+ const result = ruleChecker(data, rules)
292
+ expect(result.valid).toBe(false)
294
293
  if (!result.valid) {
295
- expect(result.errors).toContain('ids 元素必须唯一');
294
+ expect(result.errors).toContain('ids 元素必须唯一')
296
295
  }
297
- });
296
+ })
298
297
 
299
298
  it('应该通过数组元素唯一性验证', () => {
300
- const data = { ids: [1, 2, 3, 4] };
299
+ const data = {ids: [1, 2, 3, 4]}
301
300
  const rules: RuleDescription<typeof data> = {
302
- ids: { unique: true },
303
- };
304
- const result = ruleChecker(data, rules);
305
- expect(result.valid).toBe(true);
306
- });
301
+ ids: {unique: true},
302
+ }
303
+ const result = ruleChecker(data, rules)
304
+ expect(result.valid).toBe(true)
305
+ })
307
306
 
308
307
  it('应该验证数组元素规则', () => {
309
- const data = { emails: ['valid@email.com', 'invalid-email'] };
308
+ const data = {emails: ['valid@email.com', 'invalid-email']}
310
309
  const rules: RuleDescription<typeof data> = {
311
310
  emails: {
312
- elementRule: { email: true },
311
+ elementRule: {email: true},
313
312
  },
314
- };
315
- const result = ruleChecker(data, rules);
316
- expect(result.valid).toBe(false);
313
+ }
314
+ const result = ruleChecker(data, rules)
315
+ expect(result.valid).toBe(false)
317
316
  if (!result.valid) {
318
317
  // 检查错误信息包含了数组元素索引的错误
319
- expect(result.errors.some((error) => error.includes('emails[1]'))).toBe(
320
- true
321
- );
318
+ expect(result.errors.some((error) => error.includes('emails[1]'))).toBe(true)
322
319
  }
323
- });
324
- });
320
+ })
321
+ })
325
322
 
326
323
  // ==== 依赖验证测试 ====
327
324
  describe('依赖验证', () => {
328
325
  it('应该验证 dependsOn - 返回 boolean', () => {
329
- const data = { type: 'premium', discount: 0.9 };
326
+ const data = {type: 'premium', discount: 0.9}
330
327
  const rules: RuleDescription<typeof data> = {
331
328
  discount: {
332
329
  dependsOn: (data) => data.type === 'basic', // 当类型不是basic时会失败
333
330
  message: '只有基础用户才能设置折扣',
334
331
  },
335
- };
336
- const result = ruleChecker(data, rules);
337
- expect(result.valid).toBe(false);
332
+ }
333
+ const result = ruleChecker(data, rules)
334
+ expect(result.valid).toBe(false)
338
335
  if (!result.valid) {
339
- expect(result.errors).toContain('只有基础用户才能设置折扣');
336
+ expect(result.errors).toContain('只有基础用户才能设置折扣')
340
337
  }
341
- });
338
+ })
342
339
 
343
340
  it('应该验证 dependsOn - 返回 string', () => {
344
- const data = { age: 16, hasLicense: true };
341
+ const data = {age: 16, hasLicense: true}
345
342
  const rules: RuleDescription<typeof data> = {
346
343
  hasLicense: {
347
- dependsOn: (data) =>
348
- (data.age || 0) < 18 ? '未成年人不能有驾驶证' : true,
344
+ dependsOn: (data) => ((data.age || 0) < 18 ? '未成年人不能有驾驶证' : true),
349
345
  },
350
- };
351
- const result = ruleChecker(data, rules);
352
- expect(result.valid).toBe(false);
346
+ }
347
+ const result = ruleChecker(data, rules)
348
+ expect(result.valid).toBe(false)
353
349
  if (!result.valid) {
354
- expect(result.errors).toContain('未成年人不能有驾驶证');
350
+ expect(result.errors).toContain('未成年人不能有驾驶证')
355
351
  }
356
- });
352
+ })
357
353
 
358
354
  it('应该通过 dependsOn 验证', () => {
359
- const data = { type: 'basic', discount: undefined };
355
+ const data = {type: 'basic', discount: undefined}
360
356
  const rules: RuleDescription<typeof data> = {
361
357
  discount: {
362
358
  dependsOn: (data) => data.type === 'premium',
363
359
  },
364
- };
365
- const result = ruleChecker(data, rules);
366
- expect(result.valid).toBe(true);
367
- });
368
- });
360
+ }
361
+ const result = ruleChecker(data, rules)
362
+ expect(result.valid).toBe(true)
363
+ })
364
+ })
369
365
 
370
366
  // ==== 复杂场景测试 ====
371
367
  describe('复杂场景', () => {
372
368
  it('应该处理多个规则数组', () => {
373
- const data = { password: '123' };
369
+ const data = {password: '123'}
374
370
  const rules: RuleDescription<typeof data> = {
375
371
  password: [
376
- { required: true },
377
- { min: 6, message: '密码至少6位' },
378
- { regex: /[A-Z]/, message: '密码必须包含大写字母' },
372
+ {required: true},
373
+ {min: 6, message: '密码至少6位'},
374
+ {regex: /[A-Z]/, message: '密码必须包含大写字母'},
379
375
  ],
380
- };
381
- const result = ruleChecker(data, rules);
382
- expect(result.valid).toBe(false);
376
+ }
377
+ const result = ruleChecker(data, rules)
378
+ expect(result.valid).toBe(false)
383
379
  if (!result.valid) {
384
- expect(result.errors).toContain('密码至少6位');
385
- expect(result.errors).toContain('密码必须包含大写字母');
380
+ expect(result.errors).toContain('密码至少6位')
381
+ expect(result.errors).toContain('密码必须包含大写字母')
386
382
  }
387
- });
383
+ })
388
384
 
389
385
  it('应该收集多个字段的错误', () => {
390
- const data = { name: '', email: 'invalid', age: 5 };
391
- const rules: RuleDescription<typeof data> = {
392
- name: { required: true },
393
- email: { email: true },
394
- age: { min: 18 },
395
- };
396
- const result = ruleChecker(data, rules);
397
- expect(result.valid).toBe(false);
386
+ const data = {name: '', email: 'invalid', age: 5}
387
+ const rules: RuleDescription<typeof data> = {
388
+ name: {required: true},
389
+ email: {email: true},
390
+ age: {min: 18},
391
+ }
392
+ const result = ruleChecker(data, rules)
393
+ expect(result.valid).toBe(false)
398
394
  if (!result.valid) {
399
- expect(result.errors).toHaveLength(3);
400
- expect(result.fieldErrors.name).toContain('name 为必填项');
401
- expect(result.fieldErrors.email).toContain('email 不是有效的邮箱');
402
- expect(result.fieldErrors.age).toContain('age 不能小于 18');
395
+ expect(result.errors).toHaveLength(3)
396
+ expect(result.fieldErrors.name).toContain('name 为必填项')
397
+ expect(result.fieldErrors.email).toContain('email 不是有效的邮箱')
398
+ expect(result.fieldErrors.age).toContain('age 不能小于 18')
403
399
  }
404
- });
400
+ })
405
401
 
406
402
  it('应该处理复杂的用户注册场景', () => {
407
403
  const data = {
@@ -412,86 +408,77 @@ describe('ruleChecker', () => {
412
408
  age: 25,
413
409
  hobbies: ['reading'],
414
410
  terms: false,
415
- };
411
+ }
416
412
 
417
413
  const rules: RuleDescription<typeof data> = {
418
- username: { required: true, min: 3, max: 20 },
419
- email: { required: true, email: true },
420
- password: [
421
- { required: true },
422
- { min: 6 },
423
- { regex: /[A-Z]/, message: '密码必须包含大写字母' },
424
- ],
414
+ username: {required: true, min: 3, max: 20},
415
+ email: {required: true, email: true},
416
+ password: [{required: true}, {min: 6}, {regex: /[A-Z]/, message: '密码必须包含大写字母'}],
425
417
  confirmPassword: {
426
418
  required: true,
427
- validator: (value, data) =>
428
- value === data.password || '两次密码不一致',
419
+ validator: (value, data) => value === data.password || '两次密码不一致',
429
420
  },
430
- age: { required: true, min: 18, max: 120 },
431
- hobbies: { min: 2, max: 5 },
421
+ age: {required: true, min: 18, max: 120},
422
+ hobbies: {min: 2, max: 5},
432
423
  terms: {
433
424
  required: true,
434
425
  validator: (value) => value === true || '必须同意用户协议',
435
426
  },
436
- };
427
+ }
437
428
 
438
- const result = ruleChecker(data, rules);
439
- expect(result.valid).toBe(false);
429
+ const result = ruleChecker(data, rules)
430
+ expect(result.valid).toBe(false)
440
431
  if (!result.valid) {
441
- expect(result.fieldErrors.username).toContain(
442
- 'username 长度不能少于 3'
443
- );
444
- expect(result.fieldErrors.password).toContain(
445
- 'password 长度不能少于 6'
446
- );
447
- expect(result.fieldErrors.confirmPassword).toContain('两次密码不一致');
448
- expect(result.fieldErrors.hobbies).toContain('hobbies 长度不能小于 2');
449
- expect(result.fieldErrors.terms).toContain('必须同意用户协议');
450
- }
451
- });
432
+ expect(result.fieldErrors.username).toContain('username 长度不能少于 3')
433
+ expect(result.fieldErrors.password).toContain('password 长度不能少于 6')
434
+ expect(result.fieldErrors.confirmPassword).toContain('两次密码不一致')
435
+ expect(result.fieldErrors.hobbies).toContain('hobbies 长度不能小于 2')
436
+ expect(result.fieldErrors.terms).toContain('必须同意用户协议')
437
+ }
438
+ })
452
439
 
453
440
  it('应该在所有验证通过时返回正确的数据', () => {
454
441
  const data = {
455
442
  name: 'John Doe',
456
443
  email: 'john@example.com',
457
444
  age: 30,
458
- };
445
+ }
459
446
 
460
447
  const rules: RuleDescription<typeof data> = {
461
- name: { required: true, min: 2 },
462
- email: { required: true, email: true },
463
- age: { required: true, min: 18, max: 120 },
464
- };
448
+ name: {required: true, min: 2},
449
+ email: {required: true, email: true},
450
+ age: {required: true, min: 18, max: 120},
451
+ }
465
452
 
466
- const result = ruleChecker(data, rules);
467
- expect(result.valid).toBe(true);
453
+ const result = ruleChecker(data, rules)
454
+ expect(result.valid).toBe(true)
468
455
  if (result.valid) {
469
- expect(result.data).toEqual(data);
456
+ expect(result.data).toEqual(data)
470
457
  }
471
- });
472
- });
458
+ })
459
+ })
473
460
 
474
461
  // ==== 类型安全测试 ====
475
462
  describe('类型安全验证', () => {
476
463
  it('数字字段应该只支持数字相关规则', () => {
477
- const data = { age: 25 };
464
+ const data = {age: 25}
478
465
 
479
466
  // 这些应该是有效的数字规则
480
467
  const validRules: RuleDescription<typeof data> = {
481
- age: { min: 0, max: 120, required: true },
482
- };
468
+ age: {min: 0, max: 120, required: true},
469
+ }
483
470
 
484
- const result = ruleChecker(data, validRules);
485
- expect(result.valid).toBe(true);
471
+ const result = ruleChecker(data, validRules)
472
+ expect(result.valid).toBe(true)
486
473
 
487
474
  // 注意:TypeScript 会阻止以下无效的数字规则
488
475
  // age: { email: true }, // ❌ 编译错误
489
476
  // age: { regex: /test/ }, // ❌ 编译错误
490
477
  // age: { len: 10 }, // ❌ 编译错误
491
- });
478
+ })
492
479
 
493
480
  it('字符串字段应该支持长度和格式规则', () => {
494
- const data = { email: 'test@example.com', name: 'John' };
481
+ const data = {email: 'test@example.com', name: 'John'}
495
482
 
496
483
  const rules: RuleDescription<typeof data> = {
497
484
  email: {
@@ -506,35 +493,35 @@ describe('ruleChecker', () => {
506
493
  max: 50,
507
494
  regex: /^[a-zA-Z]+$/,
508
495
  },
509
- };
496
+ }
510
497
 
511
- const result = ruleChecker(data, rules);
512
- expect(result.valid).toBe(true);
513
- });
498
+ const result = ruleChecker(data, rules)
499
+ expect(result.valid).toBe(true)
500
+ })
514
501
 
515
502
  it('数组字段应该支持长度和唯一性规则', () => {
516
- const data = { tags: ['react', 'typescript'], ids: [1, 2, 3] };
503
+ const data = {tags: ['react', 'typescript'], ids: [1, 2, 3]}
517
504
 
518
505
  const rules: RuleDescription<typeof data> = {
519
506
  tags: {
520
507
  min: 1,
521
508
  max: 5,
522
509
  unique: true,
523
- elementRule: { min: 2, max: 20 }, // 元素是字符串
510
+ elementRule: {min: 2, max: 20}, // 元素是字符串
524
511
  },
525
512
  ids: {
526
513
  len: 3,
527
514
  unique: true,
528
- elementRule: { min: 1, max: 1000 }, // 元素是数字
515
+ elementRule: {min: 1, max: 1000}, // 元素是数字
529
516
  },
530
- };
517
+ }
531
518
 
532
- const result = ruleChecker(data, rules);
533
- expect(result.valid).toBe(true);
534
- });
519
+ const result = ruleChecker(data, rules)
520
+ expect(result.valid).toBe(true)
521
+ })
535
522
 
536
523
  it('布尔字段应该只支持基础规则', () => {
537
- const data = { isActive: false, hasPermission: false };
524
+ const data = {isActive: false, hasPermission: false}
538
525
 
539
526
  const rules: RuleDescription<typeof data> = {
540
527
  isActive: {
@@ -544,14 +531,14 @@ describe('ruleChecker', () => {
544
531
  hasPermission: {
545
532
  required: true,
546
533
  },
547
- };
534
+ }
548
535
 
549
- const result = ruleChecker(data, rules);
550
- expect(result.valid).toBe(false);
536
+ const result = ruleChecker(data, rules)
537
+ expect(result.valid).toBe(false)
551
538
  if (!result.valid) {
552
- expect(result.errors).toContain('必须激活账户');
539
+ expect(result.errors).toContain('必须激活账户')
553
540
  }
554
- });
541
+ })
555
542
 
556
543
  it('应该正确处理混合类型的复杂对象', () => {
557
544
  const data = {
@@ -561,89 +548,89 @@ describe('ruleChecker', () => {
561
548
  tags: ['electronics', 'mobile'],
562
549
  isActive: true,
563
550
  description: 'A great product',
564
- };
551
+ }
565
552
 
566
553
  const rules: RuleDescription<typeof data> = {
567
- id: { required: true, min: 1 }, // 数字规则
568
- name: { required: true, min: 3, max: 50 }, // 字符串长度规则
569
- price: { required: true, min: 0, max: 10000 }, // 数字范围规则
570
- tags: { min: 1, max: 10, unique: true }, // 数组规则
571
- isActive: { required: true }, // 布尔基础规则
572
- description: { min: 10, max: 500, regex: /^[a-zA-Z\s]+$/ }, // 字符串格式规则
573
- };
554
+ id: {required: true, min: 1}, // 数字规则
555
+ name: {required: true, min: 3, max: 50}, // 字符串长度规则
556
+ price: {required: true, min: 0, max: 10000}, // 数字范围规则
557
+ tags: {min: 1, max: 10, unique: true}, // 数组规则
558
+ isActive: {required: true}, // 布尔基础规则
559
+ description: {min: 10, max: 500, regex: /^[a-zA-Z\s]+$/}, // 字符串格式规则
560
+ }
574
561
 
575
- const result = ruleChecker(data, rules);
576
- expect(result.valid).toBe(true);
577
- });
578
- });
562
+ const result = ruleChecker(data, rules)
563
+ expect(result.valid).toBe(true)
564
+ })
565
+ })
579
566
 
580
567
  // ==== 边缘情况测试 ====
581
568
  describe('边缘情况', () => {
582
569
  it('应该正确处理空字符串的各种验证', () => {
583
- const data = { text: '' };
570
+ const data = {text: ''}
584
571
  const rules: RuleDescription<typeof data> = {
585
- text: { min: 1 }, // 空字符串长度为0,应该失败
586
- };
587
- const result = ruleChecker(data, rules);
588
- expect(result.valid).toBe(false);
589
- });
572
+ text: {min: 1}, // 空字符串长度为0,应该失败
573
+ }
574
+ const result = ruleChecker(data, rules)
575
+ expect(result.valid).toBe(false)
576
+ })
590
577
 
591
578
  it('应该正确处理空数组的各种验证', () => {
592
- const data = { items: [] as string[] };
579
+ const data = {items: [] as string[]}
593
580
  const rules: RuleDescription<typeof data> = {
594
- items: { min: 1 }, // 空数组长度为0,应该失败
595
- };
596
- const result = ruleChecker(data, rules);
597
- expect(result.valid).toBe(false);
598
- });
581
+ items: {min: 1}, // 空数组长度为0,应该失败
582
+ }
583
+ const result = ruleChecker(data, rules)
584
+ expect(result.valid).toBe(false)
585
+ })
599
586
 
600
587
  it('应该正确处理数字 0 的验证', () => {
601
- const data = { count: 0 };
588
+ const data = {count: 0}
602
589
  const rules: RuleDescription<typeof data> = {
603
- count: { required: true, min: 0 }, // 0 是有效值,应该通过
604
- };
605
- const result = ruleChecker(data, rules);
606
- expect(result.valid).toBe(true);
607
- });
590
+ count: {required: true, min: 0}, // 0 是有效值,应该通过
591
+ }
592
+ const result = ruleChecker(data, rules)
593
+ expect(result.valid).toBe(true)
594
+ })
608
595
 
609
596
  it('应该正确处理 false 值的验证', () => {
610
- const data = { isEnabled: false };
597
+ const data = {isEnabled: false}
611
598
  const rules: RuleDescription<typeof data> = {
612
- isEnabled: { required: true }, // false 是有效值,应该通过
613
- };
614
- const result = ruleChecker(data, rules);
615
- expect(result.valid).toBe(true);
616
- });
599
+ isEnabled: {required: true}, // false 是有效值,应该通过
600
+ }
601
+ const result = ruleChecker(data, rules)
602
+ expect(result.valid).toBe(true)
603
+ })
617
604
 
618
605
  it('应该正确处理只有空格的字符串', () => {
619
- const data = { text: ' ' };
606
+ const data = {text: ' '}
620
607
  const rules: RuleDescription<typeof data> = {
621
- text: { required: true }, // 只有空格被视为空值,应该失败
622
- };
623
- const result = ruleChecker(data, rules);
624
- expect(result.valid).toBe(false);
625
- });
608
+ text: {required: true}, // 只有空格被视为空值,应该失败
609
+ }
610
+ const result = ruleChecker(data, rules)
611
+ expect(result.valid).toBe(false)
612
+ })
626
613
 
627
614
  it('应该处理非常长的字符串', () => {
628
- const longText = 'a'.repeat(1000);
629
- const data = { content: longText };
615
+ const longText = 'a'.repeat(1000)
616
+ const data = {content: longText}
630
617
  const rules: RuleDescription<typeof data> = {
631
- content: { max: 500 }, // 超过最大长度,应该失败
632
- };
633
- const result = ruleChecker(data, rules);
634
- expect(result.valid).toBe(false);
618
+ content: {max: 500}, // 超过最大长度,应该失败
619
+ }
620
+ const result = ruleChecker(data, rules)
621
+ expect(result.valid).toBe(false)
635
622
  if (!result.valid) {
636
- expect(result.errors).toContain('content 长度不能超过 500');
623
+ expect(result.errors).toContain('content 长度不能超过 500')
637
624
  }
638
- });
625
+ })
639
626
 
640
627
  it('应该处理复杂的嵌套数组元素验证', () => {
641
628
  const data = {
642
629
  users: [
643
- { name: 'Alice', email: 'alice@test.com' },
644
- { name: 'B', email: 'invalid-email' }, // 名字太短,邮箱无效
630
+ {name: 'Alice', email: 'alice@test.com'},
631
+ {name: 'B', email: 'invalid-email'}, // 名字太短,邮箱无效
645
632
  ],
646
- };
633
+ }
647
634
 
648
635
  // 注意:这个例子展示了当前系统的限制
649
636
  // 对于复杂嵌套对象,需要扩展 elementRule 支持
@@ -653,10 +640,10 @@ describe('ruleChecker', () => {
653
640
  max: 10,
654
641
  // elementRule 目前不支持对象验证
655
642
  },
656
- };
643
+ }
657
644
 
658
- const result = ruleChecker(data, rules);
659
- expect(result.valid).toBe(true); // 基本数组规则通过
660
- });
661
- });
662
- });
645
+ const result = ruleChecker(data, rules)
646
+ expect(result.valid).toBe(true) // 基本数组规则通过
647
+ })
648
+ })
649
+ })