0
votes

My component is as below

import React from 'react';
import { connect } from 'react-redux';
import { Button } from 'react-bootstrap';

import UserActions from '../../../actions/sampleUserAction';
import UserForm from '../../../views/sample/userForm';
import UsersList from '../../../views/sample/usersList';

@connect(store => ({
    users: store.sampleUserReducer.users,
}))

export default class UserComponent extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            displayForm: false,
            user: { id: '', fName: '', lName: '' },
            isCreationMode: true,
        };

        this.addNewUser = this.addNewUser.bind(this);
        this.handleChange = this.handleChange.bind(this);
        this.submitForm = this.submitForm.bind(this);
        this.editUser = this.editUser.bind(this);
        this.deleteUser = this.deleteUser.bind(this);
    }

    addNewUser() {
        this.setState({
            displayForm: !this.state.displayForm,
            isCreationMode: true,
            user: { id: '', fName: '', lName: '' },
        });
    }

    createUser(users) {
        users.push({
            id: users.length + 1,
            fName: this.state.user.fName,
            lName: this.state.user.lName,
        });
        return users;
    }

    updateUser(users) {
        users.forEach((user) => {
            if (user.id === this.state.user.id) {
                user.fName = this.state.user.fName;
                user.lName = this.state.user.lName;
            }
        });
        return users;
    }

    submitForm(e) {
        e.preventDefault();
        let { users } = this.props;

        if (this.state.isCreationMode) {
            users = this.createUser(users);
        } else if (!this.state.isCreationMode) {
            users = this.updateUser(users);
        }
        this.addNewUser();
        this.props.dispatch(UserActions.listUsers(users));
    }

    handleChange(e) {
        const { id } = this.state.user;
        let { fName, lName } = this.state.user;
        if (e.target.name === 'fName') {
            fName = e.target.value;
        }

        if (e.target.name === 'lName') {
            lName = e.target.value;
        }

        this.setState({ user: { id, fName, lName } });
    }

    editUser(e, id) {
        const { users } = this.props;
        let user = users.filter(obj => obj.id === id);
        user = user.length > 0 ? user[0] : null;
        if (user != null) {
            this.setState({
                displayForm: true,
                isCreationMode: false,
                user: { id: user.id, fName: user.fName, lName: user.lName },
            });
        }
    }

    deleteUser(e, id) {
        let { users } = this.props;
        users = users.filter(user => user.id !== id);
        this.props.dispatch(UserActions.listUsers(users));
    }

    render() {
        console.log(this.state.displayForm);
        return (
            <div className="container-fluid">
                <div className="well">
                    Sample Users App With Redux
                </div>
                <UserForm
                  displayForm={this.state.displayForm}
                  isCreationMode={this.state.isCreationMode}
                  submitForm={this.submitForm}
                  handleChange={this.handleChange}
                  user={this.state.user}
                  addNewUser={this.addNewUser}
                />
                <UsersList
                  users={this.props.users}
                  editUser={this.editUser}
                  deleteUser={this.deleteUser}
                />
                <div className="clearfix">
                    <Button bsStyle="primary" onClick={this.addNewUser}>Add User</Button>
                </div>
            </div>
        );
    }
}

and test file is as below

import React from 'react';
import { createMockStore } from 'redux-test-utils';
import { shallowWithStore } from 'enzyme-redux';
import { Button } from 'react-bootstrap';

import UserComponent from '../../../../src/components/containers/sample/userComponent';
import UserForm from '../../../../src/views/sample/userForm';
import UsersList from '../../../../src/views/sample/usersList';


describe('UsersComponent', () => {
    let store;
    let container;
    const props = {
        submitForm: jest.fn(),
        addNewUser: jest.fn(),
    };

    beforeEach(() => {
        const defaultState = { sampleUserReducer: { users: [] } };
        store = createMockStore(defaultState);
        container = shallowWithStore(<UserComponent />, store);
    });

    it('should work', () => {
        expect(true).toEqual(true);
    });

    it('container should have UserForm component', () => {
        expect(container.dive().find(UserForm)).toHaveLength(1);
    });

    it('container should have UsersList component', () => {
        expect(container.dive().find(UsersList)).toHaveLength(1);
    });

    it('should have add new user button', () => {
        expect(container.dive().find(Button)).toHaveLength(1);
        expect(container.dive().find(Button).dive().text()).toEqual('Add User');
    });

    it('On click add user button', () => {
        container.dive().find(Button).simulate('click');
        expect(props.addNewUser).toHaveBeenCalled();
    });
});

I'm using jest, enzyme, enzyme-redux. I'm new to react unit testing. Last test case is giving error as below. React version is 16.x. In last test case I'm trying to call mocked jest function on button click. For button using react-bootstrap inbuilt Button component

expect(jest.fn()).toHaveBeenCalled() Expected mock function to have been called.

3

3 Answers

0
votes

You are likely to need to add container.update(); which forces a re-render after external inputs like clicking.

http://airbnb.io/enzyme/docs/api/ShallowWrapper/update.html

0
votes

Sometimes container.update() does not work and in such cases, try container.instance().forceUpdate() in your tests after the click which updates the component after the state changes.

0
votes

Another option would be to use jest's spy to assert that addNewUser was called.

const spy = jest.spyOn(container.instance(), 'addNewUser');
container.dive().find(Button).simulate('click');
expect(spy).toBeCalled();