diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-11-03 19:34:16 +0100 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-11-11 18:15:27 +0100 |
| commit | ddd45e29745b73e7fe1684e197dcff598b375644 (patch) | |
| tree | 8bf01305b5c0d163c52a7dce747ed7a4a4650acb /src/utils/hooks/use-form/use-form-submit/use-form-submit.test.ts | |
| parent | 5d3e8a4d0c2ce2ad8f22df857ab3ce54fcfc38ac (diff) | |
feat(hooks): add an useForm hook
* add two "sub"-hooks: useFormValues and useFormSubmit (that
can be used independently)
* handle initial data
* handle custom submit callback
* handle data validation
* handle submit status
Diffstat (limited to 'src/utils/hooks/use-form/use-form-submit/use-form-submit.test.ts')
| -rw-r--r-- | src/utils/hooks/use-form/use-form-submit/use-form-submit.test.ts | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/utils/hooks/use-form/use-form-submit/use-form-submit.test.ts b/src/utils/hooks/use-form/use-form-submit/use-form-submit.test.ts new file mode 100644 index 0000000..cb0da16 --- /dev/null +++ b/src/utils/hooks/use-form/use-form-submit/use-form-submit.test.ts @@ -0,0 +1,163 @@ +import { describe, expect, it, jest } from '@jest/globals'; +import { act, renderHook } from '@testing-library/react'; +import type { FormEvent } from 'react'; +import { type FormSubmitValidation, useFormSubmit } from './use-form-submit'; + +const generateSubmitEvent = () => + new Event('submit', { + bubbles: true, + cancelable: true, + }) as unknown as FormEvent<HTMLFormElement>; + +describe('useFormSubmit', () => { + const data = { foo: 'tempore', bar: false, baz: 42 }; + const messages = { error: 'Error', success: 'Success' }; + + it('can submit the provided data', async () => { + const { result } = renderHook(() => useFormSubmit(data)); + + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + expect.assertions(4); + + expect(result.current.messages).toBeNull(); + expect(result.current.submitStatus).toBe('IDLE'); + + await act(async () => { + await result.current.submit(generateSubmitEvent()); + }); + + expect(result.current.messages).toBeNull(); + expect(result.current.submitStatus).toBe('SUCCEEDED'); + }); + + it('can use a callback to handle submit', async () => { + const callback = jest.fn((_data) => undefined); + const { result } = renderHook(() => + useFormSubmit(data, { submit: callback }) + ); + + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + expect.assertions(5); + + expect(callback).not.toHaveBeenCalled(); + expect(result.current.messages).toBeNull(); + + await act(async () => { + await result.current.submit(generateSubmitEvent()); + }); + + expect(callback).toHaveBeenCalledTimes(1); + expect(callback).toHaveBeenCalledWith(data); + expect(result.current.messages).toBeNull(); + }); + + it('can use a callback that fails validating data on submit', async () => { + const callback = jest.fn( + (values: typeof data): FormSubmitValidation<typeof data> => { + return { + messages, + validator: () => values.bar, + }; + } + ); + const { result } = renderHook(() => + useFormSubmit(data, { submit: callback }) + ); + + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + expect.assertions(6); + + expect(callback).not.toHaveBeenCalled(); + expect(result.current.messages).toBeNull(); + + await act(async () => { + await result.current.submit(generateSubmitEvent()); + }); + + expect(callback).toHaveBeenCalledTimes(1); + expect(callback).toHaveBeenCalledWith(data); + expect(result.current.submitStatus).toBe('FAILED'); + expect(result.current.messages).toBe(messages); + }); + + it('can use a callback that succeeds validating data on submit', async () => { + const callback = jest.fn( + (values: typeof data): FormSubmitValidation<typeof data> => { + return { + messages, + validator: () => !values.bar, + }; + } + ); + const { result } = renderHook(() => + useFormSubmit(data, { submit: callback }) + ); + + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + expect.assertions(6); + + expect(callback).not.toHaveBeenCalled(); + expect(result.current.messages).toBeNull(); + + await act(async () => { + await result.current.submit(generateSubmitEvent()); + }); + + expect(callback).toHaveBeenCalledTimes(1); + expect(callback).toHaveBeenCalledWith(data); + expect(result.current.submitStatus).toBe('SUCCEEDED'); + expect(result.current.messages).toBe(messages); + }); + + it('can call an onSuccess callback on success', async () => { + const callback = jest.fn(); + const { result } = renderHook(() => + useFormSubmit(data, { onSuccess: callback }) + ); + + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + expect.assertions(6); + + expect(callback).not.toHaveBeenCalled(); + expect(result.current.messages).toBeNull(); + expect(result.current.submitStatus).toBe('IDLE'); + + await act(async () => { + await result.current.submit(generateSubmitEvent()); + }); + + expect(result.current.messages).toBeNull(); + expect(callback).toHaveBeenCalledTimes(1); + expect(result.current.submitStatus).toBe('SUCCEEDED'); + }); + + it('can call an onFailure callback on failure', async () => { + const handlers = { + onFailure: jest.fn(), + submit: jest.fn( + (values: typeof data): FormSubmitValidation<typeof data> => { + return { + messages, + validator: () => values.bar, + }; + } + ), + }; + const { result } = renderHook(() => useFormSubmit(data, handlers)); + + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + expect.assertions(6); + + expect(handlers.onFailure).not.toHaveBeenCalled(); + expect(result.current.messages).toBeNull(); + expect(result.current.submitStatus).toBe('IDLE'); + + await act(async () => { + await result.current.submit(generateSubmitEvent()); + }); + + expect(result.current.messages).toBe(messages); + expect(handlers.onFailure).toHaveBeenCalledTimes(1); + expect(result.current.submitStatus).toBe('FAILED'); + }); +}); |
