I’m facing challenges while trying to add tests using Jest to my existing Create React App (CRA) project, which uses Mantine v6 components. I’ve been following the testing guidelines in the Mantine documentation and other online resources, but I’m still running into some issues.
Project Details:
Framework: Create React App
Mantine Version: v6.0.21
Testing Framework: Jest
Issue Description:
I’ve created a custom render function that wraps my components with MantineProvider to provide the Mantine theme and context. However, I’m encountering a recurring issue where the MantineProvider shows up as null or undefined in the logs, causing my tests to fail.
Steps I’ve Taken:
Mocked Theme: I’ve tried mocking the theme object in my test file to provide a default value before it’s loaded.
useMantineTheme and waitFor: I’ve used the useMantineTheme hook inside my custom render function and wrapped my assertions in waitFor to ensure the theme is loaded before the tests run.
Checked for Circular Dependencies: I’ve made sure there are no circular dependencies that could be causing issues.
Code Snippets:
render.tsx :
import {
render as rtlRender,
RenderOptions,
waitFor,
} from "@testing-library/react";
import { MantineProvider, useMantineTheme } from "@mantine/core";
export const AllTheProviders = ({
children,
}: {
children: React.ReactNode;
}) => {
const comp = <MantineProvider>{children}</MantineProvider>;
return comp;
};
export const render = async (
ui: React.ReactNode,
options?: Omit<RenderOptions, "wrapper">,
) => {
const result = rtlRender(ui, {
wrapper: AllTheProviders,
...options,
});
return result;
};
Header.tsx :
import {
Burger,
Container,
Group,
Header,
Image,
MediaQuery,
Text,
useMantineTheme,
} from "@mantine/core";
import { Dispatch, SetStateAction } from "react";
import { Settings } from "../../../../Types";
import { useMediaQuery } from "@mantine/hooks";
export const HeaderComponent = ({
navBarOpened,
setNavBarOpened,
settings,
}: {
navBarOpened: boolean;
setNavBarOpened: Dispatch<SetStateAction<boolean>>;
settings: Settings;
}) => {
const theme = useMantineTheme();
const mobileScreen = useMediaQuery(`(max-width: ${theme.breakpoints.sm})`);
return (
<Header
height={80}
sx={(theme) => ({
display: "flex",
alignItems: "center",
paddingLeft: theme.spacing.md,
paddingRight: theme.spacing.md,
})}
>
<Group w="100%">
<MediaQuery largerThan="sm" styles={{ display: "none" }}>
<Burger
opened={navBarOpened}
onClick={() => setNavBarOpened((o) => !o)}
size="sm"
maw="0.5rem"
mr="xl"
/>
</MediaQuery>
<Image
width={mobileScreen ? "18em" : "24em"}
/>
{!mobileScreen && (
<Container pos="absolute" right="0rem">
<Text fz="xs" c="dimmed">
index: {settings.index}
</Text>
<Text fz="xs" c="dimmed">
model: {settings.name}
</Text>
<Text fz="xs" c="dimmed">
model id: {settings.modelId}
</Text>
</Container>
)}
</Group>
</Header>
);
};
Header.test.tsx :
import { HeaderComponent } from ".";
import { render, screen } from "../../../../test-utils";
import { Settings } from "../../../../Types";
const mockUseMediaQuery = jest.fn();
const mockUseMantineTheme = jest.fn();
jest.mock("@mantine/hooks", () => ({
useMediaQuery: () => mockUseMediaQuery(),
}));
jest.mock("@mantine/core", () => ({
useMantineTheme: () => mockUseMantineTheme(),
createStyles: () => () => ({}),
}));
jest.mock("@mantine/prism", () => ({
Prism: () => <div>Mocked Prism Component</div>,
}));
jest.mock("@mantine/dates", () => ({
Dates: () => <div>Mocked Date Component</div>,
}));
jest.mock("@emotion/react", () => ({
...jest.requireActual("@emotion/react"),
useTheme: () => ({}),
}));
describe("HeaderComponent", () => {
it("renders logo and settings on larger screens", () => {
mockUseMediaQuery.mockReturnValue(false);
const settings = new Settings({
index: "myIndex",
modelName: "myModel",
modelId: "myModelId",
});
render(
<HeaderComponent
navBarOpened={false}
setNavBarOpened={jest.fn()}
settings={settings}
/>,
);
expect(screen.getByRole("img")).toBeInTheDocument();
expect(screen.getByText(/index: myIndex/i)).toBeInTheDocument();
expect(screen.getByText(/model: myModel/i)).toBeInTheDocument();
expect(screen.getByText(/model id: myModelId/i)).toBeInTheDocument();
});
});
Error message :
console.error
Warning: React.jsx: type is invalid — expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it’s defined in, or you might have mixed up default and named imports.
Check the render method of `AllTheProviders`.
at AllTheProviders (/Users/soham/Desktop/sycamore/apps/demo-ui/ui/src/test-utils/render.tsx:11:11)
13 | children: React.ReactNode;
14 | }) => {
> 15 | const comp = <MantineProvider>{children}</MantineProvider>;
| ^
16 | return comp;
17 | };
18 | export const render = async (
throw new Error(‘Element type is invalid: expected a string (for built-in ‘ + ‘components) or a class/function (for composite components) ‘ + (“but got: ” + (type == null ? type : typeof type) + “.” + info));^
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it’s defined in, or you might have mixed up default and named imports.
Check the render method of AllTheProviders.
Soham Kasar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.