у меня есть настройка с Webpack и Jest для тестирования реакции, а также с использованием псевдонимов Webpack с использованием знака "@" для каталога моего проекта, который называется "src / app", я также знаю, что он должен быть сопоставлен с jest .config, используя свойство moduleNameMapper для правильного выравнивания с этим псевдонимом.
проблема в том, что есть компонент <Icon />
, который интернирует динамически импортирует значки .svg, используя динамический импорт ES.
это регулярное выражение для этого отображения для jest.config.js
'^ @ /': '/ src / app / $ 1'
но он ломается ТОЛЬКО при тестировании
все отлично работает, кроме как при тестировании
моя структура папок следующая:
config/
webpack-config/
src/
app/
assets/
img/
some images
svg/
icons/
cart.svg
components/
base/
core/
shared/
...
client/
...
server/
...
это псевдоним Webpack, который я использую:
module.exports = {
extensions: ['.js', '.mjs', '.json', '.jsx', '.css'],
modules: paths.resolveModules,
alias: {
'@': paths.srcApp, // that just point
}
};
это мой файл jest.config:
const paths = require('./config/paths');
module.exports = {
verbose: true,
collectCoverageFrom: ['src/**/*.{js,jsx,mjs}'],
setupFiles: [
'<rootDir>/node_modules/regenerator-runtime/runtime',
'<rootDir>/config/polyfills.js',
],
// A list of paths to modules that run some code to configure or set up the testing framework before each test.
setupFilesAfterEnv: ['<rootDir>config/jest/setup.js'],
testMatch: [
'<rootDir>/src/**/__tests__/**/*.{js,jsx,mjs}',
'<rootDir>/src/**/?(*.)(spec|test).{js,jsx,mjs}',
],
testEnvironment: 'node',
testURL: 'http://localhost',
modulePaths: ['src'],
moduleNameMapper: {
'^@[/](.+)': '<rootDir>/src/app/$1',
},
transform: {
'^.+\\.(js|jsx|mjs)$': '<rootDir>/node_modules/babel-jest',
'^.+\\.css$': '<rootDir>/config/jest/cssTransform.js',
'^(?!.*\\.(js|jsx|mjs|css|json|svg)$)': '<rootDir>/config/jest/fileTransform.js',
},
transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$'],
moduleDirectories: paths.resolveModules,
moduleFileExtensions: ['js', 'json', 'jsx', 'node', 'mjs'],
};
это компонент, который я тестирую
// @flow strict
import React, { useState } from 'react';
import './Icon.scss';
type PropsType = {
name: string,
selected?: string,
size: number | string
};
const Icon = ({ name, size }: PropsType) => {
const [iconPath, setIconPath] = useState('');
(async () => {
const icon = await import(`@/assets/svg/icons/${name}.svg`);
setIconPath(icon.default);
})();
return (
<img
alt={`icon ${name}`}
className="icon"
style={{
height: `${size}px`,
width: `${size}px`,
}}
src={iconPath}
/>
);
};
Icon.defaultProps = {
size: 16,
};
export default Icon;
и это тест
// @flow strict
import React from 'react';
import {
render,
} from 'react-testing-library';
import Icon from './Icon';
describe('Icon', () => {
it('should have "name" with the path of the icon', () => {
const { container } = render(<Icon name="cart" />);
});
});
и это вывод
Configuration error:
Could not locate module @/assets/svg/icons/${name}.svg mapped as:
/Users/jero/Documents/my-shit/react-shop/src/app/assets/svg/icons/${name}.svg.
Please check your configuration for these entries:
{
"moduleNameMapper": {
"/^@[\/](.+)/": "/Users/jero/Documents/my-shit/react-shop/src/app/$1"
},
"resolver": null
}
Интересно то, что когда я использую это регулярное выражение для jest.config
moduleNameMapper: {
'/^@\/(.*)$/': '<rootDir>/src/app$1'
}
ошибка исчезла, но она исчезает, когда компонент импортирует другие компоненты при тестировании:
FAIL src/app/components/shared/ImgLoader/ImgLoader.test.js
● Test suite failed to run
Cannot find module '@/components/base/Spinner/Spinner' from 'ImgLoader.js'
However, Jest was able to find:
'./ImgLoader.js'
'./ImgLoader.scss'
'./ImgLoader.test.js'
You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'node', 'mjs'].
See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string
2 | import React, { useState } from 'react';
3 |
> 4 | import Spinner from '@/components/base/Spinner/Spinner';
| ^
5 |
6 | import './ImgLoader.scss';
7 |
at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:230:17)
at Object.<anonymous> (src/app/components/shared/ImgLoader/ImgLoader.js:4:1)
а это <ImageLoader />
// @flow strict
import React, { useState } from 'react';
import Spinner from '@/components/base/Spinner/Spinner';
import './ImgLoader.scss';
type PropsType = {
src: string
};
function ImgLoader({ src }: PropsType) {
const [imgObj, setImg] = useState({ img: null, isLoading: true });
const image = new Image();
image.onload = () => setImg({ img: image.src, isLoading: false });
image.src = src;
return (
imgObj.isLoading ? (<Spinner />) : (<img className="imgLoader img-fluid" src={imgObj.img} alt="img" />)
);
}
export default ImgLoader;
и его тестовый ответ
// @flow strict
import React from 'react';
import {
render,
} from 'react-testing-library';
import ImgLoader from './ImgLoader';
describe('ImgLoader', () => {
it('tests \'src\'', () => {
const src = 'https://static.street-beat.ru/upload/resize_cache/iblock/d69/450_450_1/d699afc7b3428f2f51c2f2de6665b506.jpg';
const { container } = render(<ImgLoader src={src} />);
console.log('container', container);
});
});
Я полагаю, что-то связано с динамическим импортом?