美文网首页
enzyme 简单介绍与使用

enzyme 简单介绍与使用

作者: w晚风 | 来源:发表于2021-06-06 21:23 被阅读0次

    Enzyme 来自 airbnb 公司,是一个用于 React 的 JavaScript 测试工具,方便你判断、操纵和历遍 React Components 输出。

    Enzyme 的 API 通过模仿 jQuery 的 API ,使得 DOM 操作和历遍很灵活、直观。Enzyme 兼容所有的主要测试运行器和判断库,

    安装与配置

    在umi中使用enzyme之前,需要在项目中安装enzyme依赖,安装的命令如下:

    npm i --save-dev enzyme enzyme-adapter-react-16
    
    npm i --save-dev @types/enzyme
    

    最后,您需要配置酶以使用您要使用的适配器。为此,您可以使用顶级configure(...)API。

    import Enzyme from 'enzyme';
    import Adapter from 'enzyme-adapter-react-16';
    
    Enzyme.configure({ adapter: new Adapter() });
    

    enzyme支持三种方式的渲染:

    shallow:浅渲染,是对官方的Shallow Renderer的封装。将组件渲染成虚拟DOM对象,只会渲染第一层,子组件将不会被渲染出来,因而效率非常高。不需要DOM环境, 并可以使用jQuery的方式访问组件的信息;

    render:静态渲染,它将React组件渲染成静态的HTML字符串,然后使用Cheerio这个库解析这段字符串,并返回一个Cheerio的实例对象,可以用来分析组件的html结构。

    mount:完全渲染,它将组件渲染加载成一个真实的DOM节点,用来测试DOM API的交互和组件的生命周期,用到了jsdom来模拟浏览器环境。

    简单使用介绍

    为了方便讲解Enzyme测试的用法,我们首先新建一个enzyme.jsx的测试文件。代码如下:

    import React from 'react'
    
    const Example = (props)=>{
        return (
            <div>
                <div id="title">{props.title}</div>
                <button>{props.text}</button>
            </div>
        )
    }
    export default Example
    

    浅渲染shallow

    Shallow Rendering用于将一个组件渲染成虚拟DOM对象,但是只渲染第一层,不渲染所有子组件,所以处理速度非常快。并且它不需要DOM环境,因为根本没有加载进DOM。

    为了进行浅渲染shallow测试,我们新建一个名为enzyme.test.js的测试文件。

    import React from 'react'
    import Enzyme from 'enzyme'
    import Adapter from 'enzyme-adapter-react-16'
    import Example from '../src/components/enzyme'
    
    const { shallow } = Enzyme
    Enzyme.configure({ adapter: new Adapter() })
    
    describe('Example 组件相关',  ()=> {
        it('测试组件传值 文本是否符合预期',  ()=> {
            const button = '按钮名';
            const title = '标题';
    
            let app = shallow(<Example text={button} title={title}  />);
            
            const appButton = app.find('button').text();
            const appTitle =  app.find('#title').text();
    
            // 判断名称是否跟标签文本名称一致
            expect(button).toBe(appButton);
            expect(title).toBe(appTitle);
        })
    })
    

    执行测试案例可以看到正常通过

    Enzyme工具api

    .childAt(index) => ShallowWrapper 返回具有指定索引的子元素到新的wrapper
    .find(selector) => ShallowWrapper 根据选择器查找节点,找到渲染树中的节点。selector可以是CSS中的选择器,也可以是组件的构造函数,以及组件的display name等;

    例:

       const loginComponent = outLayer.find('form')
       const usernameInput = outLayer.find('input#userName')
       const passwordInput = outLayer.find('input[type="password"]')
       const submitButton = outLayer.find('button[type="submit"]')
       const errorComponent = outLayer.find('div.ant-alert-error')
    
    describe('测试 counter2Component 文件', function () {
      // 浅渲染 Counter2
      const wrapper = shallow(<Counter2 />)
      
      // 查找 a 便签的属性 href 是否为 #
      it('a 标签的属性 href 为 #', function () {
        expect(
          wrapper.find('a').prop('href')
        ).to.equal('#')
      })
      // 通过属性 [type="text"] 查找
      it('[type="text"] is existing',() => {
        expect(
          wrapper.find('[type="text"]').length
        ).to.equal(1)
      })
       // 测试是否含有两个 button 标签
      it('Counter2 includes two button elements',() => {
        expect(
          wrapper.find('button')
        ).to.have.lengthOf(2)
      })
      // 通过 className 查找标签
      it('it includes an element which className is addBtn',() => {
        expect(
          wrapper.find('.addBtn')
        ).to.have.lengthOf(1)
      })
    
    .findWhere(predicate) => ShallowWrapper 找到渲染树中里被的断言函数返回true的节点 参数:predicate (ShallowWrapper => Boolean) 断言函数返回布尔值
    .filter(selector) => ShallowWrapper 过滤当前包装器中与所提供的选择器不匹配的节点。
    .filterWhere(predicate) => ShallowWrapper 过滤当前包装器里被断言函数predicate不返回true的节点
    .contains(nodeOrNodes) => Boolean 返回给定的 节点/节点数组 是否在渲染树中的布尔值。当前对象是否包含参数重点 node,参数类型为react对象或对象数组;
    /* Counter2component.js */
    class Counter2 extends React.Component{
        render(){
        const num = 4;
            return(
                <div>
                    <div data-id="id" data-name="name" className="container">id</div>
                </div>
                <div data-num="num">
                  {num}
                </div>
            )
        }
    }
    
    /* test/components.test.js */
    describe('测试 counter2Component 文件', function () {
      const wrapper = shallow(<Counter2 />)
      it('测试是否包含完整自定义属性便签',() => {
        expect(
          wrapper.contains(
            <div data-id="id" data-name="name"className="container">id</div>) // 必须完整的书写,有一点不同,都无法通过
        ).to.equal(true)
      })
       const num = 4;
        expect(
          wrapper.contains(<div data-num="num">{num}</div>)
        ).to.equal(true);
    })
    
    

    contains()期望使用一个ReactElement,而不是选择器(与许多其他方法一样)。确保在调用它时,使用的是ReactElement或JSX表达
    请记住,此方法还基于节点的子节点的相等来确定相等。

    .containsMatchingElement(node) => Boolean 返回在浅渲染树中是否存在给定的node节点 的布尔值。
    /* Counter2component.js */
    class Counter2 extends React.Component{
        render(){
        const num = 4;
            return(
                <div>
                    <div data-id="id" data-name="name" className="container">id</div>
                </div>
            )
        }
    }
    
    /* test/components.test.js */
    describe('测试 counter2Component 文件', function () {
      const wrapper = shallow(<Counter2 />)
       it('测试是否匹配任意含有的属性标签', () => {
        expect(
          wrapper.containsMatchingElement(<div data-id="id">id</div>)
        ).to.equal(true);
        expect(
          wrapper.containsMatchingElement(<div data-id="id" data-num="num">id</div>)
        ).to.equal(false); // 匹配不到 data-num="num" 属性
    })
    
    
    .containsAllMatchingElements(nodes) => Boolean 返回在浅渲染树中是否存在给定的 所有 react元素 的布尔值。
    /* Counter2component.js */
    class Counter2 extends React.Component{
        render(){
            <div>
                <div data-id="id" data-name="name" className="container">
                  id
                </div>
                <div data-num="num">
                  {num}
                </div>
                <Counter className="foo" />
                <span className="foo"></span>
            </div>
        }
    }
    
    /* test/components.test.js */
    describe('测试 counter2Component 文件', function () {
      const wrapper = shallow(<Counter2 />)
        it('测试是否匹配任意含有的属性标签数组', () => {
        expect(
          wrapper.containsAllMatchingElements(
            [<div data-id="id">id</div>,
              <span></span>,            
              <Counter className="foo" />] // 必须是数组
            )
        ).to.equal(true);
      })
    })
    
    
    .containsAnyMatchingElements(nodes) => Boolean 返回在浅渲染树中是否存在给定react元素 之一 的布尔值
     describe('测试 counter2Component 文件', function () {
      const wrapper = shallow((
        <div>
          <h1>hi</h1>
          <span>welcome</span>
        </div>
      ))
      it('匹配至少一个含有的标签数组', () => {
        expect(
          wrapper.containsAnyMatchingElements([<span>welcome</span>,<em>quite</em>])
        ).to.equal(true) // <span>welcome</span> 存在,<em>quite</em> 不存在
      })
    })
    
    
    .equals(node) => Boolean 根据期望值,返回当前渲染树是否等于给定节点的 布尔值
    /* pComponent.js */
    class PEle extends React.Component {
      render() {
        return <p><span>123</span></p>;
      }
    }
    /* test/components.test.js */
     describe('测试 pComponent 文件', function () {
      const wrapper = shallow(<PEle />)
      it('测试',() => {
        expect(
          wrapper.equals(<p><span>123</span>1</p>)
        ).to.equal(true); // 必须完全匹配
      })
    })
    
    
    .matchesElement(node) => Boolean 返回当前给定的react元素 是否 匹配浅渲染树 的布尔值
    describe('测试 pComponent 文件', function () {
       const wrapper = shallow((
        <button type="button" 
            style={{border:"1px solid",backgroundColor:"blcak"}} 
            className="btn">
        hello</button>
      ))
      it('测试标签是否匹配', () => {
        expect(
          wrapper.matchesElement(<button 
              style={{border:"1px solid",backgroundColor:"blcak"}}  
              className="btn">hello
          </button>)
        ).to.equal(true);
      })
    })
    
    
    .hasClass(className) => Boolean 是否有这个className
    .is(selector) => Boolean 当前节点是否与提供的选择器匹配
    describe('测试 counter2Component 文件', function () {
      const wrapper = shallow(
        <div className="foo other" />
      )
      it('匹配 className',() => {
       expect(
         wrapper.is(".other")
       ).to.equal(true);
      }) 
    });
    
    
    
    .exists() => Boolean 当前节点是否存在
     const wrapper = shallow(
        <div className="foo other" />
      )
      it('测试某个 className 是否存在', () => {
        // 两种形式等价
        expect(
          wrapper.exists(".foo")
        ).to.equal(true);
        expect(
          wrapper.find(".foo").exists()
        ).to.equal(true)
    });
    
    
    .isEmptyRender( ) => Boolean 返回包装器最终是否只呈现允许的假值:false或null。
     function Foo() {
        return null;
      }
      const wrapper = shallow(<Foo />);
      it('测试 isEmptyRender 函数',() => {
        expect(
          wrapper.isEmptyRender()
        ).to.equal(true);
      })
    
    
    .not(selector) => ShallowWrapper 删除当前wrapper中与所提供的选择器匹配的节点。 (与 .filter()作用相反)
     const wrapper = shallow(
        <div className="hello">
          <span className="foo">1</span>
          <span className="other">2</span>
          <span className="foo">1</span>
        </div>
      )
      it('测试 .not 函数',() => {
        expect(
          wrapper.find("span").not(".foo")
        ).to.have.lengthOf(1)
      })
    
    
    .children() => ShallowWrapper 获取当前 wrapper 中所有子节点的 wrapper.
    function Box() {
        return (
          <ul>
            <li>1</li>
            <li>1</li>
            <li>1</li>
            <li>1</li>
          </ul>
        );
    }
    const items = [1, 2, 3, 4];
      const wrapper = shallow(<Box items={items} />);
      it('测试 .children 函数', () => {
        expect(
          wrapper.find("ul").children()
        ).to.have.lengthOf(items.length)
    });
    
    
    .childAt(index) => ShallowWrapper 返回具有指定索引的子元素的 wrapper
    function Box() {
         <ul>
            <li>1</li>
            <li>1</li>
            <li>1</li>
            <li>1</li>
         </ul>
    }
    const wrapper = shallow(<Box />);
      it('测试 childAt 函数',() => {
        expect(
          wrapper.find('ul').childAt(0).type()
        ).to.equal('li')
    })
    
    
    .parents() => ShallowWrapper 获取当前节点的所有父级(祖先)
    function Box() {
        return (
            <div>
                <ul>
                  <li>1</li>
                  <li>1</li>
                  <li>1</li>
                  <li>1</li>
                </ul>
            </div>
        )
    }
    const wrapper = shallow(<Box />);
      it('测试 childAt 函数',() => {
        expect(
          wrapper.find('ul').parents()
        ).to.lengthOf(1) // 查看父级的层数
    })
    
    
    .parent() => ShallowWrapper 获取当前节点的直接父级
    
    
    .closest(selector) => ShallowWrapper 根据选择器,获取当前节点的第一个祖先
    
    
    .shallow([options]) => ShallowWrapper Shallow renders the current node and returns a shallow wrapper around it.
    function Bar() {
        return (
          <div>
            <div className="in-bar" />
          </div>
        );
      }
      function Foo() {
        return (
          <div>
            <Bar />
          </div>
        );
      }
      const wrapper = shallow(<Foo />);
      it('测试 shallow 函数', () => {
        expect(
          wrapper.find('.in-bar')
        ).to.have.lengthOf(0);
        expect(
          wrapper.find(Bar)
        ).to.have.lengthOf(1)
        expect(
          wrapper.find(Bar).shallow().find('.in-bar') // 浅渲染不能直接渲染 React 组件内部的属性,                                                     通过 shallow 属性才能访问 React 组件内                                                     部的属性
        ).to.have.lengthOf(1)
    })
    
    
    .render() => CheerioWrapper 返回当前节点的子树的CheerioWrapper
    
    
    .unmount() => ShallowWrapper 卸载组件的方法
    
    
    .text() => String 返回当前渲染树中文本节点的 字符串表示形式。当前组件的文本内容;
    const wrapper = shallow(<div><b>important</b></div>);
    expect(wrapper.text()).to.equal('important');
        
    const wrapper = shallow(<div><Foo /><b>important</b></div>);
    expect(wrapper.text()).to.equal('<Foo />important');
    
    
    .html() => String 返回当前节点的静态HTML呈现
    function Foo() {
      return (<div className="in-foo" />);
    }
    function Bar() {
      return (
        <div className="in-bar">
          <Foo />
        </div>
      );
    }
    const wrapper = shallow(<Bar />);
    expect(wrapper.html()).to.equal('<div class="in-bar"><div class="in-foo"></div></div>');
    expect(wrapper.find(Foo).html()).to.equal('<div class="in-foo"></div>');
    
    
    .get(index) => ReactElement 返回给出索引的节点 ReactElement 要测试它,需要重新渲染;
     function Bar(props) {
        return(
          <p>{this.props.name}</p>
        )
      }
      function Foo() {
        return(
          <div>
            <Bar name="hello" />
          </div>
        )
      }
      const wrapper = shallow(<Foo />);
      it('测试 .get 函数',() => {
        expect(
          wrapper.find(Bar).get(0).props.name
        ).to.equal('hello')
      })
    
    
    .getNode() => ReactElement 返回底层节点
    
    
    .getNodes() => Array 返回底层的一些节点
    
    
    .at(index) => ShallowWrapper 返回 参数:索引节点的 浅wrapper。
     function Bar(props) {
        return(
          <p>{this.props.name}</p>
        )
      }
      function Foo() {
        return(
          <div>
            <Bar name="hello" />
          </div>
        )
      }
      const wrapper = shallow(<Foo />);
      it('测试 .get 函数',() => {
        expect(
          wrapper.find(Bar).at(0).props().name
        ).to.equal('hello')
      })
    
    
    .first() => ShallowWrapper 返回当前第一个节点 wrapper
      function Bar(props) {
        return(
          <div>
            <p>{this.props.name}</p>
            <span>{this.props.age}</span>
          </div>
        )
      }
      function Foo() {
        return(
          <div>
            <Bar name="hello" age="18" />
          </div>
        )
      }
      const wrapper = shallow(<Foo />);
      it('测试 .get 函数',() => {
        expect(
          wrapper.find(Bar).first().props().name
        ).to.equal('hello')
      })
    
    
    .last() => ShallowWrapper 返回当前最后一个节点 wrapper
    function Bar(props) {
        return(
          <div>
            <p>{this.props.name}</p>
            <span>{this.props.age}</span>
          </div>
        )
      }
      function Foo() {
        return(
          <div>
            <Bar name="hello" age="18" />
          </div>
        )
      }
      const wrapper = shallow(<Foo />);
      it('测试 .get 函数',() => {
        expect(
          wrapper.find(Bar).last().props().age
        ).to.equal('18')
      })
    
    
    .state([key]) => Any 返回根组件的状态
    class PEle extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          name: 'lili',
        }
      }
      render() {
        return <p>
          <span></span>
          <span className="foo"></span>
          <span></span>
        </p>;
      }
    }
     const wrapper = shallow(<PEle />);
      it('测试 .state 函数',() => {
        expect(wrapper.state('name')).to.equal('lili')
        expect(wrapper.state().name).to.equal('lili');
     })
    
    
    .context([key]) => Any 返回根组件的上下文环境
    
    
    .props() => Object 返回当前节点的 props
    function MyComponent(props) {
        const { includedProp } = props;
        return (
          <div className="foo bar" includedProp={includedProp}>Hello</div>
        );
      }
      const wrapper = shallow(<MyComponent includedProp="Success!" excludedProp="I'm not    included" />);
    it('测试 props 函数',() => {
        expect(wrapper.props().includedProp).to.equal('Success!');
    })
    
    
    .prop(key) => Any 返回当前节点props的某个(key)属性的值
     function MyComponent(props) {
        const { includedProp } = props;
        return (
          <div className="foo bar" includedProp={includedProp}>Hello</div>
        );
      }
      const wrapper = shallow(<MyComponent includedProp="Success!" excludedProp="I'm not    included" />);
    it('测试 props 函数', () => {
        expect(wrapper.prop('includedProp')).to.equal('Success!');
    })
    
    
    .key() => String 返回当前节点的键(key)
    const wrapper = shallow(
        <ul>
          {
            ['foo','bar'].map(item => <li key={item}>{item}</li>)
          }
        </ul>
      ).find('li')
      it('测试 .key 函数',() => {
        expect(
          wrapper.at(0).key()
        ).to.equal('foo')
        expect(
          wrapper.last().key()
        ).to.equal('bar');
      })
    
    
    .simulate(event, mock) => 用来模拟事件触发,event为事件名称,mock为一个event object
     class Foo extends React.Component {
        constructor(props) {
          super(props);
          this.state = { count: 0 };
        }
    
        render() {
          const { count } = this.state;
          return (
            <div>
              <div className={`clicks-${count}`}>
                {count} clicks
              </div>
              <a href="url" onClick={() => { this.setState({ count: count + 1 }); }}>
                Increment
              </a>
            </div>
          );
        }
      }
      const wrapper = shallow(<Foo />);
      it('测试 .simulate 函数', () => {
        wrapper.find('a').simulate('click');
        expect(wrapper.state('count')).to.equal(1)
        wrapper.find('a').simulate('click');
        expect(wrapper.state('count')).to.equal(2)
      })
    
    
    .setState(nextState) => ShallowWrapper 手动setState更新根组件状态
     class Foo extends React.Component {
        constructor(props) {
          super(props);
          this.state = { name: 'foo' };
        }
        render() {
          const { name } = this.state;
          return (
            <div className={name} />
          );
        }
      }
      const wrapper = shallow(<Foo />);
      it('测试 setState 函数', () => {
        expect(wrapper.state('name')).to.equal('foo');
        wrapper.setState({ age: 18 });
        wrapper.setState({ name: 'bar' });
        expect(wrapper.state('name')).to.equal('bar');
        expect(wrapper.state('age')).to.equal(18);
      })
    
    
    .setProps(nextProps) => ShallowWrapper 手动更新根组件的props
    function MyComponent(props) {
        const { includedProp } = props;
        return (
          <div className="foo bar" includedProp={includedProp}>Hello</div>
        );
      }
      const wrapper = shallow(<MyComponent includedProp="Success!" excludedProp="I'm not    included" />);
      it('测试 props 函数', () => {
        expect(wrapper.prop('includedProp')).to.equal('Success!');
        wrapper.setProps({includedProp:'hello'});
        expect(wrapper.prop('includedProp')).to.equal('hello');
      })
    
    
    .setContext(context) => ShallowWrapper 手动设置根组件的上下文
    import PropTypes from 'prop-types'; 
    
    function SimpleComponent(props, context) {
        const { name } = context;
        return <div>{name}</div>;
      }
      SimpleComponent.contextTypes = { // 必须这样写
        name: PropTypes.string,
      };
      const context = { name: 'foo' };
      const wrapper = shallow(<SimpleComponent />, { context });
      it('测试 .setContext 函数', () => {
        expect(wrapper.text()).to.equal('foo');
        wrapper.setContext({name:'bar'});
        expect(wrapper.text()).to.equal('bar');
      })
    
    
    .instance() => ReactComponent 返回根组件的实例,返回测试组件的实例
     function Stateless() {
        return <div>Stateless</div>;
      }
    
      class Stateful extends React.Component {
        render() {
          return <div>Stateful</div>;
        }
      }
      it('测试 .instance 函数在无状态组件中', () => {
        const wrapper = shallow(<Stateless />);
        const instance = wrapper.instance();
        expect(instance).to.equal(null);
      })
      it('测试 .instance 函数在类组件中', () => {
        const wrapper = shallow(<Stateful />);
        const instance = wrapper.instance();
        expect(instance).to.be.instanceOf(Stateful);
      })
    
    
    .update() => ShallowWrapper 在根组件实例上调用.forceUpdate()
    class ImpureRender extends React.Component {
        constructor(props) {
          super(props);
          this.count = 0;
        }
        render() {
          this.count += 1;
          return <div>{this.count}</div>;
        }
      }
      it('测试 update 函数', () => {
        const wrapper = shallow(<ImpureRender />);
        wrapper.update();
        expect(wrapper.text()).to.equal('1');
      })
    
    
    .debug() => String 返回当前浅渲染树的字符串表示形式,以便进行调试
    function Book({ title, pages }) {
      return (
        <div>
          <h1 className="title">{title}</h1>
          {pages && (
            <NumberOfPages
              pages={pages}
              object={{ a: 1, b: 2 }}
            />
          )}
        </div>
      );
    }
    Book.propTypes = {
      title: PropTypes.string.isRequired,
      pages: PropTypes.number,
    };
    Book.defaultProps = {
      pages: null,
    };
    
    
    const wrapper = shallow(<Book title="Huckleberry Finn" />);
    console.log(wrapper.debug());
    
    .type() => String|Function 返回包装器(wapper)的当前节点的类型。
     function Foo() {
        return <div />
      };
      function Bar() {
        return <Foo />
      };
      it('测试 .type 函数', () => {
        const wrapper = shallow(<Foo />);
        expect(
          wrapper.type()
        ).to.equal('div')
        const wrapper = shallow(<Bar />);
        expect(
          wrapper.type()
        ).to.equal(Foo)
        function Null() {
          return null;
        }
        const wrapper = shallow(<Null />);
        expect(
          wrapper.type()
        ).to.equal(null);
      })
    
    
    .name() => String 返回当前节点的名称
    function Foo() {
        return <div>
          <ul>
            <li>1</li>
            <li>1</li>
            <li>1</li>
          </ul>
        </div>
      }
      function Bar() {
        return <Foo />
      }
      const wrapper = shallow(<div />);
      expect(wrapper.name()).to.equal('div');
      const wrapper = shallow(<Foo />);
      expect(wrapper.name()).to.equal('div');
      const wrapper = shallow(<Bar />);
      expect(
        wrapper.name()
      ).to.equal('Foo');
    
    
    function Foo() {
        return <div>
          <ul>
            <li>1</li>
            <li>1</li>
            <li>1</li>
          </ul>
        </div>
      }
      function Bar() {
        return <Foo />
      }
      it('测试 .name 函数', () => {
        Foo.displayName = "hello world";
        function Bar() {
          return <Foo />
        }
        const wrapper = shallow(<Bar />);
        expect(
          wrapper.name()
        ).to.equal('hello world')
      })
    
    
    .forEach(fn) => ShallowWrapper 迭代当前的每个节点并执行提供的函数
    const wrapper = shallow((
        <div>
          <div className="foo" >123</div>
          <div className="foo" >123</div>
          <div className="foo" >123</div>
        </div>
      ))
      it('测试 .forEach 函数', () => {
        wrapper.find('.foo').forEach((node) => {
          expect(node.text()).to.equal('123');
          expect(node.hasClass('foo')).to.equal(true);
        })
      })
    
    
    .map(fn) => Array 将当前的节点数组映射到另一个数组
    const wrapper = shallow((
        <div>
          <div className="foo">bax</div>
          <div className="foo">bar</div>
          <div className="foo">baz</div>
        </div>
      ));
      it('测试 .map 函数', () => {
        const texts = wrapper.find('.foo').map(node => node.text());
        expect(texts).to.eql(['bax', 'bar', 'baz']);
      })
    
    
    .reduce(fn[, initialValue]) => Any 将当前节点数组减少为一个值
    function Bar(props) {
        const { amount } = props;
        return <div>{amount}</div>
      }
      function Foo() {
        return (
          <div>
            <Bar amount={2} />
            <Bar amount={4} />
            <Bar amount={8} />
          </div>
        );
      }
       it('测试 .reduce 函数', () => {
        const wrapper = shallow(<Foo />);
        const total = wrapper.find(Bar).reduce((amount, n) => amount + n.prop('amount'), 0);
        expect(total).to.equal(14);
      })
    
    
    .reduceRight(fn[, initialValue]) => Any 将当前节点数组从右到左减少为一个值
    function Foo() {
      return (
        <div>
          <Bar amount={2} />
          <Bar amount={4} />
          <Bar amount={8} />
        </div>
      );
    }
    const wrapper = shallow(<Foo />);
    const total = wrapper.find(Bar).reduceRight((amount, n) => amount + n.prop('amount'), 0);
    expect(total).to.equal(14);
    
    
    .slice([begin[, end]]) => ShallowWrapper 根据Array#slice的规则返回具有原始包装器的节点的子集的新包装器。
    const wrapper = shallow((
      <div>
        <div className="foo bax" />
        <div className="foo bar" />
        <div className="foo baz" />
      </div>
    ));
    expect(wrapper.find('.foo').slice(1)).to.have.lengthOf(2);
    expect(wrapper.find('.foo').slice(1).at(0).hasClass('bar')).to.equal(true);
    expect(wrapper.find('.foo').slice(1).at(1).hasClass('baz')).to.equal(true);
    
    
    const wrapper = shallow((
      <div>
        <div className="foo bax" />
        <div className="foo bar" />
        <div className="foo baz" />
      </div>
    ));
    expect(wrapper.find('.foo').slice(1, 2)).to.have.lengthOf(1);
    expect(wrapper.find('.foo').slice(1, 2).hasClass('bar')).to.equal(true);
    
    
    .tap(intercepter) => Self 点击wrapper方法链。有助于调试。
    const result = shallow((
      <ul>
        <li>xxx</li>
        <li>yyy</li>
        <li>zzz</li>
      </ul>
    )).find('li')
      .tap(n => console.log(n.debug()))
      .map(n => n.text());
    
    
    .some(selector) => Boolean 返回 是否有 节点与提供的选择器匹配。
    const wrapper = shallow((
        <div>
          <div className="foo qoo" />
          <div className="foo boo" />
          <div className="foo hoo" />
        </div>
      ));
      it('测试 .some 函数',() => {
        expect(wrapper.find('.foo').some('.qoo')).to.equal(true)
        expect(wrapper.find('.foo').some('.bar')).to.equal(false)
      })
    
    
    .someWhere(predicate) => Boolean 返回 是否有 节点 传递所提供的断言函数。
    const wrapper = shallow((
        <div>
          <div className="foo qoo" />
          <div className="foo boo" />
          <div className="foo hoo" />
        </div>
      ));
      it('测试 .someWhere 函数', () => {
        expect(wrapper.find('.foo').someWhere(node => node.hasClass('hoo'))).to.equal(true);
        expect(wrapper.find('.foo').someWhere(node => node.hasClass('bar'))).to.equal(false);
      })
    
    
    .every(selector) => Boolean 返回 是否 有节点与提供的选择器匹配。
     const wrapper = shallow((
        <div>
          <div className="foo qoo" />
          <div className="foo boo" />
          <div className="foo hoo" />
        </div>
      ));
      it('测试 .someWhere 函数', () => {
        expect(wrapper.find('.foo').every('.foo')).to.equal(true);
        expect(wrapper.find('.foo').every('.qoo')).to.equal(false);
      })
    
    
    .everyWhere(predicate) => Boolean 返回 是否 所有 节点都传递所提供的断言函数。
    const wrapper = shallow((
        <div>
          <div className="foo qoo" />
          <div className="foo boo" />
          <div className="foo hoo" />
        </div>
      ));
      it('测试 .someWhere 函数', () => {
        expect(wrapper.find('.foo').everyWhere(node => node.hasClass('foo'))).to.equal(true);
        expect(wrapper.find('.foo').everyWhere(node => node.hasClass('qoo'))).to.equal(false);
      })
    
    
    .dive([options]) => ShallowWrapper 浅渲染当前wrapper的一个非DOM子元素,并在结果周围返回一个wrapper
     function Bar() {
        return (
          <div>
            <div className="in-bar">123123</div>
          </div>
        );
      }
      function Foo() {
        return (
          <div>
            <Bar />
          </div>
        );
      }
      it('测试 .dive 函数',() => {
        const wrapper = shallow(<Foo />);
        expect(
          wrapper.find('.in-bar')
        ).to.have.lengthOf(0)
        expect(
          wrapper.find(Bar).dive().find('.in-bar').text()
        ).to.equal('123123')
      })
    
    
    .hostNodes => ShallowWrapper 查找主节点时,默认查找的是 HTML 标签而不是 React components
    /* Counter2component.js */
    class Counter2 extends React.Component{
        render(){
            return(
                <div>
                    <Box className="foo" />
                    <span className="foo"></span>
                    <span className="foo"></span>
                    <span className="foo"></span>
                </div>
            )
        }
    }
    
    /* test/components.test.js */
    describe('测试 Counter2Component 文件',() => {
        it('主节点是 HTML 而不是 React 组件', () => {
            const wrapper = shallow(<Counter2 />)
            const twoNodes = wrapper.find(".foo");
            expect(
                twoNodes.hostNodes()
            ).to.have.lengthOf(3)
      })
    })
    
    

    覆盖率

    修改package.json添加执行命令

    "scripts": {
        "test": "umi-test --coverage"
     },
    

    然后执行npm run test 跑单元测试的在跟目录会生成一个coverage目录,

    通过打开这个HTML文件再浏览器查看 就可以看到整个项目的测试报告了

    12.jpg

    如:

    6.jpg

    相关文章

      网友评论

          本文标题:enzyme 简单介绍与使用

          本文链接:https://www.haomeiwen.com/subject/yetkeltx.html