The shop's menu page lists today's teas. Build TeaMenu, a named export of App.jsx. It gets teas, an array of { id, name, price, soldOut } objects, and onAdd, a function to call when someone adds a tea to their order. The default export, App, is only for the Preview.
Show the teas in a <ul>, one <li> per tea, in the order they come. Each item shows the tea's name, its price with a dollar sign and two decimals (4 is $4.00, 3.5 is $3.50), and a button whose text is Add and the tea's name, like Add Sencha.
Clicking a button calls onAdd with that tea's id. When a tea's soldOut is true, its item also shows the text Sold out, and its button is disabled.
Give every item a key, so React logs no key warning. When teas is empty, show the paragraph No teas on the menu today. instead of the list.
<TeaMenu
teas={[
{ id: "sencha", name: "Sencha", price: 4, soldOut: false },
{ id: "matcha", name: "Matcha", price: 12.25, soldOut: true },
]}
onAdd={(id) => console.log("added", id)}
/>
// draws:
<ul>
<li>Sencha $4.00 <button>Add Sencha</button></li>
<li>Matcha $12.25 Sold out <button disabled>Add Matcha</button></li>
</ul>
const teas = [
{ id: "sencha", name: "Sencha", price: 4, soldOut: false },
{ id: "chai", name: "Masala chai", price: 3.5, soldOut: false },
{ id: "matcha", name: "Matcha", price: 12.25, soldOut: true },
];
render(<TeaMenu teas={teas} onAdd={() => {}} />);
const items = screen.getAllByRole("listitem");
expect(items).toHaveLength(3);
expect(items[0]).toHaveTextContent("Sencha");
expect(items[1]).toHaveTextContent("Masala chai");
expect(items[2]).toHaveTextContent("Matcha");
const teas = [
{ id: "sencha", name: "Sencha", price: 4, soldOut: false },
{ id: "chai", name: "Masala chai", price: 3.5, soldOut: false },
{ id: "matcha", name: "Matcha", price: 12.25, soldOut: true },
{ id: "mint", name: "Mint", price: 0.5, soldOut: false },
];
render(<TeaMenu teas={teas} onAdd={() => {}} />);
const items = screen.getAllByRole("listitem");
expect(items[0]).toHaveTextContent("$4.00");
expect(items[1]).toHaveTextContent("$3.50");
expect(items[2]).toHaveTextContent("$12.25");
expect(items[3]).toHaveTextContent("$0.50");
const teas = [
{ id: "sencha", name: "Sencha", price: 4, soldOut: false },
{ id: "matcha", name: "Matcha", price: 12.25, soldOut: true },
{ id: "chai", name: "Masala chai", price: 3.5, soldOut: false },
];
render(<TeaMenu teas={teas} onAdd={() => {}} />);
const items = screen.getAllByRole("listitem");
expect(items[0]).not.toHaveTextContent("Sold out");
expect(items[1]).toHaveTextContent("Sold out");
expect(items[2]).not.toHaveTextContent("Sold out");
const teas = [
{ id: "sencha", name: "Sencha", price: 4, soldOut: false },
{ id: "matcha", name: "Matcha", price: 12.25, soldOut: true },
];
render(<TeaMenu teas={teas} onAdd={() => {}} />);
expect(screen.getByRole("button", { name: "Add Sencha" })).toBeEnabled();
expect(screen.getByRole("button", { name: "Add Matcha" })).toBeDisabled();
const teas = [
{ id: "sencha", name: "Sencha", price: 4, soldOut: false },
{ id: "chai", name: "Masala chai", price: 3.5, soldOut: false },
];
const onAdd = spy();
render(<TeaMenu teas={teas} onAdd={onAdd} />);
await user.click(screen.getByRole("button", { name: "Add Masala chai" }));
expect(onAdd).toHaveBeenCalledTimes(1);
expect(onAdd).toHaveBeenCalledWith("chai");
const teas = [{ id: "matcha", name: "Matcha", price: 12.25, soldOut: true }];
const onAdd = spy();
render(<TeaMenu teas={teas} onAdd={onAdd} />);
await user.click(screen.getByRole("button", { name: "Add Matcha" }));
expect(onAdd).not.toHaveBeenCalled();
render(<TeaMenu teas={[]} onAdd={() => {}} />);
expect(screen.getByText("No teas on the menu today.")).toBeInTheDocument();
expect(screen.queryByRole("list")).not.toBeInTheDocument();
const teas = [
{ id: "sencha", name: "Sencha", price: 4, soldOut: false },
{ id: "chai", name: "Masala chai", price: 3.5, soldOut: false },
];
render(<TeaMenu teas={teas} onAdd={() => {}} />);
expect(logs.join("\n")).not.toMatch(/unique "key"/);
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 Tea menu list. 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.