Jest · Unit tests that survive refactors

How do you test DOM behaviour in Jest?

Easydomtesting libraryqueriesUpdated Oct 2026
Quiz this track

Short answer

Render markup into the jsdom document, query it by role or label, and interact through realistic events. Assert on visible DOM state rather than internal variables.

A DOM test should look like a user interaction. The arrangement is the rendered markup, the action is a click, typing or submit, and the assertion is the resulting visible state. Querying by role and accessible name keeps the test resilient to markup refactors.

ts
import { screen } from "@testing-library/dom";
import userEvent from "@testing-library/user-event";

test("toggles the panel", async () => {
  const user = userEvent.setup();
  document.body.innerHTML =
    '<button aria-expanded="false">Details</button><div hidden>More</div>';

  const button = screen.getByRole("button", { name: "Details" });
  await user.click(button);

  expect(button).toHaveAttribute("aria-expanded", "true");
});

Query and interaction rules

  • Prefer getByRole, getByLabelText and getByText over CSS selectors
  • Use userEvent for clicks and typing because it models real event sequences
  • Use findBy and waitFor for updates that happen after an event loop turn
  • Assert on attributes, text and visibility that a user can perceive
  • Avoid reading component state or calling internal methods

Use getBy when the element must already exist, queryBy to assert absence, and findBy when it appears asynchronously. The distinction matters because getBy throws on a missing element, which produces a clearer failure than a null check.

Visible text is usually the best selector. A missing accessible role or label is often a real accessibility issue, not a reason to fall back to a test ID.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1When do you use queryBy instead of getBy?
  2. 2Why is userEvent preferred over fireEvent?
  3. 3How do you assert that an element is not present?
  4. 4Why should DOM tests avoid CSS selectors?

Say it in the interview

I render the markup, query it by role, label or text, and interact with userEvent. I assert on what the user can see, such as text, attributes and visibility. getBy is for elements that must exist, queryBy for absence, and findBy for async appearance. I avoid reaching into internal state, because that couples the test to the implementation.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Jest mock interview and get scored feedback on depth, clarity and confidence.