'React testing with Jest and Enzyme: How to write test for connected components with API call and props
I am fairly new to testing React applications with Jest and Enzyme. I am trying to test some connected components, but don't understand how to mock data for those. I have an API call and use props. Here are my files:
News Page
import React, { Component } from 'react';
import './news.style.css';
import NewsList from '../../components/news-list/news-list.component';
import { SearchBar } from '../../components/search-bar/search-bar.component';
import Header from '../../components/header/header.component';
import { NewsFooter } from '../../components/news-footer/news-footer.component';
class News extends Component {
constructor() {
super();
this.state = {
news: [],
searchField: '',
topics: ''
};
}
componentDidMount() {
fetch('https://sheltered-earth-94987.herokuapp.com/news')
.then(response => response.json())
.then(news => this.setState({ news: news}));
}
render() {
const { news, searchField, topics } = this.state;
const filteredNewsname = news
.filter(news => news.news_topic.toLowerCase().includes(topics.toLowerCase()))
.filter(news => news.news_headline.toLowerCase().includes(searchField.toLowerCase()));
return (
<div>
<Header/>
<h1 className="pageheadline">News</h1>
<SearchBar
placeholder='Search News'
handleChange= {e => this.setState({ searchField: e.target.value})}
/>
<div className="newslist">
<NewsList news={filteredNewsname}>
</NewsList>
</div>
<div className="newsfooter">
<NewsFooter
handleClick= {e => this.setState({ topics: e.target.id})}
/>
</div>
</div>
);
}
}
export default News;
NewsList Component
import React from 'react';
import './news-list.style.css';
import { NewsCard } from '../news-card/news-card.component';
import { Link } from 'react-router-dom';
const NewsList = props => {
return <div className='news-list'>
{
props.news.map(newsentry => <Link to={`/news/${newsentry.news_id}`}>
<NewsCard key={newsentry.news_id} newsentry={newsentry}/></Link>)
}
</div>;
};
export default NewsList;
NewsCard Component
import React from 'react';
import './news-card.style.css';
const NewsCard = props => (
<div className='news-card-container' data-test="news-card-container">
<img className="newsimg" alt="Newsimage" src={ props.newsentry.news_header_image}></img>
<div className="newsinfo">
<h4 className="newstitle"> { props.newsentry.news_headline } </h4>
<p className="teaser">{props.newsentry.news_teaser}</p>
<p className="author">By {props.newsentry.news_author} </p>
</div>
<p className="newstopic">#{props.newsentry.news_topic}</p>
</div>
)
export default NewsCard;
How can I test the NewsList and the NewsCard Components with mocked data?
This is how I started:
Testfile
import { shallow } from 'enzyme';
import React from 'react';
import NewsCard from './news-card.component';
import { findByTestAttr } from '../../../utils/index';
const setUp = (props={}) => {
const component = shallow(<NewsCard {... props}/>);
return component;
}
describe('NewsCard Component', () => {
describe('Have props', () => {
let wrapper;
beforeEach(() => {
const props = {
news: [],
};
wrapper = setUp(props);
});
it('Should render without errors', async () => {
const component = findByTestAttr(wrapper, 'news-card-container');
expect(component.length).toBe(1);
})
});
})
File with findByTestAttr function
export const findByTestAttr = (component, attr) => {
const wrapper = component.find(`[data-test='${attr}']`);
return wrapper;
}
For this right now I get an error, saying:
TypeError: Cannot read properties of undefined (reading 'news_header_image')
Solution 1:[1]
Before rendering components in test block; you can provide a new, mockup variable to your component.
Example:
<NewsCard key={..} newsentry={mockupNewsentry}/> with mockupNewsentry being your mockup data variable.
Longer example:
test("renders singleitem with data", async () => {
const mockupData = {
name: "Homer Simpson",
job: "Nuclear Safety Inspector",
id: "14",
};
render(
<SingleItem data={mockupData} />
);
const element = await screen.findByText(/Homer Simpson/i);
expect(element).toBeInTheDocument();
});
Solution 2:[2]
Check out this package. It will mock the network layer. Everyone is using this one for integration testing of components.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Emre A |
| Solution 2 | Alexander Krum |
