A.A
A.A

Reputation: 4081

Mock react hook in jest

How can I mock the following hook in Jest? I use this hook in another hook, When I want to test the other hook, I need to mock useScrollDetect and remove the throttle part, than means I need to immediately call onScroll on scroll events

For educational purpose, I don't want to mock lodash.throttle

use-scroll-detect.ts

import { useCallback, useEffect, useRef } from 'react';
import { throttle } from 'lodash';

/**
 * A hook to listen to the scroll event
 * @param onScroll Scroll listener
 * @param throttleTime Throttling time of the events
 * @param enable Enable or disable the listener
 */
const useScrollDetect = (
  onScroll: (e: Event) => void,
  throttleTime = 100,
  enable = true
) => {
  const handleScrollThrottle = useCallback(
    throttle(onScroll, throttleTime, {
      leading: false,
      trailing: true,
    }),
    [onScroll, throttleTime]
  );
  useEffect(() => {
    if (enable) {
      window.addEventListener('scroll', handleScrollThrottle, {
        passive: true,
      });
    }
    return () => {
      if (enable) {
        window.removeEventListener('scroll', handleScrollThrottle);
      }
    };
  }, [enable, handleScrollThrottle]);
};

export { useScrollDetect };

Upvotes: 1

Views: 2571

Answers (1)

Ruslan
Ruslan

Reputation: 39

You could try to mock it via this approach:

// your test file
import * as hooks from './use-scroll-detect.ts';

// typescript will highlight useScrollDetect from jest.spyOn and hooks object
jest.spyOn(hooks, 'useScrollDetect').mockImplementation((
    onScroll: (e: Event) => void, 
    throttleTime: number, 
    enable: boolean
 ) => {
   const mockEvent = {}; // pass necessary values into the object
   onScroll(mockEvent); // call your mock fn with some info
});

Or you can mock only your throttle function from lodash:

jest.mock('lodash', () => ({
    ...jest.requireActual('lodash'),
    throttle: jest.fn().mockImplementation((onScroll: (e: Event) => void) => {
        onScroll(new Event('scroll'));
    })
}))

fireEvent.scroll(screen.getByText('bla bla')) // put your own function from screen to find element for scrolling

Upvotes: 2

Related Questions