SVG가 포함된 컴포넌트를 render할 때 SVG파일을 인식하지 못해서 "SyntaxError: Unexpected token '<'" 에러가 발생할 수 있다. 이럴 때에는 직접 transformer 파일을 만들어서 해결할 수 있다.
1. transformer 파일 직접 만들기
// svgTransformer.js
module.exports = {
process() {
return { code: 'module.exports = {};' };
}
};
이렇게 transformer 파일을 만든 후에 jest 설정(jest.config.js 또는 package.json)의 transform에 svg파일일 때 svgTransformer.js를 적용하도록 설정하면 된다.
// package.json
{
"jest": {
"transform": {
"^.+\\.svg$": "<rootDir>/svgTransformer.js"
}
}
}
위와 같이 설정하면 테스트 코드가 정상적으로 실행될 것이다.
그런데 이러한 에러가 발생하는 원인은 무엇일까?
공식 문서에 따르면, Jest는 코드를 자바스크립트에서 실행시키므로, Node에서 지원하지 않는 문법으로 작성되어 있으면 자바스크립트로 코드를 바꿔주는 transformer 파일이 필요하다고 한다.
Jest runs the code in your project as JavaScript, but if you use some syntax not supported by Node out of the box (such as JSX, TypeScript, Vue templates) then you'll need to transform that code into plain JavaScript, similar to what you would do when building for browsers.
SVG 파일은 xml 파일 형식의 마크업 언어로 작성되어 있으므로, Jest에서 코드를 해석할 수 없다. 따라서, 직접 transformer 파일을 만들어서 SVG 파일인 경우에만(^.+\\.svg$) svgTransformer를 거쳐서 자바스크립트 코드로 변환한 후 읽게 되는 것이다.
그러나 위 예시대로 하면 SVG를 원래 형태 그대로 React 컴포넌트로 변환하는 것이 아니라, 일단 임시로 자바스크립트 코드로 만들어서 svg 파일을 읽을 수 있게 하여 코드가 돌아가게끔만 하는 것이다. snapshot을 찍어보면 정상적인 형태의 태그로 변환되지 않는 것을 볼 수 있다.
// index.tsx
// 여기서는 svgr을 사용하고 있기 때문에 SunIcon는 React 컴포넌트임
import SunIcon from '@assets/images/sun-solid.svg';
function App() {
return <SunIcon className="icon-mode" />;
}
// index.test.tsx
import App from '@src/App';
import { render } from '@testing-library/react';
describe('App', () => {
it('snapshot', () => {
const { container } = render(<App />);
expect(container).toMatchSnapshot();
});
});
// __snapshots__/index.test.tsx.snap
exports[`App snapshot 1`] = `
<div>
<moon-solid.svg
classname="icon-mode"
/>
</div>
`;
태그 이름이 파일명과 동일하게 설정되어 있다. 또한, svg 태그 내에 존재하는 path 태그나 g태그 등의 다른 자식 요소가 전혀 없다.
2. jest-transformer-svg 사용하기
※ jest-svg-transformer는 jest 27까지만 지원하는 버전이다. jest 28 이상부터는 반드시 jest-transformer-svg를 사용하여야 한다. (jest가 27 -> 28로 업데이트 되면서 transformer의 process와 processAsync 메서드가 string이 아닌 { code: string } 형태의 객체를 반환하도록 변하였기 때문)
npm i -D jest-transformer-jest
// package.json
{
"jest": {
"transform": {
"^.+\\.svg$": "jest-transformer-svg"
}
}
}
직접 transformer 파일을 만들 필요 없이 svg를 임시로 자바스크립트로 변환시켜주는 jest-transformer-svg를 사용하여 해결할 수도 있다. 패키지를 다운 받고 transform 설정만 해주면 바로 적용된다.
그러나 jest-transformer-svg도 온전한 형태의 svg를 재현하지 않는다.
// __snapshots__/index.test.tsx.snap
exports[`App snapshot 1`] = `
<div>
<svg
class="icon-mode"
data-file-name="SvgMoonSolid"
/>
</div>
`;
jest-transformer-svg는 태그를 svg로 맞추고 data-file-name이라는 data 어트리뷰트가 추가하였다. 그러나 여전히 내부에 다른 태그(path, g 등)는 존재하지 않는 것을 확인할 수 있다.
만약에 transform을 통해 온전한 형태의 svg를 얻으려면 svg 태그의 자손 요소들까지 모두 파싱하는 transformer를 따로 만들어야 할 것 같다. 나중에 시간이 되면 직접 만들어서 내용을 추가하도록 하겠다.
참고자료
https://jestjs.io/docs/code-transformation
Code Transformation · Jest
Jest runs the code in your project as JavaScript, but if you use some syntax not supported by Node out of the box (such as JSX, TypeScript, Vue templates) then you'll need to transform that code into plain JavaScript, similar to what you would do when buil
jestjs.io
https://stackoverflow.com/questions/46791263/jest-svg-require-causes-syntaxerror-unexpected-token
Jest: SVG require causes "SyntaxError: Unexpected token <"
Not sure where to look for this error. Using Typescript with React, and Jest and Enzyme for unit testing. Package.json sample: "scripts": { "start": "node server.js", "bundle": "cross-env
stackoverflow.com
https://www.npmjs.com/package/jest-transformer-svg
jest-transformer-svg
a jest transformer for testing with svg files in react. Latest version: 2.0.0, last published: a month ago. Start using jest-transformer-svg in your project by running `npm i jest-transformer-svg`. There are no other projects in the npm registry using jest
www.npmjs.com
https://jestjs.io/docs/upgrading-to-jest28
From v27 to v28 · Jest
Upgrading Jest from v27 to v28? This guide aims to help refactoring your configuration and tests.
jestjs.io
'IT > React' 카테고리의 다른 글
[Recoil] Duplicate atom key 에러 메시지 없애기 (Next.js, Vite) (0) | 2023.01.22 |
---|---|
[Vite/React] Vite HMR 에러 (feat. ContextAPI) (0) | 2023.01.15 |
[styled-components] 폰트 깜빡임(FOUT) 해결하기 (1) | 2022.04.19 |
[React] You are running create-react-app 4.0.3 which is behind the latest release (5.0.0) (0) | 2022.01.07 |