Reputation: 9905
I'm trying to implement snapshots
with jest
and i ran into a problem. The solution is probably simple, but i can't find it.
LoginForm.js
class LoginForm extends React.Component {
constructor(props) {
super(props)
}
}
componentWillMount(){
this.props.startSpinner()
}
render(){
return(....)
}
}
LoginForm.spec.js
it('should render snapshot', () => {
const component = renderer.create(
<LoginForm />
)
const tree = component.toJSON()
expect(tree).toMatchSnapshot()
})
startSpinner action
export function startSpinner() {
return (dispatch) => {
dispatch({
type: 'WINDOW_START_SPINNER',
})
}
}
When i run tests, it throws this error, not only with this action, but with all functions called as a redux
action.
TypeError: this.props.startSpinner is not a function
How can i make jest
play nice with this redux
actions?
Upvotes: 3
Views: 493
Reputation: 1247
I believe that you are not applying the test properly. You must test actions, reducers, and components separately,
The test is failing because the LoginForm component is trying to use the connect function without been wrapped by a provider and so it's trying to access to an unexistign store.
To implement snapsots in your tests you should first mock a store, there is a nice mock already out there, you can find it here: https://github.com/arnaudbenard/redux-mock-store
Then, you must configure your store, in my projects I do something like this, change it at your will:
// Import your actions and their names (I separate the names in a
// different file to avoid typos.
import * as actions from '../../src/actions';
import * as types from '../../src/actions';
// You must import an Initial state or create one, I usually import
// the one I have in the reducer.
import { INITIAL_STATE } from '../../src/reducers/AuthReducer'
// Import your middleware and redux mock store
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import MockAdapter from 'axios-mock-adapter';
// --- Mocking config --> Crete your store
const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);
let store = mockStore(INITIAL_STATE);
// Clear actions before each time
beforeEach(() => {
store.clearActions();
});
And now just test your action:
describe('[ ScannerActions ]', () => {
describe('*** toggleCamera()', () => {
it('Should dispatch TOGGLE_CAMERA action', () => {
store.dispatch(actions.toggleCamera());
expect(store.getActions()).toMatchSnapshot();
})
});
});
Upvotes: 1
Reputation: 303
You forgot to pass startSpinner
as a props in your unit test. If you only need to test the render function you should pass something like a noop
function (lodash provide one).
it('should render snapshot', () => {
const component = renderer.create(
<LoginForm startSpinner={_.noop} />
)
const tree = component.toJSON()
expect(tree).toMatchSnapshot()
})
For redux actions i would test them separately (jest snapshots are great for them too).
Upvotes: 2
Reputation: 347
I would test the redux functionality seperately, and pass in startSpinner as a mock function instead.
e.g:
const mockFn = jest.fn()
const component = renderer.create(
<LoginForm startSpinner={mockFn} />
)
expect(mockFn.toHaveBeenCalled()).toBe(true)
Upvotes: 2