开玩笑,酶 - 测试 returns jsx 的方法
jest, enzyme - testing a method that returns jsx
我有以下组件:
import React, { Component } from 'react';
import {Link, IndexLink} from 'react-router';
class Navbar extends Component {
renderLinks = (linksData) => {
return linksData.map((linkData) => {
if(linkData.to === '/') {
return(
<div className="navbar-link-container" key={linkData.to}>
<IndexLink activeClassName="navbar-active-link" to={linkData.to}>
<i className="navbar-icon material-icons">{linkData.icon}</i>
<span className="navbar-link-text">{linkData.text}</span>
</IndexLink>
</div>
)
}
else {
return(
<div className="navbar-link-container" key={linkData.to}>
<Link activeClassName="navbar-active-link" to={linkData.to}>
<i className="navbar-icon material-icons">{linkData.icon}</i>
<span className="navbar-link-text">{linkData.text}</span>
</Link>
</div>
)
}
})
};
render() {
return (
<div className={`navbar navbar-${this.props.linksData.length}`}>
{this.renderLinks(this.props.linksData)}
</div>
)
}
}
Navbar.propTypes = {
linksData: React.PropTypes.array.isRequired,
};
export default Navbar;
现在我正在尝试编写一个单元测试来检查 if 条件(returning IndexLink 或 Link 取决于 .to 属性) :
但我似乎无法测试该函数的确切 jsx return,因为当我 console.log 其中一个 return 我得到这个:
{ '$$typeof': Symbol(react.element),
type: 'div',
key: '/',
ref: null,
props:
{ className: 'navbar-link-container',
children:
{ '$$typeof': Symbol(react.element),
type: [Object],
key: null,
ref: null,
props: [Object],
_owner: null,
_store: {} } },
_owner: null,
_store: {} }
这是我目前写的测试:
it('renderLinks should return a IndexLink', () => {
const wrapper = shallow(<Navbar linksData={mockLinksData}/>);
const renderLinksReturn = wrapper.instance().renderLinks(mockLinksData);
let foundIndexLink = false;
renderLinksReturn.map((linkHtml) => {
console.log(linkHtml);
});
expect(foundIndexLink).toBe(true);
})
现在我不知道要根据什么来测试函数是否 运行 正确。有没有办法把'mount'函数的return像一个组件一样?或者是否有一种简单的方法来 return 实际 return 的 html 字符串,我可以检查它?
原来元素的类型存储在对象中。所以条件是:
props.children.type.displayName
我为 IndexLink 编写的最终测试如下所示:
it('renderLinks should return a IndexLink when passed a link with to:\"/\"', () => {
const wrapper = shallow(<Navbar linksData={mockLinksData}/>);
const renderLinksReturn = wrapper.instance().renderLinks(mockLinksData);
let foundIndexLink = false;
renderLinksReturn.map((linkHtml) => {
{linkHtml.props.children.type.displayName === 'IndexLink' ? foundIndexLink = true : null};
});
expect(foundIndexLink).toBe(true);
});
我想你不需要打电话给
const renderLinksReturn = wrapper.instance().renderLinks(mockLinksData);
因为它将在 Navbar
呈现时被调用。
您的解决方案是正确的,但以防万一您需要一些其他可靠的方法来测试它。
由于此测试专门测试 IndexLink
并假设 mockLinksData
包含 to = "/"
it('renderLinks should return a IndexLink when passed a link with to:\"/\"', () => {
const wrapper = shallow(<Navbar linksData={mockLinksData}/>);
// You can use both component name or component displayname
// IndexLink or "IndexLink"
expect(wrapper.find('IndexLink')).to.have.length(1);
// In case you want to test whether indexLink has appropriate props or classes.
const indexLink = wrapper.find(IndexLink).first();
// Check whether indexLink has pass prop
expect(indexLink.props().to).to.equal("/");
// Check whether indexLink has correct classes set.
expect(indexLink.hasClass('navbar-active-link')).to.equal(true);
// Check whether indexLink displays the link test correctly
expect(indexLink.find('navbar-link-text').text()).to.equal(mockLinksData.text);
});
遇到类似的问题,我们将 jsx 组件作为 prop 传递给另一个组件。
您可以浅渲染返回的 jsx,因为它就像一个有效的 React Function/Stateless 组件。
例如:
const renderLinks = shallow(wrapper.instance().renderLinks(mockLinksData))
然后继续您通常的酶断言。
要建立在@Nachiketha 的答案之上,当返回的是 fragment
时,该语法将不起作用,这可以通过将结果包装在 div
中来解决,例如:
const renderLinks = shallow(<div>
{wrapper.instance().renderLinks(mockLinksData)
</div>
)}
如 this tread 中所建议。
我有以下组件:
import React, { Component } from 'react';
import {Link, IndexLink} from 'react-router';
class Navbar extends Component {
renderLinks = (linksData) => {
return linksData.map((linkData) => {
if(linkData.to === '/') {
return(
<div className="navbar-link-container" key={linkData.to}>
<IndexLink activeClassName="navbar-active-link" to={linkData.to}>
<i className="navbar-icon material-icons">{linkData.icon}</i>
<span className="navbar-link-text">{linkData.text}</span>
</IndexLink>
</div>
)
}
else {
return(
<div className="navbar-link-container" key={linkData.to}>
<Link activeClassName="navbar-active-link" to={linkData.to}>
<i className="navbar-icon material-icons">{linkData.icon}</i>
<span className="navbar-link-text">{linkData.text}</span>
</Link>
</div>
)
}
})
};
render() {
return (
<div className={`navbar navbar-${this.props.linksData.length}`}>
{this.renderLinks(this.props.linksData)}
</div>
)
}
}
Navbar.propTypes = {
linksData: React.PropTypes.array.isRequired,
};
export default Navbar;
现在我正在尝试编写一个单元测试来检查 if 条件(returning IndexLink 或 Link 取决于 .to 属性) :
但我似乎无法测试该函数的确切 jsx return,因为当我 console.log 其中一个 return 我得到这个:
{ '$$typeof': Symbol(react.element), type: 'div', key: '/', ref: null, props: { className: 'navbar-link-container', children: { '$$typeof': Symbol(react.element), type: [Object], key: null, ref: null, props: [Object], _owner: null, _store: {} } }, _owner: null, _store: {} }
这是我目前写的测试:
it('renderLinks should return a IndexLink', () => {
const wrapper = shallow(<Navbar linksData={mockLinksData}/>);
const renderLinksReturn = wrapper.instance().renderLinks(mockLinksData);
let foundIndexLink = false;
renderLinksReturn.map((linkHtml) => {
console.log(linkHtml);
});
expect(foundIndexLink).toBe(true);
})
现在我不知道要根据什么来测试函数是否 运行 正确。有没有办法把'mount'函数的return像一个组件一样?或者是否有一种简单的方法来 return 实际 return 的 html 字符串,我可以检查它?
原来元素的类型存储在对象中。所以条件是:
props.children.type.displayName
我为 IndexLink 编写的最终测试如下所示:
it('renderLinks should return a IndexLink when passed a link with to:\"/\"', () => {
const wrapper = shallow(<Navbar linksData={mockLinksData}/>);
const renderLinksReturn = wrapper.instance().renderLinks(mockLinksData);
let foundIndexLink = false;
renderLinksReturn.map((linkHtml) => {
{linkHtml.props.children.type.displayName === 'IndexLink' ? foundIndexLink = true : null};
});
expect(foundIndexLink).toBe(true);
});
我想你不需要打电话给
const renderLinksReturn = wrapper.instance().renderLinks(mockLinksData);
因为它将在 Navbar
呈现时被调用。
您的解决方案是正确的,但以防万一您需要一些其他可靠的方法来测试它。
由于此测试专门测试 IndexLink
并假设 mockLinksData
包含 to = "/"
it('renderLinks should return a IndexLink when passed a link with to:\"/\"', () => {
const wrapper = shallow(<Navbar linksData={mockLinksData}/>);
// You can use both component name or component displayname
// IndexLink or "IndexLink"
expect(wrapper.find('IndexLink')).to.have.length(1);
// In case you want to test whether indexLink has appropriate props or classes.
const indexLink = wrapper.find(IndexLink).first();
// Check whether indexLink has pass prop
expect(indexLink.props().to).to.equal("/");
// Check whether indexLink has correct classes set.
expect(indexLink.hasClass('navbar-active-link')).to.equal(true);
// Check whether indexLink displays the link test correctly
expect(indexLink.find('navbar-link-text').text()).to.equal(mockLinksData.text);
});
遇到类似的问题,我们将 jsx 组件作为 prop 传递给另一个组件。
您可以浅渲染返回的 jsx,因为它就像一个有效的 React Function/Stateless 组件。 例如:
const renderLinks = shallow(wrapper.instance().renderLinks(mockLinksData))
然后继续您通常的酶断言。
要建立在@Nachiketha 的答案之上,当返回的是 fragment
时,该语法将不起作用,这可以通过将结果包装在 div
中来解决,例如:
const renderLinks = shallow(<div>
{wrapper.instance().renderLinks(mockLinksData)
</div>
)}
如 this tread 中所建议。