//Component
import _ from 'lodash';
constructor(props) {
super(props);
this.onScroll = _.debounce(::this.onScroll, 100);
}
onScroll() {
//some code
}
//Test
it('onScroll', () => {
const component = shallow(<Component />);
component.instance().onScroll(); //Dosn't call method
})
I use enzyme for render component, and lodash for debounce
. How to call component.instance().onScroll()
?
TL;DR; use lolex
to advance in time while mocking timers for testing _.debounce
I was ready to describe several ways to mock timers with jest by useFakeTimers
and advanceTimersByTime
. But it did not work.
After some time I've found it works with _.throttle
but not _.debounce
.
And then I've found issue reported in Jest's repo. Also there is dedicated bug report "_.debounce breaks fake timers" and I don't see it's resolved(ignore its status and check last comments there).
According to veeeeery detailed explanation _.debounce
not just put setTimeout
but also checks time difference. So we should mock also Date.now
that Jest's jest.runOnlyPendingTimers
or jest.advanceTimersByTime
don't do.
So for simple component like
function Debounced({onClick}) {
return <button onClick={_debounce(onClick,500)}>Click Me</button>;
}
next test has passed:
let clock = lolex.install();
const onClick = jest.fn();
const wrapper = shallow(<Debounced onClick={onClick} />);
const button = wrapper.find('button').at(0);
button.simulate('click');
button.simulate('click');
button.simulate('click');
clock.tick(510);
expect(onClick).toHaveBeenCalledTimes(1);
clock.uninstall();
PS for sure you could run lolex.install()
and clock.uninstall()
in beforeEach
/afterEach
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With