Reputation: 39018
I'm following along in this Jest test tutorial on Pluralsight here. And I've written code exactly like the author, but for some reason my test is not passing.
My Pull request to the author's repo: https://github.com/danielstern/isomorphic-react/pull/19
I have a simple React component, it updates it's count
state with a async/await call to a service within the componentDidMount
.
{this.state.count != -1 ? `${this.state.count} Notifications Awaiting` : 'Loading...'}
Since I've mocked the NotificationsService, and set count to 42
, the test should pass with text inside the component being "42 Notifications Awaiting!"
The text stays stuck as the default Loading...
I've mocked the service correctly, and the count
variable is even being logged correctly as 42
! However this.state.count
is still -1
so instead of displaying: ${this.state.count} Notifications Awaiting
it still displays Loading...
and thus fails the test.
1) I've tried adding 1000 into the delay.
2) Tried using setTimeout inside the test.
3) Tried jest.useFakeTimers();
and jest.runAllTimers();
However nothing is working, the count
inside of the component is stuck at -1
even though count
is set to 42. It just seems to me that my test is running before the state is finished being set?
import React from 'react';
import NotificationsService from '../services/NotificationsService';
export default class componentName extends React.Component {
constructor(...args) {
super(...args);
this.state = {
count: -1
}
}
async componentDidMount () {
let { count } = await NotificationsService.GetNotifications();
console.log('count:', count);
this.setState({
count
});
}
componentDidUpdate() {
console.log('componentDidUpdate:', this.state);
}
render() {
return (
<div className="mt-3 mb-2">
<div className="notifications">
{this.state.count != -1 ? `${this.state.count} Notifications Awaiting` : `Loading...`}
</div>
</div>
)
}
}
import { delay } from 'redux-saga';
export default {
async GetNotifications() {
console.warn("REAL NOTIFICATION SERVICE! CONTACTING APIS!");
await delay(1000);
return { count: 42 };
}
}
let count = 0;
export default {
__setCount(_count) {
count = _count;
},
async GetNotifications() {
console.warn("GOOD JOB! USING MOCK SERVICE");
return { count };
}
}
Finally...
import React from 'react';
import renderer from 'react-test-renderer';
import delay from 'redux-saga';
import NotificationsViewer from '../NotificationsViewer';
jest.mock('../../services/NotificationsService');
const notificationService = require('../../services/NotificationsService').default;
describe('The notification viewer', () => {
beforeAll(() => {
notificationService.__setCount(42);
});
it('should display the correct number of notifications', async() => {
const tree = renderer
.create(
<NotificationsViewer/>
);
await delay();
const instance = tree.root;
const component = instance.findByProps({className: `notifications`});
const text = component.children[0];
console.log('text is:', text);
expect(text).toEqual('42 Notifications Awaiting!');
});
})
Upvotes: 3
Views: 969
Reputation: 39018
The problem was that await delay()
did not work to let all the React life cycle methods like componentDidMount
instantiate / get called.
I had to result to using Enzyme
even though the author did not recommend it due to a lot of open bug issues.
Using Enzyme I could ensure that the componentDidMount
was called, and thus setting the state of count
to 42
with the mocked service.
I also needed to installed the following packages:
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
import React from 'react';
import renderer from 'react-test-renderer';
import Adapter from 'enzyme-adapter-react-16';
import { shallow, configure } from 'enzyme';
configure({adapter: new Adapter()});
import NotificationsViewer from './NotificationsViewer';
jest.mock('../services/NotificationsService');
const notificationService = require('../services/NotificationsService').default;
notificationService.default = jest.fn();
describe('The notification viewer', () => {
beforeAll(() => {
notificationService.__setCount(42);
});
// it('pass', () => {});
it('should display the correct number of notifications', async() => {
const tree = renderer.create(<NotificationsViewer />);
const wrapper = shallow(<NotificationsViewer />);
const instance = tree.root;
await wrapper.instance().componentDidMount();
const component = instance.findByProps({className: `notifications`});
const text = component.children[0];
console.log('text is:', text);
expect(text).toEqual('42 Notifications Awaiting');
});
})
Upvotes: 1
Reputation: 26
In fact, the real problem was in isomorphic-react/src/components/__tests__/NotificationsViewer.js
file. The delay
are imported the wrong way and that was causing the error on test.
If importing delay
like this: import { delay } from 'redux-saga'
fix the problem. =D
Upvotes: 1
Reputation: 470
Maybe your describe
also needs to be an async function? await
statements need to be declared inside an async
scope, no?
Upvotes: 0