I have been working on a React app with a new team and the discussion came up around writing unit tests for components that trigger methods on window.scroll events.
So, let's take this component as an example.
import React, { Component } from 'react';
class MyComponent extends Component {
componentDidMount() {
window.addEventListener('scroll', this.props.myScrollMethod);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.props.myScrollMethod);
}
render() {
return (
<div>
<h1>Hello MyComponent!</h1>
</div>
)
};
};
export default MyComponent;
As you can see, I am taking a method which is passed into the component via a prop and binding it to the window event listener, where the event is scroll. In the real world this component would call myScrollMethod as the user is scrolling down a page (let's assume the use case here is to show a sticky navigation bar when the user has scrolled beyond a certain point on the page).
The problem is...I need to find a suitable way of testing this. My end goal is to create a spy method which is passed into the component via the myScrollMethod prop, then trigger a scroll (or mock a scroll in the test) and finally assert whether the scroll handler method has fired or not. Here is my attempt at this:
import React from 'react';
import sinon from 'sinon';
import expect, { createSpy } from 'expect';
import { shallow } from 'enzyme';
import MyComponent from './MyComponent';
describe('The <MyComponent /> component', () => {
let onScroll;
let MyTestComponent;
beforeEach(() => {
onScroll = createSpy();
MyTestComponent = shallow(
<MyComponent
myScrollMethod={onScroll}
/>
);
});
it('Should call the onScroll method when a user scrolls', () => {
expect(onScroll).toNotHaveBeenCalled();
window.dispatchEvent(new window.UIEvent('scroll', { detail: 0 }));
expect(onScroll).toHaveBeenCalled();
});
});
The issue that I am having is that the final assertion is failing because the spy is never called. I've referred to a number of other posts on this site but so far have not found a suitable solution. Any suggestions would be greatly appreciated as it's been racking my brain for a while now!
Thanks very much!