DEV Community

Abel Varga
Abel Varga

Posted on • Edited on

Why testing-library fails to do what it set out to do

The problem that testing-library aims to solve is that when we write tests for our components, we rely upon the implementation details of said component, which in turn make our tests fragile, and not refactor proof. This goal is an admirable one and something which could help every developer to ship reliable and maintainable code.

The problem with this is not a conceptual one, but an execution one.

I was testing a custom input component because I found a bug. In a specific situation, the user could not type in it. Yes, it was a bug I introduced but thought before fixing it, I'll write tests to cover this. TDD, right? It turns out you cannot cover this scenario with react-testing-library and jest, because how it only partially implements a DOM.

What I needed was to test if, in the given situation, the user focuses the input and starts typing, the value of the input changes accordingly. The test has failed as it should have. So I began fixing the issue. It was quick and easy and could confirm the fix in my browser. When I went back to check up on my tests, they still failed.

My test consisted of using keyDown events to emulate typing. Because this is the user does, right? Well, it turns out that according to testing-library, the user is not pressing buttons, but fires change events! AS we all do when we do a Google search. We hit it up, and fire change event left and right and boom, here comes the search result.

My issue with this concept is that there are cases when firing a change event works, but pressing keys does not. And I could not find a solution for this since.

This issue is similar to not being able to query innerText because you'd need a layout engine for that. As if the user would be using your components without one. But worry not, there is data-test-id. Which is a way of saying, do not test implementation details, but implement details to test the thing.

I think while the concept is excellent, the tools are not in place to deliver yet. You still need puppeteer, playwright or selenium to get into the shoes of your end-user. If you know of any ways to run my existing testing-library specs in a browser a way that allows for querying elements by input text, like an xPath selector or something, and has a complete chain of events, please let me know.

Thank you, rant over

Top comments (8)

Collapse
 
vonheikemen profile image
Heiker • Edited

In theory, if you use a test runner that can be used in a browser (mocha and tape comes to mind), you could use a bundler to gather all your tests together and run them in a real browser. I did this experiment in 2018 with tape and dom-testing-library, at that time it worked great (just had to make sure to add { node: fs: 'empty' } on my webpack config).

If jest is the real problem then you could try one of these testing library wrapper

Collapse
 
rangeoshun profile image
Abel Varga • Edited

Thanks for your reply!

We already use Puppeteer for E2E testing, but currently transitioning to Playwright. Tried Cypress, which is awesome, but lacked the cross-domain support, which we still need for the time being. I have not familiarized myself with TestCafe tho.

But to sum up, you say we should bundle jest and all test files, open in a browser, and it should work with react-testing-library as long as it's bundled with it?

Do you reckon, from the top of your head, that it would be easy to support file watching as well?

Collapse
 
vonheikemen profile image
Heiker • Edited

But to sum up, you say we should bundle jest and all test files, open in a browser, and it should work with react-testing-library as long as it's bundled with it?

Oh no. Heavens no! That's not what I'm saying. Jest is a monster of a framework, I don't think you can make it run in a browser. I'm just trying to defend the testing-library family here.

Do you use pptr-testing-library with puppeteer?

Thread Thread
 
rangeoshun profile image
Abel Varga

Nope, we created a test suite with cucumber-js and a lot of custom steps to support Gherkin for our PMs and non-technical staff.

Does it allow to run @testing-library/react based tests in Puppeteer?

Because I'm under the impression, they won't work together like that, and that's where I may be wrong.

Thread Thread
 
vonheikemen profile image
Heiker

Does it allow to run @testing-library/react based tests in Puppeteer?

No. pptr-testing-library was made to control puppeteer. So, technically puppeteer will render your app, then you use pptr-testing-library to query and manipulate the DOM (just like you would with react-testing-library).

Thread Thread
 
rangeoshun profile image
Abel Varga

Thanks! That's what I thought. What I would like ultimately, is my unit-tests to run in an actual browser.

Collapse
 
revelt profile image
Roy Revelt

To sum up, serious projects need unit testing (React Testing Library, Jest — TDD) but also end-to-end testing (Cypress/WebdriverIO — BDD). That's just two different testing angles. Running Cypress on a component, to test prop is overkill. That's what RTL is for. On the same way, user interactions like you described with user typing is typical Cypress area. Using RTL for that is cumbersome if not impossible like you noted.

PS. let's fix typo "rent over" to "rant over"

Collapse
 
rangeoshun profile image
Abel Varga

Thanks for noting the typo, fixed it.

On the matter of RTL, I'm not sure if it's unavoidable. If you maintain a Storybook, you could do a lot of your unit tests there, with puppeteer, you need to assert your expectations in your E2E framework.

There are cases where I cannot imagine using a browser with current tooling but could imagine tooling that would allow. Like mocking global variables like location and etc.

So in short TDD does not say anything about the environment you run it in IMHO.