Reputation: 314
I am following the tutorial on jest on how to test my component, and am wondering if I am missing anything. I am trying to test my weatherApp.js
whose sole purpose is to display information from my TemperatureData.js
with a color from my colorize.js
export default class Weather extends React.Component {
constructor(props) {
super(props);
this.state = {temp: undefined}}
componentDidMount() {temperatureData().then(temp => {this.setState({temp: temp})})
}
render() {
const temperature = this.state.temp;
return <>{this.state.temp === undefined ?<somegraph />:<p style={{ color: colorize(temperature) }} id="temperature">{temperature}</p>}</>
}
}
Here is what I have to test this application, I'm not sure if i need to test anything else or what else im missing, any input appreciated.
describe("<WeatherApp> component test", () => {
test("displays data from temperature data", async () => {
const mockedTemp = "something irrelevant";
temperatureData.mockImplementation(() => {
return Promise.resolve(mockedTemp)
})
const weatherComponent = render(<WeatherApp />);
expect(temperatureData).toHaveBeenCalled()
await wait(() => {
const paragraph = weatherComponent.getByText(mockedTemp)
//console.log(paragraph)
expect(paragraph).toBeInTheDocument()
expect(paragraph).toBeDefined()
});
})
})
I am not sure if i should test to see if the correct color is returned based on my temperature input as i have a separate unit test for my colorize file...
Upvotes: 0
Views: 276
Reputation: 5646
Whether your unit-test is sufficient depends on what you define as the critical criteria for your component. If it is critically important to ensure the temperature is displayed in the correct color, you should probably test that. However, as you said, you have a separate test for the colorize function, so that may be enough. If that gives you confidence that it will work there is no need to test it again in the weatherApp.js
Those decisions are relatively subjective, and one of the reasons unit-testing is challenging - there are relatively few prescriptive answers as far as what to test. For some better guidance, this is a pretty good read on the subject.
There are, however, ways of structuring your components that facilitate easier unit testing, and in that regard I have a suggestion for changing the way your component is built since really, I think, what you care about is that:
WeatherApp
component displays colorized temperature dataRight? You don't really care that it calls the API...the data could come from anywhere. And you don't really care that it calls the colorize function...only that there is a color applied. Testing those details only makes your unit-test brittle, meaning for instance that you will have to update the unit-test definition if your API changes.
Instead, make the WeatherApp
component stateless and presentational. Use a parent component to handle:
WeatherApp
class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
temp: undefined,
color: undefined,
}
}
componentDidMount() {
temperatureData().then(temp => {
this.setState({
temp: temp
color: colorize(temp)
})
})
}
render(
return (
<WeatherApp temp={this.state.temp} color={this.state.color} />
)
)
}
Then your test looks something like this instead:
describe("<WeatherApp> component test", () => {
test("displays data from temperature data", () => {
const mockedTemp = "something irrelevant";
const weatherComponent = render(<WeatherApp temp={mockedTemp} />);
const paragraph = weatherComponent.getByText(mockedTemp)
expect(paragraph).toBeInTheDocument()
})
})
You could include the color there in the test, or not...up to you.
Since you can test all 3 units
(temp/color/weatherApp) that make up the parent component separately, you can be relatively confident that the parent component will work. You also have an added bonus of not needing to write any asynchronous code in the unit-test.
Upvotes: 1
Reputation: 1448
You can configure jest
to report test coverage information, by adding --coverage=true
option to your test command line :
jest --coverage=true
Test coverage will give you a first hint of what's missing in your tests.
For example, if you forgot to test a conditional rendering based on a ternary operator (which is the case here, you don't test that if this.state.temp
is undefined
, <somegraph />
should be displayed), the coverage report (something like this) will give you the uncovered lines, which is a great indicator to know if you forgot to test some basic logic of your component.
However, test coverage might not be aware of some more subtil logic, like side effects or css styling etc.. Sometimes you'll need to think a bit further for testing more specific logic in your components.
I suggest you start by making sure you don't have uncovered lines by looking at coverage report. Hope it will help !
Upvotes: 1