当前位置: 首页 > 工具软件 > Enzyme > 使用案例 >

Enzyme

郎嘉树
2023-12-01

Since the enzyme can make us get easier to update to new version of React and make our test code more lean and maintainable
You'd better not use props() to get props from component, because Enzyme document said that only the root component can get props by the function. We can use chai-moment to do the assertion

Render a component

Please use methods in require('test/unit/helpers/renderHelpers') to render component, do not use enzyme directly, this gives us the flexibility to handle the memory issue.

  • Currently the renderHelper.js is only on the spike branch. And will make a pr soon.
  • You can also checkout this spike branch to see how we change the existing tests to enzyme.

UI component

const {mount} = require('test/unit/helpers/renderHelpers')

const wrapper = mount(<div></div>);

You can specify the DOM node you want to mount on by provide the second argument:

const container = document.createElement('div');

const wrapper = mount(<div></div>, {
  attachTo: container
});

enzyme also provide shallow render, but I suggest to use mount for keeping things consistant.

Page or component with route dependency

const {mountWithRouteContext} = require('test/unit/helpers/renderHelpers')

const wrapper = mount(<YourPage/>);

Wrapper methods of enzyme

When you call the render method we metioned before, instead of return a ReactComponent, now we returns a wrapper provide by enzyme.
Here I would like to introduce some most useful methods. And please check the document for more information.

find a child component

find

the powerful find method can find a node with powerful Enzyme Selector which support CSS selector and component constructor.

const wrapper = mount(
  <div>
    <span className='foo'>
      <span className='bar'>
        <Icon type='baz'/>
      </span>
    </span>
  </div>);

//by jQuery selector
const fooWrapper = wrapper.find('.foo')

//find also returns a wrapper, so it support chaining call
const barWrapper = wrapper.find('.foo').find('.bar')

//by Component type
const iconWrapper = wrapper.find(Icon)

ref

class Foo extends React.Component {
  render() {
    return (
      <div>
        <span ref="firstRef" amount={2}>First</span>
        <span ref="secondRef" amount={4}>Second</span>
        <span ref="thirdRef" amount={8}>Third</span>
      </div>
    );
  }
}

const wrapper = mount(<Foo />);
expect(wrapper.ref('secondRef').prop('amount')).to.equal(4);

at/childAt

The wrapper in enzyme is just like jQuery object. so it might have multiple components inside, the at and childAt can find a node in the current wrapper by index passed in
Note : the index is zero-based

const wrapper = mount(
  <ul>
    <li/>
    <li/>
    <li/>
  </ul>
)

//find the first li
wrapper.find('li').at(0)
wrapper.find('li').first()

//find the third li node
wrapper.find('li').at(2)
wrapper.find('li').last()
wrapper.childAt(2)

instance

You can get the ReactComponent instance, but it's only available for the wrapper of root node (the node passed into mount())

wrapper.state() in enzyme is only available for root component
It's useful when you want to stub a method like transitionTo

buttonLink.instance().transitionTo = spy();

//This is unvaliable! .instance is only for the root node
buttonLink.find('span').instance()

simulate

To simulate events:

const wrapper = mount(<div/>)
wrapper.simulate('click')

Assertion

  • suggest to use chai and chai-enzyme to do the assertion instead of should.js, we've created some customized assert method like containText work with should.js before, but I think chai-enzyme cover more scenarioes.
  • highly suggest you to check the document of chai-enzyme when you don't know how to do the assertion, and below are the most common cases we will meet

A node is shown

const wrapper = mount(<div><span></span></div>);

expect(wrapper.find('span')).to.be.present();
expect(wrapper.find('span')).to.exist; //exist is an alias

expect(wrapper.find('ul')).to.not.be.present();
expect(wrapper.find('ul')).to.not.exist;

Have or contain some text

const wrapper = mount(
  <div id='root'>
    <span id='child'>Test</span>
  </div>
) 

expect(wrapper.find('#child')).to.have.text('Test')

expect(wrapper.find('#child')).to.contain.text('Te')

expect(wrapper.find('#child')).to.not.have.text('Other text')

Have some prop or className

const wrapper = mount(
  <div>
    <ul>
      <li><User index={1} user={{name: 'Jane'}} /></li>
      <li><User index={2} /></li>
    </ul>
  </div>
) 

expect(wrapper.find(User).first()).to.have.prop('index')
expect(wrapper.find(User).first()).to.not.have.prop('invalid')


expect(wrapper.find(User).first()).to.have.prop('index', 1)
expect(wrapper.find(User).first()).to.not.have.prop('index', 2)

expect(wrapper.find(User).first()).to.have.prop('index').equal(1)
expect(wrapper.find(User).first()).to.have.prop('user').deep.equal({name: 'Jane'})
And if you want to check the className, here is a better way: 
const wrapper = mount(
  <div className='root top'>
    <span className='child bottom'>test</span>
  </div>
)

expect(wrapper.find('span')).to.have.className('child')
expect(wrapper.find('span')).to.not.have.className('root')
to.be.true;
to.be.null;
to.have.lengthOf(2);
to.have.deep.property(‘response.title’, ’sdfdgd')
 类似资料: