mirror of
https://github.com/LukeHagar/form.git
synced 2025-12-06 04:19:43 +00:00
* chore: first pass * chore: onto something I think * chore: closer but no cigar * chore: infer validator * chore: infer zod * feat: add validation transformer logic * chore: fix typings for react adapter * chore: fix issue with `this` not being defined properly * chore: mostly update FieldInfo types from Vue * chore: work on fixing type inferencing * fix: make ValidatorType optional * chore: make TName restriction easier to grok * chore: fix React types * chore: fix Vue types * chore: fix typing issues * chore: fix various linting items * chore: fix ESlint and validation logic * chore: fix inferencing from formdata * chore: fix form inferencing * chore: fix React TS types to match form validator logic * chore: fix Vue types * chore: migrate zod validation to dedicated package * chore: add first integration test for zod adapter * chore: enable non-validator types to be passed to validator * feat: add yup 1.x adapter * chore: add functionality and tests for form-wide validators * chore: fix typings of async validation types * fix: async validation should now run as-expected more often * chore: add async tests for Yup validator * chore: rename packages to match naming schema better * chore: add Zod examples for React and Vue * chore: add React and Vue Yup support * chore: fix formatting * chore: fix CI types * chore: initial work to drastically improve docs * docs: improve docs for validation * docs: add adapter validation docs
142 lines
3.8 KiB
TypeScript
142 lines
3.8 KiB
TypeScript
/// <reference lib="dom" />
|
|
import { h, defineComponent, ref } from 'vue-demi'
|
|
import { render, waitFor } from '@testing-library/vue'
|
|
import '@testing-library/jest-dom'
|
|
import {
|
|
createFormFactory,
|
|
type FieldApi,
|
|
provideFormContext,
|
|
useForm,
|
|
} from '../index'
|
|
import userEvent from '@testing-library/user-event'
|
|
import * as React from 'react'
|
|
|
|
const user = userEvent.setup()
|
|
|
|
describe('useForm', () => {
|
|
it('preserved field state', async () => {
|
|
type Person = {
|
|
firstName: string
|
|
lastName: string
|
|
}
|
|
|
|
const formFactory = createFormFactory<Person, unknown>()
|
|
|
|
const Comp = defineComponent(() => {
|
|
const form = formFactory.useForm()
|
|
|
|
provideFormContext({ formApi: form })
|
|
|
|
return () => (
|
|
<form.Field name="firstName" defaultValue="">
|
|
{({
|
|
field,
|
|
}: {
|
|
field: FieldApi<Person, 'firstName', never, never>
|
|
}) => (
|
|
<input
|
|
data-testid={'fieldinput'}
|
|
value={field.state.value}
|
|
onBlur={field.handleBlur}
|
|
onInput={(e) =>
|
|
field.handleChange((e.target as HTMLInputElement).value)
|
|
}
|
|
/>
|
|
)}
|
|
</form.Field>
|
|
)
|
|
})
|
|
|
|
const { getByTestId, queryByText } = render(Comp)
|
|
const input = getByTestId('fieldinput')
|
|
expect(queryByText('FirstName')).not.toBeInTheDocument()
|
|
await user.type(input, 'FirstName')
|
|
expect(input).toHaveValue('FirstName')
|
|
})
|
|
|
|
it('should allow default values to be set', async () => {
|
|
type Person = {
|
|
firstName: string
|
|
lastName: string
|
|
}
|
|
|
|
const formFactory = createFormFactory<Person, unknown>()
|
|
|
|
const Comp = defineComponent(() => {
|
|
const form = formFactory.useForm({
|
|
defaultValues: {
|
|
firstName: 'FirstName',
|
|
lastName: 'LastName',
|
|
},
|
|
})
|
|
form.provideFormContext()
|
|
|
|
return () => (
|
|
<form.Field name="firstName">
|
|
{({
|
|
field,
|
|
}: {
|
|
field: FieldApi<Person, 'firstName', never, never>
|
|
}) => <p>{field.state.value}</p>}
|
|
</form.Field>
|
|
)
|
|
})
|
|
|
|
const { findByText, queryByText } = render(Comp)
|
|
expect(await findByText('FirstName')).toBeInTheDocument()
|
|
expect(queryByText('LastName')).not.toBeInTheDocument()
|
|
})
|
|
|
|
it('should handle submitting properly', async () => {
|
|
const Comp = defineComponent(() => {
|
|
const submittedData = ref<{ firstName: string }>()
|
|
|
|
const form = useForm({
|
|
defaultValues: {
|
|
firstName: 'FirstName',
|
|
},
|
|
onSubmit: (data) => {
|
|
submittedData.value = data
|
|
},
|
|
})
|
|
form.provideFormContext()
|
|
|
|
return () => (
|
|
<form.Provider>
|
|
<form.Field name="firstName">
|
|
{({
|
|
field,
|
|
}: {
|
|
field: FieldApi<{ firstName: string }, 'firstName', never, never>
|
|
}) => {
|
|
return (
|
|
<input
|
|
value={field.state.value}
|
|
onBlur={field.handleBlur}
|
|
onChange={(e) =>
|
|
field.handleChange((e.target as HTMLInputElement).value)
|
|
}
|
|
placeholder={'First name'}
|
|
/>
|
|
)
|
|
}}
|
|
</form.Field>
|
|
<button onClick={form.handleSubmit}>Submit</button>
|
|
{submittedData.value && (
|
|
<p>Submitted data: {submittedData.value.firstName}</p>
|
|
)}
|
|
</form.Provider>
|
|
)
|
|
})
|
|
|
|
const { findByPlaceholderText, getByText } = render(Comp)
|
|
const input = await findByPlaceholderText('First name')
|
|
await user.clear(input)
|
|
await user.type(input, 'OtherName')
|
|
await user.click(getByText('Submit'))
|
|
await waitFor(() =>
|
|
expect(getByText('Submitted data: OtherName')).toBeInTheDocument(),
|
|
)
|
|
})
|
|
})
|