The tea shop's order page has keyboard shortcuts, and pressing ? should show them. Build App: the page, with a help panel that opens on ? and closes on Escape, wherever the focus is on the page.
The page has a text box labelled Search teas (an <input>), a text box labelled Order note (a <textarea>), and a line that says Press ? to see the keyboard shortcuts. When the help is open, it's a <section> labelled Keyboard shortcuts, with a heading and a short list. When it's closed, it isn't on the page at all.
Pressing ? opens the help and pressing Escape closes it. Both keys are ignored while the focus is in an <input> or a <textarea>, so people can type a question mark in their note. Once the focus leaves the text box, the keys work again. Other keys do nothing.
App takes an optional onOpenHelp prop and calls it each time the help opens (pressing ? while it's already open doesn't count). The parent may pass a different function on any render, and the latest one is the one called.
Listen on window, and stop listening when App leaves the page.
<App onOpenHelp={() => console.log("help opened")} />
// renders, after pressing ?:
<label>Search teas <input /></label>
<label>Order note <textarea /></label>
<p>Press ? to see the keyboard shortcuts.</p>
<section aria-label="Keyboard shortcuts">
<h2>Keyboard shortcuts</h2>
...
</section>
render(<App />);
expect(screen.queryByRole("region", { name: "Keyboard shortcuts" })).not.toBeInTheDocument();
expect(screen.getByLabelText("Search teas")).toBeInTheDocument();
expect(screen.getByLabelText("Order note")).toBeInTheDocument();
render(<App />);
await user.keyboard("?");
expect(screen.getByRole("region", { name: "Keyboard shortcuts" })).toBeInTheDocument();
render(<App />);
await user.keyboard("?");
await user.keyboard("{Escape}");
expect(screen.queryByRole("region", { name: "Keyboard shortcuts" })).not.toBeInTheDocument();
render(<App />);
await user.type(screen.getByLabelText("Search teas"), "green?");
expect(screen.getByLabelText("Search teas")).toHaveValue("green?");
expect(screen.queryByRole("region", { name: "Keyboard shortcuts" })).not.toBeInTheDocument();
render(<App />);
await user.keyboard("?");
await user.click(screen.getByLabelText("Order note"));
await user.keyboard("{Escape}");
expect(screen.getByRole("region", { name: "Keyboard shortcuts" })).toBeInTheDocument();
render(<App />);
const search = screen.getByLabelText("Search teas");
await user.type(search, "oolong");
act(() => search.blur());
await user.keyboard("?");
expect(screen.getByRole("region", { name: "Keyboard shortcuts" })).toBeInTheDocument();
const onOpenHelp = spy();
render(<App onOpenHelp={onOpenHelp} />);
await user.keyboard("?");
expect(onOpenHelp.callCount).toBe(1);
await user.keyboard("?");
expect(onOpenHelp.callCount).toBe(1);
await user.keyboard("{Escape}");
await user.keyboard("?");
expect(onOpenHelp.callCount).toBe(2);
const first = spy();
const second = spy();
const { rerender } = render(<App onOpenHelp={first} />);
rerender(<App onOpenHelp={second} />);
await user.keyboard("?");
expect(first.callCount).toBe(0);
expect(second.callCount).toBe(1);
const onOpenHelp = spy();
const { unmount } = render(<App onOpenHelp={onOpenHelp} />);
unmount();
await user.keyboard("?");
expect(onOpenHelp.callCount).toBe(0);
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 Keyboard shortcuts help. 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.