Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enzyme's shallow().text() with React Native doesn't work as I expected

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

  1. props() seems to get the correct values, but in a different format than described by the api
  2. text() doesnt render the nodes textContent, 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

like image 811
Ashley Coolman Avatar asked Jun 08 '16 14:06

Ashley Coolman


Video Answer


4 Answers

Solution 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)
  });
like image 27
Ashley Coolman Avatar answered Oct 09 '22 03:10

Ashley Coolman


You can ue expect(wrapper.find(Foo).render().text()).to.equal('Hello World') trick

like image 198
Kasra Avatar answered Oct 09 '22 03:10

Kasra


  1. You can reference the specific prop you would like to test:

    expect( shallow(<Block title="Something" />).prop('title') ).to.equal( "Something" );

  2. 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

like image 4
Ryan27 Avatar answered Oct 09 '22 05:10

Ryan27


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" );
  });
like image 2
Black Avatar answered Oct 09 '22 05:10

Black