Я разрабатываю приложение React, используя среду разработки Vite. Поскольку Vite хорошо поддерживается, я включил несколько плагинов, которые довольно хорошо с ним работают, в частности тот, который дает мне возможность создавать компоненты, напрямую импортирующие *.svg в определенном формате. Он называется vite-plugin-svgr
, и вы можете создать компонент следующим образом, просто включив ?react
в конце:
import Lock from '../assets/icons/lock.svg?react'
Как только я это сделал, я начал разрабатывать несколько тестов с помощью Jest и test-library/react, и похоже, что методу «рендеринг» из test-library/react не нравится, как компоненты создаются с помощью плагина.
В основном выдает следующую ошибку: `console.error Предупреждение: React.jsx: тип недействителен — ожидалась строка (для встроенных компонентов) или класс/функция (для составных компонентов), но получен: объект.
Check the render method of `Widget`.
at repositoryData (/Users/joscormir/Dev/dashboard_project/src/components/Widget.jsx:13:26)
at section
at Dashboard (/Users/joscormir/Dev/dashboard_project/src/components/Dashboard.jsx:9:61)
24 | {repositoryData.organization.login}/{repositoryData.name}
25 | </a>
> 26 | {repositoryData.private ? <Lock /> : <UnLock />}
| ^
27 | </header>
28 |
29 | <div className = {styles.widget__body}>`
Учтите, что <UnLock />
— это компонент, созданный описанным ранее способом:
import UnLock from '../assets/icons/unlock.svg?react'
и Widget.jsx
— это компонент, включающий компонент <UnLock />
.
У него явно проблемы с рендерингом этого компонента.
Поскольку это довольно просто, я подумал об использовании плагина Jest под названием jest-transformer-svg
import React from 'react';
import MySvg from '../images/an-image.svg';
function MyComponent() {
return (
<div>
<MySvg style = {{ color: 'blue' }} />
</div>
);
}
Затем, поскольку расширение моих файлов немного отличается, я попытался использовать Jest для преобразования расширения, чтобы соответствовать требованиям приведенного выше примера, включая следующее предложение в моем файле.
\*.svg?react
Но это не сработало. Весь тестовый комплект не работает, поскольку он говорит, что теперь не может найти модуль, объявленный с расширениями jest.config.js\
, что означает, что '^.+\\.(svg\\?react)$': 'jest-transformer-svg'
не совсем работает, насколько я понимаю.
Я нашел способ заставить это работать. Он работает как шарм, и я нашел его, прочитав вопросы в vite-plugin-svgr. Ключевым моментом здесь является замена расширения .svg?react
на .svg
. Это возможно, изменив способ включения vite.config.js
вызова плагина.
Нам нужно изменить его следующим образом:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import svgr from 'vite-plugin-svgr'
export default defineConfig({
plugins: [react(), svgr({ include: '**/*.svg' })],
})
Ключевым моментом является то, как мы подключаем файлы svg. С помощью этой модификации мы можем изменить способ импорта компонентов с использования UnLock from '../assets/icons/unlock.svg?react'
на использование UnLock from '../assets/icons/unlock.svg'
.
Благодаря этой модификации мы теперь можем правильно использовать jest-transformer-svg
, поскольку он будет правильно интерпретировать файлы .svg
, включая в файл jest.config.js
правило преобразования, сообщающее преобразователю jest преобразовать все файлы с этими расширениями '^.+\\.svg$': 'jest-transformer-svg'
:
module.exports = {
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/tests/setupTests.js'],
testMatch: ['<rootDir>/tests/**/*.(test).(js|jsx)'],
testPathIgnorePatterns: ['<rootDir>/tests/e2e/'],
transform: {
'^.+\\.(js|jsx|ts|tsx)$': [
'@swc/jest',
{
sourceMaps: true,
jsc: {
parser: {
syntax: 'ecmascript',
jsx: true,
},
transform: {
react: {
runtime: 'automatic',
},
},
},
},
],
'^.+\\.svg$': 'jest-transformer-svg',
},
moduleNameMapper: {
'\\.(css|less|scss|sass)$': 'identity-obj-proxy',
'\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'jest-transform-stub',
},
}
Выше приведены мои файлы конфигурации, которыми я поделился только для того, чтобы уточнить, где должно быть размещено правило преобразования, все остальное может измениться в зависимости от вашей собственной конфигурации jest.
Вы можете издеваться над файлами SVG
"jest": {
"moduleNameMapper": {
"\\.svg\\?(react|url)$": "<rootDir>/src/__mocks__/svgMock.js"
}
},
src/mocks/svgMock.js
const SvgMock = (props) => {
return (
<svg {...props}>
<title>Mock SVG</title>
</svg>
)
}
export default SvgMock