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...'}
EXPECTED
Since I've mocked the NotificationsService, and set count to 42, the test should pass with text inside the component being "42 Notifications Awaiting!"
RESULTS
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.
What I've tried
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?
The NotificationsViewser.jsx Component
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>
)
}
}
NotificationsService.js
import { delay } from 'redux-saga';
export default {
async GetNotifications() {
console.warn("REAL NOTIFICATION SERVICE! CONTACTING APIS!");
await delay(1000);
return { count: 42 };
}
}
mocks: NotificationsService.js
let count = 0;
export default {
__setCount(_count) {
count = _count;
},
async GetNotifications() {
console.warn("GOOD JOB! USING MOCK SERVICE");
return { count };
}
}
Finally...
The Test
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!');
});
})


await delay()is not letting the life cycle methods run first before theexpectblock is tested. Because the results ofconsole.log('text is:', text);are hit first, then thecomponentDidMountandcomponentDidUpdatelogs are hit.