CodePark/ questions / Forms & accessibility
START PRACTICINGPRACTICE
Frontend question · Testing › Forms & accessibility

How would you test a sign-up form with client-side validation and submission?

test("shows an error for an invalid email", async () => {
  const user = userEvent.setup();
  const onSubmit = jest.fn();
  render(<SignUpForm onSubmit={onSubmit} />);
  await user.type(screen.getByLabelText(/email/i), "not-an-email");
  await user.click(screen.getByRole("button", { name: /sign up/i }));
  expect(await screen.findByText(/enter a valid email/i)).toBeInTheDocument();
  expect(screen.getByLabelText(/email/i)).toBeInvalid();
  expect(onSubmit).not.toHaveBeenCalled();
});

Test it like a user: find fields by label, type and click with user-event, and assert what the user sees.

How to find things:

  • Find fields with getByLabelText.
  • Find the button with getByRole('button', { name: /sign up/i }).
  • Use user-event for typing and clicking.

The important paths to cover:

  • Submitting empty or invalid input shows the right error messages. It doesn't call the submit handler or the API.
  • Fixing the input clears the errors.
  • Valid input calls onSubmit with the right values, or sends the right request (checked through MSW). Then the success state shows.
  • If the button is disabled while submitting, assert toBeDisabled().

Assert on what users see, such as error text or role='alert'. Also assert accessibility attributes, like aria-invalid through toBeInvalid().

Don't assert on the form library's internal state. Then you could switch from React Hook Form to something else without rewriting the tests.

  • Find fields by label and role, and interact with user-event.
  • Invalid input shows errors, and submit is not called.
  • Valid input submits the correct values, then shows the success state.
  • Test the pending state, for example a disabled button.
  • Don't assert on the form library's internal state.