I am testing my React app with Jest and Enzyme. For mocking an API call I use Mock Service Worker. My problem is, that I get an error with my current test code, saying "TypeError: Cannot read properties of undefined (reading 'company')".
I will add the code of the connected components below. The structure is the following: I have a "Finder" component which imports and uses a "FinderList" component. This "FinderList" component imports a "FinderCard" component and maps it out.
The API call is in the "Finder" component. I try to test this while mocking the API call with Mock Service Worker.Unfortunately, it gives me an empty array for the "location" prop. I am not sure how to solve this, since I am very new to the topic.
Is it even correct that I am mounting the "Finder" component? Or should I mount "FinderList" instead?
finder.jsx component:
import React, { Component } from 'react';
import FinderList from './finder-list.component';
import { SearchBar } from './search-bar.component';
class Finder extends Component {
constructor() {
super();
this.state = {
location: [],
searchField: ''
};
}
componentDidMount() {
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => response.json())
.then(location => this.setState({ location: location}));
}
render() {
const { location, searchField } = this.state;
const filteredLocation = location.filter(location => location.company.name.toLowerCase().includes(searchField.toLowerCase()))
return (
<div key="component-wrapper">
<SearchBar
placeholder='Search Locations'
handleChange= {e => this.setState({ searchField: e.target.value})}
/>
<FinderList className="finder-list" location={filteredLocation} key="finder-list" data-test="finder-list">
</FinderList>
</div>
);
}
}
export default Finder;
finder-list.jsx component:
import React from 'react';
import FinderCard from './finder-card.component';
const FinderList = props => {
return <div className='finder-list' key="finder-list">
{
props.location.map(locationentry =>
<FinderCard key={locationentry.id} locationentry={locationentry}/>)
}
</div>;
};
export default FinderList;
finder-card.jsx component:
import React from 'react';
import finderimg from './finderimg.png'
const FinderCard = props => (
<div className='finder-card-container' data-test="finder-card-container" key="finder-card-container">
<h4 className="locationtitle" data-test="locationtitle" key="locationtitle">{props.locationentry.company.name}</h4>
<div className="background" key="background"></div>
<img className="finderimg" alt="finderimage" src={finderimg} data-test="finderimg" key="finderimg"></img>
<div className="finderinfo" key="finderinfo">
<p className="address" data-test="address" key="address">{ props.locationentry.address.street } { props.locationentry.address.suite }</p>
<p className="tag" data-test="tag" key="tag">Media</p>
</div>
</div>
);
export default FinderCard;
finder-test.js:
import { mount } from 'enzyme';
import React from 'react';
import Finder from './finder.component';
import { findByTestAttr } from '../../../utils/index';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
const locationResponse = rest.get("https://jsonplaceholder.typicode.com/users",
(req, res, ctx) => {
return res(ctx.json([{
location: {
company: {name: "Name"},
address: {street: "Street", suite: "12"}
}
}]))
});
const handlers = [locationResponse];
const server = new setupServer(...handlers);
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
describe('Finder Component', () => {
describe('Should render correctly', () => {
it("Should have the correct location name", async () => {
const wrapper = mount(<Finder/>);
const locationItem = await findByTestAttr(wrapper, 'finder-list');
expect(locationItem.props.location.company.name).toEqual("Name");
})
});
})