oxform-core 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/export/index.ts +7 -0
- package/export/schema.ts +1 -0
- package/package.json +40 -0
- package/readme.md +13 -0
- package/src/field-api.constants.ts +15 -0
- package/src/field-api.ts +139 -0
- package/src/form-api.ts +84 -0
- package/src/form-api.types.ts +148 -0
- package/src/form-array-field-api.ts +233 -0
- package/src/form-context-api.ts +232 -0
- package/src/form-field-api.ts +174 -0
- package/src/more-types.ts +178 -0
- package/src/tests/array/append.spec.ts +138 -0
- package/src/tests/array/insert.spec.ts +182 -0
- package/src/tests/array/move.spec.ts +175 -0
- package/src/tests/array/prepend.spec.ts +138 -0
- package/src/tests/array/remove.spec.ts +174 -0
- package/src/tests/array/swap.spec.ts +152 -0
- package/src/tests/array/update.spec.ts +148 -0
- package/src/tests/field/change.spec.ts +226 -0
- package/src/tests/field/reset.spec.ts +617 -0
- package/src/tests/field/set-errors.spec.ts +254 -0
- package/src/tests/field-api/field-api.spec.ts +341 -0
- package/src/tests/form-api/reset.spec.ts +535 -0
- package/src/tests/form-api/submit.spec.ts +409 -0
- package/src/types.ts +5 -0
- package/src/utils/get.ts +5 -0
- package/src/utils/testing/sleep.ts +1 -0
- package/src/utils/testing/tests.ts +18 -0
- package/src/utils/update.ts +6 -0
- package/src/utils/validate.ts +8 -0
- package/tsconfig.json +3 -0
- package/tsdown.config.ts +10 -0
- package/vitest.config.ts +3 -0
|
@@ -0,0 +1,617 @@
|
|
|
1
|
+
import { FormApi } from '#form-api';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import z from 'zod';
|
|
4
|
+
|
|
5
|
+
const schema = z.object({
|
|
6
|
+
name: z.string(),
|
|
7
|
+
email: z.string().email('Invalid email format'),
|
|
8
|
+
age: z.number().min(0, 'Age must be non-negative'),
|
|
9
|
+
nested: z.object({
|
|
10
|
+
deep: z.object({
|
|
11
|
+
value: z.string(),
|
|
12
|
+
array: z.string().array(),
|
|
13
|
+
}),
|
|
14
|
+
}),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const defaultValues = {
|
|
18
|
+
name: 'Default Name',
|
|
19
|
+
email: 'default@example.com',
|
|
20
|
+
age: 25,
|
|
21
|
+
nested: {
|
|
22
|
+
deep: {
|
|
23
|
+
value: 'default value',
|
|
24
|
+
array: ['default1', 'default2'],
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const setup = async () => {
|
|
30
|
+
const form = new FormApi({
|
|
31
|
+
schema,
|
|
32
|
+
defaultValues,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
form['~mount']();
|
|
36
|
+
|
|
37
|
+
return { form };
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
describe('basic field reset', () => {
|
|
41
|
+
it('should reset field value to default', async () => {
|
|
42
|
+
const { form } = await setup();
|
|
43
|
+
|
|
44
|
+
form.field.change('name', 'Changed Name');
|
|
45
|
+
|
|
46
|
+
expect(form.field.get('name')).toBe('Changed Name');
|
|
47
|
+
|
|
48
|
+
form.field.reset('name');
|
|
49
|
+
|
|
50
|
+
expect(form.field.get('name')).toBe('Default Name');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should reset nested field value to default', async () => {
|
|
54
|
+
const { form } = await setup();
|
|
55
|
+
|
|
56
|
+
form.field.change('nested.deep.value', 'changed nested');
|
|
57
|
+
|
|
58
|
+
expect(form.field.get('nested.deep.value')).toBe('changed nested');
|
|
59
|
+
|
|
60
|
+
form.field.reset('nested.deep.value');
|
|
61
|
+
|
|
62
|
+
expect(form.field.get('nested.deep.value')).toBe('default value');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should reset array field value to default', async () => {
|
|
66
|
+
const { form } = await setup();
|
|
67
|
+
|
|
68
|
+
form.field.change('nested.deep.array', ['changed1', 'changed2', 'changed3']);
|
|
69
|
+
|
|
70
|
+
expect(form.field.get('nested.deep.array')).toEqual(['changed1', 'changed2', 'changed3']);
|
|
71
|
+
|
|
72
|
+
form.field.reset('nested.deep.array');
|
|
73
|
+
|
|
74
|
+
expect(form.field.get('nested.deep.array')).toEqual(['default1', 'default2']);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should not affect other fields when resetting single field', async () => {
|
|
78
|
+
const { form } = await setup();
|
|
79
|
+
|
|
80
|
+
form.field.change('name', 'Changed Name');
|
|
81
|
+
form.field.change('email', 'changed@example.com');
|
|
82
|
+
form.field.change('age', 30);
|
|
83
|
+
|
|
84
|
+
form.field.reset('name');
|
|
85
|
+
|
|
86
|
+
expect(form.field.get('name')).toBe('Default Name');
|
|
87
|
+
expect(form.field.get('email')).toBe('changed@example.com');
|
|
88
|
+
expect(form.field.get('age')).toBe(30);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe('field metadata reset', () => {
|
|
93
|
+
it('should reset field metadata to defaults', async () => {
|
|
94
|
+
const { form } = await setup();
|
|
95
|
+
|
|
96
|
+
form.field.change('name', 'Changed Name');
|
|
97
|
+
form.field.focus('name');
|
|
98
|
+
form.field.blur('name');
|
|
99
|
+
|
|
100
|
+
expect(form.field.meta('name').dirty).toBe(true);
|
|
101
|
+
expect(form.field.meta('name').touched).toBe(true);
|
|
102
|
+
expect(form.field.meta('name').blurred).toBe(true);
|
|
103
|
+
|
|
104
|
+
form.field.reset('name');
|
|
105
|
+
|
|
106
|
+
expect(form.field.meta('name').dirty).toBe(false);
|
|
107
|
+
expect(form.field.meta('name').touched).toBe(false);
|
|
108
|
+
expect(form.field.meta('name').blurred).toBe(false);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('should reset computed metadata properties', async () => {
|
|
112
|
+
const { form } = await setup();
|
|
113
|
+
|
|
114
|
+
form.field.change('name', 'Changed Name');
|
|
115
|
+
|
|
116
|
+
expect(form.field.meta('name').pristine).toBe(false);
|
|
117
|
+
expect(form.field.meta('name').default).toBe(false);
|
|
118
|
+
|
|
119
|
+
form.field.reset('name');
|
|
120
|
+
|
|
121
|
+
expect(form.field.meta('name').pristine).toBe(true);
|
|
122
|
+
expect(form.field.meta('name').default).toBe(true);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('should not affect metadata of other fields', async () => {
|
|
126
|
+
const { form } = await setup();
|
|
127
|
+
|
|
128
|
+
form.field.change('name', 'Changed Name');
|
|
129
|
+
form.field.change('email', 'changed@example.com');
|
|
130
|
+
form.field.focus('email');
|
|
131
|
+
|
|
132
|
+
form.field.reset('name');
|
|
133
|
+
|
|
134
|
+
expect(form.field.meta('name').dirty).toBe(false);
|
|
135
|
+
expect(form.field.meta('email').dirty).toBe(true);
|
|
136
|
+
expect(form.field.meta('email').touched).toBe(true);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
describe('field errors reset', () => {
|
|
141
|
+
it('should clear field errors', async () => {
|
|
142
|
+
const { form } = await setup();
|
|
143
|
+
|
|
144
|
+
form.field.change('email', 'invalid-email');
|
|
145
|
+
await form.validate();
|
|
146
|
+
|
|
147
|
+
expect(form.field.errors('email')).not.toHaveLength(0);
|
|
148
|
+
|
|
149
|
+
form.field.reset('email');
|
|
150
|
+
|
|
151
|
+
expect(form.field.errors('email')).toHaveLength(0);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('should not affect errors of other fields', async () => {
|
|
155
|
+
const { form } = await setup();
|
|
156
|
+
|
|
157
|
+
form.field.change('email', 'invalid-email');
|
|
158
|
+
form.field.change('age', -5);
|
|
159
|
+
await form.validate();
|
|
160
|
+
|
|
161
|
+
expect(form.field.errors('email')).not.toHaveLength(0);
|
|
162
|
+
expect(form.field.errors('age')).not.toHaveLength(0);
|
|
163
|
+
|
|
164
|
+
form.field.reset('email');
|
|
165
|
+
|
|
166
|
+
expect(form.field.errors('email')).toHaveLength(0);
|
|
167
|
+
expect(form.field.errors('age')).not.toHaveLength(0);
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
describe('field refs reset', () => {
|
|
172
|
+
it('should clear field ref', async () => {
|
|
173
|
+
const { form } = await setup();
|
|
174
|
+
|
|
175
|
+
const nameElement = document.createElement('input');
|
|
176
|
+
const emailElement = document.createElement('input');
|
|
177
|
+
|
|
178
|
+
form.field.register('name')(nameElement);
|
|
179
|
+
form.field.register('email')(emailElement);
|
|
180
|
+
|
|
181
|
+
expect(form.store.state.refs.name).toBe(nameElement);
|
|
182
|
+
expect(form.store.state.refs.email).toBe(emailElement);
|
|
183
|
+
|
|
184
|
+
form.field.reset('name');
|
|
185
|
+
|
|
186
|
+
expect(form.store.state.refs.name).toBeUndefined();
|
|
187
|
+
expect(form.store.state.refs.email).toBe(emailElement);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
describe('reset with options', () => {
|
|
192
|
+
describe('custom value option', () => {
|
|
193
|
+
it('should reset field to custom value instead of default', async () => {
|
|
194
|
+
const { form } = await setup();
|
|
195
|
+
|
|
196
|
+
form.field.change('name', 'Changed Name');
|
|
197
|
+
|
|
198
|
+
form.field.reset('name', { value: 'Custom Reset Value' });
|
|
199
|
+
|
|
200
|
+
expect(form.field.get('name')).toBe('Custom Reset Value');
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('should reset nested field to custom value', async () => {
|
|
204
|
+
const { form } = await setup();
|
|
205
|
+
|
|
206
|
+
form.field.change('nested.deep.value', 'changed');
|
|
207
|
+
|
|
208
|
+
form.field.reset('nested.deep.value', { value: 'custom nested' });
|
|
209
|
+
|
|
210
|
+
expect(form.field.get('nested.deep.value')).toBe('custom nested');
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('should reset array field to custom value', async () => {
|
|
214
|
+
const { form } = await setup();
|
|
215
|
+
|
|
216
|
+
form.field.change('nested.deep.array', ['changed']);
|
|
217
|
+
|
|
218
|
+
form.field.reset('nested.deep.array', { value: ['custom1', 'custom2'] });
|
|
219
|
+
|
|
220
|
+
expect(form.field.get('nested.deep.array')).toEqual(['custom1', 'custom2']);
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
describe('keep options', () => {
|
|
225
|
+
it('should keep field metadata when keep.meta is true', async () => {
|
|
226
|
+
const { form } = await setup();
|
|
227
|
+
|
|
228
|
+
form.field.change('name', 'Changed Name');
|
|
229
|
+
form.field.focus('name');
|
|
230
|
+
form.field.blur('name');
|
|
231
|
+
|
|
232
|
+
expect(form.field.meta('name').dirty).toBe(true);
|
|
233
|
+
expect(form.field.meta('name').touched).toBe(true);
|
|
234
|
+
expect(form.field.meta('name').blurred).toBe(true);
|
|
235
|
+
|
|
236
|
+
form.field.reset('name', { keep: { meta: true } });
|
|
237
|
+
|
|
238
|
+
expect(form.field.get('name')).toBe('Default Name');
|
|
239
|
+
expect(form.field.meta('name').dirty).toBe(true);
|
|
240
|
+
expect(form.field.meta('name').touched).toBe(true);
|
|
241
|
+
expect(form.field.meta('name').blurred).toBe(true);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('should keep field errors when keep.errors is true', async () => {
|
|
245
|
+
const { form } = await setup();
|
|
246
|
+
|
|
247
|
+
form.field.change('email', 'invalid-email');
|
|
248
|
+
await form.validate();
|
|
249
|
+
|
|
250
|
+
expect(form.field.errors('email')).not.toHaveLength(0);
|
|
251
|
+
|
|
252
|
+
form.field.reset('email', { keep: { errors: true } });
|
|
253
|
+
|
|
254
|
+
expect(form.field.get('email')).toBe('default@example.com');
|
|
255
|
+
expect(form.field.errors('email')).not.toHaveLength(0);
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it('should keep field refs when keep.refs is true', async () => {
|
|
259
|
+
const { form } = await setup();
|
|
260
|
+
|
|
261
|
+
const nameElement = document.createElement('input');
|
|
262
|
+
form.field.register('name')(nameElement);
|
|
263
|
+
|
|
264
|
+
form.field.change('name', 'Changed Name');
|
|
265
|
+
|
|
266
|
+
form.field.reset('name', { keep: { refs: true } });
|
|
267
|
+
|
|
268
|
+
expect(form.field.get('name')).toBe('Default Name');
|
|
269
|
+
expect(form.store.state.refs.name).toBe(nameElement);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('should keep multiple things when multiple keep options are true', async () => {
|
|
273
|
+
const { form } = await setup();
|
|
274
|
+
|
|
275
|
+
const nameElement = document.createElement('input');
|
|
276
|
+
form.field.register('name')(nameElement);
|
|
277
|
+
|
|
278
|
+
form.field.change('name', 'invalid-name-that-would-cause-error');
|
|
279
|
+
form.field.focus('name');
|
|
280
|
+
form.field.blur('name');
|
|
281
|
+
|
|
282
|
+
const mockErrors = [{ code: 'test', message: 'Test error', path: ['name'] }];
|
|
283
|
+
form.field.setErrors('name', mockErrors);
|
|
284
|
+
|
|
285
|
+
expect(form.field.meta('name').dirty).toBe(true);
|
|
286
|
+
expect(form.field.meta('name').touched).toBe(true);
|
|
287
|
+
expect(form.field.errors('name')).toEqual(mockErrors);
|
|
288
|
+
expect(form.store.state.refs.name).toBe(nameElement);
|
|
289
|
+
|
|
290
|
+
form.field.reset('name', {
|
|
291
|
+
keep: {
|
|
292
|
+
meta: true,
|
|
293
|
+
errors: true,
|
|
294
|
+
refs: true,
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
expect(form.field.get('name')).toBe('Default Name');
|
|
299
|
+
expect(form.field.meta('name').dirty).toBe(true);
|
|
300
|
+
expect(form.field.meta('name').touched).toBe(true);
|
|
301
|
+
expect(form.field.errors('name')).toEqual(mockErrors);
|
|
302
|
+
expect(form.store.state.refs.name).toBe(nameElement);
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
describe('combined options', () => {
|
|
307
|
+
it('should handle custom value and keep options together', async () => {
|
|
308
|
+
const { form } = await setup();
|
|
309
|
+
|
|
310
|
+
form.field.change('name', 'Changed Name');
|
|
311
|
+
form.field.focus('name');
|
|
312
|
+
|
|
313
|
+
form.field.reset('name', {
|
|
314
|
+
value: 'Custom Reset Value',
|
|
315
|
+
keep: { meta: true },
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
expect(form.field.get('name')).toBe('Custom Reset Value');
|
|
319
|
+
expect(form.field.meta('name').dirty).toBe(true);
|
|
320
|
+
expect(form.field.meta('name').touched).toBe(true);
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
describe('meta overrides', () => {
|
|
325
|
+
it('should set specific meta values when provided', async () => {
|
|
326
|
+
const { form } = await setup();
|
|
327
|
+
|
|
328
|
+
form.field.change('name', 'Changed Name');
|
|
329
|
+
|
|
330
|
+
expect(form.field.meta('name').dirty).toBe(true);
|
|
331
|
+
expect(form.field.meta('name').touched).toBe(true);
|
|
332
|
+
expect(form.field.meta('name').blurred).toBe(false);
|
|
333
|
+
|
|
334
|
+
form.field.reset('name', {
|
|
335
|
+
meta: {
|
|
336
|
+
dirty: false,
|
|
337
|
+
touched: false,
|
|
338
|
+
blurred: true,
|
|
339
|
+
},
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
expect(form.field.get('name')).toBe('Default Name');
|
|
343
|
+
expect(form.field.meta('name').dirty).toBe(false);
|
|
344
|
+
expect(form.field.meta('name').touched).toBe(false);
|
|
345
|
+
expect(form.field.meta('name').blurred).toBe(true);
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
it('should partially override meta values if keep.meta is true', async () => {
|
|
349
|
+
const { form } = await setup();
|
|
350
|
+
|
|
351
|
+
form.field.change('name', 'Changed Name');
|
|
352
|
+
form.field.focus('name');
|
|
353
|
+
form.field.blur('name');
|
|
354
|
+
|
|
355
|
+
expect(form.field.meta('name').dirty).toBe(true);
|
|
356
|
+
expect(form.field.meta('name').touched).toBe(true);
|
|
357
|
+
expect(form.field.meta('name').blurred).toBe(true);
|
|
358
|
+
|
|
359
|
+
form.field.reset('name', {
|
|
360
|
+
meta: {
|
|
361
|
+
dirty: false,
|
|
362
|
+
},
|
|
363
|
+
keep: {
|
|
364
|
+
meta: true,
|
|
365
|
+
},
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
expect(form.field.get('name')).toBe('Default Name');
|
|
369
|
+
expect(form.field.meta('name').dirty).toBe(false);
|
|
370
|
+
expect(form.field.meta('name').touched).toBe(true);
|
|
371
|
+
expect(form.field.meta('name').blurred).toBe(true);
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
it('should fully override meta values if keep.meta is undefined', async () => {
|
|
375
|
+
const { form } = await setup();
|
|
376
|
+
|
|
377
|
+
form.field.change('name', 'Changed Name');
|
|
378
|
+
form.field.focus('name');
|
|
379
|
+
form.field.blur('name');
|
|
380
|
+
|
|
381
|
+
expect(form.field.meta('name').dirty).toBe(true);
|
|
382
|
+
expect(form.field.meta('name').touched).toBe(true);
|
|
383
|
+
expect(form.field.meta('name').blurred).toBe(true);
|
|
384
|
+
|
|
385
|
+
form.field.reset('name', {
|
|
386
|
+
meta: {
|
|
387
|
+
blurred: true,
|
|
388
|
+
},
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
expect(form.field.get('name')).toBe('Default Name');
|
|
392
|
+
expect(form.field.meta('name').dirty).toBe(false);
|
|
393
|
+
expect(form.field.meta('name').touched).toBe(false);
|
|
394
|
+
expect(form.field.meta('name').blurred).toBe(true);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
it('should work with custom value and meta overrides', async () => {
|
|
398
|
+
const { form } = await setup();
|
|
399
|
+
|
|
400
|
+
form.field.reset('name', {
|
|
401
|
+
value: 'Custom Value',
|
|
402
|
+
meta: {
|
|
403
|
+
dirty: true,
|
|
404
|
+
touched: true,
|
|
405
|
+
blurred: false,
|
|
406
|
+
},
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
expect(form.field.get('name')).toBe('Custom Value');
|
|
410
|
+
expect(form.field.meta('name').dirty).toBe(true);
|
|
411
|
+
expect(form.field.meta('name').touched).toBe(true);
|
|
412
|
+
expect(form.field.meta('name').blurred).toBe(false);
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it('should work with keep.meta true and meta overrides', async () => {
|
|
416
|
+
const { form } = await setup();
|
|
417
|
+
|
|
418
|
+
form.field.change('name', 'Changed Name');
|
|
419
|
+
form.field.focus('name');
|
|
420
|
+
form.field.blur('name');
|
|
421
|
+
|
|
422
|
+
expect(form.field.meta('name').dirty).toBe(true);
|
|
423
|
+
expect(form.field.meta('name').touched).toBe(true);
|
|
424
|
+
expect(form.field.meta('name').blurred).toBe(true);
|
|
425
|
+
|
|
426
|
+
form.field.reset('name', {
|
|
427
|
+
keep: { meta: true },
|
|
428
|
+
meta: {
|
|
429
|
+
blurred: false,
|
|
430
|
+
},
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
expect(form.field.get('name')).toBe('Default Name');
|
|
434
|
+
expect(form.field.meta('name').dirty).toBe(true);
|
|
435
|
+
expect(form.field.meta('name').touched).toBe(true);
|
|
436
|
+
expect(form.field.meta('name').blurred).toBe(false);
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
it('should create meta when field has no existing meta', async () => {
|
|
440
|
+
const { form } = await setup();
|
|
441
|
+
|
|
442
|
+
expect(form.field.meta('name').dirty).toBe(false);
|
|
443
|
+
expect(form.field.meta('name').touched).toBe(false);
|
|
444
|
+
expect(form.field.meta('name').blurred).toBe(false);
|
|
445
|
+
|
|
446
|
+
form.field.reset('name', {
|
|
447
|
+
meta: {
|
|
448
|
+
dirty: true,
|
|
449
|
+
touched: true,
|
|
450
|
+
blurred: true,
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
expect(form.field.get('name')).toBe('Default Name');
|
|
455
|
+
expect(form.field.meta('name').dirty).toBe(true);
|
|
456
|
+
expect(form.field.meta('name').touched).toBe(true);
|
|
457
|
+
expect(form.field.meta('name').blurred).toBe(true);
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
it('should handle meta overrides with nested fields', async () => {
|
|
461
|
+
const { form } = await setup();
|
|
462
|
+
|
|
463
|
+
form.field.change('nested.deep.value', 'changed value');
|
|
464
|
+
form.field.focus('nested.deep.value');
|
|
465
|
+
|
|
466
|
+
expect(form.field.meta('nested.deep.value').dirty).toBe(true);
|
|
467
|
+
expect(form.field.meta('nested.deep.value').touched).toBe(true);
|
|
468
|
+
expect(form.field.meta('nested.deep.value').blurred).toBe(false);
|
|
469
|
+
|
|
470
|
+
form.field.reset('nested.deep.value', {
|
|
471
|
+
meta: {
|
|
472
|
+
dirty: false,
|
|
473
|
+
blurred: true,
|
|
474
|
+
},
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
expect(form.field.get('nested.deep.value')).toBe('default value');
|
|
478
|
+
expect(form.field.meta('nested.deep.value').dirty).toBe(false);
|
|
479
|
+
expect(form.field.meta('nested.deep.value').touched).toBe(false);
|
|
480
|
+
expect(form.field.meta('nested.deep.value').blurred).toBe(true);
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
it('should handle meta overrides with all options combined', async () => {
|
|
484
|
+
const { form } = await setup();
|
|
485
|
+
|
|
486
|
+
const nameElement = document.createElement('input');
|
|
487
|
+
form.field.register('name')(nameElement);
|
|
488
|
+
|
|
489
|
+
form.field.change('name', 'invalid-name');
|
|
490
|
+
|
|
491
|
+
const mockErrors = [{ code: 'test', message: 'Test error', path: ['name'] }];
|
|
492
|
+
form.field.setErrors('name', mockErrors);
|
|
493
|
+
|
|
494
|
+
form.field.reset('name', {
|
|
495
|
+
value: 'Custom Reset Value',
|
|
496
|
+
meta: {
|
|
497
|
+
dirty: true,
|
|
498
|
+
touched: true,
|
|
499
|
+
blurred: false,
|
|
500
|
+
},
|
|
501
|
+
keep: {
|
|
502
|
+
errors: true,
|
|
503
|
+
refs: true,
|
|
504
|
+
},
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
expect(form.field.get('name')).toBe('Custom Reset Value');
|
|
508
|
+
expect(form.field.meta('name').dirty).toBe(true);
|
|
509
|
+
expect(form.field.meta('name').touched).toBe(true);
|
|
510
|
+
expect(form.field.meta('name').blurred).toBe(false);
|
|
511
|
+
expect(form.field.errors('name')).toEqual(mockErrors);
|
|
512
|
+
expect(form.store.state.refs.name).toBe(nameElement);
|
|
513
|
+
});
|
|
514
|
+
});
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
describe('edge cases', () => {
|
|
518
|
+
it('should handle resetting non-existent field gracefully', async () => {
|
|
519
|
+
const { form } = await setup();
|
|
520
|
+
|
|
521
|
+
expect(() => {
|
|
522
|
+
form.field.reset('nonExistent' as any);
|
|
523
|
+
}).not.toThrow();
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
it('should handle undefined custom value gracefully', async () => {
|
|
527
|
+
const { form } = await setup();
|
|
528
|
+
|
|
529
|
+
form.field.change('name', 'Changed Name');
|
|
530
|
+
|
|
531
|
+
form.field.reset('name', { value: undefined });
|
|
532
|
+
|
|
533
|
+
expect(form.field.get('name')).toBe('Default Name');
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
it('should work after form reset', async () => {
|
|
537
|
+
const { form } = await setup();
|
|
538
|
+
|
|
539
|
+
form.field.change('name', 'Changed Name');
|
|
540
|
+
form.field.change('email', 'changed@example.com');
|
|
541
|
+
|
|
542
|
+
form.reset();
|
|
543
|
+
|
|
544
|
+
expect(form.field.get('name')).toBe('Default Name');
|
|
545
|
+
expect(form.field.get('email')).toBe('default@example.com');
|
|
546
|
+
|
|
547
|
+
form.field.change('name', 'New Change');
|
|
548
|
+
|
|
549
|
+
form.field.reset('name');
|
|
550
|
+
|
|
551
|
+
expect(form.field.get('name')).toBe('Default Name');
|
|
552
|
+
expect(form.field.get('email')).toBe('default@example.com');
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
it('should not affect form-level status', async () => {
|
|
556
|
+
const { form } = await setup();
|
|
557
|
+
|
|
558
|
+
const onSuccess = () => {};
|
|
559
|
+
await form.submit(onSuccess)();
|
|
560
|
+
|
|
561
|
+
expect(form.status.submits).toBe(1);
|
|
562
|
+
expect(form.status.submitted).toBe(true);
|
|
563
|
+
|
|
564
|
+
form.field.change('name', 'Changed Name');
|
|
565
|
+
form.field.reset('name');
|
|
566
|
+
|
|
567
|
+
expect(form.status.submits).toBe(1);
|
|
568
|
+
expect(form.status.submitted).toBe(true);
|
|
569
|
+
});
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
describe('integration with other form methods', () => {
|
|
573
|
+
it('should work correctly with validation', async () => {
|
|
574
|
+
const { form } = await setup();
|
|
575
|
+
|
|
576
|
+
form.field.change('email', 'invalid-email');
|
|
577
|
+
await form.validate();
|
|
578
|
+
|
|
579
|
+
expect(form.field.errors('email')).not.toHaveLength(0);
|
|
580
|
+
expect(form.status.valid).toBe(false);
|
|
581
|
+
|
|
582
|
+
form.field.reset('email');
|
|
583
|
+
|
|
584
|
+
expect(form.field.errors('email')).toHaveLength(0);
|
|
585
|
+
await form.validate();
|
|
586
|
+
expect(form.status.valid).toBe(true);
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
it('should work correctly after field interactions', async () => {
|
|
590
|
+
const { form } = await setup();
|
|
591
|
+
|
|
592
|
+
form.field.change('name', 'Changed Name');
|
|
593
|
+
form.field.focus('name');
|
|
594
|
+
form.field.blur('name');
|
|
595
|
+
|
|
596
|
+
const nameElement = document.createElement('input');
|
|
597
|
+
form.field.register('name')(nameElement);
|
|
598
|
+
|
|
599
|
+
expect(form.field.get('name')).toBe('Changed Name');
|
|
600
|
+
expect(form.field.meta('name').dirty).toBe(true);
|
|
601
|
+
expect(form.field.meta('name').touched).toBe(true);
|
|
602
|
+
expect(form.field.meta('name').blurred).toBe(true);
|
|
603
|
+
expect(form.store.state.refs.name).toBe(nameElement);
|
|
604
|
+
|
|
605
|
+
form.field.reset('name');
|
|
606
|
+
|
|
607
|
+
expect(form.field.get('name')).toBe('Default Name');
|
|
608
|
+
expect(form.field.meta('name').dirty).toBe(false);
|
|
609
|
+
expect(form.field.meta('name').touched).toBe(false);
|
|
610
|
+
expect(form.field.meta('name').blurred).toBe(false);
|
|
611
|
+
expect(form.store.state.refs.name).toBeUndefined();
|
|
612
|
+
|
|
613
|
+
form.field.change('name', 'New Value After Reset');
|
|
614
|
+
expect(form.field.get('name')).toBe('New Value After Reset');
|
|
615
|
+
expect(form.field.meta('name').dirty).toBe(true);
|
|
616
|
+
});
|
|
617
|
+
});
|