2015-09-04 58 views
10

背景

React Shallow Rendering tests陣營測試:事件處理程序作出反應淺渲染單元測試

我想學習如何使用做出反應淺渲染TestUtil,並測試通過,直到我添加了一個onClick事件處理程序都;看來,必須有Accordion.toggle功能,我試圖在Accordion.test.jsthis.toggleAccordian.js ...但我不明白。

問題

我怎樣才能獲得兩個突出的Accordian.test.js測試通過?

步驟來重現

  1. 克隆https://github.com/trevordmiller/shallow-rendering-testing-playground
  2. npm install
  3. npm run dev - 看到組件的工作,當你點擊 「Lorem存有」
  4. npm run test:watch - 看到測試失敗

回答

8

有一些防止通過您的測試問題。

望着測試「應該是默認禁用」:

  1. Accordion.toggle在您的測試是Accordion類的屬性,並this.toggle在你的代碼是Accordion類的實例的屬性 - 所以在這種情況下你要比較兩種不同的東西。要在您的測試中訪問「實例」方法,您可以用Accordion.prototype.toggle替換Accordion.toggle。如果它不是在你的構造函數中的this.toggle = this.toggle.bind(this);,它會起作用。這引出了第二點。

  2. 當您在函數上調用.bind()時,它會在運行時創建一個新函數 - 因此您無法將其與原始的Accordion.prototype.toggle進行比較。解決這個問題的唯一辦法就是拉「綁定」功能,出來的結果,從渲染:

    let toggle = result.props.children[0].props.onClick; 
    
    assert.deepEqual(result.props.children, [ 
        <a onClick={toggle}>This is a summary</a>, 
        <p style={{display: 'none'}}>This is some details</p> 
    ]); 
    

至於你的第二個失敗的測試「應該成爲活躍的時候點擊」:

  1. 您嘗試撥打電話result.props.onClick(),這不存在。你打算撥打電話result.props.children[0].props.onClick();

  2. React中存在一個缺陷,需要在調用setState和淺呈現時聲明全局「文檔」變量 - 如何在每種情況下解決這個問題超出了這個問題的範圍,但快速解決問題的方法是在調用onClick方法之前添加global.document = {};。換句話說,其中原始測試有:

    result.props.onClick(); 
    

    現在應該說:

    global.document = {}; 
    result.props.children[0].props.onClick(); 
    

    參看 「修復損壞的setState()」 on this pagethis react issue

2

Marcin Grzywaczewski寫了一個偉大的article有一種變通方法用於測試單擊處理與淺渲染工作。

鑑於與onClick支柱和具有上下文的處理程序綁定到組件的嵌套元素:

render() { 
    return (
    <div> 
     <a className="link" href="#" onClick={this.handleClick}> 
     {this.state.linkText} 
     </a> 
     <div>extra child to make props.children an array</div> 
    </div> 
); 
} 

handleClick(e) { 
    e.preventDefault(); 
    this.setState({ linkText: 'clicked' }); 
} 

可以手動調用onClick支柱的函數值,在事件對象磕碰:

it('updates link text on click',() => { 
    let tree, link, linkText; 

    const renderer = TestUtils.createRenderer(); 
    renderer.render(<MyComponent />); 

    tree = renderer.getRenderOutput(); 
    link = tree.props.children[0]; 
    linkText = link.props.children; 

    // initial state set in constructor 
    expect(linkText).to.equal('Click Me'); 

    // manually invoke onClick handler via props 
    link.props.onClick({ preventDefault:() => {} }); 

    tree = renderer.getRenderOutput(); 
    link = tree.props.children[0]; 
    linkText = link.props.children; 

    expect(linkText).to.equal('Clicked'); 
}); 
0

我已經成功測試了我在無狀態組件中的點擊。這裏是如何:

我的組件:

import './ButtonIcon.scss'; 

import React from 'react'; 
import classnames from 'classnames'; 

const ButtonIcon = props => { 
    const {icon, onClick, color, text, showText} = props, 
    buttonIconContainerClass = classnames('button-icon-container', { 
     active: showText 
    }); 

    return (
    <div 
     className={buttonIconContainerClass} 
     onClick={onClick} 
     style={{borderColor: color}}> 
     <div className={`icon-container ${icon}`}></div> 
     <div 
     className="text-container" 
     style={{display: showText ? '' : 'none'}}>{text}</div> 
    </div> 
); 
} 

ButtonIcon.propTypes = { 
    icon: React.PropTypes.string.isRequired, 
    onClick: React.PropTypes.func.isRequired, 
    color: React.PropTypes.string, 
    text: React.PropTypes.string, 
    showText: React.PropTypes.bool 
} 

export default ButtonIcon; 

我的測試:

it('should call onClick prop when clicked',() => { 
    const iconMock = 'test', 
    clickSpy = jasmine.createSpy(), 
    wrapper = ReactTestUtils.renderIntoDocument(<div><ButtonIcon icon={iconMock} onClick={clickSpy} /></div>); 

    const component = findDOMNode(wrapper).children[0]; 

    ReactTestUtils.Simulate.click(component); 

    expect(clickSpy).toHaveBeenCalled(); 
    expect(component).toBeDefined(); 
}); 

重要的是包裝組件:

<div><ButtonIcon icon={iconMock} onClick={clickSpy} /></div> 

希望它能幫助!