Reputation: 17332
I'm trying to do some enzyme/jest unit testing for a asynchronous function in my reactJS component, which gets injected as prop.
My Problem is to test for a value in the then()
part of the function and to test for catch()
if an error occures.
This is how the function of my component (<CreateAccount />
) looks like:
_onSubmit = (event) => {
event.preventDefault()
const { username, password } = this.state
this.props.createUserMutation({
variables: { username, password }
}).then(response => {
const token = response.data.createUser.token
if (token) {
Cookies.set('auth-token', token, { expires: 1 })
}
}).catch(error => {
console.warn(error)
})
}
The first test should check for .catch(error => {})
as data is undefined:
it('_onSubmit() should throw error if data is missing', () => {
const createUserMutation = () => {
return Promise.resolve({})
}
const wrapper = shallow(<CreateAccount createUserMutation={createUserMutation} />)
wrapper.update().find(Form).simulate('submit', {
preventDefault: () => {}
})
const state = wrapper.instance().state
expect(wrapper).toThrow() // <-- How to do it correctly?
})
And the second test should check if cookie is set correctly. Here I don't know how to do that? I think I have to mock Cookie
it('_onSubmit() should get token', () => {
const createUserMutation = () => {
return Promise.resolve({
data: {
createUser: { token: 'token' }
}
})
}
const wrapper = shallow(<CreateAccount createUserMutation={createUserMutation} />)
wrapper.find(Form).simulate('submit', {
preventDefault: () => {}
})
// How to check for token value and Cookies?
})
Upvotes: 1
Views: 6500
Reputation: 9978
What I usually have to do when I want to see if the spy worked on the catch or then, is to add another then() on the test. For example:
it('_onSubmit() should throw error if data is missing', () => {
const createUserMutation = jest.fn(() => Promise.reject(new Error()));
const spy = jest.spyOn(console,"warn");
const wrapper = shallow(<CreateAccount createUserMutation={createUserMutation} />)
wrapper.update().find(Form).simulate('submit', {
preventDefault: () => {}
});
return createUserMutation.catch(() => {
expect(wrapper).toMatchSnapshot();
})
.then(() => {
expect(spy).toHaveBeenCalledTimes(1);
});
})
I guess it is somehow related to how NodeJS handles the queues, promises, ticks, etc, internally.
That is the rejected/catch branch. If you want to test the IF path, just use a Promise.resolve and return a promise.then() instead of catch.
Upvotes: 1
Reputation: 7656
Why are you using console.warn
for an error? Use console.error
instead. You will need to mock it out to a spy as well to test it.
First test:
it('_onSubmit() should throw error if data is missing', (done) => {
const createUserMutation = () => new Promise();
const wrapper = shallow(<CreateAccount createUserMutation={createUserMutation} />)
wrapper.update().find(Form).simulate('submit', {
preventDefault: () => {}
})
const state = wrapper.instance().state
createUserMutation.resolve().then(() => {
expect(console.warn).toHaveBeenCalled();
done();
});
})
If you are running this in a mock browser environment and not a real browser then you must mock out Cookies.set
.
Second test:
it('_onSubmit() should get token', (done) => {
const createUserMutation = () => new Promise();
const wrapper = shallow(<CreateAccount createUserMutation={createUserMutation} />)
wrapper.find(Form).simulate('submit', {
preventDefault: () => {}
});
jest.spyOn(window.Cookies, 'set');
const response = {
data: {
createUser: { token: 'token' }
}
}
createUserMutation.resolve(response).then(() => {
expect(window.Cookies.set).toHaveBeenCalled();
done();
});
})
afterEach(() => {
// Reset the spies so that they don't leak to other tests
jest.restoreAllMocks();
});
Upvotes: 0