单元测试使用Material UI Dialog React组件

时间:2015-12-16 12:55:10

标签: unit-testing reactjs material-ui reactjs-testutils

我目前正在为我的React + MaterialUi应用程序编写单元测试。

在我的应用程序中,我有一个Dialog。我想确保取决于按下对话框上的按钮:

<FlatButton
  label="Cancel"
  secondary={true}
  onTouchTap={this._cancelDialog.bind(this)} 
 />
 <FlatButton
   label="Submit"
   primary={true}
   onTouchTap={this._confirmDialog.bind(this)} 
 />

内部状态相应变化。

不幸的是我无法使用对话框内容 TestUtils.scryRenderedComponentsWithType(FlatButton)

scryRenderedComponentsWithTag("button")
等等。

有关如何测试该流程的任何想法?

更新1

所以我可以通过调用TestUtils.scryRenderedComponentsWithType(Dialog)来获取Dialog实例。但我无法得到对话框的内容。 DOM明智的内容不会在视图内部呈现。它在文档级别(div)上的新创建节点中呈现。所以我试过这个:

let cancelButton = window.document.getElementsByTagName("button")[0];
Simulate.click(cancelButton);

上面的例子中的cancelButton是正确的DOM元素。但是,Simulate.click不会触发组件单击功能。

问候 纳斯

5 个答案:

答案 0 :(得分:5)

刚遇到同样的问题。我查看了源代码,Dialog组件的render方法实际上创建了组件RenderToLayer的实例。此组件表现为门户网站,并通过在其“渲染函数”中返回null并将其直接附加到正文来中断反应的DOM树。

幸运的是,RenderToLayer组件接受了prop render,它实质上允许组件将一个函数传递给门户,当它处于渲染周期时。这意味着我们实际上可以自己手动触发此事件。我承认,这并不完美,但经过几天的努力寻找解决方案后,我正在试着写下我的测试:

var component = TestUtils.renderIntoDocument(<UserInteractions.signupDialog show={true}/>)
var dialog = TestUtils.renderIntoDocument(component.refs.dialog.renderLayer())
var node = React.findDOMNode(dialog)

这是我的UserInteractions.signupDialog的样子:

exports.signupDialog = React.createClass({
...
  render: function() {
    var self = this;

    return (
      <div>
        <Dialog
          ref='dialog'
          title="Signup"
          modal={false}
          actions={[
            <Button
              label="Cancel"
              secondary={true}
              onTouchTap={self.__handleClose}
            />,
            <Button
              label="Submit"
              primary={true}
              keyboardFocused={true}
              onTouchTap={self.__handleClose}
            />
          ]}
          open={self.props.show}
          onRequestClose={self.__handleClose}
          >
          <div className='tester'>ham</div>
          <TextField id='tmp-email-input' hintText='email' type='text'/>
        </Dialog>
      </div>
    )
  }
})

现在我可以对对话框中呈现的子组件进行断言,甚至可以对绑定到原始组件的事件进行断言,因为它们的关系得以维持。

如果您要继续使用材料ui,我绝对建议您在测试堆栈中设置调试器。对这样的事情没有太大的帮助。这是我的调试脚本的样子:

// package.json
{
  ...
  "scripts": {
    "test": "mocha --compilers .:./test/utils/compiler.js test/**/*.spec.js",
    "debug": "mocha debug --compilers .:./test/utils/compiler.js test/**/*.spec.js"
  }
}

现在您可以使用npm test运行mocha测试,并使用npm run debug进入调试器。一旦进入调试器,它将立即暂停并等待您输入断点。此时,输入c继续。现在,您可以在代码中的任何位置放置debugger;语句,以生成调试器将响应的断点。找到断点后,它会暂停并允许您使用本地范围使用代码。此时,输入repl以输入代码的本地范围并访问您当地的变种。

也许您不需要调试器,但也许其他人会觉得这很有帮助。祝你好运,编码愉快!

答案 1 :(得分:4)

解决方法如下:

/*
* I want to verify that when i click on cancel button my showModal state is set * to false
*/

//shallow render my component having Dialog
const wrapper= shallow(<MyComponent store={store} />).dive();

//Set showModal state to true
wrapper.setState({showModal:true});

//find out cancel button with id 'cancelBtn' object from actions and call onTouchTap to mimic button click
wrapper.find('Dialog').props().actions.find((elem)=>(elem.props.id=='cancelBtn')).props.onTouchTap();

//verify that the showModal state is set to false
expect(wrapper.state('showModal')).toBe(false);

答案 2 :(得分:0)

我遇到了同样的问题并解决了这个问题:

const myMock = jest.genMockFunction();
const matcherComponent = TestUtils.renderIntoDocument(
      <MatcherComponent onClickCancel={myMock} activAction/>
        );
const raisedButton = TestUtils.findRenderedComponentWithType(
            matcherComponent, RaisedButton);

TestUtils.Simulate.click(ReactDOM.findDOMNode(raisedButton).firstChild);

expect(myMock).toBeCalled();

对我来说很好。但是,我仍在努力使用Simulate.change

答案 3 :(得分:0)

Solution by avocadojesus很棒。但我有一个补充。如果您尝试应用此解决方案并收到错误:

  

错误:'警告:上下文类型失败:标记了上下文muiTheme   根据{{​​1}}的要求,但其值为DialogInline

你应该修改他的代码如下:

undefined

答案 4 :(得分:0)

材料UI分叉这2种酶方法。您需要将createMountcreateShallow与潜水选项https://material-ui.com/guides/testing/#createmount-options-mount一起使用