Mocking snackbar using jest
Asked Answered
I

2

9

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?

Irregular answered 22/7, 2020 at 16:14 Comment(0)
F
15

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
    };
  }
}));
Freestyle answered 13/11, 2020 at 13:53 Comment(0)
M
0

I use vite and do not use the hooks, instead using the handlers directly. To fix my issue, I called this in my setup.ts:

beforeAll(() => {
  vi.mock("notistack", () => ({
    enqueueSnackbar: vi.fn(),
    closeSnackbar: vi.fn(),
  }));
});
Mckim answered 26/4 at 22:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.