Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Query a button with specific text

I have a (Jest) test to determine if a button exists:

it('renders a signup button', () => {
  expect(sut.getByText('Sign up for free')).toBeDefined()
})

This test because there is both a button AND heading with "Sign up for free" text in the component.

Screenshot showing both a heading and button with "Sign up for free" text

A testid could be added to the button, but I'd prefer to follow the react-testing-library principle of simulating user behaviour.

I feel it's legitimate a user would want to "click the button labelled 'Sign up for free'". In this situation, specifying the type of HTML element makes sense as a <button /> is a distinctive element to the user, as opposed to be <h2 /> vs <h3 />.

How can I query for a button element labelled "Sign up for free"? For example can getByText() be further limited by a query selector?

like image 659
Matt Stone Avatar asked Oct 16 '19 07:10

Matt Stone


People also ask

What is getByRole?

getByRole : This can be used to query every element that is exposed in the accessibility tree. With the name option you can filter the returned elements by their accessible name. This should be your top preference for just about everything.

How do you simulate click in react testing in library?

it("should invoke an onClick handler when passed", () => { const onClick = jest. fn(); const { getByText } = render( <Button variant="standard" onClick={onClick}> Dummy Label </Button> ); Simulate. click(getByText("Dummy Label")); expect(onClick). toHaveBeenCalled(); }); });

How do I get the element by className in react testing library?

To find elements by className in React testing library: Render a component and destructure the container object from the result. Use the getElementsByClassName() method on the container to find elements by class name.

What is a testing library?

The testing library is a family of packages that help you test UI components in a user-centric way. The more your test resembles the way your software is used, the more confidence they can give you.


3 Answers

I'm surprised no one here gives the most idiomatic answer yet. You can use getByRole() and pass an accessible name. The accessible name is the text of the button or the value of aria-label attribute.

It can be used to query a specific element if multiple elements with the same role are presented on the screen.

Text button

<button>Text Button</button>
screen.getByRole('button', {
  name: /text button/i
})

Icon button

<button aria-label='edit'>
  <edit-icon />
</button>
screen.getByRole('button', {
  name: /edit/i
})
like image 125
NearHuscarl Avatar answered Nov 13 '22 20:11

NearHuscarl


You can pass options to your query to change its default behavior:

getByText('Sign up for free', { selector: 'button' })

You can find the full documentation here

like image 42
Giorgio Polvara - Gpx Avatar answered Nov 13 '22 20:11

Giorgio Polvara - Gpx


You can do it like this:

getByText('Sign up for free').closest('button')

You can read more about closest from here

like image 11
Abdullah Danyal Avatar answered Nov 13 '22 19:11

Abdullah Danyal