'Mocking dot notation React components in Jest
I have a component that, depending on data being loaded, renders either a component or a loading component:
// components/example
import Component from 'components/component';
const Example = ({loaded}) => (
<>
{loaded ? <Component/> : <Component.Loading/>}
</>
)
The loading component is written as dot notation, because I feel like it makes it easier to read and use.
Is there any way to mock <Component.Loading/> in my unit tests?
This was my best guess, but it didn't work:
// components/example.test
import Example from './example'
const mockedComponent = jest.fn();
jest.mock('components/component', () => ({
__esModule: true,
default: () => mockedComponent(),
}));
const setup = () => {
const utils = render(<Example loading={false} />);
return {
...utils,
};
};
it('Renders correctly', () => {
const component = () => <>Main component</>;
component.Loading = () => <>Loading component</>;
mockedComponent.mockReturnValue(component);
setup();
});
Jest doesn't like this, and tells me that <Component.Loading/> is undefined.
console.error
Warning: React.createElement: 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.
Solution 1:[1]
Right so this while doing this I was going off how you usually mock react components:
jest.mock('component/something', () => ({
__esModule: true,
default: () => <>Mocked component</>,
}));
This usually works, but for dot-notation component the syntax is different:
const component = () => <>Main component</>;
component.Loading = () => <>Loading</>;
jest.mock('components/component', () => ({
__esModule: true,
default: component,
}));
If you want to go a step further you can mock with a jest.fn():
const mockedItemStatus = jest.fn();
const mockedItemStatusSkeleton = jest.fn();
const component = () => mockedItemStatus();
component.Loading = () => mockedItemStatusSkeleton();
jest.mock('components/component', () => ({
__esModule: true,
default: component,
}));
Then in your tests you can make the mock return the specific component you need:
it('Renders correctly', () => {
mockedItemStatusSkeleton.mockImplementation(() => <>Loading</>);
render(<Component/>)
expect(mockedItemStatusSkeleton).toHaveBeenCalled();
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
