I'm trying to get some basic understanding around React Native tests w/enzyme and react-native-mock.
Not included below: A custom compiler for mocha to get the babel goodness.
My code is as follows:
Block.jsx
:
import React from 'react';
import {View} from 'react-native';
export default ({title, ui}) => (
<View>
Title: {title}
</View>
);
Block.test.js
import { shallow } from 'enzyme';
import { expect } from 'chai';
import {Block} from '../';
import React from 'react';
describe('<Block /> with props: title', () => {
it('should have correct props', () => {
expect(
shallow(<Block title="Something" />).props()
).to.deep.equal( {title:"Something"} );
});
it('should have correct title', () => {
expect(
shallow(<Block title="Something" />).text()
).to.equal( "Something" );
});
});
Test results
Mocha command:
mocha --compilers js:./test/support/compiler.js --require react-native-mock/mock --recursive **/test/*.test.js --watch
Mocha test results:
<Block /> with props: title
1) should have correct props
2) should have correct title
2 failing
1) <Block /> with props: title should have correct props <Text />:
AssertionError: expected { Object (children) } to equal { title: 'Something' }
+ expected - actual
{
- "children": [
- "Title: "
- "Something"
- ]
+ "title": "Something"
}
at Context.<anonymous> (components/test/Block.test.js:24:120)
2) <Block /> with props: title should have correct title <Text />:
AssertionError: expected '<View />' to equal 'Something'
+ expected - actual
-<View />
+Something
at Context.<anonymous> (components/test/Block.test.js:28:119)
Unexpected behavior
props()
seems to get the correct values, but in a different format than described by the apitext()
doesnt render the nodestextContent
, but instead, the stringified tag "<View />
"
Alternative: props().children
Given the component:
import React from 'react';
import {View, Text} from 'react-native';
export default ({title, ui}) => (
<View>
<Text> The title...</Text>
{title}
</View>
);
props().children
is the array [<Text component instance>, "Something"]
So the follow test passes:
it('should have correct props', () => {
expect(
shallow(<Block title="Something" />).props().children
).to.contain( "Something" );
});
Question
Why is Enzyme API behaving differently that described in the docs?
Specifically looking at the docs shallow(<Block title="Something" />).text()
should equal something like: The title...Something
Am I doing something incorrect, or is it one the technologies I'm using?
EDIT 1: Other problems
html()
, render()
, update()
also don't seem to work with my setup
EDIT: React native only works with shallow
at the moment
I'm trying to get some basic understanding around React Native tests w/enzyme and react-native-mock.
Not included below: A custom compiler for mocha to get the babel goodness.
My code is as follows:
Block.jsx
:
import React from 'react';
import {View} from 'react-native';
export default ({title, ui}) => (
<View>
Title: {title}
</View>
);
Block.test.js
import { shallow } from 'enzyme';
import { expect } from 'chai';
import {Block} from '../';
import React from 'react';
describe('<Block /> with props: title', () => {
it('should have correct props', () => {
expect(
shallow(<Block title="Something" />).props()
).to.deep.equal( {title:"Something"} );
});
it('should have correct title', () => {
expect(
shallow(<Block title="Something" />).text()
).to.equal( "Something" );
});
});
Test results
Mocha command:
mocha --compilers js:./test/support/compiler.js --require react-native-mock/mock --recursive **/test/*.test.js --watch
Mocha test results:
<Block /> with props: title
1) should have correct props
2) should have correct title
2 failing
1) <Block /> with props: title should have correct props <Text />:
AssertionError: expected { Object (children) } to equal { title: 'Something' }
+ expected - actual
{
- "children": [
- "Title: "
- "Something"
- ]
+ "title": "Something"
}
at Context.<anonymous> (components/test/Block.test.js:24:120)
2) <Block /> with props: title should have correct title <Text />:
AssertionError: expected '<View />' to equal 'Something'
+ expected - actual
-<View />
+Something
at Context.<anonymous> (components/test/Block.test.js:28:119)
Unexpected behavior
props()
seems to get the correct values, but in a different format than described by the apitext()
doesnt render the nodestextContent
, but instead, the stringified tag "<View />
"
Alternative: props().children
Given the component:
import React from 'react';
import {View, Text} from 'react-native';
export default ({title, ui}) => (
<View>
<Text> The title...</Text>
{title}
</View>
);
props().children
is the array [<Text component instance>, "Something"]
So the follow test passes:
it('should have correct props', () => {
expect(
shallow(<Block title="Something" />).props().children
).to.contain( "Something" );
});
Question
Why is Enzyme API behaving differently that described in the docs?
Specifically looking at the docs shallow(<Block title="Something" />).text()
should equal something like: The title...Something
Am I doing something incorrect, or is it one the technologies I'm using?
EDIT 1: Other problems
html()
, render()
, update()
also don't seem to work with my setup
EDIT: React native only works with shallow
at the moment
4 Answers
Reset to default 7Solution 1: A solution for textContent
From an Enzyme example app:
const title = "Blah";
const wrapper = shallow(<Block title={title} />);
expect(wrapper.length).to.equal(1);
expect(wrapper.contains(<Text>{title}</Text>)).to.equal(true);
Solution 2: More semantic
Ok the more semantic version of Alternative: props().children above is below. This Github discussion also helped.
Block.js
:
import React from 'react';
import {View, Text} from 'react-native';
export default ({title, ui}) => (
<View>
<Text data={title}>{title}</Text>
</View>
);
Block.test.js
:
it('should have correct props', () => {
const title = title;
expect(
shallow(<Block title={title} />)
.find('Text') // Use selector to get certain children
.first() // Get the first child
.props() // Get its props
.data
).to.equal(title)
});
You can reference the specific prop you would like to test:
expect( shallow(<Block title="Something" />).prop('title') ).to.equal( "Something" );
text() is not doing what you are thinking here. Have a look at the second example in the docs, shallow won't render out your
<View>
tag
Another solution (very similar to props().children
) is to access children in prop
it('should have correct props', () => {
expect(
shallow(<Block title="Something" />).prop('children')
).toBe( "Something" );
});
You can ue expect(wrapper.find(Foo).render().text()).to.equal('Hello World')
trick
.to.equal
does a "triple equals" check, meaning two objects will not be===
unless they are references to the same object in memory. Instead, use.to.deep.equal
when comparing object. – ZekeDroid Commented Jun 8, 2016 at 19:03shallow().text()
returning what's rendered. Instead always use.props().children
. – ZekeDroid Commented Jun 8, 2016 at 19:09expect(shallow(<div><b>important</b></div>).text()).to.equal('important');
airbnb.io/enzyme/docs/api/ShallowWrapper/text.html – Ashley Coolman Commented Jun 8, 2016 at 20:12Returns a string of the rendered text of the current render tree. This function should be looked at with skepticism if being used to test what the actual HTML output of the component will be.
This only works if you don't have a React Component in there. As soon as you do, it will return the.toString
method of the component, which is usually just the name. – ZekeDroid Commented Jun 8, 2016 at 21:29