问题
I'm running npm test and getting the following error:
FAIL src/App.test.js
● Test suite failed to run
TypeError: symbol is not a function
at String (<anonymous>)
3 | import styled from "styled-components";
4 |
> 5 | const NoAccess = styled(NoAccess_)`
| ^
6 | width: 100px;
7 | height: 75px;
8 | `;
at options (node_modules/styled-components/src/models/StyledComponent.js:265:68)
at je (node_modules/styled-components/src/models/StyledComponent.js:265:68)
at Object.<anonymous> (src/App.js:5:18)
at Object.<anonymous> (src/App.test.js:2:1)
Styled is imported in the component where the error is thrown, so I'm not sure why it is "not a function".
I have created a minimal example underneath.
Minimal example
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
App.js
import React from "react"
import NoAccess_ from './NO_ACCESS.svg';
import styled from "styled-components";
const NoAccess = styled(NoAccess_)`
width: 100px;
height: 75px;
`;
function App() {
return (
<div className="App">
<NoAccess />
</div>
);
}
export default App;
App.test.js
import React from "react"
import App from './App'
import { render, screen } from "@testing-library/react";
test("renders correct content", () => {
const { getByText, getByLabelText } = render(<App />)
screen.debug()
})
package.json
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"@babel/plugin-transform-react-jsx": "^7.12.5",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"identity-obj-proxy": "^3.0.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-scripts": "4.0.0",
"styled-components": "^5.2.1",
"web-vitals": "^0.2.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "jest",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"jest": {
"verbose": false,
"rootDir": ".",
"collectCoverageFrom": [
"**/*.{js,jsx,ts,tsx}",
"!**/*.d.ts"
],
"moduleFileExtensions": [
"js",
"jsx",
"ts",
"tsx"
],
"moduleNameMapper": {
"\\.(css|less|scss|sass|svg)$": "identity-obj-proxy"
},
"transform": {
"\\.[jt]sx?$": "babel-jest",
"^.+\\.jsx?$": "babel-jest",
"^.+\\.svg$": "<rootDir>/svgTransform.js"
},
"transformIgnorePatterns": [
"/node_modules/"
],
"testMatch": [
"**/*.{spec,test}.{js,jsx,ts,tsx}"
]
},
"devDependencies": {
"@babel/plugin-proposal-class-properties": "^7.12.1",
"@babel/preset-env": "^7.12.1",
"@babel/preset-react": "^7.12.5",
"babel-jest": "^26.6.3",
"jest": "^26.6.3"
}
}
<svg width="100" height="75" viewBox="0 0 100 75" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M98.333 0H1.66699C0.746094 0 0 0.746094 0 1.66699V58.3335C0 59.2537 0.746094 59.9998 1.66699 59.9998H46.667V73.333C46.667 74.2539 47.4131 75 48.334 75H81.667C82.5879 75 83.334 74.2539 83.334 73.333V59.9998H98.333C99.2539 59.9998 100 59.2537 100 58.3335V1.66699C100 0.746094 99.2539 0 98.333 0ZM50 71.6667V44.9998H80V71.6667H50ZM65 28.3333C60.3994 28.3386 56.6719 32.0664 56.667 36.667V41.6665H53.333V36.667C53.333 30.2231 58.5566 25 65 25C71.4434 25 76.666 30.2239 76.666 36.667V41.6665H73.333V36.667C73.3281 32.0664 69.5996 28.3386 65 28.3333ZM70 36.667V41.6665H60V36.667C60 33.905 62.2383 31.6665 65 31.6665C67.7617 31.6665 70 33.905 70 36.667ZM96.667 56.6665H83.334V43.3335C83.334 42.4126 82.5879 41.6665 81.667 41.6665H80V36.667C80 28.3821 73.2842 21.6667 65 21.6667C56.7158 21.6667 50 28.3821 50 36.667V41.6665H48.334C47.4131 41.6665 46.667 42.4126 46.667 43.3335V56.6665H3.33301V16.6665H96.667V56.6665ZM96.667 13.333H3.33301V3.33325H96.667V13.333ZM10 53.333H26.667C27.5879 53.333 28.334 52.5869 28.334 51.6667V40.0212C28.3242 37.187 26.5273 34.6677 23.8506 33.7363C24.6006 32.6353 25.002 31.333 25 30V21.6665C25 20.7456 24.2539 19.9995 23.333 19.9995H13.334C12.4131 19.9995 11.667 20.7456 11.667 21.6665V30C11.666 31.333 12.0664 32.6353 12.8174 33.7363C10.1396 34.6677 8.34277 37.187 8.33398 40.0212V51.6667C8.33398 52.5869 9.08008 53.333 10 53.333ZM15.001 23.3328H21.667V30C21.667 31.8411 20.1748 33.3335 18.334 33.3335C16.4932 33.3335 15.001 31.8411 15.001 30V23.3328ZM11.667 40.0212C11.6689 38.1697 13.1699 36.6682 15.0215 36.6667H21.6455C23.4971 36.6682 24.999 38.1697 25 40.0212V49.9998H11.667V40.0212ZM93.333 6.66675H90V10H93.333V6.66675ZM83.334 6.66675H86.667V10H83.334V6.66675ZM63.333 66.6665V59.6931C61.9102 59.1897 60.79 58.0696 60.2861 56.646C59.3662 54.042 60.7305 51.1855 63.333 50.2654C65.9375 49.3447 68.7939 50.7095 69.7148 53.3127C70.6348 55.9158 69.2705 58.7729 66.667 59.6931V66.6665H63.333ZM66.667 55.0002C66.667 54.0793 65.9209 53.3333 65 53.3333C64.0791 53.3333 63.333 54.0793 63.333 55.0002C63.333 55.9204 64.0791 56.6665 65 56.6665C65.9209 56.6665 66.667 55.9204 66.667 55.0002Z" fill="#007079"/>
</svg>
I'm guessing something needs to be added to the config, but I'm not sure what.
What I have tried so far:
1. Wrapping svg in brackets made the test go through, but not the compile the project (npm run dev)
2. Using moduleMapper (Not working)
"moduleNameMapper": {
"\\.(svg)$": "<rootDir>/test/__mocks__/svgMock.js"
}
and svgMock:
module.exports = '';
Inspired by Unit testing of styled-components with SVG imports.
(Working) Dirty solution:
Exporting svg with JS:
export default () =>
(<svg width="100" height="75" viewBox="0 0 100 75" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M98.333 0H1.66699C0.746094 0 0 0.746094 0 1.66699V58.3335C0 59.2537 0.746094 59.9998 1.66699 59.9998H46.667V73.333C46.667 74.2539 47.4131 75 48.334 75H81.667C82.5879 75 83.334 74.2539 83.334 73.333V59.9998H98.333C99.2539 59.9998 100 59.2537 100 58.3335V1.66699C100 0.746094 99.2539 0 98.333 0ZM50 71.6667V44.9998H80V71.6667H50ZM65 28.3333C60.3994 28.3386 56.6719 32.0664 56.667 36.667V41.6665H53.333V36.667C53.333 30.2231 58.5566 25 65 25C71.4434 25 76.666 30.2239 76.666 36.667V41.6665H73.333V36.667C73.3281 32.0664 69.5996 28.3386 65 28.3333ZM70 36.667V41.6665H60V36.667C60 33.905 62.2383 31.6665 65 31.6665C67.7617 31.6665 70 33.905 70 36.667ZM96.667 56.6665H83.334V43.3335C83.334 42.4126 82.5879 41.6665 81.667 41.6665H80V36.667C80 28.3821 73.2842 21.6667 65 21.6667C56.7158 21.6667 50 28.3821 50 36.667V41.6665H48.334C47.4131 41.6665 46.667 42.4126 46.667 43.3335V56.6665H3.33301V16.6665H96.667V56.6665ZM96.667 13.333H3.33301V3.33325H96.667V13.333ZM10 53.333H26.667C27.5879 53.333 28.334 52.5869 28.334 51.6667V40.0212C28.3242 37.187 26.5273 34.6677 23.8506 33.7363C24.6006 32.6353 25.002 31.333 25 30V21.6665C25 20.7456 24.2539 19.9995 23.333 19.9995H13.334C12.4131 19.9995 11.667 20.7456 11.667 21.6665V30C11.666 31.333 12.0664 32.6353 12.8174 33.7363C10.1396 34.6677 8.34277 37.187 8.33398 40.0212V51.6667C8.33398 52.5869 9.08008 53.333 10 53.333ZM15.001 23.3328H21.667V30C21.667 31.8411 20.1748 33.3335 18.334 33.3335C16.4932 33.3335 15.001 31.8411 15.001 30V23.3328ZM11.667 40.0212C11.6689 38.1697 13.1699 36.6682 15.0215 36.6667H21.6455C23.4971 36.6682 24.999 38.1697 25 40.0212V49.9998H11.667V40.0212ZM93.333 6.66675H90V10H93.333V6.66675ZM83.334 6.66675H86.667V10H83.334V6.66675ZM63.333 66.6665V59.6931C61.9102 59.1897 60.79 58.0696 60.2861 56.646C59.3662 54.042 60.7305 51.1855 63.333 50.2654C65.9375 49.3447 68.7939 50.7095 69.7148 53.3127C70.6348 55.9158 69.2705 58.7729 66.667 59.6931V66.6665H63.333ZM66.667 55.0002C66.667 54.0793 65.9209 53.3333 65 53.3333C64.0791 53.3333 63.333 54.0793 63.333 55.0002C63.333 55.9204 64.0791 56.6665 65 56.6665C65.9209 56.6665 66.667 55.9204 66.667 55.0002Z" fill="#007079"/>
</svg>)
回答1:
Looks like you set up loader to import svg
to return a component which means as long as you can do the same way with jest
by using a transformer which returns a jsx
in case of svg
file.
I suggest to use jest-svg-transformer
to transform svg
file as following:
// Install
// npm i -D jest-svg-transformer / yarn add -D jest-svg-transformer
transform: {
// ...
"\\.svg$": "jest-svg-transformer"
},
You also have to remove the existing mapper mocking svg
file at:
"moduleNameMapper": {
"\\.(css|less|scss|sass)$": "identity-obj-proxy", // Remove `svg` from this pattern
},
来源:https://stackoverflow.com/questions/64854258/typeerror-styled-symbol-is-not-a-function