I am using these packages:
"@mui/material": "^7.0.2",
"jest": "^29.4.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"typescript": "^5.8.3",
"@types/react": "^18.0.27",
"@types/react-dom": "^18.0.10",
I am using a React Component 'Alert' from Material UI as shown below.
import Alert from "@mui/material/Alert";
<Alert
key="error"
icon={<ReportIcon />}
onClose={() => setError(false)}
severity="error"
sx={{ alignItems: 'flex-start' }}>
{errorMsgData ?? "Error Saving Configuration"}
</Alert>
this works fine in application, but in unit test it fails with the console log shown below:
Cannot read properties of undefined (reading 'mode')
TypeError: Cannot read properties of undefined (reading 'mode')
at /Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/@mui/material/Alert/Alert.js:57:34
at styleMemoized (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/@mui/system/memoTheme.js:28:46)
at processStyle (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/@mui/system/createStyled/createStyled.js:47:55)
at styleFunctionProcessor (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/@mui/system/createStyled/createStyled.js:158:18)
at handleInterpolation (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/@emotion/serialize/dist/emotion-serialize.cjs.js:119:24)
at Object.serializeStyles (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/@emotion/serialize/dist/emotion-serialize.cjs.js:219:15)
at /Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/@emotion/styled/base/dist/emotion-styled-base.browser.cjs.js:141:34
at /Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/@emotion/react/dist/emotion-element-25f9958c.browser.cjs.js:57:12
at renderWithHooks (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/react-dom/cjs/react-dom.development.js:15486:18)
at updateForwardRef (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/react-dom/cjs/react-dom.development.js:19245:20)
at beginWork (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/react-dom/cjs/react-dom.development.js:21675:16)
at beginWork$1 (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/react-dom/cjs/react-dom.development.js:27465:14)
at performUnitOfWork (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/react-dom/cjs/react-dom.development.js:26599:12)
at workLoopSync (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/react-dom/cjs/react-dom.development.js:26505:5)
at renderRootSync (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/react-dom/cjs/react-dom.development.js:26473:7)
at recoverFromConcurrentError (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/react-dom/cjs/react-dom.development.js:25889:20)
at performConcurrentWorkOnRoot (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/react-dom/cjs/react-dom.development.js:25789:22)
at workLoop (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/scheduler/cjs/scheduler.development.js:266:34)
at flushWork (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/scheduler/cjs/scheduler.development.js:239:14)
at performWorkUntilDeadline (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/scheduler/cjs/scheduler.development.js:533:21)
at Timeout.task \[as \_onTimeout\] (/Users/asitu/Documents/repos/allstate/kitab-ui/node_modules/jsdom/lib/jsdom/browser/Window.js:520:19)
at listOnTimeout (node:internal/timers:569:17)
at processTimers (node:internal/timers:512:7)
What could be the reason for this issue?
Test case that I have written:
beforeEach(async () => {
const theme = createTheme();
renderResult = render(
<ThemeProvider theme={theme}> // suggestion from 1st answer implemented and it works but i have few questions
<AlertProvider AlertComponent={AlertDialog}>
<Configuration index={0}/>
</AlertProvider></ThemeProvider>,
{ preloadedState: storePreLoadedData });
});
...
it('should be an invalid form on input change', async () => {
const editButtonIcon = screen.getByTestId('editButton');
fireEvent.click(editButtonIcon);
const input = screen.getByRole('textbox', { name: "transactionTypeEntCd" });
fireEvent.change(input, { target: { value: '' } });
const formElement = document.querySelector(fieldsForm) as HTMLFormElement;
expect(formElement.checkValidity()).toBe(false);
});
You can fix this by adding a ThemeProvider
to your test files before rendering the components.
It looks similar to this code snippet:
const theme = createTheme();
test('renders error alert', () => {
render(
<ThemeProvider theme={theme}>
<MyComponent />
</ThemeProvider>
);
expect(screen.getByText(/error saving configuration/i)).toBeInTheDocument();
});
If you aren't using a ThemeProvider
in your App code already, you can create another file that just accepts a children and injects the theme:
const theme = createTheme()
const LibProvider = ({children}) => {
return (
<ThemeProvider theme={theme}>
{children}
</ThemeProvider>
)
}
Then you can import this file to both your app root file and your tests, to avoid duplicating code.