Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are these Jest tests failing? TypeError: Cannot read property 'apply' of undefined

I have 2 components/tests Login.js and Routes.js both have the same error:

TypeError: Cannot read property 'apply' of undefined enter image description here

Not sure what is trying to be applied here...


The components

Login.js

import React from 'react'
import { connect } from "react-redux"
import { bindActionCreators } from 'redux'; 
import { setCurrentUser } from '../../actions/authActions'
import * as api from '../../services/api'
import Notification from '../common/Notification'

const mapDispatchToProps = (dispatch) => {
    return {
        setUser: (user) => {
            bindActionCreators(setCurrentUser(user), dispatch)
        }
    }
};

export class LoginContainer extends React.Component {
    constructor(props) {
        super(props)

        this.state = {};

        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleSubmit(e) {
        ...
    }

    render() {
        return (
            <div className="app-bg">
                ...
            </div>
        )
    }
}

export default connect(null, mapDispatchToProps)(LoginContainer); 

Routes.js

import React from 'react'
import { Route, Switch } from 'react-router-dom'
import LoginContainer from './auth/Login'
import Dashboard from './Dashboard'
import NoMatch from './NoMatch'

const Routes = () => {
    return (
        <Switch>
            <Route exact={ true } path="/" component={ LoginContainer }/>
            <Route path="/dashboard" component={ Dashboard }/>
            <Route component={ NoMatch } />
        </Switch>
    );
}

export default Routes

The Tests

Login.test

import React from 'react'
import { Provider } from "react-redux"
import ReactTestUtils from 'react-dom/test-utils'
import { createCommonStore } from "../../store";
import { mount, shallow } from 'enzyme'
import toJson from 'enzyme-to-json'
import { missingLogin } from '../../consts/errors'
// import Login from './Login'
import { LoginContainer as Login } from './Login';
import Notification from '../common/Notification'

const store = createCommonStore();

const user = {
    id: 1,
    role: 'Admin',
    username: 'leongaban'
};
const loginComponent = shallow(
    <Provider store={store}>
        <LoginContainer/>
    </Provider>
);
const fakeEvent = { preventDefault: () => '' };

describe('<Login /> component', () => {
    it('should render', () => {
        const tree = toJson(loginComponent);
        expect(tree).toMatchSnapshot();
    });

    it('should contains the words "Forgot Password"', () => {
        expect(loginComponent.contains('Forgot Password')).toBe(true);
    });

    it('should render the Notification component if state.error is true', () => {
        loginComponent.setState({ error: true });
        expect(loginComponent.find(Notification).length).toBe(1);
    });
});

Routes.test

import React from 'react'
import { Provider } from "react-redux"
import { mount, shallow } from 'enzyme'
import { MemoryRouter } from 'react-router'
import { createCommonStore } from "../store";
import toJson from 'enzyme-to-json'

import Routes from './Routes'
import Login from './auth/Login'
import Dashboard from './Dashboard'
import NoMatch from './NoMatch'

const store = createCommonStore();

const routesMount = (path) => {
    return mount(
        <Provider store={store}>
            <MemoryRouter initialEntries={[ path ]} initialIndex={0}>
                <Routes />
            </MemoryRouter>
        </Provider>
    );
};

describe('<Routes /> component', () => {
    it('should save a snapshot', () => {
        const routesComponent = shallow(<Routes />);
        const tree = toJson(routesComponent);
        expect(tree).toMatchSnapshot();
    });

    it('should render Login component when visiting /', () => {
        const routesComponent = routesMount('/');
        expect(routesComponent.find(Login).length).toBe(1);
    });

    it('should render Dashboard component when visiting /dashboard', () => {
        const routesComponent = routesMount('/dashboard');
        expect(routesComponent.find(Dashboard).length).toBe(1);
    });

    it('should render the NoMatch component when visiting invalid path', () => {
        const routesComponent = routesMount('/404');
        expect(routesComponent.find(NoMatch).length).toBe(1);
    });
});

The Store

store.js

The Redux Chrome plugin window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()

import React from "react"
import { applyMiddleware, combineReducers, compose, createStore} from "redux"
import thunk from "redux-thunk"
import { userReducer } from "./reducers/UserReducer"
import { authReducer } from "./reducers/AuthReducer"

export const createCommonStore = (trackStore=false) => {
    const reducers = combineReducers({
        user: userReducer,
        user: authReducer
    });

    //noinspection JSUnresolvedVariable
    const store = createStore(reducers,
        compose(
            applyMiddleware(thunk),
            window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
        )
    );

    if (trackStore) {
        store.subscribe((() => {
            console.log("  store changed", store.getState());
        }));
    }

    return store;
};
like image 948
Leon Gaban Avatar asked Jun 13 '17 14:06

Leon Gaban


People also ask

Can I use jest without enzyme?

Jest can be used without Enzyme, and snapshots can be created and tested perfectly fine. But the Enzyme adds additional functionality to it. An enzyme can also be used without Jest, but we need any other test runner paired with it. Jest:- Jest as a test runner, assertion library, and mocking library.

What are the limitations of jest?

Limitations of Jest TestingIt has less tooling and library support available compared to more mature libraries (like Mocha). This can be a big drawback for developers who want to run and debug their tests in an IDE like WebStorm. Using auto-mocking features can slow down your test suite.

How do you mock a function?

There are two ways to mock functions: Either by creating a mock function to use in test code, or writing a manual mock to override a module dependency.

Do you need jest and Cypress?

short answers: It's very common to use Jest and Cypress in the same codebase. With component Libraries like Vue and React, the line between integration and unit tests can get a bit fuzzy.


1 Answers

In store.js, the expression window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() evaluates to undefined. This causes the error in compose. The plugin documentation has the solution for that:

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducers,
    composeEnhancers(
        applyMiddleware(thunk),
    )
);
like image 88
Tiddo Avatar answered Oct 21 '22 09:10

Tiddo