Differences Between CLI Testing Library & Testing Library
While we clearly take inspiration from
DOM Testing Library
and
React Testing Library,
and try to do our best to align as much as possible, there are some major
distinctions between the project’s APIs.
Instances
While the DOM Testing Library and it’s descendants have a concept of both a
container and element, CLI Testing Library only has a single concept to
replace them both: a TestInstance.
This is because, while the DOM makes a clear distinction between different
elements (say,
HTMLBodyElement
and
HTMLDivElement),
there is no such distinction between processes in the CLI as far as I’m aware.
While this may change in the future (maybe container can be a sort of
TestProcess of some kind), there are
unanswered questions around what that API looks like and whether we can meaningfully handle the distinction.
Queries
Similarly, HTMLElements provide clean lines between user input items.
Meanwhile, the CLI only has the concepts of stdin, stdout, and stderr.
It’s unclear how matching a single line of stdout would help in a beneficial
matter, much less how APIs like fireEvent would utilize this seemingly
extraneous metadata.
As a result, we don’t have any *AllBy queries that DOM Testing Library does.
All of our queries are non-plural (*By) and will simply return either the test
instance the query was called on, or null depending on the query.
While we would be happy to reconsider, there are once again
lots of questions around what *AllBy queries would like and whether we can meaningfully use that concept.
Events
Another area where we diverge from the DOM is in our event system (as
implemented via fireEvent and userEvent).
Despite our APIs’ naming indicating an actual event system (complete with bubbling and more, like the DOM), the CLI has no such concept.
FireEvent
This means that, while fireEvent in the DOM Testing Library has the ability
to inherent from all baked-into-browser events, we must hard-code a list of
“events” and actions a user may take.
We try our best to implement ones that make sense:
- fireEvent.write({value: str})to write- strinto stdin
- fireEvent.sigkill()to send a sigkill to the process
- fireEvent.sigint()to send a sigint to the process
There is a missing API for that might make sense in keypress. It’s unclear
what this behavior would do that write wouldn’t be able to.
UserEvent
There’s also the API of userEvent that allows us to implement a fairly similar
keyboard event
to upstream.
However, there are a few differences here as well:
- userEventcan be bound to the- renderoutput. This is due to limitations of not having a- screenAPI. It’s unclear how this would work in practice, due to a lack of the- windowAPI.
- userEvent.keyboarddoes not support modifier keys. It’s only key-presses, no holding. This is because of API differences that would require us to figure out a manual binding system for every single key using ANSI AFAIK.
- Relatedly, we’ve remove the {syntax support, since there is no standard keybinding for the CLI, like there is for the DOM. Instead, we only support[and]syntax.
Matchers
While most of this document has been talking about DOM Testing Library and
React Testing Library, let’s take a moment to talk about
jest-dom matchers.
Usually, in a Testing Library testbed, you’d expect a getByText to look
something like this:
const {getByText} = render(/* Something */)
expect(getByText('Hello World')).toBeInTheDocument()In today’s version of CLI Testing Library, the same would look something like
this:
const {getByText} = render(/* Something */)
expect(getByText('Hello World')).toBeInTheConsole()Similarities
None of this is to say that we’re not dedicated to being aligned with upstream. We would love to work with the broader Testing Library community to figure out these problems and adjust our usage.
This is the primary reason the library is still published as an @alpha,
despite being stable enough to successfully power
a popular CLI application’s testbed.
What’s more, we’re dedicated enough to making this happen that we’ve made sure to:
- Use the same source code organization (as much as possible) as
DOM Testing LibraryandReact Testing Library
- Use the same deployment process as DOM Testing Library
- Use similar documentation styles
And more!
