I am trying to determine how best to mock Providers when Jest testing with React Context. The most promising lead I've found is RTL, which provides the following example in their docs: https://testing-library.com/docs/example-react-context
I have been experimenting with multiple structures, but even when I follow their example closely I get the above error.
Here I am following their example almost exactly when testing my Dialog component:
Jest Test
import React from 'react';
import { render } from '@testing-library/react';
import { DialogContext, defaultState } from '../../../../store/contexts/dialogContext';
const customRender = (ui, { providerProps, ...renderOptions }) => {
return render(
<DialogContext.Provider {...providerProps}>{ui}</DialogContext.Provider>,
renderOptions
);
};
it('Dialog should work', async () => {
const providerProps = {
dialogType: 'CANCEL',
...defaultState,
};
const { container } = customRender(<Dialog />, { providerProps });
const results = await axe(container);
expect(results).toHaveNoViolations();
});
Dialog Component
import React, { useContext } from 'react';
import { DialogContext } from '../../../store/contexts/dialogContext';
export default function Dialog() {
const [dialogState, dialogDispatch] = useContext(DialogContext);
//logic
return (
<div id='dialog'/>
);
}
This is a simplified version of my Dialog Component, but I receive the following error as soon as it invokes useContext() on line 2.
Error: Uncaught [TypeError: (0 , _react.useContext) is not a function or its return value is not iterable]
As 'React' is in scope in the relevant files, and I'm following the RTL example closely, I'm stumped. Solutions or recommendations for other ways to mock Providers welcome.
EDIT: Adding the dialogContext file for clarity. The component and the context work fine when not in the Jest flow.
import React, { createContext, useReducer } from 'react';
import { dialogReducer } from '../reducers/dialogReducer';
export const DialogContext = createContext({});
const { Provider } = DialogContext;
export const defaultState = {
//state object
}
export const DialogProvider = ({ children }) => {
const [state, reducer] = useReducer(dialogReducer, defaultState);
return <Provider value={[state, reducer]}>{children}</Provider>
}
and when DialogContext is logged from within the Dialog component (the line before), it looks as expected:
{ '$$typeof': Symbol(react.context),
_calculateChangedBits: null,
_currentValue: undefined,
_currentValue2: {},
_threadCount: 0,
Provider: { '$$typeof': Symbol(react.provider), _context: [Circular] },
Consumer:
{ '$$typeof': Symbol(react.context),
_context: [Circular],
_calculateChangedBits: null },
_currentRenderer: {},
_currentRenderer2: null }