@teamnovu/kit-vue-forms 0.0.1 → 0.0.2
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/PLAN.md +3 -1
- package/package.json +1 -1
- package/src/composables/useField.ts +4 -4
- package/src/composables/useFieldRegistry.ts +1 -1
- package/src/composables/useForm.ts +5 -5
- package/src/composables/useFormData.ts +4 -4
- package/src/composables/useFormState.ts +2 -3
- package/src/composables/useSubform.ts +4 -4
- package/src/composables/useValidation.ts +5 -8
- package/src/index.ts +1 -1
- package/src/types/form.ts +4 -4
- package/src/utils/path.ts +3 -3
- package/tests/formState.test.ts +36 -65
- package/tests/integration.test.ts +7 -7
- package/tests/nestedPath.test.ts +70 -70
- package/tests/subform.test.ts +64 -64
- package/tests/useField.test.ts +10 -10
- package/tests/useForm.test.ts +3 -3
- package/tests/useValidation.test.ts +9 -9
package/tests/nestedPath.test.ts
CHANGED
|
@@ -117,8 +117,8 @@ describe('Nested Path Handling', () => {
|
|
|
117
117
|
const nameField = form.defineField({ path: 'user.name' })
|
|
118
118
|
const emailField = form.defineField({ path: 'user.email' })
|
|
119
119
|
|
|
120
|
-
expect(nameField.
|
|
121
|
-
expect(emailField.
|
|
120
|
+
expect(nameField.data.value).toBe('John Doe')
|
|
121
|
+
expect(emailField.data.value).toBe('john@example.com')
|
|
122
122
|
})
|
|
123
123
|
|
|
124
124
|
it('should define and access fields with deeply nested paths', () => {
|
|
@@ -128,9 +128,9 @@ describe('Nested Path Handling', () => {
|
|
|
128
128
|
const themeField = form.defineField({ path: 'user.profile.preferences.theme' })
|
|
129
129
|
const notificationsField = form.defineField({ path: 'user.profile.preferences.notifications' })
|
|
130
130
|
|
|
131
|
-
expect(ageField.
|
|
132
|
-
expect(themeField.
|
|
133
|
-
expect(notificationsField.
|
|
131
|
+
expect(ageField.data.value).toBe(30)
|
|
132
|
+
expect(themeField.data.value).toBe('dark')
|
|
133
|
+
expect(notificationsField.data.value).toBe(true)
|
|
134
134
|
})
|
|
135
135
|
|
|
136
136
|
it('should update nested field values reactively', async () => {
|
|
@@ -139,13 +139,13 @@ describe('Nested Path Handling', () => {
|
|
|
139
139
|
const nameField = form.defineField({ path: 'user.name' })
|
|
140
140
|
const ageField = form.defineField({ path: 'user.profile.age' })
|
|
141
141
|
|
|
142
|
-
nameField.
|
|
143
|
-
ageField.
|
|
142
|
+
nameField.data.value = 'Jane Doe'
|
|
143
|
+
ageField.data.value = 25
|
|
144
144
|
|
|
145
145
|
await nextTick()
|
|
146
146
|
|
|
147
|
-
expect(form.
|
|
148
|
-
expect(form.
|
|
147
|
+
expect(form.data.value.user.name).toBe('Jane Doe')
|
|
148
|
+
expect(form.data.value.user.profile.age).toBe(25)
|
|
149
149
|
})
|
|
150
150
|
|
|
151
151
|
it('should retrieve fields using getField with nested paths', () => {
|
|
@@ -159,8 +159,8 @@ describe('Nested Path Handling', () => {
|
|
|
159
159
|
|
|
160
160
|
expect(nameField).toBeDefined()
|
|
161
161
|
expect(ageField).toBeDefined()
|
|
162
|
-
expect(nameField?.
|
|
163
|
-
expect(ageField?.
|
|
162
|
+
expect(nameField?.data.value).toBe('John Doe')
|
|
163
|
+
expect(ageField?.data.value).toBe(30)
|
|
164
164
|
})
|
|
165
165
|
|
|
166
166
|
it('should handle nested paths with complex coordinate data', () => {
|
|
@@ -169,14 +169,14 @@ describe('Nested Path Handling', () => {
|
|
|
169
169
|
const latField = form.defineField({ path: 'company.address.coordinates.lat' })
|
|
170
170
|
const lngField = form.defineField({ path: 'company.address.coordinates.lng' })
|
|
171
171
|
|
|
172
|
-
expect(latField.
|
|
173
|
-
expect(lngField.
|
|
172
|
+
expect(latField.data.value).toBe(40.7128)
|
|
173
|
+
expect(lngField.data.value).toBe(-74.0060)
|
|
174
174
|
|
|
175
|
-
latField.
|
|
176
|
-
lngField.
|
|
175
|
+
latField.data.value = 41.8781
|
|
176
|
+
lngField.data.value = -87.6298
|
|
177
177
|
|
|
178
|
-
expect(form.
|
|
179
|
-
expect(form.
|
|
178
|
+
expect(form.data.value.company.address.coordinates.lat).toBe(41.8781)
|
|
179
|
+
expect(form.data.value.company.address.coordinates.lng).toBe(-87.6298)
|
|
180
180
|
})
|
|
181
181
|
})
|
|
182
182
|
|
|
@@ -187,8 +187,8 @@ describe('Nested Path Handling', () => {
|
|
|
187
187
|
const firstTagField = form.defineField({ path: 'tags.0' })
|
|
188
188
|
const secondTagField = form.defineField({ path: 'tags.1' })
|
|
189
189
|
|
|
190
|
-
expect(firstTagField.
|
|
191
|
-
expect(secondTagField.
|
|
190
|
+
expect(firstTagField.data.value).toBe('javascript')
|
|
191
|
+
expect(secondTagField.data.value).toBe('vue')
|
|
192
192
|
})
|
|
193
193
|
|
|
194
194
|
it('should handle nested object arrays with index paths', () => {
|
|
@@ -198,9 +198,9 @@ describe('Nested Path Handling', () => {
|
|
|
198
198
|
const firstContactEmailField = form.defineField({ path: 'contacts.0.email' })
|
|
199
199
|
const secondContactNameField = form.defineField({ path: 'contacts.1.name' })
|
|
200
200
|
|
|
201
|
-
expect(firstContactNameField.
|
|
202
|
-
expect(firstContactEmailField.
|
|
203
|
-
expect(secondContactNameField.
|
|
201
|
+
expect(firstContactNameField.data.value).toBe('Jane Smith')
|
|
202
|
+
expect(firstContactEmailField.data.value).toBe('jane@example.com')
|
|
203
|
+
expect(secondContactNameField.data.value).toBe('Bob Johnson')
|
|
204
204
|
})
|
|
205
205
|
|
|
206
206
|
it('should handle deeply nested arrays with multiple levels', () => {
|
|
@@ -219,10 +219,10 @@ describe('Nested Path Handling', () => {
|
|
|
219
219
|
path: 'contacts.1.addresses.0.street',
|
|
220
220
|
})
|
|
221
221
|
|
|
222
|
-
expect(firstContactFirstAddressTypeField.
|
|
223
|
-
expect(firstContactFirstAddressStreetField.
|
|
224
|
-
expect(firstContactSecondAddressTypeField.
|
|
225
|
-
expect(secondContactFirstAddressStreetField.
|
|
222
|
+
expect(firstContactFirstAddressTypeField.data.value).toBe('home')
|
|
223
|
+
expect(firstContactFirstAddressStreetField.data.value).toBe('456 Oak Ave')
|
|
224
|
+
expect(firstContactSecondAddressTypeField.data.value).toBe('work')
|
|
225
|
+
expect(secondContactFirstAddressStreetField.data.value).toBe('321 Elm St')
|
|
226
226
|
})
|
|
227
227
|
|
|
228
228
|
it('should update array element values reactively', async () => {
|
|
@@ -231,28 +231,28 @@ describe('Nested Path Handling', () => {
|
|
|
231
231
|
const firstTagField = form.defineField({ path: 'tags.0' })
|
|
232
232
|
const firstContactNameField = form.defineField({ path: 'contacts.0.name' })
|
|
233
233
|
|
|
234
|
-
firstTagField.
|
|
235
|
-
firstContactNameField.
|
|
234
|
+
firstTagField.data.value = 'react'
|
|
235
|
+
firstContactNameField.data.value = 'Janet Smith'
|
|
236
236
|
|
|
237
237
|
await nextTick()
|
|
238
238
|
|
|
239
|
-
expect(form.
|
|
240
|
-
expect(form.
|
|
239
|
+
expect(form.data.value.tags[0]).toBe('react')
|
|
240
|
+
expect(form.data.value.contacts[0].name).toBe('Janet Smith')
|
|
241
241
|
})
|
|
242
242
|
|
|
243
243
|
it('should handle dynamic array indices', async () => {
|
|
244
244
|
const form = useForm({ initialData })
|
|
245
245
|
|
|
246
246
|
// Test that we can access different indices
|
|
247
|
-
for (let i = 0; i < form.
|
|
247
|
+
for (let i = 0; i < form.data.value.tags.length; i++) {
|
|
248
248
|
const tagField = form.defineField({ path: `tags.${i}` as `tags.${number}` })
|
|
249
|
-
expect(tagField.
|
|
249
|
+
expect(tagField.data.value).toBe(initialData.tags[i])
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
// Test that we can access different contact indices
|
|
253
|
-
for (let i = 0; i < form.
|
|
253
|
+
for (let i = 0; i < form.data.value.contacts.length; i++) {
|
|
254
254
|
const contactNameField = form.defineField({ path: `contacts.${i}.name` as `contacts.${number}.name` })
|
|
255
|
-
expect(contactNameField.
|
|
255
|
+
expect(contactNameField.data.value).toBe(initialData.contacts[i].name)
|
|
256
256
|
}
|
|
257
257
|
})
|
|
258
258
|
})
|
|
@@ -266,10 +266,10 @@ describe('Nested Path Handling', () => {
|
|
|
266
266
|
const debugField = form.defineField({ path: 'metadata.settings.debug' })
|
|
267
267
|
const timeoutField = form.defineField({ path: 'metadata.settings.timeout' })
|
|
268
268
|
|
|
269
|
-
expect(versionField.
|
|
270
|
-
expect(createdField.
|
|
271
|
-
expect(debugField.
|
|
272
|
-
expect(timeoutField.
|
|
269
|
+
expect(versionField.data.value).toBe('1.0')
|
|
270
|
+
expect(createdField.data.value).toBe('2023-01-01')
|
|
271
|
+
expect(debugField.data.value).toBe(false)
|
|
272
|
+
expect(timeoutField.data.value).toBe(5000)
|
|
273
273
|
})
|
|
274
274
|
|
|
275
275
|
it('should handle record object updates', async () => {
|
|
@@ -278,13 +278,13 @@ describe('Nested Path Handling', () => {
|
|
|
278
278
|
const versionField = form.defineField({ path: 'metadata.version' })
|
|
279
279
|
const debugField = form.defineField({ path: 'metadata.settings.debug' })
|
|
280
280
|
|
|
281
|
-
versionField.
|
|
282
|
-
debugField.
|
|
281
|
+
versionField.data.value = '2.0'
|
|
282
|
+
debugField.data.value = true
|
|
283
283
|
|
|
284
284
|
await nextTick()
|
|
285
285
|
|
|
286
|
-
expect(form.
|
|
287
|
-
expect(form.
|
|
286
|
+
expect(form.data.value.metadata.version).toBe('2.0')
|
|
287
|
+
expect(form.data.value.metadata.settings.debug).toBe(true)
|
|
288
288
|
})
|
|
289
289
|
})
|
|
290
290
|
|
|
@@ -298,13 +298,13 @@ describe('Nested Path Handling', () => {
|
|
|
298
298
|
expect(nameField.dirty.value).toBe(false)
|
|
299
299
|
expect(ageField.dirty.value).toBe(false)
|
|
300
300
|
|
|
301
|
-
nameField.
|
|
301
|
+
nameField.data.value = 'Jane Doe'
|
|
302
302
|
await nextTick()
|
|
303
303
|
|
|
304
304
|
expect(nameField.dirty.value).toBe(true)
|
|
305
305
|
expect(ageField.dirty.value).toBe(false)
|
|
306
306
|
|
|
307
|
-
ageField.
|
|
307
|
+
ageField.data.value = 25
|
|
308
308
|
await nextTick()
|
|
309
309
|
|
|
310
310
|
expect(ageField.dirty.value).toBe(true)
|
|
@@ -332,20 +332,20 @@ describe('Nested Path Handling', () => {
|
|
|
332
332
|
const nameField = form.defineField({ path: 'user.name' })
|
|
333
333
|
const ageField = form.defineField({ path: 'user.profile.age' })
|
|
334
334
|
|
|
335
|
-
nameField.
|
|
336
|
-
ageField.
|
|
335
|
+
nameField.data.value = 'Jane Doe'
|
|
336
|
+
ageField.data.value = 25
|
|
337
337
|
nameField.onBlur()
|
|
338
338
|
|
|
339
339
|
await nextTick()
|
|
340
340
|
|
|
341
|
-
expect(nameField.
|
|
341
|
+
expect(nameField.data.value).toBe('Jane Doe')
|
|
342
342
|
expect(nameField.dirty.value).toBe(true)
|
|
343
343
|
expect(nameField.touched.value).toBe(true)
|
|
344
344
|
|
|
345
345
|
nameField.reset()
|
|
346
346
|
await nextTick()
|
|
347
347
|
|
|
348
|
-
expect(nameField.
|
|
348
|
+
expect(nameField.data.value).toBe('John Doe')
|
|
349
349
|
expect(nameField.dirty.value).toBe(false)
|
|
350
350
|
expect(nameField.touched.value).toBe(false)
|
|
351
351
|
})
|
|
@@ -401,8 +401,8 @@ describe('Nested Path Handling', () => {
|
|
|
401
401
|
const nameField = form.defineField({ path: 'user.name' })
|
|
402
402
|
const emailField = form.defineField({ path: 'user.email' })
|
|
403
403
|
|
|
404
|
-
nameField.
|
|
405
|
-
emailField.
|
|
404
|
+
nameField.data.value = 'A'
|
|
405
|
+
emailField.data.value = 'invalid-email'
|
|
406
406
|
|
|
407
407
|
await nextTick()
|
|
408
408
|
|
|
@@ -422,8 +422,8 @@ describe('Nested Path Handling', () => {
|
|
|
422
422
|
const ageField = form.defineField({ path: 'user.profile.age' })
|
|
423
423
|
const themeField = form.defineField({ path: 'user.profile.preferences.theme' })
|
|
424
424
|
|
|
425
|
-
ageField.
|
|
426
|
-
themeField.
|
|
425
|
+
ageField.data.value = 16
|
|
426
|
+
themeField.data.value = 'blue' as typeof themeField.data.value
|
|
427
427
|
|
|
428
428
|
await nextTick()
|
|
429
429
|
|
|
@@ -443,8 +443,8 @@ describe('Nested Path Handling', () => {
|
|
|
443
443
|
const firstContactNameField = form.defineField({ path: 'contacts.0.name' })
|
|
444
444
|
const firstContactEmailField = form.defineField({ path: 'contacts.0.email' })
|
|
445
445
|
|
|
446
|
-
firstContactNameField.
|
|
447
|
-
firstContactEmailField.
|
|
446
|
+
firstContactNameField.data.value = ''
|
|
447
|
+
firstContactEmailField.data.value = 'invalid-email'
|
|
448
448
|
|
|
449
449
|
await nextTick()
|
|
450
450
|
|
|
@@ -464,8 +464,8 @@ describe('Nested Path Handling', () => {
|
|
|
464
464
|
const addressTypeField = form.defineField({ path: 'contacts.0.addresses.0.type' })
|
|
465
465
|
const addressStreetField = form.defineField({ path: 'contacts.0.addresses.0.street' })
|
|
466
466
|
|
|
467
|
-
addressTypeField.
|
|
468
|
-
addressStreetField.
|
|
467
|
+
addressTypeField.data.value = 'office' as typeof addressTypeField.data.value
|
|
468
|
+
addressStreetField.data.value = ''
|
|
469
469
|
|
|
470
470
|
await nextTick()
|
|
471
471
|
|
|
@@ -483,7 +483,7 @@ describe('Nested Path Handling', () => {
|
|
|
483
483
|
|
|
484
484
|
const nonExistentField = form.defineField({ path: 'user.nonexistent' as any })
|
|
485
485
|
|
|
486
|
-
expect(nonExistentField.
|
|
486
|
+
expect(nonExistentField.data.value).toBeUndefined()
|
|
487
487
|
})
|
|
488
488
|
|
|
489
489
|
it('should handle deeply non-existent paths', () => {
|
|
@@ -491,7 +491,7 @@ describe('Nested Path Handling', () => {
|
|
|
491
491
|
|
|
492
492
|
const deepNonExistentField = form.defineField({ path: 'user.nonexistent.deep.path' as any })
|
|
493
493
|
|
|
494
|
-
expect(deepNonExistentField.
|
|
494
|
+
expect(deepNonExistentField.data.value).toBeUndefined()
|
|
495
495
|
})
|
|
496
496
|
|
|
497
497
|
it('should handle array index out of bounds', () => {
|
|
@@ -499,7 +499,7 @@ describe('Nested Path Handling', () => {
|
|
|
499
499
|
|
|
500
500
|
const outOfBoundsField = form.defineField({ path: 'tags.99' as any })
|
|
501
501
|
|
|
502
|
-
expect(outOfBoundsField.
|
|
502
|
+
expect(outOfBoundsField.data.value).toBeUndefined()
|
|
503
503
|
})
|
|
504
504
|
|
|
505
505
|
it('should handle nested array index out of bounds', () => {
|
|
@@ -507,7 +507,7 @@ describe('Nested Path Handling', () => {
|
|
|
507
507
|
|
|
508
508
|
const outOfBoundsField = form.defineField({ path: 'contacts.99.name' as any })
|
|
509
509
|
|
|
510
|
-
expect(outOfBoundsField.
|
|
510
|
+
expect(outOfBoundsField.data.value).toBeUndefined()
|
|
511
511
|
})
|
|
512
512
|
|
|
513
513
|
it('should handle paths with spaces around dots', () => {
|
|
@@ -515,7 +515,7 @@ describe('Nested Path Handling', () => {
|
|
|
515
515
|
|
|
516
516
|
const nameField = form.defineField({ path: 'user . name' as any })
|
|
517
517
|
|
|
518
|
-
expect(nameField.
|
|
518
|
+
expect(nameField.data.value).toBe('John Doe')
|
|
519
519
|
})
|
|
520
520
|
|
|
521
521
|
it('should handle empty path segments', () => {
|
|
@@ -523,7 +523,7 @@ describe('Nested Path Handling', () => {
|
|
|
523
523
|
|
|
524
524
|
const nameField = form.defineField({ path: 'user..name' as any })
|
|
525
525
|
|
|
526
|
-
expect(nameField.
|
|
526
|
+
expect(nameField.data.value).toBe('John Doe')
|
|
527
527
|
})
|
|
528
528
|
|
|
529
529
|
it('should handle setting values on non-existent paths', async () => {
|
|
@@ -531,11 +531,11 @@ describe('Nested Path Handling', () => {
|
|
|
531
531
|
|
|
532
532
|
const nonExistentField = form.defineField({ path: 'user.newField' as any })
|
|
533
533
|
|
|
534
|
-
nonExistentField.
|
|
534
|
+
nonExistentField.data.value = 'new value'
|
|
535
535
|
|
|
536
536
|
await nextTick()
|
|
537
537
|
|
|
538
|
-
expect((form.
|
|
538
|
+
expect((form.data.value.user as any).newField).toBe('new value')
|
|
539
539
|
})
|
|
540
540
|
})
|
|
541
541
|
|
|
@@ -559,7 +559,7 @@ describe('Nested Path Handling', () => {
|
|
|
559
559
|
|
|
560
560
|
// Create many nested fields
|
|
561
561
|
for (let i = 0; i < 100; i++) {
|
|
562
|
-
if (i < form.
|
|
562
|
+
if (i < form.data.value.contacts.length) {
|
|
563
563
|
fields.push(form.defineField({ path: `contacts.${i}.name` }))
|
|
564
564
|
fields.push(form.defineField({ path: `contacts.${i}.email` }))
|
|
565
565
|
}
|
|
@@ -579,7 +579,7 @@ describe('Nested Path Handling', () => {
|
|
|
579
579
|
|
|
580
580
|
expect(form.isDirty.value).toBe(false)
|
|
581
581
|
|
|
582
|
-
nameField.
|
|
582
|
+
nameField.data.value = 'Jane Doe'
|
|
583
583
|
await nextTick()
|
|
584
584
|
|
|
585
585
|
expect(form.isDirty.value).toBe(true)
|
|
@@ -629,8 +629,8 @@ describe('Nested Path Handling', () => {
|
|
|
629
629
|
await form.validateForm()
|
|
630
630
|
expect(form.isValid.value).toBe(true)
|
|
631
631
|
|
|
632
|
-
nameField.
|
|
633
|
-
emailField.
|
|
632
|
+
nameField.data.value = 'A'
|
|
633
|
+
emailField.data.value = 'invalid'
|
|
634
634
|
|
|
635
635
|
await nextTick()
|
|
636
636
|
|
|
@@ -638,8 +638,8 @@ describe('Nested Path Handling', () => {
|
|
|
638
638
|
await form.validateForm()
|
|
639
639
|
expect(form.isValid.value).toBe(false)
|
|
640
640
|
|
|
641
|
-
nameField.
|
|
642
|
-
emailField.
|
|
641
|
+
nameField.data.value = 'John Doe'
|
|
642
|
+
emailField.data.value = 'john@example.com'
|
|
643
643
|
|
|
644
644
|
await nextTick()
|
|
645
645
|
|