我很抱歉,但是我一直在努力尝试通过点击按钮来关闭我的React Modal。 Modal尽可能简单,我已经尝试了所有我能想到或发现的东西,但我仍然无法查询它的孩子。
模态组件:
var React = require('react');
var Modal = require('react-bootstrap').Modal;
var Button = require('react-bootstrap').Button;
var MyModal = React.createClass({
...
render: function() {
return (
<Modal className="my-modal-class" show={this.props.show}>
<Modal.Header>
<Modal.Title>My Modal</Modal.Title>
</Modal.Header>
<Modal.Body>
Hello, World!
</Modal.Body>
<Modal.Footer>
<Button onClick={this.props.onHide}>Close</Button>
</Modal.Footer>
</Modal>
);
}
});
我的目标是测试点击按钮时是否触发onHide()
功能。
我的测试文件:
describe('MyModal.jsx', function() {
it('tests the Close Button', function() {
var spy = sinon.spy();
var MyModalComponent = TestUtils.renderIntoDocument(
<MyModal show onHide={spy}/>
);
// This passes
TestUtils.findRenderedComponentWithType(MyModalComponent, MyModal);
// This fails
var CloseButton = TestUtils.findRenderedDOMComponentWithTag(MyModalComponent, 'button');
// Never gets here
TestUtils.Simulate.click(CloseButton);
expect(spy.calledOnce).to.be.true;
});
});
无论我尝试什么,我似乎都找不到关闭按钮。
答案 0 :(得分:7)
我使用jsFiddle编写了一个React Base Fiddle (JSX)来查找测试中发生了什么(我创建了自己的'间谍',在调用时只是登录到控制台)。
我发现找不到按钮的原因是因为它不存在于您可能期望的位置。
Bootstrap Modal Component(<Modal/>
)实际上包含在React-Overlays模态组件中(代码中名为BaseModal
,来自here)。这反过来呈现一个名为Portal
的组件,render method只返回null
。您正试图在此处找到渲染组件的null
值。
由于模态没有以传统的React方式呈现,React无法看到模式以便使用TestUtils
。一个完全独立的<div/>
子节点放在document
主体中,这个新的<div/>
用于构建模态。
因此,为了允许您使用React的TestUtils
模拟单击(按钮上的单击处理程序仍然绑定到按钮的单击事件),您可以使用标准JS方法来搜索DOM。按如下方式设置测试:
describe('MyModal.jsx', function() {
it('tests the Close Button', function() {
var spy = sinon.spy();
var MyModalComponent = TestUtils.renderIntoDocument(
<MyModal show onHide={spy}/>
);
// This passes
TestUtils.findRenderedComponentWithType(MyModalComponent, MyModal);
// This will get the actual DOM node of the button
var closeButton = document.body.getElementsByClassName("my-modal-class")[0].getElementsByClassName("btn btn-default")[0];
// Will now get here
TestUtils.Simulate.click(CloseButton);
expect(spy.calledOnce).to.be.true;
});
});
函数getElementsByClassName
返回该类的元素集合,因此您必须从每个集合中获取第一个元素(在测试用例中,您唯一的元素)。
您的测试现在应该通过^ _ ^
答案 1 :(得分:1)
这是我最终选择的解决方案。它将React渲染模态的方式存储为仅渲染<div>
。
test-utils.js
:
var sinon = require('sinon');
var React = require('react');
var Modal = require('react-bootstrap').Modal;
module.exports = {
stubModal: function() {
var createElement = React.createElement;
modalStub = sinon.stub(React, 'createElement', function(elem) {
return elem === Modal ?
React.DOM.div.apply(this, [].slice.call(arguments, 1)) :
createElement.apply(this, arguments);
});
return modalStub;
},
stubModalRestore: function() {
if (modalStub) {
modalStub.restore();
modalStub = undefined;
} else {
console.error('Cannot restore nonexistent modalStub');
}
}
};
modal-test.jsx
var testUtils = require('./test-utils');
describe('test a Modal!', function() {
before(testUtils.stubModal);
after(testUtils.stubModalRestore);
it('renders stuff', function() {
var MyModalComponent = TestUtils.renderIntoDocument(
<MyModal show/>
);
// Do more stuff you normally expect you can do
});
});