Reputation: 11
Running jest test I faced following issue:
` SyntaxError: Cannot use import statement outside a module
30 | certificateEuropean: '/icons/certificate-european.svg',
31 | check: '/icons/check.svg',
> 32 | checkGold: '/icons/check-gold.svg',
`
This is the test:
` import React from 'react'; import { render } from '@testing-library/react';
import { Icon } from '@/components/UI/Icon';
describe('RegistrationForm', () => {
test('should update and retrieve values correctly', () => {
render(<Icon type="accreditation" />);
});
});
`
This is the component:
` const iconMap = { accreditation: '/icons/accreditation.svg', . . }
export const getIconSrc = (type: IconType): string => iconMap[type];
export const Icon = React.forwardRef<HTMLImageElement, IconProps>(
({ type, size, width, alt = '', id, quantity }, ref) => {
const _size = size ?? 24;
const _width = width ?? _size;
const iconSrc = getIconSrc(type);
return (
<>
<img
data-testid={id}
className="h-full"
ref={ref}
src={iconSrc}
width={_width}
height={_size}
alt={alt}
/>
{typeof quantity === 'number' && quantity > 0 ? (
<span>
{quantity}
</span>
) : null}
</>
);
}
);
Icon.displayName = 'Icon';
`
and this is my jest.config.js
` // jest.config.js const nextJest = require('next/jest');
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
});
const customJestConfig = {
moduleDirectories: ['node_modules', '<rootDir>/'],
moduleNameMapper: {
'@/(.*)$': '<rootDir>/src/$1',
'@@/(.*)$': '<rootDir>/$1',
'\\.(ttf|otf|eot|svg)$': '<rootDir>/__mocks__/fontMock.js',
},
testEnvironment: 'jsdom',
setupFiles: ['./text-encoder.mock.ts'],
setupFilesAfterEnv: ['@testing-library/jest-dom'],
};
module.exports = createJestConfig(customJestConfig);`
I tried adding following fields to jest.config.js
`
preset: 'ts-jest',
testEnvironment: //every possible option
transform: {
'^.+\.tsx?$': 'ts-jest',
},
transformIgnorePatterns: ['/node_modules/'],
globals: {
"ts-jest": {
isolatedModules: true,
},
},`
in package.json
"type": "module",
your text
run node --experimental-vm-modules node_modules/jest/bin/jest.js
instead of npm test
result:
Must use import to load ES Module: C:\Users\USERNAME\frontend\node_modules\@sitecore-feaas\clientside\dist\browser\react.esm.js
Upvotes: 1
Views: 355
Reputation: 11
The issue is due to how the module entrypoint is being selected based on the environment, browser vs node. @sitecore-feaas and @sitecore/byoc use esm for browsers and cjs for node.
When you are running tests within jest, you are likely running jsdom or jest-environment-jsdom environment to run your tests within a simulated browser environment. This causes the module entrypoint to select "browser" which @sitecore-feaas and @sitecore/byoc map the browser entrypoint to esm instead of cjs.
Instead of configuring jest to transpile the esm modules back to cjs, you can override the entrypoint to select the cjs version.
In jest.config.js
add a moduleNameMapper
property to your jest config to map the entrypoints (example using next.js and jest):
const nextJest = require('next/jest');
const createJestConfig = nextJest({
dir: './',
});
/** @type {import('jest').Config} */
const customJestConfig = {
// Add this property if it does not exist and map the package imports to the correct entrypoint
moduleNameMapper: {
'@sitecore-feaas/clientside/react': '<rootDir>/node_modules/@sitecore-feaas/clientside/dist/browser/react.cjs',
'@sitecore/byoc': '<rootDir>/node_modules/@sitecore/byoc/dist/browser/index.cjs',
},
};
module.exports = createJestConfig(customJestConfig);
Upvotes: 1
Reputation: 144
Here is the other solution: mock @sitecore-jss
in your test.
For example if your component uses RichText
you can mock it like this:
jest.mock('@sitecore-jss/sitecore-jss-nextjs', () => ({
RichText: (props) => {
return props.field?.value;
},
}));
Upvotes: 0
Reputation: 144
It seems like something wrong with @sitecore-feaas
package.json — when I deleted "exports" field in @sitecore-feaas/package.json
and did the same with @sitecore/byoc
it started working.
I created a jest settings workaround:
jest.config.ts:
globalSetup: '<rootDir>/jest/sitecoreLibsExportFixing.ts',
globalTeardown: '<rootDir>/jest/sitecoreLibsExportFixingRestore.ts',
sitecoreLibsWithWrongExport.ts:
export const sitecoreLibsWithWrongExport = ['@sitecore/byoc', '@sitecore-feaas/clientside'];
sitecoreLibsExportFixing.ts:
import fs from 'fs';
import { sitecoreLibsWithWrongExport } from './sitecoreLibsWithWrongExport';
const sitecoreLibsExportFixing = (libsToPatch: string[]) => {
libsToPatch.forEach((lib) => {
const packageFilePath = `node_modules/${lib}/package.json`;
const backupFilePath = `node_modules/${lib}/package.backup.json`;
// Store a backup
fs.copyFileSync(packageFilePath, backupFilePath);
// Read the file
const rawData = fs.readFileSync(packageFilePath, 'utf-8');
const packageData = JSON.parse(rawData);
// Remove the 'exports' property
if (packageData.exports) {
delete packageData.exports;
// Write the updated content back to the file
const updatedData = JSON.stringify(packageData, null, 2);
fs.writeFileSync(packageFilePath, updatedData);
}
});
};
export default () => sitecoreLibsExportFixing(sitecoreLibsWithWrongExport);
sitecoreLibsExportFixingRestore.ts:
import fs from 'fs';
import { sitecoreLibsWithWrongExport } from './sitecoreLibsWithWrongExport';
const sitecoreLibsExportFixingRestore = (libsToRestore: string[]) => {
libsToRestore.forEach((lib) => {
const packageFilePath = `node_modules/${lib}/package.json`;
const backupFilePath = `node_modules/${lib}/package.backup.json`;
// Restore the backup file
if (fs.existsSync(backupFilePath)) {
fs.copyFileSync(backupFilePath, packageFilePath);
}
});
};
export default () => sitecoreLibsExportFixingRestore(sitecoreLibsWithWrongExport);
Upvotes: 0