mirror of
https://github.com/cupcakearmy/formhero.git
synced 2025-09-06 14:20:40 +00:00
v1
This commit is contained in:
154
test/basic.test.tsx
Normal file
154
test/basic.test.tsx
Normal file
@@ -0,0 +1,154 @@
|
||||
import { act, cleanup, fireEvent, render, screen } from '@testing-library/react'
|
||||
import React, { useEffect } from 'react'
|
||||
import { beforeEach, describe, expect, test } from 'vitest'
|
||||
|
||||
import { useForm } from '../lib'
|
||||
|
||||
beforeEach(cleanup)
|
||||
|
||||
const Insight = {
|
||||
Portal({ data }: { data: any }) {
|
||||
return <div data-testid="result">{JSON.stringify(data)}</div>
|
||||
},
|
||||
async verify(obj: any) {
|
||||
const result = await screen.findByTestId('result')
|
||||
const data = JSON.parse(result.innerText)
|
||||
expect(data).toMatchObject(obj)
|
||||
},
|
||||
}
|
||||
|
||||
const Util = {
|
||||
find<E extends HTMLElement = HTMLInputElement>(id: string) {
|
||||
return screen.findByTestId<E>(id)
|
||||
},
|
||||
writeToField(node: HTMLInputElement, value: string) {
|
||||
fireEvent.change(node, { target: { value } })
|
||||
},
|
||||
}
|
||||
|
||||
describe('Field', () => {
|
||||
test('Basic Form', async () => {
|
||||
const BasicForm = () => {
|
||||
const form = useForm({ username: '', password: '' })
|
||||
const { field } = form
|
||||
return (
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault()
|
||||
}}
|
||||
>
|
||||
<input data-testid="username" {...field('username')} />
|
||||
<input data-testid="password" {...field('password')} />
|
||||
<button data-testid="submit" type="submit">
|
||||
Go
|
||||
</button>
|
||||
<Insight.Portal data={form} />
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
render(<BasicForm />)
|
||||
async function inputIntoForm(id: string, value: string) {
|
||||
const node = await Util.find(id)
|
||||
await act(() => {
|
||||
Util.writeToField(node, value)
|
||||
})
|
||||
await Insight.verify({ form: { [id]: value } })
|
||||
}
|
||||
|
||||
await inputIntoForm('username', 'foo')
|
||||
await inputIntoForm('password', 'bar')
|
||||
})
|
||||
|
||||
test('setField', async () => {
|
||||
const value = 'foo'
|
||||
const Component = () => {
|
||||
const { field, setField, form } = useForm({ username: '', password: '' })
|
||||
useEffect(() => setField('username', value), [])
|
||||
return (
|
||||
<div>
|
||||
<input data-testid="field" {...field('username')}></input>
|
||||
<Insight.Portal data={form} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
render(<Component />)
|
||||
const node = await screen.findByTestId<HTMLInputElement>('field')
|
||||
expect(node.value).toBe(value)
|
||||
Insight.verify({ username: value, password: '' })
|
||||
})
|
||||
|
||||
test('Field sync', async () => {
|
||||
const value = 'foo'
|
||||
const Component = () => {
|
||||
const { field, form } = useForm({ name: '' })
|
||||
return (
|
||||
<form>
|
||||
<input {...field('name')} data-testid="a" />
|
||||
<input {...field('name')} data-testid="b" />
|
||||
<Insight.Portal data={form} />
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
render(<Component />)
|
||||
const a = await Util.find('a')
|
||||
const b = await Util.find('b')
|
||||
await act(() => {
|
||||
Util.writeToField(a, value)
|
||||
})
|
||||
await Insight.verify({ name: value })
|
||||
expect(a.value).toBe(b.value)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Validation', () => {
|
||||
test('Basic', async () => {
|
||||
const Component = () => {
|
||||
const { errors, field } = useForm({ password: '' }, { rules: { password: [(p) => p.length > 8] } })
|
||||
|
||||
return (
|
||||
<div>
|
||||
<input {...field('password')} data-testid="field" />
|
||||
<Insight.Portal data={errors} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
render(<Component />)
|
||||
const node = await Util.find('field')
|
||||
await act(() => {
|
||||
Util.writeToField(node, '123')
|
||||
})
|
||||
Insight.verify({ password: true })
|
||||
})
|
||||
|
||||
test('Array of rules', async () => {
|
||||
const Component = () => {
|
||||
const { errors, field } = useForm({ password: '' }, { rules: { password: [(p) => p.length > 8, /#/] } })
|
||||
|
||||
return (
|
||||
<div>
|
||||
<input {...field('password')} data-testid="field" />
|
||||
<Insight.Portal data={errors} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
render(<Component />)
|
||||
const node = await Util.find('field')
|
||||
await act(() => {
|
||||
Util.writeToField(node, '12345678')
|
||||
})
|
||||
Insight.verify({ password: true })
|
||||
await act(() => {
|
||||
Util.writeToField(node, '1234#5678')
|
||||
})
|
||||
Insight.verify({})
|
||||
})
|
||||
})
|
||||
|
||||
// Is valid
|
||||
// Reset / setForm
|
||||
// Set error
|
||||
// Checkbox
|
||||
// Extractor
|
||||
// Custom extractor
|
@@ -1,19 +0,0 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
<title>Form Hero</title>
|
||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css" />
|
||||
<style>
|
||||
body {
|
||||
padding: 1em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="./test.tsx"></script>
|
||||
</body>
|
||||
</html>
|
2
test/setup.ts
Normal file
2
test/setup.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
// https://github.com/testing-library/react-testing-library/issues/1061#issuecomment-1117450890
|
||||
global.IS_REACT_ACT_ENVIRONMENT = true
|
112
test/test.tsx
112
test/test.tsx
@@ -1,112 +0,0 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
import { useForm } from '../'
|
||||
|
||||
const TextError: React.FC<{ error?: string }> = ({ error }) => (!error ? null : <div className="has-text-danger">{error}</div>)
|
||||
|
||||
const initial = {
|
||||
username: '',
|
||||
password: '',
|
||||
type: 'formhero',
|
||||
awesome: true,
|
||||
}
|
||||
|
||||
const Index: React.FC = () => {
|
||||
const { field, form, errors, isValid, setForm, setErrors, setField } = useForm(initial, {
|
||||
username: [
|
||||
/^abc/,
|
||||
{
|
||||
validator: async (s: string) => {
|
||||
return true
|
||||
},
|
||||
message: 'Async shit not working',
|
||||
},
|
||||
(s: string) => (s.includes('d') ? true : 'Needs the D'),
|
||||
],
|
||||
password: {
|
||||
validator: /^.{3,}$/,
|
||||
message: 'To short',
|
||||
},
|
||||
awesome: value => !!value,
|
||||
})
|
||||
|
||||
const _submit = (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
console.log(form, errors, isValid)
|
||||
}
|
||||
|
||||
const reset = () => {
|
||||
setForm(initial)
|
||||
setField('username', 'asdf')
|
||||
}
|
||||
|
||||
const error = () => {
|
||||
setErrors({
|
||||
username: 'nope',
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<form onSubmit={_submit}>
|
||||
<div>Username</div>
|
||||
<input className="input" {...field('username')} />
|
||||
<TextError error={errors.username} />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<div>Password</div>
|
||||
<input className="input" {...field('password')} />
|
||||
<TextError error={errors.password} />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<div>Which one to choose?</div>
|
||||
<div className="select">
|
||||
<select {...field('type')}>
|
||||
<option value="redux-form">Redux-Form</option>
|
||||
<option value="react-hook-forms">React-Hook-Forms</option>
|
||||
<option value="formik">Formik</option>
|
||||
<option value="formhero">FormHero</option>
|
||||
</select>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<label className="checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
{...field('awesome', {
|
||||
setter: 'checked',
|
||||
getter: 'onChange',
|
||||
extractor: e => e.target.checked,
|
||||
})}
|
||||
/>
|
||||
Is it awesome?
|
||||
</label>
|
||||
<TextError error={errors.awesome} />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<button className="button" type="submit">
|
||||
Go 🚀
|
||||
</button>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<button className="button" onClick={reset}>
|
||||
Reset 🔥
|
||||
</button>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<button className="button" onClick={error}>
|
||||
Set Error ❌
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
ReactDOM.render(<Index />, document.getElementById('root'))
|
Reference in New Issue
Block a user