Hi, I spent some time trying to mount stateless component with passed props. It wasn't successfully, every time when I ran tests I got this error:
Error: Uncaught [Error: Warning: Invalid DOM property `%s`. Did you mean `%s`?%s]
7 | console.error = message => {
> 8 | throw new Error(message);
9 | };
...
at mount (node_modules/enzyme/build/mount.js:21:10)
at Suite.<anonymous> (src/components/OrderedList/index.test.js:25:19)
at Object.describe (src/components/OrderedList/index.test.js:9:1)
Based on enzyme docs it should work. Also Without props it seems it works, shallow works properly as well.
Here is my simplified component _(OrderedList/index.js)_:
const OrderedList = ({title, items, type}) => {
const orderedListItems = items.map((item) => {
return (
<li
key={item.id}
className="orderedlist__item">
<div class="orderedlist__item-dash"></div>
<a
href={item.url}
target="_blank"
className="orderedlist__text"
>{item.name}</a>
</li>
)
});
return (
<div className="orderedlist">
<h5 className="orderedlist__title font-s-12-secondary">{title}</h5>
<ol className="orderedlist__list">
{orderedListItems}
</ol>
</div>
)
};
OrderedList.propTypes = {
title: PropTypes.string,
items: PropTypes.instanceOf(Array), // tried to replace with PropTypes.arrayOf(PropTypes.shape({})) it didn't work
type: PropTypes.string
};
OrderedList.defaultProps = {
title: '',
items: [],
type: ''
};
export default OrderedList;
and my test _(OrderedList/index.test.js)_:
import {shallow, render, mount} from 'enzyme';
import React from 'react';
import OrderedList from './index';
describe('<OrderedList />', () => {
const title = 'title';
const items = [
{
id: 1,
text: 'test text 1',
url: 'test.urlone'
},
{
id: 2,
text: 'test text 2',
url: 'test.urltwo'
}
];
const component = mount(<OrderedList title={title} items={items} type=""/>);
expect(component.find('li').first().childAt(1).is('a')).toBeTruthy();
it won't work as well, if I change two last lines like so:
const component = mount(<OrderedList/>);
component.setProps({...items}); // <- when I use two params like component.setProps({...title, ...items}) it doesn't show an error but also not change the DOM structure, so below test will fail
expect(component.find('li').first().childAt(1).is('a')).toBeTruthy();
and my _jestsetup.js_ file:
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });
console.error = message => {
throw new Error(message);
};
The most interesting thing that I found was the case when I called several tests with the same component (see comments in the code), like so:
... <same variables as above> ...
describe('props tests', () => {
beforeEach(() => {
component = mount(<OrderedList />);
});
it('renders 1 simple link', () => {
expect('items' in component.props()).toBeTruthy(); // test result: true
expect(component.find('li').first().childAt(0).is('a')).toBeTruthy(); // test result: false
component.unmount();
});
it('renders masked link', () => {
component.setProps({...title, ...items});
component.update();
expect('items' in component.props()).toBeTruthy(); // test result: true
component.unmount();
});
});
Mount works with passed props like in docs: https://airbnb.io/enzyme/docs/api/ReactWrapper/mount.html
macOS High Sierra v10.13.6
node v8.12.0
npm v6.4.1
| library | version
| ------------------- | -------
| enzyme | ^3.7.0
| react | ^16.5.2
| react-dom | ^16.5.2
| react-test-renderer | ^16.5.2
| adapter (below) | ^1.6.0
I'm not sure why the error message is wrong, but you have this code:
<div class="orderedlist__item-dash"></div>
and that should be this:
<div className="orderedlist__item-dash" />
(className, not class)
Damn! Thanks, I haven't even noticed it, I thought it's probably related to the fact that it is a stateless component or something wrong with the configuration file.
I agree the error could have a bit better message and the stacktrace.
Since i think that error is coming from react itself (and your console.error shim is broken, because it鈥檚 not supporting printf-style formatting), i don鈥檛 think there鈥檚 anything actionable here.