The checkout page shows an order summary: each line, then the subtotal, the tax, and the total. PriceSummary (a named export of App.jsx) looks right the first time it draws, but in the Preview, which renders in StrictMode, every total is doubled, and it changes the array it's given. Fix it.
It takes items, an array of { name, price, quantity }. Keep what it shows: a <section> with aria-label="Order summary", holding a <ul> with one <li> per item, sorted by name, that reads like Sencha x 2: $8.00 (the price times the quantity); then three paragraphs, Subtotal: $20.50, Tax: $1.64, and Total: $22.14. Tax is 8% of the subtotal, and every amount has a dollar sign and two decimals.
Make it pure. It must show the same totals however many times React calls it, in StrictMode or not, and with more than one summary on the page. It must not change items: the parent's array keeps its order, and a frozen array works.
<PriceSummary
items={[
{ name: "Sencha", price: 4, quantity: 2 },
{ name: "Oolong", price: 6.5, quantity: 1 },
{ name: "Earl Grey", price: 3, quantity: 2 },
]}
/>
// shows:
// Earl Grey x 2: $6.00
// Oolong x 1: $6.50
// Sencha x 2: $8.00
// Subtotal: $20.50
// Tax: $1.64
// Total: $22.14
const items = [
{ name: "Sencha", price: 4, quantity: 2 },
{ name: "Oolong", price: 6.5, quantity: 1 },
{ name: "Earl Grey", price: 3, quantity: 2 },
];
render(<PriceSummary items={items} />);
const lines = within(screen.getByRole("region", { name: "Order summary" })).getAllByRole("listitem");
expect(lines.map((line) => line.textContent)).toEqual(["Earl Grey x 2: $6.00", "Oolong x 1: $6.50", "Sencha x 2: $8.00"]);
const items = [
{ name: "Sencha", price: 4, quantity: 2 },
{ name: "Oolong", price: 6.5, quantity: 1 },
{ name: "Earl Grey", price: 3, quantity: 2 },
];
render(<PriceSummary items={items} />);
expect(screen.getByText("Subtotal: $20.50")).toBeInTheDocument();
expect(screen.getByText("Tax: $1.64")).toBeInTheDocument();
expect(screen.getByText("Total: $22.14")).toBeInTheDocument();
const items = [
{ name: "Sencha", price: 4, quantity: 2 },
{ name: "Oolong", price: 6.5, quantity: 1 },
];
render(
<React.StrictMode>
<PriceSummary items={items} />
</React.StrictMode>,
);
expect(screen.getByText("Subtotal: $14.50")).toBeInTheDocument();
expect(screen.getByText("Tax: $1.16")).toBeInTheDocument();
expect(screen.getByText("Total: $15.66")).toBeInTheDocument();
const order = () => [
{ name: "Sencha", price: 4, quantity: 2 },
{ name: "Oolong", price: 6.5, quantity: 1 },
];
const { rerender } = render(<PriceSummary items={order()} />);
rerender(<PriceSummary items={order()} />);
rerender(<PriceSummary items={order()} />);
expect(screen.getByText("Subtotal: $14.50")).toBeInTheDocument();
expect(screen.getByText("Total: $15.66")).toBeInTheDocument();
render(
<div>
<PriceSummary items={[{ name: "Sencha", price: 4, quantity: 2 }]} />
<PriceSummary items={[{ name: "Oolong", price: 6.5, quantity: 1 }]} />
</div>,
);
const [first, second] = screen.getAllByRole("region", { name: "Order summary" });
expect(within(first).getByText("Subtotal: $8.00")).toBeInTheDocument();
expect(within(second).getByText("Subtotal: $6.50")).toBeInTheDocument();
expect(within(second).getByText("Total: $7.02")).toBeInTheDocument();
const items = [
{ name: "Sencha", price: 4, quantity: 2 },
{ name: "Oolong", price: 6.5, quantity: 1 },
{ name: "Earl Grey", price: 3, quantity: 2 },
];
render(<PriceSummary items={items} />);
expect(items.map((item) => item.name)).toEqual(["Sencha", "Oolong", "Earl Grey"]);
const items = Object.freeze([
Object.freeze({ name: "Sencha", price: 4, quantity: 2 }),
Object.freeze({ name: "Earl Grey", price: 3, quantity: 2 }),
]);
render(<PriceSummary items={items} />);
const lines = screen.getAllByRole("listitem");
expect(lines.map((line) => line.textContent)).toEqual(["Earl Grey x 2: $6.00", "Sencha x 2: $8.00"]);
expect(screen.getByText("Subtotal: $14.00")).toBeInTheDocument();
render(<PriceSummary items={[]} />);
expect(screen.queryAllByRole("listitem")).toHaveLength(0);
expect(screen.getByText("Subtotal: $0.00")).toBeInTheDocument();
expect(screen.getByText("Tax: $0.00")).toBeInTheDocument();
expect(screen.getByText("Total: $0.00")).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 Fix the impure price summary. 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.