React Context everything is working fine but my tests are failing using react-testing-library

Viewed 145

I am using context that updates my snackbar content from a single place. So whenever I want to display snackbar in some other component as a consumer, I update its value. Everything is functionally working but my tests are failing.

I am using mui snackbar.

For the reference: I am using react testing library coupled with jest.

Note: What I have done already:

  • waitFor with timeout property
  • Wrapped ContextProvider in render function

This is my code:

HOME.JS

import React from 'react';
import {Suspense} from 'react';
import {useState} from 'react';

import {Route} from 'react-router-dom';
import {Switch} from 'react-router-dom';
import {useLocation} from 'react-router-dom';

import withStyles from '@mui/styles/withStyles';

import BillingDetails from 'views/BillingDetails/BillingDetails';
import ErrorBoundary from 'containers/ErrorBoundary/ErrorBoundary';
import PageNotFound from 'views/PageNotFound/PageNotFound';
import SideBar from 'components/SideBar/SideBar';
import Snackbar from 'components/CustomSnackbar/CustomSnackbar';
import Unauthorized from 'views/Unauthorized/Unauthorized';

import {subRoutesConfig} from 'constants/routeConfig';

import {styles} from './styles';

import {BILLING_OVERDUE} from 'views/BillingDetails/constants';

import SidebarJobsContext from 'context/sidebarJobsContext';
import SnackbarContext from 'context/snackbarContext';


import {PropTypes} from 'prop-types';


const useStyles = (theme) => ({
  ...styles(theme),
});

const Home = (props) => {
  let location = useLocation();

  const [sidebarJobs, setSidebarJobs] = useState([]);
  const [updateJobs, setUpdateJobs] = useState(false);
  const [snackbar, setSnackbar] = useState({});

  const sidebarJobsContextValue = {sidebarJobs, setSidebarJobs, updateJobs, setUpdateJobs};
  const snackbarContextValue = {snackbar, setSnackbar};



  const handleSnackbarClose = (reason, onClose) => {
    if (reason == 'clickaway') {
      return;
    }
    onClose && onClose();
    setSnackbar({...snackbar, open: false});
  };

  const showSnackbar = () => {
    const {
      autoHideDuration,
      text,
      severity,
      onExternalLink,
      open=false,
      onClose,
      handleUndo,
    } = snackbar;
    return <Snackbar
      autoHideDuration={autoHideDuration}
      handleClose={(event, reason) => handleSnackbarClose(reason, onClose)}
      handleExternalLink={onExternalLink}
      handleUndo={handleUndo}
      open={open}
      severity={severity}
      text={text}
    />;
  };

  const {
    classes,
  } = props;
  const currentURLPath = location.pathname;
  return (
    <>
      <SidebarJobsContext.Provider value={sidebarJobsContextValue}>
        <SnackbarContext.Provider value={snackbarContextValue}>
          <SideBar/>
          <div className={classes.root}>
            <div className={classes.offset}>
              <ErrorBoundary key={currentURLPath}>
                <Suspense fallback={<span></span>}>
                  <Switch>
                    {
                      (redirect || billingInfo.subscription_expiry) && <Route>
                        <BillingDetails/>
                      </Route>
                    }
                    {subRoutesConfig.map((route, i) => {
                      let component = isRouteAllowed(route) ? route.component : Unauthorized;
                      return (
                        <Route
                          component={component}
                          exact={route.exact}
                          key={route}
                          path={route.path}
                        />
                      );
                    })}
                    <Route component={PageNotFound} />
                  </Switch>
                  {showProductTour()}
                  {showSnackbar()}
                </Suspense>
              </ErrorBoundary>
            </div>
          </div>
        </SnackbarContext.Provider>
      </SidebarJobsContext.Provider>
    </>
  );
};

Home.propTypes = {
  classes: PropTypes.object,
};

export default withStyles(useStyles)(Home);

As you can see this is the Home.js component where I have added the provider and showSnackbar() takes care of displaying snackbar.

and then I am using useContext in functional and contextType in class components.

There are many tests that are failing here's an example of one:

import React from 'react';

import {fireEvent} from '@testing-library/react';
import {render} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import {waitFor} from '@testing-library/react';

import {convertIntoRGB} from 'utilities/utils';
import {ThemeWrapper} from 'utilities/testUtilities';

import {error} from 'constants/colors';
import {success} from 'constants/colors';

import CompanySettings from '../CompanySettings';
import SnackbarContext from '../../app/src/context/snackbarContext';


let snackbarContextValue = {
    snackbar: {
      text: '',
      severity: 'success',
      open: false,
      autoHideDuration: 3000,
      handleUndo: () => {},
      onClose: () => {},
    },
    setSnackbar: () => {},
  };

const component = (props) => {
  return (render(<ThemeWrapper
    storeIncluded={true}>
    <SnackbarContext.Provider value={snackbarContextValue}>
        <CompanySettings />
    </SnackbarContext.Provider>
  </ThemeWrapper>));
};

describe('CompanySettings', () => {

  test('should Render success snackbar', async () => {
    const {getByText, getByTestId, container, queryAllByTestId} = component();
    expect(getByText('Company logo')).toBeInTheDocument();
    expect(getByTestId('custom-icon-Package')).toBeVisible();
    expect(queryAllByTestId('custom-skeleton').length).toBe(8);
    await waitFor(()=> {
      expect(queryAllByTestId('custom-skeleton').length).toBe(4);
      let editBtn = getByText(/Edit company profile/i);
      fireEvent.click(editBtn);

      const inputField = container.querySelector(`input[name=companyName]`);
      userEvent.type(inputField, ' 1');
      fireEvent.click(getByTestId('saveBtn'));
    });
    await waitFor(() => {
      expect(getByText('Gomez Inc 1')).toBeInTheDocument();
      expect(container.querySelector(`input[name=companyName]`)).not.toBeInTheDocument();
    });
    await waitFor(() => {
      expect(getByText(`Changes saved to 'company profile'.`)).toBeInTheDocument();
      expect(getComputedStyle(getByTestId('alert')).backgroundColor).toEqual(convertIntoRGB(success));
    });
  });
});

The last waitFor in this test is failing as I have used context to display this snackbar content that says Changes saved to 'company profile'.

0 Answers
Related