Follow up on this (https://twitter.com/MicheleBertoli/status/936196097218883584) twitter discussion. I've got an issue with styled components not rendering my test, or not able to find elements.
I've got the following test:
import React from 'react';
import { shallow } from 'enzyme';
import toJson from 'enzyme-to-json';
import ShallowRenderer from 'react-test-renderer/shallow';
import renderer from 'react-test-renderer';
import 'jest-styled-components';
import { SelectProjects } from '../src/app/components/modules/SelectProjects';
describe('<SelectProjects /> - unit test', () => {
it('should render dumb component with projects', () => {
const projects = {
loading: false,
data: [
{ id: 1, name: 'Pack' },
{ id: 2, name: 'Portal' },
{ id: 3, name: 'Zorgboodschap' },
],
};
const props = {
projects,
history: {},
getProjects: jest.fn(),
projectsConfirmSelected: jest.fn(),
};
// Examples of https://gist.github.com/MicheleBertoli/4210aecb837b4048853c1481a6e1177f
// First try (second example)
const shallowRenderer = new ShallowRenderer();
shallowRenderer.render(<SelectProjects {...props} />);
const tree = shallowRenderer.getRenderOutput();
const rendererInput = shallowRenderer.find('input');
console.log('input', rendererInput);
const secondInput = tree.find('Input');
console.log('Input', secondInput);
// @ERROR TypeError: shallowRenderer.find is not a function
const treeInput = tree.find('input');
console.log('input', treeInput);
const treeInputEl = tree.find('Input');
console.log('Input', treeInputEl);
// @ERROR TypeError: tree.find is not a function
// Second try (first example)
const wrapper = shallow(<SelectProjects {...props} />).dive();
expect(toJson(wrapper)).toMatchSnapshot();
const input = wrapper.find('input');
console.log('input', input);
const inputStyled = wrapper.find('Input');
console.log('Input', inputStyled);
/* @OUTPUT
$ console.log __test__/SelectProjects.spec.js:96
$ input ShallowWrapper { length: 0 }
$ console.log __test__/SelectProjects.spec.js:98
$ Input ShallowWrapper { length: 0 } */
// Another try (not from examples)
const anotherTree = renderer.create(<SelectProjects {...props} />).toJSON();
const anotherTreeInput = anotherTree.find('input');
console.log('input', anotherTreeInput);
// @ERROR TypeError: tree.find is not a function
});
});
This doens't work as you can see above in my comments. I think this has to do with not good rendered styled components. My snapshot is as following:
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<SelectProjects /> - unit test should render dumb component with projects 1`] = `
.c0 {
max-width: 100vw;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
}
<section
className="c0"
>
<styled.form
onSubmit={[Function]}
>
<Title>
Selecteer de gewenste projecten
</Title>
<styled.input
name="search"
onChange={[Function]}
placeholder="Zoek naar een specifiek project.."
type="text"
/>
<styled.div
active={false}
key="1"
onClick={[Function]}
>
<styled.span
active={false}
/>
Pack
</styled.div>
<styled.div
active={false}
key="2"
onClick={[Function]}
>
<styled.span
active={false}
/>
Portal
</styled.div>
<styled.div
active={false}
key="3"
onClick={[Function]}
>
<styled.span
active={false}
/>
Zorgboodschap
</styled.div>
<styled.button
type="submit"
>
Bevestig
projecten
</styled.button>
</styled.form>
</section>
`;
I do have the following related packages installed:
"react": "^16.2.0",
"styled-components": "^2.2.3",
"babel-jest": "^21.2.0",
"babel-plugin-styled-components": "^1.3.0",
"enzyme": "^3.2.0",
"enzyme-adapter-react-16": "^1.1.0",
"enzyme-to-json": "^3.2.2",
"jest": "^21.2.1",
"jest-styled-components": "^4.9.0",
"react-test-renderer": "^16.2.0",
My Jest config is as below:
"jest": {
"verbose": true,
"transform": {
".*": "./__test__/__mock__/jestPreprocessor.js"
},
"moduleDirectories": [
"node_modules",
"src/app",
"src/app/components"
],
"moduleNameMapper": {
"^-!svg-react-loader.*$": "./__test__/__mock__/fileMock.js"
},
"snapshotSerializers": [
"enzyme-to-json/serializer"
],
"setupFiles": [
"./__test__/__settings__/shim.js",
"./__test__/__settings__/setup.js"
]
},
setup.js
import Enzyme, { shallow, render, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
// React 16 Enzyme adapter
Enzyme.configure({ adapter: new Adapter() });
// Make Enzyme functions available in all test files without importing
global.shallow = shallow;
global.render = render;
global.mount = mount;
shim.js
global.requestAnimationFrame = (callback) => {
setTimeout(callback, 0);
};
jestPreprocessor.js
const babelJest = require('babel-jest');
const includeStylesSvg = new RegExp(/require\(\s*\'.*\.(css|svg)\'\);/gm);
const storeStylesSvg = new RegExp(/= require\(\s*\'.*\.(css|svg)\'\);/gm);
module.exports = {
process: (src, filename) => {
return babelJest
.process(src, filename)
.replace(storeStylesSvg, '= \'\';')
.replace(includeStylesSvg, '');
}
};
Hope this will help.
Thanks in advance for trying to solve my issue.
Seems to be "fixed" using Input.displayName = 'Input'; as mentoined in the last comment from https://github.com/styled-components/styled-components/issues/896
Is this a proper fix and expected behavior?
Oh, now I see the "problem" @Ronnyrr.
I didn't get that having styled.* was causing you an issue in finding components, sorry.
Thank you very much for opening the issue.
Using displayName seems a correct solution, but what I usually do is just referring to the component itself (see last expectation in the following example):
test('shallow', () => {
const Input = styled.input``
const Container = styled.div``
const wrapper = shallow(
<Container>
<Input />
</Container>
)
expect(wrapper).toMatchSnapshot()
expect(wrapper.find('input')).toHaveLength(0)
expect(wrapper.find(Input)).toHaveLength(1)
})
I hope this helps!
Most helpful comment
Oh, now I see the "problem" @Ronnyrr.
I didn't get that having
styled.*was causing you an issue in finding components, sorry.Thank you very much for opening the issue.
Using
displayNameseems a correct solution, but what I usually do is just referring to the component itself (see last expectation in the following example):I hope this helps!