Build App: a converter for the tea shop's brewing guide, with two text boxes labelled Celsius and Fahrenheit. Typing a number in either box fills in the other: °F = °C × 9 / 5 + 32.
The box you type in keeps exactly what you typed, so 37.0 stays 37.0. The other box shows the converted value rounded to one decimal place, without a trailing .0: 212, 98.6, -17.8.
If the box you type in holds something that isn't a number, a message with role="alert" says Celsius must be a number. (or Fahrenheit must be a number.), and the other box is left empty instead of showing NaN. Once the text is a number again, the message goes away.
An empty box isn't a mistake: emptying one box empties the other, with no message. Both boxes start empty.
The tests only see the boxes, but aim for one piece of state for both: which box you typed in last, and its text. Work out the other box from it on every render, so the two can never disagree.
<label>Celsius <input value="100" /></label>
<label>Fahrenheit <input value="212" /></label>
// after typing "hot" in Celsius:
<label>Celsius <input value="hot" /></label>
<label>Fahrenheit <input value="" /></label>
<p role="alert">Celsius must be a number.</p>
render(<App />);
expect(screen.getByLabelText("Celsius")).toHaveValue("");
expect(screen.getByLabelText("Fahrenheit")).toHaveValue("");
expect(screen.queryByRole("alert")).not.toBeInTheDocument();
render(<App />);
await user.type(screen.getByLabelText("Celsius"), "100");
expect(screen.getByLabelText("Fahrenheit")).toHaveValue("212");
render(<App />);
await user.type(screen.getByLabelText("Fahrenheit"), "212");
expect(screen.getByLabelText("Celsius")).toHaveValue("100");
render(<App />);
await user.type(screen.getByLabelText("Celsius"), "37");
expect(screen.getByLabelText("Fahrenheit")).toHaveValue("98.6");
await user.clear(screen.getByLabelText("Fahrenheit"));
await user.type(screen.getByLabelText("Fahrenheit"), "0");
expect(screen.getByLabelText("Celsius")).toHaveValue("-17.8");
render(<App />);
await user.type(screen.getByLabelText("Celsius"), "37.0");
expect(screen.getByLabelText("Celsius")).toHaveValue("37.0");
expect(screen.getByLabelText("Fahrenheit")).toHaveValue("98.6");
render(<App />);
await user.type(screen.getByLabelText("Celsius"), "-40");
expect(screen.getByLabelText("Fahrenheit")).toHaveValue("-40");
expect(screen.queryByRole("alert")).not.toBeInTheDocument();
render(<App />);
await user.type(screen.getByLabelText("Celsius"), "100");
await user.type(screen.getByLabelText("Celsius"), "x");
expect(screen.getByRole("alert")).toHaveTextContent("Celsius must be a number.");
expect(screen.getByLabelText("Celsius")).toHaveValue("100x");
expect(screen.getByLabelText("Fahrenheit")).toHaveValue("");
render(<App />);
await user.type(screen.getByLabelText("Celsius"), "warm");
expect(screen.getByRole("alert")).toBeInTheDocument();
await user.clear(screen.getByLabelText("Celsius"));
await user.type(screen.getByLabelText("Celsius"), "25");
expect(screen.queryByRole("alert")).not.toBeInTheDocument();
expect(screen.getByLabelText("Fahrenheit")).toHaveValue("77");
render(<App />);
await user.type(screen.getByLabelText("Fahrenheit"), "hot");
expect(screen.getByRole("alert")).toHaveTextContent("Fahrenheit must be a number.");
expect(screen.getByLabelText("Celsius")).toHaveValue("");
render(<App />);
await user.type(screen.getByLabelText("Fahrenheit"), "212");
await user.clear(screen.getByLabelText("Fahrenheit"));
expect(screen.getByLabelText("Celsius")).toHaveValue("");
expect(screen.queryByRole("alert")).not.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 Temperature converter. 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.