I have some text like "Message failed to send" that I want to assert will not appear on screen. According to this answer, I should avoid compound logic in my assertions. And according to the React Testing Library guiding principles, I should write tests based on the user experience. So it seems like I should do something like this:
test('it does not display an error', () => {
render(<App />);
expect(screen).not.toDisplayText('failed to send');
});
This matcher doesn't seem to exist, though, and I can't find one equivalent to it.
expect(screen.queryByText('fail')).not.toBeInTheDocument()
, which passes if the text is nonexistent but fails if it is nonvisible.expect(screen.queryByText('fail')).not.toBeVisible()
, which passes if the text is nonvisible but fails if it is nonexistent.It seems like "this text does not exist and I don't care why" should be a pretty common query, but I can't find a clean way to test for it. Right now I'm just switching which test I use based on whether I expect the element to be nonexistent or nonvisible, but that feels wrong. Is there a better way?
Use a custom text match function that only matches visible text.
function matchVisible(text) {
return (content, element) => content.startsWith(text) && element.getAttribute('aria-hidden') !== 'true';
}
test('everything is fine', () => {
render(<MyApp />);
const error = screen.queryByText(matchVisible('flagrant error'));
expect(error).toBeNull();
});
Reference: https://github.com/testing-library/dom-testing-library/issues/929#issuecomment-1571823720