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:
waitForwithtimeoutproperty- Wrapped ContextProvider in
renderfunction
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'.