Build App: the sign-up form for a small tea shop's online club. It has three fields, labelled Email, Password, and Confirm password, and a Sign up button.
The rules. The email has some text, an @, more text, a dot, and more text, with no spaces: asha@tea.shop passes, while asha, asha@tea, and @tea.shop don't. The password has at least 8 characters. Confirm password is exactly the same as Password.
When a field breaks its rule, its message is Enter a valid email., Password must be at least 8 characters., or Passwords do not match.
Don't nag people while they're still typing: a field's message shows only after they have left that field once (it lost focus). From then on the message follows what's in the fields, so it goes away the moment the field is fixed, and Confirm password's message also follows changes to Password. While a field's message shows, the field has aria-invalid="true".
Sign up is disabled until all three fields are valid. Submitting the form, by clicking Sign up or pressing Enter in a field, replaces the form with Signed up as asha@tea.shop., using the email that was typed.
<form>
<label for="email">Email</label>
<input id="email" type="email" aria-invalid="true" />
<p>Enter a valid email.</p>
<!-- Password and Confirm password the same way -->
<button disabled>Sign up</button>
</form>
render(<App />);
const button = screen.getByRole("button", { name: "Sign up" });
expect(button).toBeDisabled();
await user.type(screen.getByLabelText("Email"), "asha@tea.shop");
await user.type(screen.getByLabelText("Password"), "oolong12");
expect(button).toBeDisabled();
await user.type(screen.getByLabelText("Confirm password"), "oolong12");
expect(button).toBeEnabled();
render(<App />);
await user.type(screen.getByLabelText("Email"), "asha");
expect(screen.queryByText("Enter a valid email.")).not.toBeInTheDocument();
expect(screen.getByLabelText("Email")).not.toHaveAttribute("aria-invalid", "true");
render(<App />);
const email = screen.getByLabelText("Email");
await user.type(email, "asha@tea");
await user.tab();
expect(screen.getByText("Enter a valid email.")).toBeInTheDocument();
expect(email).toHaveAttribute("aria-invalid", "true");
render(<App />);
await user.click(screen.getByLabelText("Password"));
await user.tab();
expect(screen.getByText("Password must be at least 8 characters.")).toBeInTheDocument();
expect(screen.queryByText("Enter a valid email.")).not.toBeInTheDocument();
render(<App />);
await user.type(screen.getByLabelText("Email"), "@tea.shop");
await user.tab();
expect(screen.getByText("Enter a valid email.")).toBeInTheDocument();
render(<App />);
const email = screen.getByLabelText("Email");
await user.type(email, "asha@tea");
await user.tab();
expect(screen.getByText("Enter a valid email.")).toBeInTheDocument();
await user.type(email, ".shop");
expect(screen.queryByText("Enter a valid email.")).not.toBeInTheDocument();
expect(email).not.toHaveAttribute("aria-invalid", "true");
render(<App />);
const password = screen.getByLabelText("Password");
await user.type(password, "oolong12");
await user.type(screen.getByLabelText("Confirm password"), "oolong12");
await user.tab();
expect(screen.queryByText("Passwords do not match.")).not.toBeInTheDocument();
await user.type(password, "3");
expect(screen.getByText("Passwords do not match.")).toBeInTheDocument();
render(<App />);
await user.type(screen.getByLabelText("Email"), "asha@tea.shop");
await user.type(screen.getByLabelText("Password"), "oolong12");
await user.type(screen.getByLabelText("Confirm password"), "oolong12");
await user.click(screen.getByRole("button", { name: "Sign up" }));
expect(screen.getByText("Signed up as asha@tea.shop.")).toBeInTheDocument();
expect(screen.queryByLabelText("Email")).not.toBeInTheDocument();
render(<App />);
await user.type(screen.getByLabelText("Email"), "ravi@chai.house");
await user.type(screen.getByLabelText("Password"), "masala-99");
await user.type(screen.getByLabelText("Confirm password"), "masala-99{Enter}");
expect(screen.getByText("Signed up as ravi@chai.house.")).toBeInTheDocument();
Run tests runs every test on your code, here in your browser. The problem is solved when they all pass.
Ctrl + Enter runs the tests (⌘ + Enter on a Mac).
I'm here to help with Sign-up form with validation. I give hints, never the solution, so you get to solve it yourself. Ask for a hint, select code to ask about it, or press Ask Tuto why on a failing test.
Your first 3 answers need no account. for free to keep asking.