I have created a styled components in a sperate file with the same name and .css.jsx for example Abc.jsx have Abc.css.jsx and it's imported to the Abc.jsx to use. But when I try to test Abc.jsx I get the below error from the Enzyme mount,
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.
Seems like React can't locate the styles written in my Abc.css.jsx. Does anyone know the reason for this and how to fix this?
Abc.jsx
import * as Styled from './Abc.css';
function Abc() {
return (<Styled.Title>ABC</ Styled.Title>);
}
export default Abc
Abc.css.jsx
import styled from 'styled-components';
export const Title = styled.div`
`;
Abc.test.js
import Abc from '../../../components/Abc';
import { mount } from 'enzyme';
describe("My Abc tests", () => {
let wrapper;
beforeAll(() => {
wrapper = mount(<Abc />);
})
test("check api call", async () => {
})
});
jest.config
module.exports = {
testPathIgnorePatterns: ["<rootDir>/.next/", "<rootDir>/node_modules/"],
setupFilesAfterEnv: ["<rootDir>/setupTests.js"],
moduleNameMapper: {
"\\.(css|less|scss|sass)$": "identity-obj-proxy"
},
transform: {
"^.+\\.(js|jsx|ts|tsx)$": "<rootDir>/node_modules/babel-jest",
"\\.(css|less|scss|sass)$": "identity-obj-proxy"
}
};
I was finally able to get the same error as you! in this codesandbox
So the issue is in the naming of styled-component files. You name them [something].css.jsx.
And in you jest.config file tries to map them as classes or something like that, I assume it is because of the import as it ends with '.css'
...
moduleNameMapper: {
"\\.(css|less|scss|sass)$": "identity-obj-proxy"
},
...
There are a couple of things you can do here.
Change naming convention for styled-components. From[something].css.jsx to [something].styled.jsx.
Remove moduleNameMapper
Remove css from moduleNameMapper
My personal favorite is option 1.
Related
I have a react native app that I am trying to run tests on, I have set up a basic greeting component as shown below called Greetings.js:
import React from 'react';
import {View, Text} from 'react-native';
const Greetings = ({hello}) => {
return (
<View>
<Text>{hello}</Text>
</View>
);
};
export default Greetings;
This is the test I am running called Greetings.test.js:
import React from 'react';
import {render, screen} from '#testing-library/react-native';
import Greetings from './Greetings';
describe('Greetings component', () => {
it('renders hello world as a test', () => {
render(<Greetings hello="Hello World!" />);
const helloWorldElement = screen.getByText('Hello World!');
expect(helloWorldElement).toBeInTheDocument();
});
});
For some reason it doesnt recognise the react native components, this is the error when running the test:
FAIL app/__tests__/components/Account/Greetings.test.js
● Console
console.error
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You li
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 `Greetings`.
at Greetings (C:\Users\meeve\OneDrive\Desktop\Cozify\smartliving-app\app\__tests__\components\Account\Greetings.js:4:21)
5 | return (
6 | <View>
> 7 | <Text>{hello}</Text>
| ^
8 | </View>
9 | );
10 | };
at printWarning (node_modules/react/cjs/react.development.js:220:30)
at error (node_modules/react/cjs/react.development.js:196:5)
at Object.createElementWithValidation [as createElement] (node_modules/react/cjs/react.development.js:2215:7)
at Greetings (app/__tests__/components/Account/Greetings.js:7:7)
at renderWithHooks (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6016:18)
at mountIndeterminateComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8744:13)
at beginWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9966:16)
at performUnitOfWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13800:12)
It shows the same error for the View Component.
Should it not automatically recognize these components after initial setup?
I have installed the following:
yarn add install -dev react-test-renderer#17.0.1 #testing-library/react-native #testing-library/jest-native
The current Jest configuration in the package.json file:
"jest": {
"preset": "react-native",
"coverageThreshold": {
"app/**/selectors.{js,ts,tsx}": {
"_comment": "Let's strive to increase coverage, instead of lowering it!",
"lines": 57
}
},
"coverageDirectory": ".coverage/",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"native"
],
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js|jsx)$",
"testPathIgnorePatterns": [
"\\.snap$",
"<rootDir>/node_modules/"
],
"cacheDirectory": ".jest/cache",
"setupFiles": [
"./jest.setup.js"
]
}
Seems nothing wrong with the component rendering but the test.
You can use getByText query which can be obtained from render.
Please refer to React Native Testing Library for more information.
import React from 'react';
import {render} from '#testing-library/react-native';
import Greetings from './Greetings';
describe('Greetings component', () => {
it('renders hello world as a test', () => {
const {getByText} = render(<Greetings hello="Hello World!" />);
expect(getByText('Hello World!')).toBeDefined();
});
});
The application was set up a while back and it seems they had mocked out the react-native imports in the jest.setup.js file so that was causing the issue
Almost no search results for "nextjs pug". Google suggests the results for "nuxtjs pug" which is the completely different framework.
One of two relevant search results is this issue. The suggested minimal setup requires too much plugins (I can't understand why I need each of them), too complicated cofigurations and does not work with current versions.
package.json
"#babel/core": "^7.0.0-beta.51",
"#babel/plugin-transform-react-jsx": "^7.0.0-beta.51",
"#babel/plugin-transform-runtime": "^7.0.0-beta.51",
"#babel/preset-env": "^7.0.0-beta.51",
"#babel/runtime": "^7.0.0-beta.51",
"babel-core": "7.0.0-bridge.0",
"babel-plugin-transform-react-pug": "git://github.com/shirohana/babel-plugin-transform-react-pug.git#dist"
} } ```
**.babelrc.js**
```javascript module.exports = function (api) { api.env() return {
presets: [
['#babel/env', { useBuiltIns: 'entry' }]
],
plugins: [
['babel-plugin-transform-react-pug'],
['#babel/plugin-transform-react-jsx'],
['#babel/plugin-transform-runtime']
] } } ```
https://github.com/pugjs/babel-plugin-transform-react-pug/pull/48#issuecomment-406466928
Other relevant search result is Is it possible to use Framer Motion in React with pug question. I tried below solution:
{
"presets": ["next/babel"],
"plugins": [
"transform-react-pug",
[
"transform-jsx-classname-components"
],
"transform-react-jsx"
]
}
It's very interesting, but sometimes in works, sometimes - no.
I tried to create two projects. Firstly it works in both projects but then broke with error:
ReferenceError: React is not defined
at HomePage (C:\Users\****\Build\InteractiveImplementation\server\pages\index.js:63:3)
at processChild (C:\Users\****\node_modules\react-dom\cjs\react-dom-server.node.development.js:3353:14)
at resolve (C:\Users\****\node_modules\react-dom\cjs\react-dom-server.node.development.js:3270:5)
at ReactDOMServerRenderer.render (C:\Users\****\node_modules\react-dom\cjs\react-dom-server.node.development.js:3753:22)
at ReactDOMServerRenderer.read (C:\Users\****\node_modules\react-dom\cjs\react-dom-server.node.development.js:3690:29)
at renderToString (C:\Users\****\node_modules\react-dom\cjs\react-dom-server.node.development.js:4298:27)
at Object.renderPage (C:\Users\****\node_modules\next\dist\next-server\server\render.js:53:854)
at Function.getInitialProps (C:\Users\****\Build\InteractiveImplementation\server\pages\_document.js:556:19)
at loadGetInitialProps (C:\Users\****\node_modules\next\dist\next-server\lib\utils.js:5:101)
at renderToHTML (C:\Users\****\node_modules\next\dist\next-server\server\render.js:53:1145)
This error will leave even don't use the Pug:
import React, { ReactNode } from "react";
class TestComponent extends React.Component<TestComponent.Properties,TestComponent.State> {
public state: TestComponent.State = {
count: 0
}
public render(): ReactNode {
// return pug`
// main
// div ${this.props.message}
// div props.message
// `;
return (
<div onClick={() => this.increment(1)}>
{this.props.message} {this.state.count}
</div>
)
}
private increment(amt: number): void {
this.setState((state: TestComponent.State): TestComponent.State => ({
count: state.count + amt,
}));
};
}
namespace TestComponent {
export type Properties = {
message: string;
}
export type State = {
count: number;
};
}
export default TestComponent;
You may want to know what I did directly before application broken.
Well, I had not record each my of actions, but I had not make some big changes like directories renamig or configuration editing directly before first failed launch. Anyway, we need know where config is wrong and how to fix it.
Try to import this in your pages/index.tsx
import React from "react";
For Babel transpilation of any jsx code, react import is needed. Import react wherever you use jsx code snippets. This fixes your issue.
Fairly new to rollup and have come across this problem. I've googled but I can't seem to find an answer but I am fairly sure it is due to the rollup config.
What I am trying to do
I have a React library I created that uses (among others) styled-components, including a number of components that extend other components created using styled-components via .withComponent.
Code example
Badge.js: -
import styled from "styled-components"
const Badge = styled.span`
...
`
export default Badge
Button.js: -
import Badge from "#my/library/Badge"
import styled from "styled-components"
export const Button = styled(Badge.withComponent("button"))`
...
`
rollup.config.js: -
import multiEntry from "rollup-plugin-multi-entry"
import babel from "rollup-plugin-babel"
export default {
input: __dirname + "/src/*.js",
plugins: [
babel({}),
multiEntry()
],
output: {
dir: __dirname + "/lib/",
format: "esm",
},
preserveModules: true,
external: ["#my/library", "styled-components"],
}
babel.config.js: -
module.exports = {
presets: [
'#babel/preset-env',
'#babel/preset-react',
],
plugins: [
"#babel/plugin-proposal-class-properties",
"babel-plugin-styled-components"
],
};
rollup produces the following code: -
Badge.js: -
import { taggedTemplateLiteral as _taggedTemplateLiteral } from './_virtual/_rollupPluginBabelHelpers.js';
import styled from 'styled-components';
function _templateObject() {
var data = _taggedTemplateLiteral([
...
]);
_templateObject = function _templateObject() {
return data;
};
return data;
}
var Badge = styled.span(_templateObject(), function (props) {
...
});
Button.js: -
import styled from 'styled-components';
import Badge from '#my/library/Badge';
var Button = styled(Badge.withComponent("button"))(_templateObject(), function (props) {
...
});
The problem
When running webpack on my app, I get the following error message: -
var Button = (0, _styledComponents["default"])(_Badge["default"].withComponent("button"))(_templateObject(), function (props) {
^
TypeError: _Badge.default.withComponent is not a function
I have no idea why this is happening. I thought that having styled-components listed as an external would resolve this but it hasn't. Again, I am new to rollup. Any help greatly appreciated.
I don't know rollup but you can try with the new syntax of styled-components with prop as
https://www.styled-components.com/docs/api#as-polymorphic-prop
import Badge from "#my/library/Badge"
import styled from "styled-components"
export const Button = styled(Badge).attrs({
as: "button"
})`
...
`
You have to make sure that your component Badge is a styled-components. If not, you could transform it with styled.
https://www.styled-components.com/docs/basics#styling-any-component
if it doesn't help , try to add style-components in globals of output in config rollup
const globals = {
react: 'React',
'styled-components': 'styled',
}
So I have a React Class lets call it A. I'm running a jest test on it, but I keep getting an
Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
In the React Class I'm doing :
export class A extends Component ..
In the jest test file I'm doing :
import { A } from './A.js'
when I run :
const wrapper = mount(<A />)
I get the error above. I'm running on a jsdom environment for jest. I'm kind of at a loss why this wouldn't work. I've read that some people export as default, but I don't see why doing a proper name import shouldn't work. Does anyone have any ideas what could be the issue?
real code :
jest file :
import Adapter from 'enzyme-adapter-react-16';
import Enzyme, { shallow, mount } from 'enzyme';
import React from 'react';
import { A } from '../A';
Enzyme.configure({ adapter: new Adapter() });
/**
* Test Suite
*/
describe('A test', () => {
it('calls componentDidMount', () => {
const wrapper = mount(<A />);
})
})
react class :
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export class A extends Component {
...
}
jest config :
module.exports = {
clearMocks: true,
// The directory where Jest should output its coverage files
coverageDirectory: 'coverage',
// The test environment that will be used for testing
testEnvironment: 'jsdom',
testURL: 'http://localhost/',
// Directory to search for tests
roots: ['src/'],
// The glob patterns Jest uses to detect test files
testMatch: [
'**/__tests__/**/*.[jt]s?(x)',
'**/?(*.)+(spec|test).[tj]s?(x)'
],
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
testPathIgnorePatterns: [
'/node_modules/'
],
snapshotSerializers: [
'enzyme-to-json/serializer'
]
};
That is the error that you get when you attempt to render an Object as a Component.
Here is an example:
A.js
import * as React from 'react';
const AnObject = {}; // <= NOT a component
export class A extends React.Component {
render() {
return (<AnObject/>); // <= Attempt to render an object as a component
}
}
A.test.js
import * as React from 'react';
import { mount } from 'enzyme';
import { A } from './A';
test('A', () => {
const wrapper = mount(<A/>); // <= Fails with "Invariant Violation: Element type...
});
...which gives the following error:
Invariant Violation: 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 A.
5 |
6 | test('A', () => {
> 7 | const wrapper = mount(<A/>);
| ^
8 | });
9 |
You'll want to check A at the point of the test and make sure it is actually your component.
Then work backwards and make sure everything rendered as a component by A is actually a component (and so on) until you find the non-component that is being used as a component.
LayoutGroup is not a default export
You cannot call LayoutGroup via import { A } from '../A'; it is not exported with default so you cannot rename it as a named import.
To do something like this change
import { A } from './A.js'
to
import A from './A.js'
and
export class LayoutGroup extends Component {
to
export default class LayoutGroup extends Component {
I am working on a React-Nextjs project and trying to integrate the BDD tool cucumber for specification and feature level testing. Though am having some trouble integrating cucumber with React when using enzyme to shallow render the component:
Here's the errors am getting:
TypeError: Cannot read property 'contextTypes' of undefined at const wrapper = shallow(<Referrer/>);
Code for cucumber step test file:
import React from 'react';
import { defineSupportCode } from "cucumber";
import { shallow } from "enzyme";
import {Referrer} from "./../../components/Referrer";
defineSupportCode(({ Given, When, Then }) => {
Given("I want to do something", function (callback) {
// Write code here that turns the phrase above into concrete actions
callback();
});
When("Xyz link is clicked", function (callback) {
const wrapper = shallow(<Referrer/>);
... // Write code here that turns the phrase above into concrete actions
});
Then("Appropriate action happens", function (callback) {
// Write code here that turns the phrase above into concrete actions
callback();
});
});
The component is a simple UI component, pretty straight forward, here's its structure:
import React from "react"; // eslint-disable-line no-unused-vars
export default class Referrer extends React.Component {
render () {
return (
<div className="some-class" id="some-id">
// html tags
<style jsx>{`
.some-class {
//styling
}
.some-class2 {
//styling
}
`}
</style>
</div>
);
}
}
I am using "cucumber": "^2.3.1", "enzyme": "^2.6.0", I am not sure how to resolve this, no help so far online, I have been trying to debug for last couple hours but no luck.
Exact error snippet:
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.
TypeError: Cannot read property 'contextTypes' of undefined at const wrapper = shallow(<Referrer/>);
I realized what was wrong, my Referrer component is being exported as a default, though I wasn't importing it correctly. I had to import it as import Referrer from "./../../components/Referrer"; instead of import {Referrer} from "./../../components/Referrer";