最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin0浏览0评论

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

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

Share Improve this question edited Dec 29, 2016 at 8:36 Ashley Coolman asked Jun 8, 2016 at 14:12 Ashley CoolmanAshley Coolman 11.6k5 gold badges62 silver badges87 bronze badges 7
  • 2 Just to be clear, mocha's .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:03
  • Ah yes that would be misleading, I'll change that now – Ashley Coolman Commented Jun 8, 2016 at 19:05
  • 2 But yeah, there's no such thing as shallow().text() returning what's rendered. Instead always use .props().children. – ZekeDroid Commented Jun 8, 2016 at 19:09
  • @ZekeDroid I don't understand ^, as thats how I read the docs snippet expect(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:12
  • 1 Ah yeah but read just a bit above, and the example just below that one: Returns 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
 |  Show 2 more comments

4 Answers 4

Reset to default 7

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)
  });
  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

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

发布评论

评论列表(0)

  1. 暂无评论