Challenge 1: An Integration Test for TodoApp — Possible Solution
====================================================================
it("adds a new todo to the list on submit", async () => {
render(); // contains a real AddTodoForm and a real TodoList
await userEvent.type(screen.getByLabelText("New todo"), "Buy milk");
await userEvent.click(screen.getByRole("button", { name: "Add" }));
expect(await screen.findByText("Buy milk")).toBeInTheDocument();
});
WHY THIS WORKS AS AN ANSWER
------------------------------
render() mounts the PARENT component with its real children
intact — neither AddTodoForm nor TodoList is mocked or replaced with a
stub, exactly this chapter's definition of an integration test (as
opposed to a component test, which would typically render AddTodoForm
or TodoList in isolation).
Typing into the form and clicking "Add" exercises the REAL
communication path between the two components: however TodoApp wires
AddTodoForm's submission to updating the data TodoList renders (props,
shared state, a context, etc.) is exercised exactly as it would be in
the real running app — this is precisely what a component test of
either piece alone could never verify, since a component test would
typically only check that AddTodoForm calls a mocked callback, or that
TodoList renders correctly given hand-provided props, never that the
two pieces are ACTUALLY wired together correctly inside TodoApp.
findByText (rather than getByText) is used for the final assertion
since the update may not be synchronous, depending on how TodoApp
manages state — treating it as potentially-async is the safer default
this course has used consistently since Chapter 5.