|  | 
|  | 1 | +import React from 'react'; | 
|  | 2 | +import { useForm } from 'react-hook-form'; | 
|  | 3 | +import { render, screen } from '@testing-library/react'; | 
|  | 4 | +import user from '@testing-library/user-event'; | 
|  | 5 | +import { string, required, object, minLength } from 'valibot'; | 
|  | 6 | +import { valibotResolver } from '..'; | 
|  | 7 | + | 
|  | 8 | +const USERNAME_REQUIRED_MESSAGE = 'username field is required'; | 
|  | 9 | +const PASSWORD_REQUIRED_MESSAGE = 'password field is required'; | 
|  | 10 | + | 
|  | 11 | +const schema = required( | 
|  | 12 | +  object({ | 
|  | 13 | +    username: string(USERNAME_REQUIRED_MESSAGE, [ | 
|  | 14 | +      minLength(2, USERNAME_REQUIRED_MESSAGE), | 
|  | 15 | +    ]), | 
|  | 16 | +    password: string(PASSWORD_REQUIRED_MESSAGE, [ | 
|  | 17 | +      minLength(2, PASSWORD_REQUIRED_MESSAGE), | 
|  | 18 | +    ]), | 
|  | 19 | +  }), | 
|  | 20 | +); | 
|  | 21 | + | 
|  | 22 | +type FormData = { username: string; password: string }; | 
|  | 23 | + | 
|  | 24 | +interface Props { | 
|  | 25 | +  onSubmit: (data: FormData) => void; | 
|  | 26 | +} | 
|  | 27 | + | 
|  | 28 | +function TestComponent({ onSubmit }: Props) { | 
|  | 29 | +  const { register, handleSubmit } = useForm<FormData>({ | 
|  | 30 | +    resolver: valibotResolver(schema), | 
|  | 31 | +    shouldUseNativeValidation: true, | 
|  | 32 | +  }); | 
|  | 33 | + | 
|  | 34 | +  return ( | 
|  | 35 | +    <form onSubmit={handleSubmit(onSubmit)}> | 
|  | 36 | +      <input {...register('username')} placeholder="username" /> | 
|  | 37 | + | 
|  | 38 | +      <input {...register('password')} placeholder="password" /> | 
|  | 39 | + | 
|  | 40 | +      <button type="submit">submit</button> | 
|  | 41 | +    </form> | 
|  | 42 | +  ); | 
|  | 43 | +} | 
|  | 44 | + | 
|  | 45 | +test("form's native validation with Zod", async () => { | 
|  | 46 | +  const handleSubmit = vi.fn(); | 
|  | 47 | +  render(<TestComponent onSubmit={handleSubmit} />); | 
|  | 48 | + | 
|  | 49 | +  // username | 
|  | 50 | +  let usernameField = screen.getByPlaceholderText( | 
|  | 51 | +    /username/i, | 
|  | 52 | +  ) as HTMLInputElement; | 
|  | 53 | +  expect(usernameField.validity.valid).toBe(true); | 
|  | 54 | +  expect(usernameField.validationMessage).toBe(''); | 
|  | 55 | + | 
|  | 56 | +  // password | 
|  | 57 | +  let passwordField = screen.getByPlaceholderText( | 
|  | 58 | +    /password/i, | 
|  | 59 | +  ) as HTMLInputElement; | 
|  | 60 | +  expect(passwordField.validity.valid).toBe(true); | 
|  | 61 | +  expect(passwordField.validationMessage).toBe(''); | 
|  | 62 | + | 
|  | 63 | +  await user.click(screen.getByText(/submit/i)); | 
|  | 64 | + | 
|  | 65 | +  // username | 
|  | 66 | +  usernameField = screen.getByPlaceholderText(/username/i) as HTMLInputElement; | 
|  | 67 | +  expect(usernameField.validity.valid).toBe(false); | 
|  | 68 | +  expect(usernameField.validationMessage).toBe(USERNAME_REQUIRED_MESSAGE); | 
|  | 69 | + | 
|  | 70 | +  // password | 
|  | 71 | +  passwordField = screen.getByPlaceholderText(/password/i) as HTMLInputElement; | 
|  | 72 | +  expect(passwordField.validity.valid).toBe(false); | 
|  | 73 | +  expect(passwordField.validationMessage).toBe(PASSWORD_REQUIRED_MESSAGE); | 
|  | 74 | + | 
|  | 75 | +  await user.type(screen.getByPlaceholderText(/password/i), 'password'); | 
|  | 76 | + | 
|  | 77 | +  // password | 
|  | 78 | +  passwordField = screen.getByPlaceholderText(/password/i) as HTMLInputElement; | 
|  | 79 | +  expect(passwordField.validity.valid).toBe(true); | 
|  | 80 | +  expect(passwordField.validationMessage).toBe(''); | 
|  | 81 | +}); | 
0 commit comments