Search code examples
reactjsjestjsnotistack

Mocking snackbar using jest


I try to test the following code

import { useSnackbar, VariantType, WithSnackbarProps } from 'notistack';
import React from 'react';

interface IProps {
  setUseSnackbarRef: (showSnackbar: WithSnackbarProps) => void;
}

const InnerSnackbarUtilsConfigurator: React.FC<IProps> = (props: IProps) => {
  props.setUseSnackbarRef(useSnackbar());
  return null;
};

let useSnackbarRef: WithSnackbarProps;
const setUseSnackbarRef = (useSnackbarRefProp: WithSnackbarProps) => {
  useSnackbarRef = useSnackbarRefProp;
};

export const SnackbarUtilsConfigurator = () =>
  <InnerSnackbarUtilsConfigurator setUseSnackbarRef={setUseSnackbarRef} />;

export default {
  success(msg: string) {
    this.toast(msg, 'success');
  },
  warning(msg: string) {
    this.toast(msg, 'warning');
  },
  info(msg: string) {
    this.toast(msg, 'info');
  },
  error(msg: string) {
    this.toast(msg, 'error');
  },
  toast(msg: string, variant: VariantType = 'default') {
    useSnackbarRef.enqueueSnackbar(msg, { variant });
  },
};

if I mock the complete notistack object

import React from "react";
import {render as testingRender} from '@testing-library/react';
import { SnackbarProvider} from 'notistack';
import SnackbarUtils,{SnackbarUtilsConfigurator} from './SnackbarUtils';

jest.mock('notistack');

beforeEach(() =>{

});

it('DownloadDialog renders correctly - open=true', async () => {
    const component = await  testingRender(<SnackbarProvider maxSnack={3}><SnackbarUtilsConfigurator /></SnackbarProvider>);
    SnackbarUtils.success("success");
});

I get an error message:

TypeError: Cannot read property 'enqueueSnackbar' of undefined

  33 |   },
  34 |   toast(msg: string, variant: VariantType = 'default') {
> 35 |     useSnackbarRef.enqueueSnackbar(msg, { variant });
     |                    ^
  36 |   },
  37 | };

because useSnackbarRef.

How can i mock only the useSnackbar method of notitstack, so that i can check if enqueueSnackbar is called with the correct values?


Solution

  • This works for me. Place this outside all tests (top level scope):

    const mockEnqueue = jest.fn();
    
    jest.mock('notistack', () => ({
      ...jest.requireActual('notistack'),
      useSnackbar: () => {
        return {
          enqueueSnackbar: mockEnqueue
        };
      }
    }));