I've been studying React, and I tried to make a jest test with the shallowRender but always return null on shallowRenderer.getRenderOutput()
MyComponent.react.js
import React from 'react';
export default class MyComponent extends React.Component {
render() {
return <div>Hello World!</div>;
}
}
__test__/MyComponent.react.js
jest.dontMock('../MyComponent.react.js');
import React from 'react/addons';
import MyComponent from '../MyComponent.react.js';
var TestUtils = React.addons.TestUtils;
describe('MyComponent', () => {
it('test', () => {
let shallowRenderer = TestUtils.createRenderer();
shallowRenderer.render(<MyComponent/>);
let vdom = shallowRenderer.getRenderOutput();
console.log(vdom);
expect(1).toEqual(1);
});
});
npm test
> jest-test#1.0.0 test /home/bruno/Stuffs/jest-test
> jest
Using Jest CLI v0.5.8
PASS __tests__/MyComponent.js (0.897s)
null
1 test passed (1 total)
Run time: 1.189s
package.json
{
...
"scripts": {
"test": "jest"
},
"devDependencies": {
"babel": "^5.8.23",
"babel-jest": "^5.3.0",
"jest-cli": "^0.5.8",
"react": "^0.13.3",
"skin-deep": "^0.6.1"
},
"jest": {
"scriptPreprocessor": "<rootDir>/node_modules/babel-jest",
"testFileExtensions": [
"es6",
"js"
],
"unmockedModulePathPatterns": [
"<rootDir>/node_modules/react"
],
"moduleFileExtensions": [
"js",
"json",
"es6"
]
}
}
The automocking feature does not work with the ES2015 imports so, if you change your MyComponent import with require statement, your code should be work.
This is the Github issue.
jest.dontMock('../MyComponent.react.js');
import React from 'react/addons';
const MyComponent require('../MyComponent.react.js'); // This is the important line!!
var TestUtils = React.addons.TestUtils;
describe('MyComponent', () => {
it('test', () => {
let shallowRenderer = TestUtils.createRenderer();
shallowRenderer.render(<MyComponent/>);
let vdom = shallowRenderer.getRenderOutput();
console.log(vdom);
expect(1).toEqual(1);
});
});
Related
I'm trying to test a component using the react-test-renderer library and i'm getting this error.
Header.test.js:
import ReactShallowRenderer from "react-test-renderer/shallow";
import React from "react";
import Header from "../../components/Header/Header";
test("should render Header correctly", () => {
const renderer = new ReactShallowRenderer();
renderer.render(<Header />);
// Returning the render output of the jsx
console.log(renderer.getRenderOutput());
});
That's my jest config:
"jest": {
"verbose": true,
"transform": {
"^.+\\.js$": "babel-jest",
"^.+\\.(css|scss|less)$": "jest-css-modules"
}
My babelrc:
{
"env": {
"development": {
"plugins": ["transform-es2015-modules-commonjs"]
},
"test": {
"plugins": ["transform-es2015-modules-commonjs"]
}
}
}
I have search all stackoverflow and github issues and haven't found a solution for this. I currently have a project that uses react#15.4.1 and I am trying to set up Enzyme.
Whenever I try to Enzyme.mount() a component I get the following error:
TypeError: _reactDom2.default.render is not a function
However if I Enzyme.shallow() shallow render the component it works.
Here is a sample test that shows the code that triggers the error:
TestComponent.test.js
import { configure, mount, shallow } from "enzyme"
import Adapter from "enzyme-adapter-react-15.4"
import React from "react"
import TestComponent from "./TestComponent"
configure({ adapter: new Adapter() })
describe("Example Tests", () => {
test("mount does not work", () => {
const shallowRendered = shallow(<TestComponent />) <-- this works
const mountedComponent = mount(<TestComponent />) <-- this throws
})
})
TestComponent.js
import React from "react"
export default class TestComponent extends React.Component {
render() {
return <p>test</p>
}
}
package.json
//...
"dependencies": {
//...
"react": "15.4.1",
"react-dom: "15.4.1"
}
"devDependencies": {
//...
"babel-jest": "24.1.0",
"enzyme": "~3.3.0",
"react-addons-test-utils": "15.4.1",
"react-test-renderer": "15.4.1",
"enzyme-adapter-react-15.4": "^1.3.1"
}
jest.config.js
module.exports = {
verbose: true,
collectCoverageFrom: ["<rootDir>/src/client/**/*.{js,jsx}"],
testPathIgnorePatterns: [
"node_modules",
"build",
],
transform: {
"^.+\\.js$": "babel-jest",
},
testEnvironment: "jsdom",
transformIgnorePatterns: ["<rootDir>/node_modules/"],
moduleNameMapper: {
"\\.(css|less)$": "<rootDir>/src/client/__mocks__/styleMock.js",
},
testURL: "http://localhost",
}
You need to import { configure } from enzyme.
import { configure } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
configure({ adapter: new Adapter() })
I am using jest and enzyme to test my react component. I am also using blueprint icons as one of the dependency in my react component. As part of my webpack config, following is added:
config.resolve.alias = {
blueprintIcons: path.resolve('./node_modules/#blueprintjs/icons'),
blueprint: path.resolve('./node_modules/#blueprintjs/core')
};
Following is added as part of jest config:
rootDir: '.',
roots: [
'<rootDir>/__test__/'
],
transformIgnorePatterns: [
'<rootDir>/node_modules/'
],
transform: {
'^.+\\.jsx?$': 'babel-jest'
},
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.jsx?$',
moduleDirectories: ['node_modules'],
moduleFileExtensions: [
'js',
'jsx',
'json',
'node'
],
moduleNameMapper: {
'\\.(css|scss)$': 'identity-obj-proxy',
blueprintIcons: '<rootDir>/node_modules/#blueprintjs/core'
blueprint: '<rootDir>/node_modules/#blueprintjs/core'
},
snapshotSerializers: ['enzyme-to-json/serializer']
};
Here is my component:
import React, { Component } from 'react';
import Icon from 'blueprint';
import IconNames from 'blueprintIcons';
class Foo extends Component {
render() {
return (
<div>
<p>Hello Foo</p>
<Icon icon={IconNames.HOME} iconSize={Icon.SIZE_LARGE}/>
</div>
);
}
}
export default Foo;
Here is my foo.test.js
import React from 'react';
import Foo from '../../src/Components/Foo';
import Adapter from 'enzyme-adapter-react-16';
import Enzyme, { mount, shallow } from 'enzyme';
describe('Reviews component', () => {
it('render component when loading in progress', () => {
const mountedComponent = mount(<Foo />);
});
});
When I am trying to test that component, the test fails with
TypeError: Cannot read property 'HOME' of undefined at IconNames.HOME
Here are some packages specified in my package.json
"babel-cli": "6.26.0",
"babel-core": "^6.26.3",
"babel-eslint": "^10.0.1",
"babel-jest": "^23.0.1",
"babel-loader": "7.1.4",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.1.1",
"enzyme-to-json": "^3.3.4",
"jest": "^23.1.0",
"jest-html-reporter": "^2.3.0",
"#blueprintjs/core": "^2.3.1",
"react": "16.2.0"
I am using react 16.2.0
I tried mocking it but doesn't work(maybe I am not doing it correctly) but here is the code which I am using:
jest.mock('#blueprintjs/icons', () => (
{ IconNames: {HOME: 'home' }}));
For me, the following solution worked:
In jest config:
moduleNameMapper: {
'^blueprint': '<rootDir>/node_modules/#blueprintjs/core',
'^#blueprintjs/(.*)$': '<rootDir>/node_modules/#blueprintjs/$1'
}
Rest everything remained the same.
I think mocking is a possible solution - Not sure exactly why your code is not working (possibly because it's not within the default key, or the name of the mock is incorrect), but you can try something else.
In your Jest config, add the following:
"setupFiles": [
"./__mocks__/mockIcons.js"
],
Create /__mocks__ folder in your root folder
Create mockIcons.js inside __mocks__ with the following code:
jest.mock("blueprint", () => ({
default: {
Icon: { SIZE_LARGE: 'large' }
}
}))
jest.mock("blueprintIcons", () => ({
default: {
IconNames: { HOME: 'home' }
}
}))
Try to use #blueprintjs/icons as the mock name if nothing else works.
If I use a Higher-Order Component (HOC) as a decorator, i.e.,
#withStyles({})
class Bar extends React.Component { ... }
I'd get this error with enzyme:
console.error node_modules/prop-types/checkPropTypes.js:19
Warning: Failed prop type: The prop `classes` is marked as required in `_class`, but its value is `undefined`.
in _class
If I use the function form, i.e.,
const Bar = withStyles({})(class extends React.Component { ... });
there are no errors.
Why?
Note that this warning only happens on a child component; see the code from reproduction steps for what I mean.
Reproduction steps
package.json:
{
"name": "test",
"version": "1.0.0",
"description": "",
"scripts": {
"test": "jest"
},
"author": "",
"dependencies": {
"prop-types": "^15.6.2",
"react": "^16.4.1",
"react-dom": "^16.4.1"
},
"devDependencies": {
"babel-jest": "^23.2.0",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-decorators-legacy": "^1.3.5",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"jest": "^23.3.0"
},
"babel": {
"plugins": [
"transform-class-properties",
"transform-decorators-legacy"
],
"presets": [
"env",
"react"
]
}
}
__tests__/app.test.js:
import Adapter from 'enzyme-adapter-react-16';
import Enzyme from 'enzyme';
import PropTypes from 'prop-types';
import React from 'react';
import { shallow } from 'enzyme';
Enzyme.configure({ adapter: new Adapter() });
const withStyles = styles => Component => class extends React.Component {
render() {
return <Component classes={styles} />
}
}
// This will produce a failed prop type warning:
#withStyles({})
class Bar extends React.Component {
static propTypes = {
classes: PropTypes.object.isRequired,
}
render() {
return <div>test</div>;
}
}
// This will NOT produce a failed prop type warning:
// const Bar = withStyles({})(class extends React.Component {
// static propTypes = {
// classes: PropTypes.object.isRequired,
// }
// render() {
// return <div>test</div>;
// }
// });
class Test extends React.Component {
render() {
return <Bar />;
}
}
it('renders without crashing', () => {
shallow(<Test />);
expect(true).toBe(true);
});
Run npm t
There are two code blocks: one with decoration and the other (currently commented out) with function form. Simply comment out the decorator block and uncomment the function form block to test both cases.
This problem originally arose when using material-ui and I can confirm that both cases render the same UI visually. This prevented me from using the decorator form of withStyles.
Note that there are some more investigations by me here: https://github.com/airbnb/enzyme/issues/1505
The #babel/plugin-proposal-decorators needs come before #babel/plugin-proposal-class-properties, i.e., in the package.json:
"babel": {
"plugins": [
"transform-decorators-legacy",
"transform-class-properties"
],
I'm trying to setup babel-plugin-rewire so that in my Jest tests I can generate a small test snapshot for a wrapper component instead of having a huge one with all the child components in it.
The settings seem all to be correct but I get the following error:
ReferenceError: Wrapper is not defined
at _get_original__ (app\components\Wrapper\tests\index.te
st.js:22:2168)
at _get__ (app\components\Wrapper\tests\index.test.js:22:
1912)
at Suite.<anonymous> (app\components\Wrapper\tests\index.
test.js:8:82)
at Object.<anonymous> (app\components\Wrapper\tests\index
.test.js:6:1)
at process._tickCallback (internal\process\next_tick.js:103:7)
package.json
"babel": {
"presets": [
[
"latest",
{
"es2015": {
"modules": false
}
}
],
"react"
],
"env": {
"test": {
"plugins": [
"babel-plugin-rewire",
"transform-es2015-modules-commonjs",
"dynamic-import-node"
]
...
"devDependencies": {
...
"babel-plugin-rewire": "^1.1.0",
webpack.base.babel.js
(common webpack configuration -same in webpack.basetest.babel.js)
module: {
loaders: [{
test: /\.js$/, // Transform all .js files required somewhere with Babel
loader: 'babel-loader?plugins=babel-plugin-rewire',
exclude: /node_modules/,
query: options.babelQuery,
},
My Test
for the Wrapper component that contains a Header child component:
import React from 'react';
import { shallow } from 'enzyme';
import Wrapper from '../index';
describe('<Wrapper />', () => {
console.log('Debugging >>> ' + JSON.stringify(Wrapper)); // Wrapper is defined but blows up here ##
// beforeEach(() => {
// Wrapper.__Rewire__('Header', class extends React.Component {
// render(){ return <div {...this.props}>TEST only the wrapper!!</div> }
// });
// })
// it('renders correctly', () => {
// const tree = shallow( <Wrapper myProps={testData.myProps} /> );
// expect(tree.html()).toMatchSnapshot();
// });
...
});
Thanks
UPDATE:
If I comment out in Wrapper the JSX where Header is used (even leaving the import for Header as it is) Wrapper.__Rewire__ becomes defined and therefore the beforeEach doesn't throw errors anymore.