What is the best way to test Window Scroll Event Handlers with Enzyme?
Answer a question
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!
Answers
Unfortunately, I don't think Enzyme is going to be much help here. The library only handles events within React's synthetic event system. So a component you render with Enzyme is not going to work with event listeners added to the window. This issues thread on Enzyme's github gives more details and there are some suggested workarounds that might help you.
For example, you might want to spy on window.addEventListener, then you can check on mount that it was called with the arguments "scroll" and your callback.
Regarding your specific code, the scroll listener is set in componentDidMount but your component is shallow rendered, so componentDidMount isn't actually called (so there is no listener). Try adding this line to your beforeEach: MyTestComponent.instance().componentDidMount()
更多推荐
所有评论(0)