๐งชMore on Tests
Testing user interactions and state.
User Interaction & State Changes
Suppose we have a button in our component, that changes the text that is rendered in the component. We want to test whether this button click is working or not, and check if the text is changed on the button click. This is where we "ACT
" within our tests (from the 3 A's
of writing a test).
Button click & State change
Greeting Component
In the Greeting
component, we have a state that stores true
/ false
, based on whether the button
was clicked, and based on the state value, we render different <p>
text to the component. We will be testing these use cases here.
Test Button Click
Lets now create the test suite for this component, where we check for the text change upon the button click. For this, we would need the userEvent
component from @testing-library/user-event
, to trigger user events in the virtual screen
. With this, we can perform all the events that the user can trigger, like click, double click, hovering, typing into inputs, etc. The userEvent.click()
accepts the screen
element as a parameter. We can select the button element by text, or even better, we can use the getByRole()
method to get the button
element from the screen
. Since here we have only one button element, it is okay to select this element using the getByRole()
function.
Here, in the test for button click, we need to "act", to simulate a button click event. After the button click simulation is done, we need to "assert" again, to check if the element [text] has changed to "Changed!", and if it does, the test will pass.
Greeting Test Code
Edge Case
We need to also check if the "Greeting from outer space" message is hidden, when the button is clicked. This is especially handy when we forget to conditionally render something, and a conditional element is always show in our component.
Here, if we try to get the element by text after the button is clicked, it will throw an error, saying that it cannot find the element with the specified text. But this is specifically what we want, and since the getByText()
will always throw and error in such a case, we need to use the queryByText()
method to get the element with the specified text. If the element with that text is not found, it returns a null
, instead of an error. So finally we can assert that we expect()
the element that we got by queryByText()
, toBeNull()
.
Results
Upon running the tests, we get the following output, where all the 3 tests in the test suite Greeting Suite
, have passed:
Testing Connected Components
Consider that the Greeting
component also imports another component called Output
, which in the end renders a paragraph with some text. Now we want to run the tests on the Greeting component, but it also has a new component, Output
, which is connected to it. The good things about the render method in the @testing-library/react
is that, it renders the entire component tree, so in a way this can be called an Integration Test
, though the connected component does not have much logic of it's own.
Of course, if the logic in the connected component becomes very large to handle on its own, like having state changes, etc., in that case it would need to have a separate test file of its own.
Connected Components
With the above changes, and no changes to the Greting.test.js
file, our test cases will execute and pass without any errors!
Results
Last updated