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
网友评论