How to Target Specific Part of a Component and Test using React Testing Library
Tags: jest, react, testing
Published: 2022-03-08 10:39:24

---
title: How to Target Specific Part of a Component and Test using React Testing Library
published: true
date: 2022-03-04 11:49:28 UTC
tags: Jest,ReactJS,Testing
canonical_url: https://robertmarshall.dev/blog/how-to-query-and-test-within-a-specific-component-in-jest/
---

Are you trying to target a specific element inside the DOM in Jest to make testing simpler and not sure how to do it?

This post on querying within components using `within` will hopefully point you in the right direction.

--------

This article was originally posted (and is more up to date) at https://robertmarshall.dev/blog/how-to-query-and-test-within-a-specific-component-in-jest/

--------

## Context

There is an component that has three cards outlining a product. Each card has a title element and a button that fires a function. We want to test if the correct function fires, when the Cat Food “Buy Item” button is clicked.

[![Jest Test Within Element Example](https://robertmarshall.dev/static/0e85807b209950ea46eb3623cf60d272/New-Project-2022-03-03T182307.357-1.jpg)](/static/0e85807b209950ea46eb3623cf60d272/New-Project-2022-03-03T182307.357-1.jpg)

This looks like this:

```javascript
import "./styles.css";
import { purchaseFunction } from "./api";

const Card = ({ title, slug }) => (
  <div className="card">
    <h2>{title}</h2>
    <button className="button" onClick={() => purchaseFunction(slug)}>
      Buy Item
    </button>
  </div>
);

const Products = ({ items }) => (
  <div className="products">
    {items.map(({ title, slug }) => (
      <Card key={slug} title={title} slug={slug} />
    ))}
  </div>
);

export default function App() {
  const items = [
    { title: "Cat Food", slug: "cat-food" },
    { title: "Dog Food", slug: "dog-food" },
    { title: "Waffles", slug: "waffles" }
  ];

  return (
    <div className="app">
      <h1>Shop</h1>
      <Products items={items} />
    </div>
  );
}
```

A working example of the above, so you can see the code: [React Testing Library Within CodeSandbox](https://codesandbox.io/s/react-testing-library-within-example-8ncgo2).

The issue is that each button has the same label “Buy Item”. How can the jest test target a specific section of the component? How can we use React Testing Library focus down into a DOM node and only use a section in the test?

## What To Do?

There are several options at this point. It would be easy to apply a `testid` to each button with a unique name, but this wouldn’t be testing the proper component. Using the `testid` query is only recommended for cases where you can’t match by role or text or it doesn’t make sense. More detail on this can be found in the [React Testing Library priority](https://testing-library.com/docs/queries/about/#priority) page.

It would also be possible to use `queryAllByText` to find each ‘Buy Item’ button, then find the second button. Like so:

```javascript
test("purchaseFunction called with correct product slug on second button click", () => {
  render(<App />);

  // Get the dog food buy button from an array of all buy buttons.
  const DogFoodButton = screen.queryAllByText("Buy Item")[1];

  userEvent.click(DogFoodButton);

  expect(purchaseFunction).toHaveBeenCalledWith("dog-food");
});
```

However this is very brittle and if the card positions are switched/moved the test will break. We do not want to test the order of the cards. We want to test if a particular button is pressed.

## The Cleaner Way To Test

This is where `within` is super handy. It allows the test to be focused within a particular DOM element. To run a jest test inside an element block.

This would be handled like so:

```javascript
test("purchaseFunction called with correct product slug on Dog Food click", () => {
  render(<App />);

  // Get the specific card and bind to query functions using within.
  const DogFoodCard = within(screen.getByText("Dog Food").parentElement);

  // Now we can click the specific button within that card.
  userEvent.click(DogFoodCard.getByRole("button", { name: "Buy Item" }));

  expect(purchaseFunction).toHaveBeenCalledWith("dog-food");
});
```

Although the test is a little longer, it is more explicit in what is happening. It allows jest queries to be restricted with within a particular element meaning that the tests themselves can be far more succinct and cleaner. Hopefully this answers the question of how to make queries in Jest test within context of particular element.

For more React and Jest hints and tips take a look at the [React Category](https://robertmarshall.dev/blog/category/reactjs/), and [Jest Testing Category](https://robertmarshall.dev/blog/category/jest/)!