@chenzy-design/core 0.3.1 → 0.4.1
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/dist/ai-chat-dialogue.d.ts +300 -0
- package/dist/ai-chat-dialogue.d.ts.map +1 -0
- package/dist/ai-chat-dialogue.js +699 -0
- package/dist/ai-chat-dialogue.js.map +1 -0
- package/dist/ai-chat-dialogue.test.d.ts +2 -0
- package/dist/ai-chat-dialogue.test.d.ts.map +1 -0
- package/dist/ai-chat-dialogue.test.js +338 -0
- package/dist/ai-chat-dialogue.test.js.map +1 -0
- package/dist/ai-chat-input.d.ts +191 -0
- package/dist/ai-chat-input.d.ts.map +1 -0
- package/dist/ai-chat-input.js +274 -0
- package/dist/ai-chat-input.js.map +1 -0
- package/dist/ai-chat-input.test.d.ts +2 -0
- package/dist/ai-chat-input.test.d.ts.map +1 -0
- package/dist/ai-chat-input.test.js +339 -0
- package/dist/ai-chat-input.test.js.map +1 -0
- package/dist/audio-player.d.ts +154 -0
- package/dist/audio-player.d.ts.map +1 -0
- package/dist/audio-player.js +254 -0
- package/dist/audio-player.js.map +1 -0
- package/dist/audio-player.test.d.ts +2 -0
- package/dist/audio-player.test.d.ts.map +1 -0
- package/dist/audio-player.test.js +275 -0
- package/dist/audio-player.test.js.map +1 -0
- package/dist/back-top.d.ts +4 -1
- package/dist/back-top.d.ts.map +1 -1
- package/dist/back-top.js +5 -2
- package/dist/back-top.js.map +1 -1
- package/dist/back-top.test.js +3 -2
- package/dist/back-top.test.js.map +1 -1
- package/dist/calendar.d.ts +132 -44
- package/dist/calendar.d.ts.map +1 -1
- package/dist/calendar.js +413 -70
- package/dist/calendar.js.map +1 -1
- package/dist/calendar.test.js +160 -76
- package/dist/calendar.test.js.map +1 -1
- package/dist/chat.d.ts +172 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +210 -0
- package/dist/chat.js.map +1 -0
- package/dist/chat.test.d.ts +2 -0
- package/dist/chat.test.d.ts.map +1 -0
- package/dist/chat.test.js +181 -0
- package/dist/chat.test.js.map +1 -0
- package/dist/code-highlight.d.ts +30 -0
- package/dist/code-highlight.d.ts.map +1 -0
- package/dist/code-highlight.js +37 -0
- package/dist/code-highlight.js.map +1 -0
- package/dist/code-highlight.test.d.ts +2 -0
- package/dist/code-highlight.test.d.ts.map +1 -0
- package/dist/code-highlight.test.js +36 -0
- package/dist/code-highlight.test.js.map +1 -0
- package/dist/collapsible.d.ts +41 -0
- package/dist/collapsible.d.ts.map +1 -0
- package/dist/collapsible.js +33 -0
- package/dist/collapsible.js.map +1 -0
- package/dist/collapsible.test.d.ts +2 -0
- package/dist/collapsible.test.d.ts.map +1 -0
- package/dist/collapsible.test.js +57 -0
- package/dist/collapsible.test.js.map +1 -0
- package/dist/color-value.d.ts +60 -0
- package/dist/color-value.d.ts.map +1 -0
- package/dist/color-value.js +165 -0
- package/dist/color-value.js.map +1 -0
- package/dist/color-value.test.d.ts +2 -0
- package/dist/color-value.test.d.ts.map +1 -0
- package/dist/color-value.test.js +104 -0
- package/dist/color-value.test.js.map +1 -0
- package/dist/config-provider.d.ts +76 -37
- package/dist/config-provider.d.ts.map +1 -1
- package/dist/config-provider.js +107 -32
- package/dist/config-provider.js.map +1 -1
- package/dist/config-provider.test.js +123 -60
- package/dist/config-provider.test.js.map +1 -1
- package/dist/cropper.d.ts +164 -0
- package/dist/cropper.d.ts.map +1 -0
- package/dist/cropper.js +841 -0
- package/dist/cropper.js.map +1 -0
- package/dist/cropper.test.d.ts +2 -0
- package/dist/cropper.test.d.ts.map +1 -0
- package/dist/cropper.test.js +259 -0
- package/dist/cropper.test.js.map +1 -0
- package/dist/drag-move.d.ts +119 -0
- package/dist/drag-move.d.ts.map +1 -0
- package/dist/drag-move.js +237 -0
- package/dist/drag-move.js.map +1 -0
- package/dist/drag-move.test.d.ts +2 -0
- package/dist/drag-move.test.d.ts.map +1 -0
- package/dist/drag-move.test.js +304 -0
- package/dist/drag-move.test.js.map +1 -0
- package/dist/editable.d.ts +24 -4
- package/dist/editable.d.ts.map +1 -1
- package/dist/editable.js +18 -0
- package/dist/editable.js.map +1 -1
- package/dist/editable.test.js +55 -2
- package/dist/editable.test.js.map +1 -1
- package/dist/ellipsis.d.ts +13 -0
- package/dist/ellipsis.d.ts.map +1 -1
- package/dist/ellipsis.js +36 -0
- package/dist/ellipsis.js.map +1 -1
- package/dist/ellipsis.test.js +37 -1
- package/dist/ellipsis.test.js.map +1 -1
- package/dist/form-path.d.ts +19 -0
- package/dist/form-path.d.ts.map +1 -0
- package/dist/form-path.js +97 -0
- package/dist/form-path.js.map +1 -0
- package/dist/form-path.test.d.ts +2 -0
- package/dist/form-path.test.d.ts.map +1 -0
- package/dist/form-path.test.js +57 -0
- package/dist/form-path.test.js.map +1 -0
- package/dist/form-validate.d.ts +13 -0
- package/dist/form-validate.d.ts.map +1 -0
- package/dist/form-validate.js +204 -0
- package/dist/form-validate.js.map +1 -0
- package/dist/form.d.ts +91 -18
- package/dist/form.d.ts.map +1 -1
- package/dist/form.js +170 -115
- package/dist/form.js.map +1 -1
- package/dist/form.test.js +349 -76
- package/dist/form.test.js.map +1 -1
- package/dist/highlight.d.ts +42 -32
- package/dist/highlight.d.ts.map +1 -1
- package/dist/highlight.js +67 -41
- package/dist/highlight.js.map +1 -1
- package/dist/highlight.test.js +73 -32
- package/dist/highlight.test.js.map +1 -1
- package/dist/hotkeys.d.ts +151 -0
- package/dist/hotkeys.d.ts.map +1 -0
- package/dist/hotkeys.js +188 -0
- package/dist/hotkeys.js.map +1 -0
- package/dist/hotkeys.test.d.ts +2 -0
- package/dist/hotkeys.test.d.ts.map +1 -0
- package/dist/hotkeys.test.js +170 -0
- package/dist/hotkeys.test.js.map +1 -0
- package/dist/index.d.ts +33 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -13
- package/dist/index.js.map +1 -1
- package/dist/input.d.ts +34 -0
- package/dist/input.d.ts.map +1 -0
- package/dist/input.js +54 -0
- package/dist/input.js.map +1 -0
- package/dist/input.test.d.ts +2 -0
- package/dist/input.test.d.ts.map +1 -0
- package/dist/input.test.js +56 -0
- package/dist/input.test.js.map +1 -0
- package/dist/markdown-render.d.ts +49 -0
- package/dist/markdown-render.d.ts.map +1 -0
- package/dist/markdown-render.js +61 -0
- package/dist/markdown-render.js.map +1 -0
- package/dist/markdown-render.test.d.ts +2 -0
- package/dist/markdown-render.test.d.ts.map +1 -0
- package/dist/markdown-render.test.js +106 -0
- package/dist/markdown-render.test.js.map +1 -0
- package/dist/notification.d.ts +40 -31
- package/dist/notification.d.ts.map +1 -1
- package/dist/notification.js +86 -70
- package/dist/notification.js.map +1 -1
- package/dist/notification.test.js +62 -39
- package/dist/notification.test.js.map +1 -1
- package/dist/numeral.d.ts +32 -0
- package/dist/numeral.d.ts.map +1 -0
- package/dist/numeral.js +67 -0
- package/dist/numeral.js.map +1 -0
- package/dist/numeral.test.d.ts +2 -0
- package/dist/numeral.test.d.ts.map +1 -0
- package/dist/numeral.test.js +59 -0
- package/dist/numeral.test.js.map +1 -0
- package/dist/overflow-list.d.ts +9 -40
- package/dist/overflow-list.d.ts.map +1 -1
- package/dist/overflow-list.js +9 -70
- package/dist/overflow-list.js.map +1 -1
- package/dist/overflow-list.test.js +1 -122
- package/dist/overflow-list.test.js.map +1 -1
- package/dist/pagination.d.ts +17 -0
- package/dist/pagination.d.ts.map +1 -1
- package/dist/pagination.js +48 -0
- package/dist/pagination.js.map +1 -1
- package/dist/pagination.test.js +40 -1
- package/dist/pagination.test.js.map +1 -1
- package/dist/pincode.d.ts +79 -0
- package/dist/pincode.d.ts.map +1 -0
- package/dist/pincode.js +119 -0
- package/dist/pincode.js.map +1 -0
- package/dist/pincode.test.d.ts +2 -0
- package/dist/pincode.test.d.ts.map +1 -0
- package/dist/pincode.test.js +151 -0
- package/dist/pincode.test.js.map +1 -0
- package/dist/progress.d.ts +32 -30
- package/dist/progress.d.ts.map +1 -1
- package/dist/progress.js +257 -64
- package/dist/progress.js.map +1 -1
- package/dist/progress.test.js +50 -47
- package/dist/progress.test.js.map +1 -1
- package/dist/resizable.d.ts +200 -0
- package/dist/resizable.d.ts.map +1 -0
- package/dist/resizable.js +329 -0
- package/dist/resizable.js.map +1 -0
- package/dist/resizable.test.d.ts +2 -0
- package/dist/resizable.test.d.ts.map +1 -0
- package/dist/resizable.test.js +302 -0
- package/dist/resizable.test.js.map +1 -0
- package/dist/scroll-list.d.ts +69 -62
- package/dist/scroll-list.d.ts.map +1 -1
- package/dist/scroll-list.js +103 -144
- package/dist/scroll-list.js.map +1 -1
- package/dist/scroll-list.test.js +100 -110
- package/dist/scroll-list.test.js.map +1 -1
- package/dist/sidebar.d.ts +46 -0
- package/dist/sidebar.d.ts.map +1 -0
- package/dist/sidebar.js +65 -0
- package/dist/sidebar.js.map +1 -0
- package/dist/sidebar.test.d.ts +2 -0
- package/dist/sidebar.test.d.ts.map +1 -0
- package/dist/sidebar.test.js +88 -0
- package/dist/sidebar.test.js.map +1 -0
- package/dist/spin.d.ts +5 -5
- package/dist/spin.d.ts.map +1 -1
- package/dist/spin.js +13 -39
- package/dist/spin.js.map +1 -1
- package/dist/spin.test.js +2 -26
- package/dist/spin.test.js.map +1 -1
- package/dist/toast.d.ts +33 -30
- package/dist/toast.d.ts.map +1 -1
- package/dist/toast.js +77 -72
- package/dist/toast.js.map +1 -1
- package/dist/toast.test.js +63 -37
- package/dist/toast.test.js.map +1 -1
- package/dist/tree.d.ts +22 -5
- package/dist/tree.d.ts.map +1 -1
- package/dist/tree.js +61 -9
- package/dist/tree.js.map +1 -1
- package/dist/tree.test.js +72 -1
- package/dist/tree.test.js.map +1 -1
- package/dist/user-guide.d.ts +73 -0
- package/dist/user-guide.d.ts.map +1 -0
- package/dist/user-guide.js +95 -0
- package/dist/user-guide.js.map +1 -0
- package/dist/user-guide.test.d.ts +2 -0
- package/dist/user-guide.test.d.ts.map +1 -0
- package/dist/user-guide.test.js +109 -0
- package/dist/user-guide.test.js.map +1 -0
- package/dist/video-player.d.ts +196 -0
- package/dist/video-player.d.ts.map +1 -0
- package/dist/video-player.js +461 -0
- package/dist/video-player.js.map +1 -0
- package/dist/video-player.test.d.ts +2 -0
- package/dist/video-player.test.d.ts.map +1 -0
- package/dist/video-player.test.js +435 -0
- package/dist/video-player.test.js.map +1 -0
- package/package.json +17 -1
- package/dist/banner.d.ts +0 -19
- package/dist/banner.d.ts.map +0 -1
- package/dist/banner.js +0 -20
- package/dist/banner.js.map +0 -1
- package/dist/banner.test.d.ts +0 -2
- package/dist/banner.test.d.ts.map +0 -1
- package/dist/banner.test.js +0 -29
- package/dist/banner.test.js.map +0 -1
- package/dist/breakpoints.d.ts +0 -30
- package/dist/breakpoints.d.ts.map +0 -1
- package/dist/breakpoints.js +0 -45
- package/dist/breakpoints.js.map +0 -1
- package/dist/breakpoints.test.d.ts +0 -2
- package/dist/breakpoints.test.d.ts.map +0 -1
- package/dist/breakpoints.test.js +0 -46
- package/dist/breakpoints.test.js.map +0 -1
- package/dist/lottie-icon.d.ts +0 -88
- package/dist/lottie-icon.d.ts.map +0 -1
- package/dist/lottie-icon.js +0 -84
- package/dist/lottie-icon.js.map +0 -1
- package/dist/lottie-icon.test.d.ts +0 -2
- package/dist/lottie-icon.test.d.ts.map +0 -1
- package/dist/lottie-icon.test.js +0 -88
- package/dist/lottie-icon.test.js.map +0 -1
- package/dist/sider.d.ts +0 -26
- package/dist/sider.d.ts.map +0 -1
- package/dist/sider.js +0 -55
- package/dist/sider.js.map +0 -1
- package/dist/sider.test.d.ts +0 -2
- package/dist/sider.test.d.ts.map +0 -1
- package/dist/sider.test.js +0 -29
- package/dist/sider.test.js.map +0 -1
package/dist/form.test.js
CHANGED
|
@@ -4,31 +4,31 @@ describe('createForm', () => {
|
|
|
4
4
|
it('registers fields and reads/writes values', () => {
|
|
5
5
|
const f = createForm({ initialValues: { name: 'a' } });
|
|
6
6
|
f.registerField('name', { label: 'Name' });
|
|
7
|
-
expect(f.
|
|
8
|
-
f.
|
|
9
|
-
expect(f.
|
|
7
|
+
expect(f.getValue('name')).toBe('a');
|
|
8
|
+
f.setValue('name', 'b');
|
|
9
|
+
expect(f.getValue('name')).toBe('b');
|
|
10
10
|
});
|
|
11
11
|
it('required rule fails on empty, passes when filled', async () => {
|
|
12
12
|
const f = createForm();
|
|
13
13
|
f.registerField('email', { label: 'Email', rules: [{ required: true }] });
|
|
14
14
|
expect(await f.validateField('email')).toBeTruthy();
|
|
15
|
-
f.
|
|
15
|
+
f.setValue('email', 'x@y.com');
|
|
16
16
|
expect(await f.validateField('email')).toBeUndefined();
|
|
17
17
|
});
|
|
18
18
|
it('email type rule rejects malformed input', async () => {
|
|
19
19
|
const f = createForm();
|
|
20
20
|
f.registerField('email', { rules: [{ type: 'email' }] });
|
|
21
|
-
f.
|
|
21
|
+
f.setValue('email', 'nope');
|
|
22
22
|
expect(await f.validateField('email')).toBeTruthy();
|
|
23
|
-
f.
|
|
23
|
+
f.setValue('email', 'a@b.co');
|
|
24
24
|
expect(await f.validateField('email')).toBeUndefined();
|
|
25
25
|
});
|
|
26
26
|
it('min/max/length rules', async () => {
|
|
27
27
|
const f = createForm();
|
|
28
28
|
f.registerField('age', { rules: [{ min: 18, max: 60 }] });
|
|
29
|
-
f.
|
|
29
|
+
f.setValue('age', 10);
|
|
30
30
|
expect(await f.validateField('age')).toBeTruthy();
|
|
31
|
-
f.
|
|
31
|
+
f.setValue('age', 30);
|
|
32
32
|
expect(await f.validateField('age')).toBeUndefined();
|
|
33
33
|
});
|
|
34
34
|
it('async validator latest-wins (race token discard)', async () => {
|
|
@@ -47,32 +47,32 @@ describe('createForm', () => {
|
|
|
47
47
|
},
|
|
48
48
|
],
|
|
49
49
|
});
|
|
50
|
-
f.
|
|
50
|
+
f.setValue('u', 'first');
|
|
51
51
|
const p1 = f.validateField('u');
|
|
52
52
|
const p2 = f.validateField('u'); // supersedes
|
|
53
53
|
await p2;
|
|
54
54
|
resolveFirst?.('stale error'); // late first result must be discarded
|
|
55
55
|
await p1;
|
|
56
|
-
expect(f.
|
|
56
|
+
expect(f.getError('u')).toBeUndefined();
|
|
57
57
|
});
|
|
58
|
-
it('
|
|
58
|
+
it('reset restores initial values and clears errors', async () => {
|
|
59
59
|
const f = createForm({ initialValues: { name: 'init' } });
|
|
60
60
|
f.registerField('name', { rules: [{ required: true }] });
|
|
61
|
-
f.
|
|
61
|
+
f.setValue('name', '');
|
|
62
62
|
await f.validateField('name');
|
|
63
|
-
expect(f.
|
|
64
|
-
f.
|
|
65
|
-
expect(f.
|
|
66
|
-
expect(f.
|
|
63
|
+
expect(f.getError('name')).toBeTruthy();
|
|
64
|
+
f.reset();
|
|
65
|
+
expect(f.getValue('name')).toBe('init');
|
|
66
|
+
expect(f.getError('name')).toBeUndefined();
|
|
67
67
|
});
|
|
68
68
|
it('submit reports validity and increments submitCount', async () => {
|
|
69
69
|
const f = createForm();
|
|
70
70
|
f.registerField('name', { rules: [{ required: true }] });
|
|
71
|
-
const r1 = await f.
|
|
71
|
+
const r1 = await f.submitForm();
|
|
72
72
|
expect(r1.valid).toBe(false);
|
|
73
|
-
expect(f.
|
|
74
|
-
f.
|
|
75
|
-
const r2 = await f.
|
|
73
|
+
expect(f.getFormState().submitCount).toBe(1);
|
|
74
|
+
f.setValue('name', 'ok');
|
|
75
|
+
const r2 = await f.submitForm();
|
|
76
76
|
expect(r2.valid).toBe(true);
|
|
77
77
|
expect(r2.values).toEqual({ name: 'ok' });
|
|
78
78
|
});
|
|
@@ -87,18 +87,19 @@ describe('createForm', () => {
|
|
|
87
87
|
},
|
|
88
88
|
],
|
|
89
89
|
});
|
|
90
|
-
f.
|
|
91
|
-
f.
|
|
90
|
+
f.setValue('password', 'aaa');
|
|
91
|
+
f.setValue('confirm', 'bbb');
|
|
92
92
|
await f.validateField('confirm');
|
|
93
|
-
expect(f.
|
|
93
|
+
expect(f.getError('confirm')).toBe('mismatch');
|
|
94
94
|
// changing password automatically re-validates the dependent confirm (which
|
|
95
95
|
// is "active" because it already shows an error). The error clears once the
|
|
96
96
|
// values match — note we do NOT validate the password field itself here.
|
|
97
|
-
f.
|
|
98
|
-
// allow the scheduled (async) dependent validation to settle
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
f.setValue('password', 'bbb');
|
|
98
|
+
// allow the scheduled (async) dependent validation to settle. The engine now
|
|
99
|
+
// runs through async-validator (Promise-based), so it needs a real task tick
|
|
100
|
+
// rather than a couple of microtasks.
|
|
101
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
102
|
+
expect(f.getError('confirm')).toBeUndefined();
|
|
102
103
|
});
|
|
103
104
|
it('dependencies: untouched/error-free dependent is not eagerly validated', async () => {
|
|
104
105
|
const f = createForm();
|
|
@@ -108,33 +109,33 @@ describe('createForm', () => {
|
|
|
108
109
|
rules: [{ validator: (v, values) => (v === values.password ? undefined : 'mismatch') }],
|
|
109
110
|
});
|
|
110
111
|
// confirm has neither been touched nor shows an error → must stay clean
|
|
111
|
-
f.
|
|
112
|
+
f.setValue('password', 'x', { validate: true });
|
|
112
113
|
await Promise.resolve();
|
|
113
|
-
expect(f.
|
|
114
|
+
expect(f.getError('confirm')).toBeUndefined();
|
|
114
115
|
});
|
|
115
116
|
it('warningOnly rule produces a warning, not an error, and does not block submit', async () => {
|
|
116
117
|
const f = createForm();
|
|
117
118
|
f.registerField('name', {
|
|
118
119
|
rules: [{ minLength: 5, warningOnly: true, message: 'too short' }],
|
|
119
120
|
});
|
|
120
|
-
f.
|
|
121
|
+
f.setValue('name', 'ab');
|
|
121
122
|
const err = await f.validateField('name');
|
|
122
123
|
// warningOnly never surfaces as a blocking error
|
|
123
124
|
expect(err).toBeUndefined();
|
|
124
|
-
expect(f.
|
|
125
|
+
expect(f.getError('name')).toBeUndefined();
|
|
125
126
|
expect(f.getFieldWarning('name')).toBe('too short');
|
|
126
127
|
// submit must still be valid despite the standing warning
|
|
127
|
-
const r = await f.
|
|
128
|
+
const r = await f.submitForm();
|
|
128
129
|
expect(r.valid).toBe(true);
|
|
129
130
|
expect(f.getFieldWarning('name')).toBe('too short');
|
|
130
131
|
});
|
|
131
132
|
it('warning clears once the warningOnly rule passes', async () => {
|
|
132
133
|
const f = createForm();
|
|
133
134
|
f.registerField('name', { rules: [{ minLength: 5, warningOnly: true, message: 'w' }] });
|
|
134
|
-
f.
|
|
135
|
+
f.setValue('name', 'ab');
|
|
135
136
|
await f.validateField('name');
|
|
136
137
|
expect(f.getFieldWarning('name')).toBe('w');
|
|
137
|
-
f.
|
|
138
|
+
f.setValue('name', 'abcdef');
|
|
138
139
|
await f.validateField('name');
|
|
139
140
|
expect(f.getFieldWarning('name')).toBeUndefined();
|
|
140
141
|
});
|
|
@@ -146,11 +147,11 @@ describe('createForm', () => {
|
|
|
146
147
|
{ required: true, message: 'err' },
|
|
147
148
|
],
|
|
148
149
|
});
|
|
149
|
-
f.
|
|
150
|
+
f.setValue('name', '');
|
|
150
151
|
const err = await f.validateField('name');
|
|
151
152
|
expect(err).toBe('err');
|
|
152
|
-
expect(f.
|
|
153
|
-
const r = await f.
|
|
153
|
+
expect(f.getError('name')).toBe('err');
|
|
154
|
+
const r = await f.submitForm();
|
|
154
155
|
expect(r.valid).toBe(false);
|
|
155
156
|
});
|
|
156
157
|
it('validating flag is set during async validation and cleared after', async () => {
|
|
@@ -159,21 +160,21 @@ describe('createForm', () => {
|
|
|
159
160
|
f.registerField('u', {
|
|
160
161
|
rules: [{ validator: () => new Promise((r) => (resolveV = r)) }],
|
|
161
162
|
});
|
|
162
|
-
f.
|
|
163
|
+
f.setValue('u', 'x');
|
|
163
164
|
const p = f.validateField('u');
|
|
164
165
|
// synchronously after kicking off: the field is marked validating
|
|
165
|
-
expect(f.
|
|
166
|
+
expect(f.getFormState().validating.u).toBe(true);
|
|
166
167
|
resolveV?.(undefined);
|
|
167
168
|
await p;
|
|
168
|
-
expect(f.
|
|
169
|
+
expect(f.getFormState().validating.u).toBe(false);
|
|
169
170
|
});
|
|
170
|
-
it('
|
|
171
|
+
it('reset clears warnings too', async () => {
|
|
171
172
|
const f = createForm();
|
|
172
173
|
f.registerField('name', { rules: [{ minLength: 5, warningOnly: true, message: 'w' }] });
|
|
173
|
-
f.
|
|
174
|
+
f.setValue('name', 'ab');
|
|
174
175
|
await f.validateField('name');
|
|
175
176
|
expect(f.getFieldWarning('name')).toBe('w');
|
|
176
|
-
f.
|
|
177
|
+
f.reset();
|
|
177
178
|
expect(f.getFieldWarning('name')).toBeUndefined();
|
|
178
179
|
});
|
|
179
180
|
// ---- validateTrigger (spec §4 L65 / L84) ----
|
|
@@ -207,7 +208,7 @@ describe('createForm', () => {
|
|
|
207
208
|
{ validator: () => (calls.push('r2'), 'second') },
|
|
208
209
|
],
|
|
209
210
|
});
|
|
210
|
-
f.
|
|
211
|
+
f.setValue('x', 'v');
|
|
211
212
|
const err = await f.validateField('x');
|
|
212
213
|
expect(err).toBe('first');
|
|
213
214
|
// both rules ran because we did NOT stop at the first error
|
|
@@ -222,7 +223,7 @@ describe('createForm', () => {
|
|
|
222
223
|
{ validator: () => (calls.push('r2'), 'second') },
|
|
223
224
|
],
|
|
224
225
|
});
|
|
225
|
-
f.
|
|
226
|
+
f.setValue('x', 'v');
|
|
226
227
|
const err = await f.validateField('x');
|
|
227
228
|
expect(err).toBe('first');
|
|
228
229
|
// second rule never ran
|
|
@@ -236,88 +237,360 @@ describe('createForm', () => {
|
|
|
236
237
|
{ minLength: 5, warningOnly: true, message: 'warn' },
|
|
237
238
|
],
|
|
238
239
|
});
|
|
239
|
-
f.
|
|
240
|
+
f.setValue('x', '');
|
|
240
241
|
await f.validateField('x');
|
|
241
|
-
expect(f.
|
|
242
|
+
expect(f.getError('x')).toBe('err');
|
|
242
243
|
// empty value skips minLength, so no warning here — sanity that error wins
|
|
243
|
-
f.
|
|
244
|
+
f.setValue('x', 'ab');
|
|
244
245
|
await f.validateField('x');
|
|
245
246
|
// 'ab' passes required, fails minLength → warning surfaces
|
|
246
|
-
expect(f.
|
|
247
|
+
expect(f.getError('x')).toBeUndefined();
|
|
247
248
|
expect(f.getFieldWarning('x')).toBe('warn');
|
|
248
249
|
});
|
|
249
250
|
// ---- allowEmpty (spec §4 L70) ----
|
|
250
|
-
it('allowEmpty:false (default) drops empty-value keys on submit/
|
|
251
|
+
it('allowEmpty:false (default) drops empty-value keys on submit/getValues', async () => {
|
|
251
252
|
const f = createForm();
|
|
252
253
|
f.registerField('name', {});
|
|
253
254
|
f.registerField('bio', {});
|
|
254
|
-
f.
|
|
255
|
-
f.
|
|
256
|
-
expect(f.
|
|
257
|
-
const r = await f.
|
|
255
|
+
f.setValue('name', 'jo');
|
|
256
|
+
f.setValue('bio', '');
|
|
257
|
+
expect(f.getValues()).toEqual({ name: 'jo' });
|
|
258
|
+
const r = await f.submitForm();
|
|
258
259
|
expect(r.values).toEqual({ name: 'jo' });
|
|
259
260
|
});
|
|
260
261
|
it('allowEmpty:true keeps empty-value keys', async () => {
|
|
261
262
|
const f = createForm({ allowEmpty: true });
|
|
262
263
|
f.registerField('name', {});
|
|
263
264
|
f.registerField('bio', {});
|
|
264
|
-
f.
|
|
265
|
-
f.
|
|
266
|
-
expect(f.
|
|
267
|
-
const r = await f.
|
|
265
|
+
f.setValue('name', 'jo');
|
|
266
|
+
f.setValue('bio', '');
|
|
267
|
+
expect(f.getValues()).toEqual({ name: 'jo', bio: '' });
|
|
268
|
+
const r = await f.submitForm();
|
|
268
269
|
expect(r.values).toEqual({ name: 'jo', bio: '' });
|
|
269
270
|
});
|
|
270
271
|
// ---- field-level initialValue (spec §4.2 L79) ----
|
|
271
272
|
it('registerField initialValue seeds the field value (field-level init)', () => {
|
|
272
273
|
const f = createForm();
|
|
273
274
|
f.registerField('plan', { initialValue: 'pro' });
|
|
274
|
-
expect(f.
|
|
275
|
-
expect(f.
|
|
275
|
+
expect(f.getValue('plan')).toBe('pro');
|
|
276
|
+
expect(f.getValues()).toEqual({ plan: 'pro' });
|
|
276
277
|
});
|
|
277
278
|
it('container initialValues take precedence over field initialValue', () => {
|
|
278
279
|
const f = createForm({ initialValues: { plan: 'team' } });
|
|
279
280
|
f.registerField('plan', { initialValue: 'pro' });
|
|
280
281
|
// container already supplied a value → field init does not clobber it
|
|
281
|
-
expect(f.
|
|
282
|
+
expect(f.getValue('plan')).toBe('team');
|
|
282
283
|
});
|
|
283
|
-
it('
|
|
284
|
+
it('reset restores the field-level initialValue', () => {
|
|
284
285
|
const f = createForm();
|
|
285
286
|
f.registerField('plan', { initialValue: 'pro' });
|
|
286
|
-
f.
|
|
287
|
-
expect(f.
|
|
288
|
-
f.
|
|
289
|
-
expect(f.
|
|
287
|
+
f.setValue('plan', 'free');
|
|
288
|
+
expect(f.getValue('plan')).toBe('free');
|
|
289
|
+
f.reset();
|
|
290
|
+
expect(f.getValue('plan')).toBe('pro');
|
|
290
291
|
});
|
|
291
292
|
// ---- field-level transform (spec §4.2 L88) ----
|
|
292
293
|
it('transform converts the value on collect/submit without mutating state', async () => {
|
|
293
294
|
const f = createForm();
|
|
294
295
|
f.registerField('tags', { transform: (v) => String(v).split(',').map((s) => s.trim()) });
|
|
295
|
-
f.
|
|
296
|
+
f.setValue('tags', 'a, b , c');
|
|
296
297
|
// live state keeps the raw string (red line #2: pure transform, no write-back)
|
|
297
|
-
expect(f.
|
|
298
|
-
expect(f.
|
|
299
|
-
const r = await f.
|
|
298
|
+
expect(f.getValue('tags')).toBe('a, b , c');
|
|
299
|
+
expect(f.getValues()).toEqual({ tags: ['a', 'b', 'c'] });
|
|
300
|
+
const r = await f.submitForm();
|
|
300
301
|
expect(r.values).toEqual({ tags: ['a', 'b', 'c'] });
|
|
301
302
|
});
|
|
302
303
|
it('transform receives sibling values and runs over emptiable input', async () => {
|
|
303
304
|
const f = createForm({ allowEmpty: true });
|
|
304
305
|
f.registerField('a', {});
|
|
305
306
|
f.registerField('full', { transform: (_v, values) => `${values.a}!` });
|
|
306
|
-
f.
|
|
307
|
-
f.
|
|
308
|
-
expect(f.
|
|
307
|
+
f.setValue('a', 'hi');
|
|
308
|
+
f.setValue('full', '');
|
|
309
|
+
expect(f.getValues()).toEqual({ a: 'hi', full: 'hi!' });
|
|
309
310
|
});
|
|
310
311
|
it('subscribe notifies on changes', () => {
|
|
311
312
|
const f = createForm();
|
|
312
313
|
f.registerField('x');
|
|
313
314
|
let count = 0;
|
|
314
315
|
const unsub = f.subscribe(() => (count += 1));
|
|
315
|
-
f.
|
|
316
|
+
f.setValue('x', 1);
|
|
316
317
|
expect(count).toBeGreaterThan(0);
|
|
317
318
|
unsub();
|
|
318
319
|
const before = count;
|
|
319
|
-
f.
|
|
320
|
+
f.setValue('x', 2);
|
|
320
321
|
expect(count).toBe(before);
|
|
321
322
|
});
|
|
323
|
+
// ---- Semi bare-name additions (批C-A) ----
|
|
324
|
+
it('getValue() with no arg returns a snapshot of all values', () => {
|
|
325
|
+
const f = createForm({ initialValues: { a: 1, b: 2 } });
|
|
326
|
+
expect(f.getValue()).toEqual({ a: 1, b: 2 });
|
|
327
|
+
// snapshot is a copy — mutating it must not affect form state
|
|
328
|
+
f.getValue().a = 99;
|
|
329
|
+
expect(f.getValue('a')).toBe(1);
|
|
330
|
+
});
|
|
331
|
+
it('getError() with no arg returns the whole errors map', async () => {
|
|
332
|
+
const f = createForm();
|
|
333
|
+
f.registerField('name', { rules: [{ required: true }] });
|
|
334
|
+
await f.validateField('name');
|
|
335
|
+
expect(f.getError()).toEqual(f.getFormState().errors);
|
|
336
|
+
expect(f.getError('name')).toBeTruthy();
|
|
337
|
+
});
|
|
338
|
+
it('setError imperatively sets a field error', () => {
|
|
339
|
+
const f = createForm();
|
|
340
|
+
f.registerField('name', {});
|
|
341
|
+
f.setError('name', 'server says no');
|
|
342
|
+
expect(f.getError('name')).toBe('server says no');
|
|
343
|
+
f.setError('name', undefined);
|
|
344
|
+
expect(f.getError('name')).toBeUndefined();
|
|
345
|
+
});
|
|
346
|
+
it('getFieldExist reflects registration and cleanup', () => {
|
|
347
|
+
const f = createForm();
|
|
348
|
+
expect(f.getFieldExist('name')).toBe(false);
|
|
349
|
+
const unregister = f.registerField('name', {});
|
|
350
|
+
expect(f.getFieldExist('name')).toBe(true);
|
|
351
|
+
unregister();
|
|
352
|
+
expect(f.getFieldExist('name')).toBe(false);
|
|
353
|
+
});
|
|
354
|
+
it('getInitValue / getInitValues expose initial values', () => {
|
|
355
|
+
const f = createForm({ initialValues: { a: 1 } });
|
|
356
|
+
f.registerField('b', { initialValue: 2 });
|
|
357
|
+
expect(f.getInitValue('a')).toBe(1);
|
|
358
|
+
expect(f.getInitValue('b')).toBe(2);
|
|
359
|
+
expect(f.getInitValue('missing')).toBeUndefined();
|
|
360
|
+
expect(f.getInitValue()).toEqual({ a: 1, b: 2 });
|
|
361
|
+
expect(f.getInitValues()).toEqual({ a: 1, b: 2 });
|
|
362
|
+
// changing a live value must not affect the init snapshot
|
|
363
|
+
f.setValue('a', 9);
|
|
364
|
+
expect(f.getInitValue('a')).toBe(1);
|
|
365
|
+
});
|
|
366
|
+
it('reset(fields) resets only the targeted fields', async () => {
|
|
367
|
+
const f = createForm({ initialValues: { a: 'a0', b: 'b0' } });
|
|
368
|
+
f.registerField('a', { rules: [{ required: true }] });
|
|
369
|
+
f.registerField('b', { rules: [{ required: true }] });
|
|
370
|
+
f.setValue('a', '');
|
|
371
|
+
f.setValue('b', '');
|
|
372
|
+
await f.validate();
|
|
373
|
+
expect(f.getError('a')).toBeTruthy();
|
|
374
|
+
expect(f.getError('b')).toBeTruthy();
|
|
375
|
+
f.reset(['a']);
|
|
376
|
+
// only `a` fell back to its initial value and lost its error
|
|
377
|
+
expect(f.getValue('a')).toBe('a0');
|
|
378
|
+
expect(f.getError('a')).toBeUndefined();
|
|
379
|
+
// `b` is untouched by the partial reset
|
|
380
|
+
expect(f.getValue('b')).toBe('');
|
|
381
|
+
expect(f.getError('b')).toBeTruthy();
|
|
382
|
+
});
|
|
383
|
+
it('reset(fields) drops a field that has no initial value', () => {
|
|
384
|
+
const f = createForm();
|
|
385
|
+
f.registerField('a', {});
|
|
386
|
+
f.setValue('a', 'x');
|
|
387
|
+
f.reset(['a']);
|
|
388
|
+
expect(f.getValue('a')).toBeUndefined();
|
|
389
|
+
expect(Object.prototype.hasOwnProperty.call(f.getValue(), 'a')).toBe(false);
|
|
390
|
+
});
|
|
391
|
+
it('setValues merges by default, replaces with isOverride', () => {
|
|
392
|
+
const f = createForm({ initialValues: { a: 1, b: 2 } });
|
|
393
|
+
f.setValues({ b: 20 });
|
|
394
|
+
expect(f.getValue()).toEqual({ a: 1, b: 20 });
|
|
395
|
+
f.setValues({ c: 3 }, { isOverride: true });
|
|
396
|
+
expect(f.getValue()).toEqual({ c: 3 });
|
|
397
|
+
});
|
|
398
|
+
// ---- 批C-E: real nested-array paths (lodash path, Semi-aligned) ----
|
|
399
|
+
it('getValue/setValue address nested array paths (users[0].name)', () => {
|
|
400
|
+
const f = createForm();
|
|
401
|
+
f.setValue('users[0].name', 'ada');
|
|
402
|
+
f.setValue('users[0].age', 30);
|
|
403
|
+
f.setValue('users[1].name', 'bob');
|
|
404
|
+
// reads resolve nested paths
|
|
405
|
+
expect(f.getValue('users[0].name')).toBe('ada');
|
|
406
|
+
expect(f.getValue('users[1].name')).toBe('bob');
|
|
407
|
+
// the underlying tree is a REAL array of objects, not flat keys
|
|
408
|
+
expect(f.getValue('users')).toEqual([
|
|
409
|
+
{ name: 'ada', age: 30 },
|
|
410
|
+
{ name: 'bob' },
|
|
411
|
+
]);
|
|
412
|
+
// no flat string keys leaked
|
|
413
|
+
const all = f.getValue();
|
|
414
|
+
expect(Object.keys(all)).toEqual(['users']);
|
|
415
|
+
expect(Array.isArray(all.users)).toBe(true);
|
|
416
|
+
});
|
|
417
|
+
it('setValue does not mutate the previous values tree (immutable)', () => {
|
|
418
|
+
const f = createForm();
|
|
419
|
+
f.setValue('a.b', 1);
|
|
420
|
+
const before = f.getFormState().values;
|
|
421
|
+
f.setValue('a.c', 2);
|
|
422
|
+
const after = f.getFormState().values;
|
|
423
|
+
// fresh root reference so Svelte subscribers see the change
|
|
424
|
+
expect(after).not.toBe(before);
|
|
425
|
+
expect(f.getValue('a')).toEqual({ b: 1, c: 2 });
|
|
426
|
+
});
|
|
427
|
+
it('collectValues rebuilds a nested array structure from registered fields', () => {
|
|
428
|
+
const f = createForm();
|
|
429
|
+
f.registerField('users[0].name', {});
|
|
430
|
+
f.registerField('users[0].age', {});
|
|
431
|
+
f.registerField('users[1].name', {});
|
|
432
|
+
f.setValue('users[0].name', 'ada');
|
|
433
|
+
f.setValue('users[0].age', 42);
|
|
434
|
+
f.setValue('users[1].name', 'bob');
|
|
435
|
+
// getValues returns a real nested array — the core Semi-alignment point
|
|
436
|
+
expect(f.getValues()).toEqual({
|
|
437
|
+
users: [
|
|
438
|
+
{ name: 'ada', age: 42 },
|
|
439
|
+
{ name: 'bob' },
|
|
440
|
+
],
|
|
441
|
+
});
|
|
442
|
+
});
|
|
443
|
+
it('nested-path field validates and reads value by path', async () => {
|
|
444
|
+
const f = createForm();
|
|
445
|
+
f.registerField('users[0].name', { label: 'Name', rules: [{ required: true }] });
|
|
446
|
+
expect(await f.validateField('users[0].name')).toBeTruthy();
|
|
447
|
+
f.setValue('users[0].name', 'ada');
|
|
448
|
+
expect(await f.validateField('users[0].name')).toBeUndefined();
|
|
449
|
+
});
|
|
450
|
+
it('nested initialValues seed nested reads and reset restores them', () => {
|
|
451
|
+
const f = createForm({ initialValues: { users: [{ name: 'seed' }] } });
|
|
452
|
+
expect(f.getValue('users[0].name')).toBe('seed');
|
|
453
|
+
f.setValue('users[0].name', 'changed');
|
|
454
|
+
expect(f.getValue('users[0].name')).toBe('changed');
|
|
455
|
+
f.reset();
|
|
456
|
+
expect(f.getValue('users[0].name')).toBe('seed');
|
|
457
|
+
// initial snapshot never aliased the mutated live tree
|
|
458
|
+
expect(f.getInitValue('users[0].name')).toBe('seed');
|
|
459
|
+
});
|
|
460
|
+
// ---- 批C-E: async-validator-specific rules ----
|
|
461
|
+
it('type=array rule (async-validator) rejects non-arrays', async () => {
|
|
462
|
+
const f = createForm();
|
|
463
|
+
f.registerField('tags', { rules: [{ type: 'array', message: 'must be array' }] });
|
|
464
|
+
f.setValue('tags', 'nope');
|
|
465
|
+
expect(await f.validateField('tags')).toBe('must be array');
|
|
466
|
+
f.setValue('tags', ['a', 'b']);
|
|
467
|
+
expect(await f.validateField('tags')).toBeUndefined();
|
|
468
|
+
});
|
|
469
|
+
it('type=enum rule (async-validator) restricts to allowed values', async () => {
|
|
470
|
+
const f = createForm();
|
|
471
|
+
f.registerField('plan', {
|
|
472
|
+
rules: [{ type: 'enum', enum: ['free', 'pro'], message: 'bad plan' }],
|
|
473
|
+
});
|
|
474
|
+
f.setValue('plan', 'gold');
|
|
475
|
+
expect(await f.validateField('plan')).toBe('bad plan');
|
|
476
|
+
f.setValue('plan', 'pro');
|
|
477
|
+
expect(await f.validateField('plan')).toBeUndefined();
|
|
478
|
+
});
|
|
479
|
+
it('len rule (async-validator) enforces exact length', async () => {
|
|
480
|
+
const f = createForm();
|
|
481
|
+
f.registerField('code', { rules: [{ len: 4, message: 'need 4 chars' }] });
|
|
482
|
+
f.setValue('code', 'ab');
|
|
483
|
+
expect(await f.validateField('code')).toBe('need 4 chars');
|
|
484
|
+
f.setValue('code', 'abcd');
|
|
485
|
+
expect(await f.validateField('code')).toBeUndefined();
|
|
486
|
+
});
|
|
487
|
+
it('whitespace rule (async-validator) rejects whitespace-only strings', async () => {
|
|
488
|
+
const f = createForm();
|
|
489
|
+
f.registerField('title', {
|
|
490
|
+
rules: [{ type: 'string', whitespace: true, message: 'blank' }],
|
|
491
|
+
});
|
|
492
|
+
f.setValue('title', ' ');
|
|
493
|
+
expect(await f.validateField('title')).toBe('blank');
|
|
494
|
+
f.setValue('title', 'hi');
|
|
495
|
+
expect(await f.validateField('title')).toBeUndefined();
|
|
496
|
+
});
|
|
497
|
+
it('type=integer rule (async-validator) rejects floats', async () => {
|
|
498
|
+
const f = createForm();
|
|
499
|
+
f.registerField('n', { rules: [{ type: 'integer', message: 'not int' }] });
|
|
500
|
+
f.setValue('n', 3.5);
|
|
501
|
+
expect(await f.validateField('n')).toBe('not int');
|
|
502
|
+
f.setValue('n', 3);
|
|
503
|
+
expect(await f.validateField('n')).toBeUndefined();
|
|
504
|
+
});
|
|
505
|
+
it('warningOnly still layers on top of async-validator (soft warning)', async () => {
|
|
506
|
+
const f = createForm();
|
|
507
|
+
f.registerField('bio', {
|
|
508
|
+
rules: [
|
|
509
|
+
{ required: true, message: 'required' },
|
|
510
|
+
{ minLength: 10, warningOnly: true, message: 'longer is better' },
|
|
511
|
+
],
|
|
512
|
+
});
|
|
513
|
+
f.setValue('bio', 'short');
|
|
514
|
+
const err = await f.validateField('bio');
|
|
515
|
+
// required passes (non-empty); minLength is warningOnly → warning, not error
|
|
516
|
+
expect(err).toBeUndefined();
|
|
517
|
+
expect(f.getFieldWarning('bio')).toBe('longer is better');
|
|
518
|
+
const r = await f.submitForm();
|
|
519
|
+
expect(r.valid).toBe(true);
|
|
520
|
+
});
|
|
521
|
+
it('getTouched reflects setTouched', () => {
|
|
522
|
+
const f = createForm();
|
|
523
|
+
f.registerField('a');
|
|
524
|
+
expect(f.getTouched('a')).toBe(false);
|
|
525
|
+
f.setTouched('a', true);
|
|
526
|
+
expect(f.getTouched('a')).toBe(true);
|
|
527
|
+
f.setTouched('a', false);
|
|
528
|
+
expect(f.getTouched('a')).toBe(false);
|
|
529
|
+
});
|
|
530
|
+
it('silent validate computes result without mutating state', async () => {
|
|
531
|
+
const f = createForm();
|
|
532
|
+
f.registerField('email', { rules: [{ required: true, message: 'required' }] });
|
|
533
|
+
// invalid but silent → returns false, yet no error is surfaced in state
|
|
534
|
+
const ok = await f.validate({ silent: true });
|
|
535
|
+
expect(ok).toBe(false);
|
|
536
|
+
expect(f.getError('email')).toBeUndefined();
|
|
537
|
+
expect(f.getFormState().touched.email).toBeUndefined();
|
|
538
|
+
// non-silent validate DOES surface the error
|
|
539
|
+
await f.validate();
|
|
540
|
+
expect(f.getError('email')).toBeTruthy();
|
|
541
|
+
});
|
|
542
|
+
it('silent validate can target specific fields', async () => {
|
|
543
|
+
const f = createForm();
|
|
544
|
+
f.registerField('a', { rules: [{ required: true }] });
|
|
545
|
+
f.registerField('b', { rules: [{ required: true }] });
|
|
546
|
+
f.setValue('b', 'filled');
|
|
547
|
+
expect(await f.validate({ fields: ['b'], silent: true })).toBe(true);
|
|
548
|
+
expect(await f.validate({ fields: ['a'], silent: true })).toBe(false);
|
|
549
|
+
// still no state mutation
|
|
550
|
+
expect(f.getError('a')).toBeUndefined();
|
|
551
|
+
});
|
|
552
|
+
it('form-level validator replaces per-field rules on validate', async () => {
|
|
553
|
+
const f = createForm({
|
|
554
|
+
validator: (values) => {
|
|
555
|
+
const errors = {};
|
|
556
|
+
if (values.name !== 'mike')
|
|
557
|
+
errors.name = 'you must name mike';
|
|
558
|
+
return errors;
|
|
559
|
+
},
|
|
560
|
+
});
|
|
561
|
+
// per-field rule would pass, but form-level validator fails it
|
|
562
|
+
f.registerField('name', { rules: [] });
|
|
563
|
+
f.setValue('name', 'bob');
|
|
564
|
+
expect(await f.validate()).toBe(false);
|
|
565
|
+
expect(f.getError('name')).toBe('you must name mike');
|
|
566
|
+
f.setValue('name', 'mike');
|
|
567
|
+
expect(await f.validate()).toBe(true);
|
|
568
|
+
expect(f.getError('name')).toBeFalsy();
|
|
569
|
+
});
|
|
570
|
+
it('form-level validator runs on submitForm', async () => {
|
|
571
|
+
const f = createForm({
|
|
572
|
+
validator: (values) => (values.age >= 18 ? {} : { age: 'must be adult' }),
|
|
573
|
+
});
|
|
574
|
+
f.registerField('age');
|
|
575
|
+
f.setValue('age', 10);
|
|
576
|
+
let r = await f.submitForm();
|
|
577
|
+
expect(r.valid).toBe(false);
|
|
578
|
+
expect(r.errors.age).toBe('must be adult');
|
|
579
|
+
f.setValue('age', 20);
|
|
580
|
+
r = await f.submitForm();
|
|
581
|
+
expect(r.valid).toBe(true);
|
|
582
|
+
});
|
|
583
|
+
it('async form-level validator is awaited', async () => {
|
|
584
|
+
const f = createForm({
|
|
585
|
+
validator: async (values) => {
|
|
586
|
+
await new Promise((res) => setTimeout(res, 10));
|
|
587
|
+
return values.name ? {} : { name: 'required' };
|
|
588
|
+
},
|
|
589
|
+
});
|
|
590
|
+
f.registerField('name');
|
|
591
|
+
expect(await f.validate()).toBe(false);
|
|
592
|
+
f.setValue('name', 'x');
|
|
593
|
+
expect(await f.validate()).toBe(true);
|
|
594
|
+
});
|
|
322
595
|
});
|
|
323
596
|
//# sourceMappingURL=form.test.js.map
|