Build App({ items }): a tea shop's restock list. items is an array of { id, name }. Show a checkbox for each item, labelled with its name, and above them a checkbox labelled Select all. Nothing is checked at first. The starter gives items a default so the Preview has something to show; the tests pass their own.
Below the list, a line reads 2 of 4 selected: how many items are checked, out of how many there are.
Select all matches the items. It's checked when every item is checked, and unchecked when none are. When only some are, it's indeterminate: its indeterminate property is true and it isn't checked. HTML has no indeterminate attribute, so you set that DOM property through a ref.
Clicking Select all checks every item, unless every item is already checked, in which case it unchecks them all. With no items, Select all is disabled and the line reads 0 of 0 selected.
<App items={[{ id: 1, name: "Assam" }, { id: 2, name: "Sencha" }]} />
const items = [{ id: 1, name: "Assam" }, { id: 2, name: "Darjeeling" }, { id: 3, name: "Sencha" }, { id: 4, name: "Oolong" }];
render(<App items={items} />);
const all = screen.getByRole("checkbox", { name: "Select all" });
expect(all).not.toBeChecked();
expect(all.indeterminate).toBe(false);
for (const item of items) expect(screen.getByRole("checkbox", { name: item.name })).not.toBeChecked();
expect(screen.getByText("0 of 4 selected")).toBeInTheDocument();
const items = [{ id: 1, name: "Assam" }, { id: 2, name: "Darjeeling" }, { id: 3, name: "Sencha" }, { id: 4, name: "Oolong" }];
render(<App items={items} />);
await user.click(screen.getByRole("checkbox", { name: "Sencha" }));
expect(screen.getByRole("checkbox", { name: "Sencha" })).toBeChecked();
const all = screen.getByRole("checkbox", { name: "Select all" });
expect(all.indeterminate).toBe(true);
expect(all).not.toBeChecked();
expect(screen.getByText("1 of 4 selected")).toBeInTheDocument();
const items = [{ id: 1, name: "Assam" }, { id: 2, name: "Darjeeling" }, { id: 3, name: "Sencha" }];
render(<App items={items} />);
for (const item of items) await user.click(screen.getByRole("checkbox", { name: item.name }));
const all = screen.getByRole("checkbox", { name: "Select all" });
expect(all).toBeChecked();
expect(all.indeterminate).toBe(false);
expect(screen.getByText("3 of 3 selected")).toBeInTheDocument();
const items = [{ id: 1, name: "Assam" }, { id: 2, name: "Darjeeling" }, { id: 3, name: "Sencha" }, { id: 4, name: "Oolong" }];
render(<App items={items} />);
await user.click(screen.getByRole("checkbox", { name: "Select all" }));
for (const item of items) expect(screen.getByRole("checkbox", { name: item.name })).toBeChecked();
expect(screen.getByRole("checkbox", { name: "Select all" })).toBeChecked();
expect(screen.getByText("4 of 4 selected")).toBeInTheDocument();
const items = [{ id: 1, name: "Assam" }, { id: 2, name: "Darjeeling" }, { id: 3, name: "Sencha" }, { id: 4, name: "Oolong" }];
render(<App items={items} />);
await user.click(screen.getByRole("checkbox", { name: "Assam" }));
await user.click(screen.getByRole("checkbox", { name: "Oolong" }));
await user.click(screen.getByRole("checkbox", { name: "Select all" }));
for (const item of items) expect(screen.getByRole("checkbox", { name: item.name })).toBeChecked();
const all = screen.getByRole("checkbox", { name: "Select all" });
expect(all).toBeChecked();
expect(all.indeterminate).toBe(false);
expect(screen.getByText("4 of 4 selected")).toBeInTheDocument();
const items = [{ id: 1, name: "Assam" }, { id: 2, name: "Darjeeling" }, { id: 3, name: "Sencha" }];
render(<App items={items} />);
const all = screen.getByRole("checkbox", { name: "Select all" });
await user.click(all);
await user.click(all);
for (const item of items) expect(screen.getByRole("checkbox", { name: item.name })).not.toBeChecked();
expect(all).not.toBeChecked();
expect(all.indeterminate).toBe(false);
expect(screen.getByText("0 of 3 selected")).toBeInTheDocument();
const items = [{ id: 1, name: "Assam" }, { id: 2, name: "Darjeeling" }, { id: 3, name: "Sencha" }];
render(<App items={items} />);
const all = screen.getByRole("checkbox", { name: "Select all" });
await user.click(all);
await user.click(screen.getByRole("checkbox", { name: "Darjeeling" }));
expect(all.indeterminate).toBe(true);
expect(all).not.toBeChecked();
expect(screen.getByText("2 of 3 selected")).toBeInTheDocument();
render(<App items={[]} />);
const all = screen.getByRole("checkbox", { name: "Select all" });
expect(all).toBeDisabled();
expect(all).not.toBeChecked();
expect(screen.getByText("0 of 0 selected")).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 Select all checkboxes. 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.