import {test} from 'node:test';
import assert from 'node:assert/strict';
import {render, screen, within} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import ShoppingCart from './main.jsx';
const products = () => screen.getByRole('list', {name: 'Products'});
const productRow = (name) => within(products()).getAllByRole('listitem').find((li) => li.textContent.startsWith(name + ' '));
const add = (user, name, label = 'Add to cart') => user.click(within(productRow(name)).getByRole('button', {name: label}));
// Each cart line's text without its buttons, e.g. "Bread × 2".
const cartLines = () => (screen.queryByRole('list', {name: 'Cart'})
? within(screen.getByRole('list', {name: 'Cart'})).getAllByRole('listitem').map((li) =>
[...li.childNodes].filter((n) => n.nodeType === 3).map((n) => n.textContent).join('').trim())
: []);
const cartRow = (name) => within(screen.getByRole('list', {name: 'Cart'})).getAllByRole('listitem').find((li) => li.textContent.startsWith(name + ' '));
const press = (user, name, label) => user.click(within(cartRow(name)).getByRole('button', {name: label}));
const total = () => screen.queryByText(/^Total:/)?.textContent ?? null;
test('Each cart line shows its price times its quantity', async () => {
const user = userEvent.setup();
render(<ShoppingCart />);
await add(user, 'Bread');
await add(user, 'Bread');
await add(user, 'Apple');
assert.deepEqual(cartLines(), ['Bread × 2 €4.98', 'Apple × 1 €0.50'], 'the cart lines are ' + JSON.stringify(cartLines()));
});
test('The total adds up every line', async () => {
const user = userEvent.setup();
render(<ShoppingCart />);
for (let i = 0; i < 3; i++) await add(user, 'Apple');
await add(user, 'Cheese');
assert.equal(total(), 'Total: €5.75', 'with Apple × 3 and Cheese × 1 the page shows ' + JSON.stringify(total()));
});
test('Add 2 adds two at once', async () => {
const user = userEvent.setup();
render(<ShoppingCart />);
await add(user, 'Cheese', 'Add 2');
assert.deepEqual(cartLines(), ['Cheese × 2 €8.50'], 'after one click on Add 2 the cart lines are ' + JSON.stringify(cartLines()));
await add(user, 'Cheese', 'Add 2');
assert.deepEqual(cartLines(), ['Cheese × 4 €17.00'], 'after two clicks on Add 2 the cart lines are ' + JSON.stringify(cartLines()));
});
test('An empty cart shows no total', async () => {
const user = userEvent.setup();
render(<ShoppingCart />);
assert.equal(total(), null, 'the empty cart shows ' + JSON.stringify(total()));
await add(user, 'Apple');
await press(user, 'Apple', 'Remove');
assert.equal(total(), null, 'after removing the last item the page shows ' + JSON.stringify(total()));
assert.ok(screen.queryByText('Your cart is empty.'), 'the empty-cart message is not shown');
});