react-testing-library or Cypress - Adding multiple data-testids

Viewed 2500

I have a box that is selectable, so I want to add this box two test ids, one to test the type of the box and the other if it is selected. Should I add two data-testid attributes or two keywords in one data-testid? what is the best practice for this when it comes to Cypress or react-testing-library?

<div data-testid="box-user" data-testid="box-user-active">

vs

<div data-testid="box-user box-user-active">

I know there are other ways to check if the box is selected, but there are plenty of other use cases when adding two test ids would make things much easier.

2 Answers

I've seen posted that data-testid and getByTestId should be a last resort (preferring getByText and getByRole), and there would lots of opinions about that.

From a purely technical standpoint, given a space-delimited list of values

<div data-testid="box-user box-user-active">

you can select by either value with a partial match expression. Ref jQuery attribute-selectors

The most useful for multiple space separated values is ~=.

cy.get('[data-testid*="box-user"]')        // either attribute
                                           // plus other variations like "unbox-user"

cy.get('[data-testid~="box-user"]')        // space-delimited (full values only)
                                           // so "box-user" but not "box-user-active"

cy.get('[data-testid~="box-user"][data-testid~="box-user-active"]') // must have both

cy.get('[data-testid^="box-user"]')          // starts with "box-user"
cy.get('[data-testid$="box-user-active"]')   // ends with "box-user-active"

For react testing library also allows partial matching: https://testing-library.com/docs/queries/about/#precision

@user14783414 's anwer for react testing library would be...

<>
  <div data-testid="box-user box-user-active">
  <div data-testid="box-user box-user-inactive">
</>
/* Return only first item */
screen.getByTestId('box-user-active', {exact: false})
screen.getByTestId('box-user box-user-active', {exact: true})

/* Return both items*/
screen.getByTestId('box-user', {exact: false})
Related