Testing/Mocking ReactComponent SVG imports with Jest - reactjs

I am importing SVG's into my component and importing them as components using ReactComponent, for example
import { ReactComponent as D1 } from '../../../assets/images/characteristics/D1.svg';
When I run Jest/Enzyme to test the component, I get the following error
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Does it appear that I need to mock this? How could I do that?

Although the solution pointed out by #skyboyer worked for me, it showed the following error in the console when running the tests:
<SvgrURL /> is using incorrect casing. Use PascalCase for React components,
or lowercase for HTML elements.
Changing to the following inside the mock file worked for me as a solution:
import React from 'react';
const SvgrMock = React.forwardRef((props, ref) => <span ref={ref} {...props} />);
export const ReactComponent = SvgrMock;
export default SvgrMock;
reference

Related

Can't import SVG in React from Webpack bundle

I have a React app that imports components from an own library of components. The library of components is a .js bundle created with Webpack.
The component that I am importing, imports another file which imports SVG files.
Original non-bundled file which imports SVGs:
import React from "react";
import {ShoppingBag32} from '#carbon/icons-react';
import {ReactComponent as OwnIcon} from "../design/icons/OwnIcon.svg";
const foo = {
shop: <ShoppingBag32/>,
ownIcon: <OwnIcon/>,
};
export default foo;
The #carbon/icons-react icons which are precompiled in their own plain JS bundle, work fine. But my own SVG fails to work.
I get:
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a
class/function (for composite components) but got: undefined. You likely forgot to export your component
from the file it's defined in, or you might have mixed up default and named imports.
The stack trace of the warning leads to the line in the bundle where ownIcon is defined. You can see that the working icon of the 3rdparty bundle points to a ShoppingBag32 key, and my own SVG points to a ReactComponent key.
var foo = {
shop: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default.a.createElement(_carbon_icons_react__WEBPACK_IMPORTED_MODULE_0__["ShoppingBag32"], null),
ownIcon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default.a.createElement(_design_icons_SolarPanel32_svg__WEBPACK_IMPORTED_MODULE_1__["ReactComponent"], null)
};
Any ideas on how fix the SVG import?
EDIT
I found out a workaround, the img tag can be used with the SVG path as source. But I don't like this solution because I would like the entire SVG markup to be rendered in the DOM instead of an img tag.
import React from "react";
import {ShoppingBag32} from '#carbon/icons-react';
import OwnIcon from "../design/icons/OwnIcon.svg";
const foo = {
shop: <ShoppingBag32/>,
ownIcon: <img src={OwnIcon}/>,
};
export default foo;
If you are using the default create react app, you will need to reference your SVG as follows:
import OwnIcon from "../design/icons/OwnIcon.svg";
The reason it is like import {ShoppingBag32} from '#carbon/icons-react'; for carbon is because it is referenced as an export in that package as opposed to locally which webpack needs a name for the default export of an image.

React InstantSearch Dropdown RefinementList not Working: expected a string or a class/function (for composite components) but got: undefined

I am trying to make use of this guide to create a dropdown refinementlist instead of the default. I first created a Dropdown.js with contents form here
import React, { Component } from 'react';
import { connectRefinementList } from 'react-instantsearch/connectors';
import PropTypes from 'prop-types';
const cx = label => `ais-DropdownRefinementList-${label}`;
/// Rest of the code from the above link follows
export default connectRefinementList(DropdownRefinementList);
I then import it into my search.js component, which builds my interface like so:
import { DropdownRefinementList} from "./Dropdown"
And use it like so:
<DropdownRefinementList attribute="major" />
This gives me the following error:
×
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of `SearchGrid`.
SearchGrid is just my search component. The issue goes away when I remove <DropdownRefinementList attribute="major" />, so that has to be the problem.
Is there something wrong with my implementation? How can I fix this?
It should be import DropdownRefinementList from "./Dropdown"
This is because you're exporting default from your Dropdown.js file.

ReactJs Package

I have created a package with multiple components and exported it in it's index.js file. I am trying to
import those components and us it. as follows:
**package index.js**
export {default as F1Button } from './f1Button';
export {F1ButtonGroup} from './f1ButtonGroup';
export {F1Label} from './f1Label';
**Used it in New.js**
import { F1Button,F1ButtonGroup,F1Label } from 'package';
function App() {
return (
<div className="App">
<F1Button name='test' buttonText="hi"></F1Button>
<F1ButtonGroup symbols={symbols}></F1ButtonGroup>
<F1Label text="label"></F1Label>
</div>
);
}
Getting error as :
Error: Element type is invalid: expected a string (for built-in components)
or a class/function (for
composite components) but got: undefined. You likely forgot to export your
component from the file
it's defined in, or you might have mixed up default and named imports.
Check the render method of `App`.
How to export multiple components in index.js and import it our file?
Exporting a single component as default
export default sample
Exporting multiple components
export {
sample1,
sample2
}
Importing a default component (here its not required to import as the same name)
import Hello from './sample'
Importing Multiple components (you need to use the exact name of export)
import {sample1, sample2} from './sample'

React Error: Error: Element type is invalid

Earlier today, I tried running create-react-app, but I got an error about templates and how my version of React may be out of date. So I removed React globally and then reinstalled. I ran create-react-app again and it started working again.
I was trying to create an app afterwards but I keep getting the following message:
×
Error:
Element type is invalid: expected a string (for built-in
components) or a class/function (for composite components) but got:
object. You likely forgot to export your component from the file it's
defined in, or you might have mixed up default and named imports.
Check the render method of App.
I never got this message before while using React. Here is my code so far:
App.js
import React, { Component } from 'react';
import UserOutput from './Components/UserOutput';
import UserInput from './Components/UserInput'
class App extends Component {
render() {
return (
<div>
<UserInput />
<UserOutput username="Test" />
</div>
)
}
};
export default App;
UserOutput.js
import React from 'react';
function UserOutput(props) {
return <h1>this is my username: {props.username} </h1>;
}
export default UserOutput;
UserInput.js
import React from 'react';
function UserInput() {
return <input>Name</input>
};
export default UserInput;
I tried searching for a fix for my error, but could not find a solution. I believe I am importing everything correctly and it complies without error in my IDE, but I get the error in my browser.

Using React.lazy gives Element type is invalid

So I have isolated the issue to this import:
const SelectRecipients = React.lazy(() =>
import('../components/SelectRecipients'))
I get the following error:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
I thought maybe it was an issue with the component itself and tried making a test component as follows:
import React from 'react'
export default () => {
return(<div>Hi</div)}
and then imported it instead of SelectRecipients and still got the error
CodeSandbox
For me, issue was having another index.js in the path, and my new component's codes was in index.jsx. This is because the index.js has higher priority when resolving imports.

Resources