Walkthrough: Testing Forecast Summary Component π¬
Overview
Let's go through the questions we asked earlier:
1. Which values could you test here?
The <ForecastSummary />
component should display 4 elements (for now): date, icon, max temperature, and description. We want to check if the UI presents them to the end user.
2. Which RTL queries will be suitable here?
That depends on the type of information we want to display:
- Description is the most obvious one - it should display a string, as it is with no change.
- Temperature is a bit complicated, as we want to display value and unit, so our test should account for that.
- Date should display a value that is human readable, but it returns a value in milliseconds. For now we will assume that it is what we want to see, but once we format the date to a human readable value, we will update our test.
- Icon is the most difficult one and will be treated differently than others.
Bearing that in mind getByText()
should be sufficient for description, temperature, and date, but icon requires getByTestId()
.
3. Can/Should you use the same assertions as you did in <LocationDetails />
?
In <LocationDetails />
we used the getByText()
query and toBeTruthy()
/ toBeInstanceOf()
matchers within our assertions. You can and should use the same queries and matchers within different test files, so long as they suit your testing needs.
4. How many tests you might need here?
We need at least 2 tests. One for snapshot testing, and one for values. The second test should have 4 assertions, one for each value we want to display.
Solution
Snapshot testing
1. Props.
Our component renders each of the 4 values in their own <div>
s as we provide 4 different props. To do snapshot testing we need to use the asFragment()
method to get the component rendered as a DocumentFragment
(more on that here), and we need to pass some stub props. The important thing here is to pass props with the correct data types.
To do so create a const validProps
that is an object storing all 4 props. This should sit within the describe
block.
π‘ Please note, we could pass values directly to the <ForecastSummary />
component, but we might be using them for other tests too, so let's store them in one place.
π€ Why do you think we named our variable validProps
here, and not just props
?
2. Component rendering.
Now it's time to render our component using asFragment()
and our props:
3. Assertion.
Now that we have our component being rendered as a DocumentFragment
we can write our assertion using toMatchSnapshot()
. The final snapshot test will look like:
4. Run tests.
Run test for this file by using npm test src/tests/components/ForecastSummary.test.js
. You should see a snapshot file being created. Feel free to check what this file looks like. You won't be ever changing it manually, as it's generated, but it's good for you to know what it looks like. Remember to commit all changes, including the snapshot.
Values testing
1. Add simple test with getByText()
.
Props/values tests are different than snapshot test, so it might be a good idea to group them within another describe block.
For props/values tests we need to use different methods. Let's start with getByText()
. Create a new test "render correct values for props" and make sure your component is rendered with getByText()
and write assertions:
You can use the toHaveAttribute()
method to check for the existence of any html attribute.
In this example we checked for the class
attribute to illustrate how to use the toHaveAttribute()
method (once our code is compiled the react specific className
attribute will become class
). Though you'd typically want to avoid testing implementation details such as class names, more info here.
2. Modify the test for icon - add data-testid
attribute.
Do you remember when we said this one requires a different test? When we come to use the real icons in the future, they won't display any text, so we need to use something else to find it. getByTestId()
is the most appropriate choice here. The docs in RTL cheatsheet are not the most comprehensive for this query, but let's start with adding data-testid
to the icon <div />
in <ForecastSummary />
, with the value of "forecast-icon"
:
3. Modify test for icon - update snapshot.
Check what happened with the tests. The snapshot test should fail now as we changed the markup. This is desired, as we know we've made that change. To fix the snapshot test you need to update it. If you see this: Watch Usage: Press w to show more.
as the last line in your tests, press "w" and you should see the list of short commands, one of them being Press u to update failing snapshots.
Follow this instruction! Now you should have only the second test to fix.
4. Modify test for icon - fix failing test.
Now it's time to alter our icon test. Add getByTestId
to methods accessible from render()
and modify the assertion in the ForecastSummary.test.js
file. Remember to pass the right value to getByTestId()
. The test should look like this:
Check tests are running in the console. Is it sorted?