Build App: a password box for a tea shop's account page that shows how strong the password is as you type.
The box is labelled Password. Under it is a list of four rules, in this order: At least 8 characters, Contains a number, Contains a symbol, and Contains an uppercase letter. Each rule is a list item whose text is just the rule. It has data-met="true" while the password meets the rule and data-met="false" while it doesn't, updated on every keystroke.
A number is a digit from 0 to 9. An uppercase letter is A to Z. A symbol is any character that isn't a letter from A to Z (either case), a digit, or a space: #, !, and - count, and spaces don't.
Below the list, a line reads Strength: Weak, Strength: Fair, or Strength: Strong. It's Weak when 0 or 1 rules are met, Fair for 2 or 3, and Strong for all 4. An empty box is Weak. You can add a <meter> as well; the tests only read the text.
<label for="password">Password</label>
<input id="password" type="password" />
<ul>
<li data-met="true">At least 8 characters</li>
<li data-met="true">Contains a number</li>
<li data-met="false">Contains a symbol</li>
<li data-met="false">Contains an uppercase letter</li>
</ul>
<p>Strength: Fair</p>
render(<App />);
for (const rule of ["At least 8 characters", "Contains a number", "Contains a symbol", "Contains an uppercase letter"]) {
expect(screen.getByText(rule)).toHaveAttribute("data-met", "false");
}
expect(screen.getByText("Strength: Weak")).toBeInTheDocument();
render(<App />);
const box = screen.getByLabelText("Password");
await user.type(box, "abcdefg");
expect(screen.getByText("At least 8 characters")).toHaveAttribute("data-met", "false");
await user.type(box, "h");
expect(screen.getByText("At least 8 characters")).toHaveAttribute("data-met", "true");
render(<App />);
const box = screen.getByLabelText("Password");
await user.type(box, "tea");
expect(screen.getByText("Contains a number")).toHaveAttribute("data-met", "false");
await user.type(box, "5");
expect(screen.getByText("Contains a number")).toHaveAttribute("data-met", "true");
render(<App />);
const box = screen.getByLabelText("Password");
await user.type(box, "green tea");
expect(screen.getByText("Contains a symbol")).toHaveAttribute("data-met", "false");
await user.type(box, "!");
expect(screen.getByText("Contains a symbol")).toHaveAttribute("data-met", "true");
render(<App />);
const box = screen.getByLabelText("Password");
await user.type(box, "chai");
expect(screen.getByText("Contains an uppercase letter")).toHaveAttribute("data-met", "false");
await user.type(box, "C");
expect(screen.getByText("Contains an uppercase letter")).toHaveAttribute("data-met", "true");
render(<App />);
await user.type(screen.getByLabelText("Password"), "Chai");
expect(screen.getByText("Strength: Weak")).toBeInTheDocument();
render(<App />);
const box = screen.getByLabelText("Password");
await user.type(box, "chai1234");
expect(screen.getByText("Strength: Fair")).toBeInTheDocument();
await user.type(box, "!");
expect(screen.getByText("Strength: Fair")).toBeInTheDocument();
render(<App />);
await user.type(screen.getByLabelText("Password"), "Oolong#12");
expect(screen.getByText("Strength: Strong")).toBeInTheDocument();
expect(screen.queryByText("Strength: Fair")).not.toBeInTheDocument();
render(<App />);
const box = screen.getByLabelText("Password");
await user.type(box, "Oolong#12");
await user.type(box, "{Backspace}{Backspace}");
expect(screen.getByText("Contains a number")).toHaveAttribute("data-met", "false");
expect(screen.getByText("At least 8 characters")).toHaveAttribute("data-met", "false");
expect(screen.getByText("Strength: Fair")).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 Password strength meter. 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.