I am trying to write some tests for two lists of users (users and members, identical markup, different semantic content) in React Testing Library. Details of each user are inside of a span element.
I have this DOM tree:
<div>
<span>
<div>
<b>Text 1</b>
</div>
<div>
<!-- other elements here -->
</div>
</span>
</div>
<div>
<span>
<div>
<b>Text 2</b>
</div>
<div>
<!-- other elements here -->
</div>
</span>
</div>
<div>
<span>
<div>
<b>Text 3</b>
</div>
<div>
<!-- other elements here -->
</div>
</span>
</div>
I want to match the span element (because it handles the onClick logic) based on the text inside the b child element (because it contains user's name and last name).
I tried doing it this way:
const getUsersLists = (doc) => ({
usersList: doc.querySelector('.users-users-list'),
membersList: doc.querySelector('.members-users-list'),
});
const getUser = (name, list) => (
screen.findByText(name), { selector: 'span' }, { container: list })
);
test('users exist', () => {
const { usersList } = getUsersLists(document);
const sampleUser = await getUser('Text 1', usersList);
expect(sampleUser).toBeInTheDocument();
});
The problem:
Those matchers successfully find the Text 1 text if I remove the { selector: 'span' } options object from the getUser method. As soon as I tell RTL to look for a span element it can't find anything.
I also want to avoid any more document.querySelector and class / ID (including data-testid) references.