使用Mocha,Chai和JSDom模拟React的TDD用户输入?

时间:2016-12-01 21:16:34

标签: unit-testing reactjs

我有一个搜索栏,我想测试用户输入。我使用React渲染视图并使用Chai,Mocha和JSDom编写测试。

以下是我到目前为止所写的简单测试

 describe('Search', () => {
    it('renders a search bar', () => {
        const component = renderIntoDocument(
            <Search />
        );
        const search_bar = scryRenderedDOMComponentsWithClass(component, 'input-group');

        expect(search_bar.length).to.equal(1);
    });

    it('invokes a callback when the Add button is clicked', () => {
        let search_term;
        const clickHandler = (term) => search_term = term;

        const component = renderIntoDocument(
            <Search onClick={clickHandler}/>
        )

        const add_button = scryRenderedDOMComponentsWithTag(component, 'button');
        Simulate.click(add_button[0]);

        expect(search_term).to.equal('');
    });

    it('accepts user input from the search button and performs a regex check for invalid input', () => {
        let search_term;
        const clickHandler = (term) => search_term = term;

        const component = renderIntoDocument(
            <Search onClick={clickHandler} />
        );

        const add_button = scryRenderedDOMComponentsWithTag(component, 'button');
        const search_bar = scryRenderedDOMComponentsWithClass(component, 'input-group');

        Simulate.change(search_bar[0], {target: {value: 'FB'}});
        expect(search_bar[0].state.value).to.equal('FB');
    })
})

1)我想测试用户在点击Add按钮之前输入字符。

2)我想测试用户没有在搜索词中输入任何数字或特殊字符,字符串只需要字母表。

我如何模拟这些测试?

2 个答案:

答案 0 :(得分:0)

好的,所以我在调试后得到了答案。但是,它似乎有点像黑客。 这是我渲染到DOM中的组件

    import React, {Component} from 'react';

    class Search extends Component {
        constructor(props){
            super(props);
            this.state = {
                value: ''
            }
        }

        handleChange(event){
            this.setState({value: event.target.value})
        }

        render() {
            return (
                <div className='input-group'>
                    <input ref='input' type='text' className='form-control' placeholder='Enter stock ticker' value={this.state.value}
                    onChange={this.handleChange}/>
                    <span className='input-group-btn'>
                        <button className='btn btn-primary' type='submit' 
                        onClick={() => this.props.onClick(this.state.value)}>
                            Add
                        </button>
                    </span>
                </div>
            )
        }
    }

    Search.propTypes = {
        onClick: React.PropTypes.func.isRequired
    }

    export default Search;

这是接受用户输入的单元测试。不包括验证

it('accepts user input from the search button', () => {
        let search_term;
        const clickHandler = (term) => search_term = term;

        const component = renderIntoDocument(
            <Search onClick={clickHandler} />
        );

        component.state.value = 'FB';

        expect(component.state.value).to.equal('FB');
    })

我对此不太确定的原因是因为我明确设置了component.state.value ='FB',然后检查它是否是,它将是什么。但这是我最接近验证值实际发生变化的原因,因为试图运行

Simulate.change(component, {state: {value: 'FB'}});

抛出错误

  

TypeError:无法读取属性   未定义的'__reactInternalInstance $ gvviufwbzvqrhtud00vbo6r'

根据React文档(https://facebook.github.io/react/docs/test-utils.html#simulate

尝试以下操作
it('accepts user input from the search button', () => {
    let search_term;
    const clickHandler = (term) => search_term = term;

    const component = renderIntoDocument(
        <Search onClick={clickHandler} />
    );
    const input = component.refs.input;
    input.value = 'FB';
    Simulate.change(input);
    expect(input.value).to.equal('FB');
    // component.state.value = 'FB';
    // expect(component.state.value).to.equal('FB');
})

返回错误

  

TypeError:无法读取未定义

的属性'setState'

可能是因为在调用Simulate函数时必须设置状态,并且输入ref只读取状态。

如果有人对这些不同的错误有任何答案,或者甚至模拟功能的确切运作方式(文档不是很好的帮助),请分享。

答案 1 :(得分:0)

所以,我要添加另一个答案,因为我仍然喜欢我在之前的答案中提出的关于Simulate对象的问题的答案。

我遇到的问题与我正在编写的测试无关,但事实上我没有将它绑定到Search容器中的handleChange方法。

以下是搜索容器的更新构造函数

constructor(props){
        super(props);
        this.state = {
            value: ''
        }
        this.handleChange = this.handleChange.bind(this);
    }

这是现在通过的测试

it('accepts user input from the search button', () => {
        let search_term;
        const clickHandler = (term) => search_term = term;

        const component = renderIntoDocument(
            <Search onClick={clickHandler} />
        );
        const input = component.refs.input;
        input.value = 'FB';
        Simulate.change(component.refs.input);
        expect(input.value).to.equal('FB');
    })