@tanstack/form-core 0.0.15 → 0.1.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.
@@ -2,6 +2,7 @@ import { expect } from 'vitest'
2
2
 
3
3
  import { FormApi } from '../FormApi'
4
4
  import { FieldApi } from '../FieldApi'
5
+ import { sleep } from './utils'
5
6
 
6
7
  describe('field api', () => {
7
8
  it('should have an initial value', () => {
@@ -151,7 +152,30 @@ describe('field api', () => {
151
152
  expect(subfield.getValue()).toBe('one')
152
153
  })
153
154
 
154
- it('should run validation onChange', async () => {
155
+ it('should not throw errors when no meta info is stored on a field and a form re-renders', async () => {
156
+ const form = new FormApi({
157
+ defaultValues: {
158
+ name: 'test',
159
+ },
160
+ })
161
+
162
+ const field = new FieldApi({
163
+ form,
164
+ name: 'name',
165
+ })
166
+
167
+ field.mount()
168
+
169
+ expect(() =>
170
+ form.update({
171
+ defaultValues: {
172
+ name: 'other',
173
+ },
174
+ }),
175
+ ).not.toThrow()
176
+ })
177
+
178
+ it('should run validation onChange', () => {
155
179
  const form = new FormApi({
156
180
  defaultValues: {
157
181
  name: 'test',
@@ -162,10 +186,33 @@ describe('field api', () => {
162
186
  form,
163
187
  name: 'name',
164
188
  onChange: (value) => {
165
- if (value === 'other') {
166
- return 'Please enter a different value'
167
- }
189
+ if (value === 'other') return 'Please enter a different value'
190
+ return
191
+ },
192
+ })
193
+
194
+ field.mount()
195
+
196
+ expect(field.getMeta().error).toBeUndefined()
197
+ field.setValue('other', { touch: true })
198
+ expect(field.getMeta().error).toBe('Please enter a different value')
199
+ })
200
+
201
+ it('should run async validation onChange', async () => {
202
+ vi.useFakeTimers()
168
203
 
204
+ const form = new FormApi({
205
+ defaultValues: {
206
+ name: 'test',
207
+ },
208
+ })
209
+
210
+ const field = new FieldApi({
211
+ form,
212
+ name: 'name',
213
+ onChangeAsync: async (value) => {
214
+ await sleep(1000)
215
+ if (value === 'other') return 'Please enter a different value'
169
216
  return
170
217
  },
171
218
  })
@@ -174,10 +221,14 @@ describe('field api', () => {
174
221
 
175
222
  expect(field.getMeta().error).toBeUndefined()
176
223
  field.setValue('other', { touch: true })
224
+ await vi.runAllTimersAsync()
177
225
  expect(field.getMeta().error).toBe('Please enter a different value')
178
226
  })
179
227
 
180
- it('should not throw errors when no meta info is stored on a field and a form re-renders', async () => {
228
+ it('should run async validation onChange with debounce', async () => {
229
+ vi.useFakeTimers()
230
+ const sleepMock = vi.fn().mockImplementation(sleep)
231
+
181
232
  const form = new FormApi({
182
233
  defaultValues: {
183
234
  name: 'test',
@@ -187,16 +238,199 @@ describe('field api', () => {
187
238
  const field = new FieldApi({
188
239
  form,
189
240
  name: 'name',
241
+ onChangeAsyncDebounceMs: 1000,
242
+ onChangeAsync: async (value) => {
243
+ await sleepMock(1000)
244
+ if (value === 'other') return 'Please enter a different value'
245
+ return
246
+ },
190
247
  })
191
248
 
192
249
  field.mount()
193
250
 
194
- expect(() =>
195
- form.update({
196
- defaultValues: {
197
- name: 'other',
198
- },
199
- }),
200
- ).not.toThrow()
251
+ expect(field.getMeta().error).toBeUndefined()
252
+ field.setValue('other', { touch: true })
253
+ field.setValue('other')
254
+ await vi.runAllTimersAsync()
255
+ // sleepMock will have been called 2 times without onChangeAsyncDebounceMs
256
+ expect(sleepMock).toHaveBeenCalledTimes(1)
257
+ expect(field.getMeta().error).toBe('Please enter a different value')
258
+ })
259
+
260
+ it('should run async validation onChange with asyncDebounceMs', async () => {
261
+ vi.useFakeTimers()
262
+ const sleepMock = vi.fn().mockImplementation(sleep)
263
+
264
+ const form = new FormApi({
265
+ defaultValues: {
266
+ name: 'test',
267
+ },
268
+ })
269
+
270
+ const field = new FieldApi({
271
+ form,
272
+ name: 'name',
273
+ asyncDebounceMs: 1000,
274
+ onChangeAsync: async (value) => {
275
+ await sleepMock(1000)
276
+ if (value === 'other') return 'Please enter a different value'
277
+ return
278
+ },
279
+ })
280
+
281
+ field.mount()
282
+
283
+ expect(field.getMeta().error).toBeUndefined()
284
+ field.setValue('other', { touch: true })
285
+ field.setValue('other')
286
+ await vi.runAllTimersAsync()
287
+ // sleepMock will have been called 2 times without asyncDebounceMs
288
+ expect(sleepMock).toHaveBeenCalledTimes(1)
289
+ expect(field.getMeta().error).toBe('Please enter a different value')
290
+ })
291
+
292
+ it('should run validation onBlur', () => {
293
+ const form = new FormApi({
294
+ defaultValues: {
295
+ name: 'other',
296
+ },
297
+ })
298
+
299
+ const field = new FieldApi({
300
+ form,
301
+ name: 'name',
302
+ onBlur: (value) => {
303
+ if (value === 'other') return 'Please enter a different value'
304
+ return
305
+ },
306
+ })
307
+
308
+ field.mount()
309
+
310
+ field.setValue('other', { touch: true })
311
+ field.validate('blur')
312
+ expect(field.getMeta().error).toBe('Please enter a different value')
313
+ })
314
+
315
+ it('should run async validation onBlur', async () => {
316
+ vi.useFakeTimers()
317
+
318
+ const form = new FormApi({
319
+ defaultValues: {
320
+ name: 'test',
321
+ },
322
+ })
323
+
324
+ const field = new FieldApi({
325
+ form,
326
+ name: 'name',
327
+ onBlurAsync: async (value) => {
328
+ await sleep(1000)
329
+ if (value === 'other') return 'Please enter a different value'
330
+ return
331
+ },
332
+ })
333
+
334
+ field.mount()
335
+
336
+ expect(field.getMeta().error).toBeUndefined()
337
+ field.setValue('other', { touch: true })
338
+ field.validate('blur')
339
+ await vi.runAllTimersAsync()
340
+ expect(field.getMeta().error).toBe('Please enter a different value')
341
+ })
342
+
343
+ it('should run async validation onBlur with debounce', async () => {
344
+ vi.useFakeTimers()
345
+ const sleepMock = vi.fn().mockImplementation(sleep)
346
+
347
+ const form = new FormApi({
348
+ defaultValues: {
349
+ name: 'test',
350
+ },
351
+ })
352
+
353
+ const field = new FieldApi({
354
+ form,
355
+ name: 'name',
356
+ onBlurAsyncDebounceMs: 1000,
357
+ onBlurAsync: async (value) => {
358
+ await sleepMock(10)
359
+ if (value === 'other') return 'Please enter a different value'
360
+ return
361
+ },
362
+ })
363
+
364
+ field.mount()
365
+
366
+ expect(field.getMeta().error).toBeUndefined()
367
+ field.setValue('other', { touch: true })
368
+ field.validate('blur')
369
+ field.validate('blur')
370
+ await vi.runAllTimersAsync()
371
+ // sleepMock will have been called 2 times without onBlurAsyncDebounceMs
372
+ expect(sleepMock).toHaveBeenCalledTimes(1)
373
+ expect(field.getMeta().error).toBe('Please enter a different value')
374
+ })
375
+
376
+ it('should run async validation onBlur with asyncDebounceMs', async () => {
377
+ vi.useFakeTimers()
378
+ const sleepMock = vi.fn().mockImplementation(sleep)
379
+
380
+ const form = new FormApi({
381
+ defaultValues: {
382
+ name: 'test',
383
+ },
384
+ })
385
+
386
+ const field = new FieldApi({
387
+ form,
388
+ name: 'name',
389
+ asyncDebounceMs: 1000,
390
+ onBlurAsync: async (value) => {
391
+ await sleepMock(10)
392
+ if (value === 'other') return 'Please enter a different value'
393
+ return
394
+ },
395
+ })
396
+
397
+ field.mount()
398
+
399
+ expect(field.getMeta().error).toBeUndefined()
400
+ field.setValue('other', { touch: true })
401
+ field.validate('blur')
402
+ field.validate('blur')
403
+ await vi.runAllTimersAsync()
404
+ // sleepMock will have been called 2 times without asyncDebounceMs
405
+ expect(sleepMock).toHaveBeenCalledTimes(1)
406
+ expect(field.getMeta().error).toBe('Please enter a different value')
407
+ })
408
+
409
+ it('should run async validation onSubmit', async () => {
410
+ vi.useFakeTimers()
411
+
412
+ const form = new FormApi({
413
+ defaultValues: {
414
+ name: 'test',
415
+ },
416
+ })
417
+
418
+ const field = new FieldApi({
419
+ form,
420
+ name: 'name',
421
+ onSubmitAsync: async (value) => {
422
+ await sleep(1000)
423
+ if (value === 'other') return 'Please enter a different value'
424
+ return
425
+ },
426
+ })
427
+
428
+ field.mount()
429
+
430
+ expect(field.getMeta().error).toBeUndefined()
431
+ field.setValue('other', { touch: true })
432
+ field.validate('submit')
433
+ await vi.runAllTimersAsync()
434
+ expect(field.getMeta().error).toBe('Please enter a different value')
201
435
  })
202
436
  })
@@ -0,0 +1,5 @@
1
+ export function sleep(timeout: number): Promise<void> {
2
+ return new Promise((resolve, _reject) => {
3
+ setTimeout(resolve, timeout)
4
+ })
5
+ }