I'm having a really hard time learning how to use jest. All the tutorials i come across either teach you how to test a script that renders to dom such as <App />
with or without snapshots. Other tutorials goes over how to mock tests with inputs. but I cant seem to find tutorials that explains clearly and give examples that i can use.
For example the script from below i have an idea on how to test the render portion, but i don't know how to test the redux or the rest of the functions.
Could anyone give an example of how to test the below script that i can use as a reference for the rest of the files i need to test in my project?
import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import CustomSearch from '../Components/CustomSearch';
import CustomToolBar from '../Components/CustomToolBar';
import Table from '../Components/Table';
import InsertButton from '../Components/InsertButton';
import UserForm from './UserForm ';
import { fetchUsers, deleteUser } from '../../actions/users';
import setModal from '../../actions/modal';
import TableColumns from '../../constants/data/TableColumns';
class Users extends Component {
constructor(props) {
super(props);
this.onInsert = this.onInsert.bind(this);
this.onDelete = this.onDelete.bind(this);
this.onEdit = this.onEdit.bind(this);
this.props.fetchUsers({ accountId: this.props.userData.account.id, token: props.userData.token });
}
onDelete(row) {
if (confirm(`Are you sure you want to delete user ${row.first} ${row.last}?`)) {
this.props.deleteUser({
registered: row.registered,
id: row.id,
accountId: this.props.userData.account.id,
token: this.props.userData.token
});
}
}
onEdit(row) {
console.log(row);
const modal = () => (<UserForm data={row} isEdit />);
this.props.setCurrentModal(modal, 'Existing User Form');
}
onInsert() {
const modal = () => (<UserForm />);
this.props.setCurrentModal(modal, 'Add New User');
}
render() {
const options = {
searchField: (props) => (<CustomSearch {...props} />),
insertBtn: () => (<InsertButton onClick={this.onInsert} />),
toolBar: (props) => (<CustomToolBar {...props} />),
onDelete: this.onDelete,
onEdit: this.onEdit,
};
return (
<Table data={this.props.users} columns={TableColumns.USERS} options={options} title="Users" />
);
}
}
User.propTypes = {
setCurrentModal: PropTypes.func.isRequired,
fetchUsers: PropTypes.func.isRequired,
deleteUser: PropTypes.func.isRequired,
userData: PropTypes.object.isRequired,
users: PropTypes.array,
};
const mapStateToProps = (state) => ({
userData: state.userData.data,
users: state.tableData.users,
});
const mapDispatchToProps = (dispatch) => ({
fetchUsers: (data) => dispatch(fetchUsers(data)),
deleteUser: (data) => dispatch(deleteUser(data)),
setCurrentModal: (modal, title) => dispatch(setModal(modal, title, null, true)),
});
export default connect(mapStateToProps, mapDispatchToProps)(User);
Some familiarity with Jest as a test runner or framework is helpful but not required. Because Jest is pre-packaged with Create React App, you do not need to install it separately.
Tests in RTL are really slow. Especially if I have some async waitFor statements then it is very common that I have like 3-5 tests for one component and they take about 10 seconds to run. It is completely unacceptable for TDD approach since I need a quick feedback loop.
Alternately pass in an already-created Redux store instance. Pass through additional options to RTL's original render function. Automatically wrap the component being tested with a <Provider store={store}> Return the store instance in case the test needs to dispatch more actions or check state.
You should test raw component because it's clear that redux works so you don't have to test it. If for some reason you want to test mapStateToProps
or mapDispatchToProps
export them as well and test them separately in isolation.
So if you export your raw component like this:
export { Users }; // here you export raw component without connect(...)
export default connect(mapStateToProps, mapDispatchToProps)(Users);
Then you can test it as a standard react component by importing named export, like
import { Users } from './Users';
describe('Users', () => ....
it('should render', () => ...
If you would like to test connected
component because you don't want shallow
rendering and maybe you render a lot of nested connected components, you need to wrap your component with <Provider>
and create a store for it.
You can help yourself by using redux-mock-store that will apply middlewares for you.
Everything is very well explained in official redux documentation in Recipes > Writing tests, so my proposal is to read the whole chapter carefully. You can read there also about testing action creators, reducers and even more advanced concepts.
To read more and get better background, I encourage to check these 2 comments below from official redux / react-redux repos.
Direct link to comment: https://github.com/reactjs/react-redux/issues/325#issuecomment-199449298
Direct link to comment: https://github.com/reactjs/redux/issues/1534#issuecomment-280929259
Related question on StackOverflow:
How to Unit Test React-Redux Connected Components?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With