The Next.js dynamic()
HOC components aren't really straightforward to tests. I have 2 issues right now;
require.resolveWeak is not a function
- seems to be added by next babel plugin)modules
logic; looks like it's simply not run when trying to render a dynamic component.Let's assume we have a component like this (using a dynamic import):
import dynamic from 'next/dynamic';
const ReactSelectNoSSR = dynamic(() => import('../components/select'), {
loading: () => <Input />,
ssr: false
});
export default () => (
<>
<Header />
<ReactSelectNoSSR />
<Footer />
</>
);
The dynamic import support offered by Next.js does not expose a way to preload the dynamically imported components in Jestโs environment. However, thanks to jest-next-dynamic, we can render the full component tree instead of the loading placeholder.
You'll need to add babel-plugin-dynamic-import-node to your .babelrc
like so.
{
"plugins": ["babel-plugin-dynamic-import-node"]
}
Then, you can use preloadAll()
to render the component instead of the loading placeholder.
import preloadAll from 'jest-next-dynamic';
import ReactSelect from './select';
beforeAll(async () => {
await preloadAll();
});
๐ Source
You can add the following to your Jest setup ex: setupTests.ts
jest.mock('next/dynamic', () => () => {
const DynamicComponent = () => null;
DynamicComponent.displayName = 'LoadableComponent';
DynamicComponent.preload = jest.fn();
return DynamicComponent;
});
Although a hacky solution, what I did was to simply mock next/dynamic
by extracting the import path and returning that import:
jest.mock('next/dynamic', () => ({
__esModule: true,
default: (...props) => {
const matchedPath = /(.)*(\'(.*)\')(.)*/.exec(props[0].toString());
if (matchedPath) return require(matchedPath[3]);
else return () => <></>;
},
}));
The following will load the required component. You can also use similar approach to load all components before hand.
jest.mock('next/dynamic', () => ({
__esModule: true,
default: (...props) => {
const dynamicModule = jest.requireActual('next/dynamic');
const dynamicActualComp = dynamicModule.default;
const RequiredComponent = dynamicActualComp(props[0]);
RequiredComponent.preload
? RequiredComponent.preload()
: RequiredComponent.render.preload();
return RequiredComponent;
},
}));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With