如何在React中测试onChange?

时间:2019-05-20 21:43:27

标签: reactjs jestjs enzyme

我有一个<Input />组件,我需要测试onChange处理程序方法,但是模拟方法不起作用,当我测试change属性时,状态不变。

下面是我使用<Input />组件的方式:

...
let formFields = formElementsArray.map(formElement => (
        <Input
            key={formElement.id}
            elementType={formElement.config.elementType}
            elementConfig={formElement.config.elementConfig}
            value={formElement.config.value}
            invalid={!formElement.config.valid}
            shouldValidate={formElement.config.validation}
            touched={formElement.config.touched}
            changed={(event) => inputChangeHandler(event, formElement.id)} />
    ))
...

下面是我的<Input />组件:

import React from 'react';

import styles from './Input.module.css';

const input = (props) => {
    let inputElement = null;
    const inputClasses = [styles.InputElement];

    if (props.invalid && props.shouldValidate && props.touched) {
        inputClasses.push(styles.Invalid);
    }

    switch (props.elementType) {
        case ('input'):
            inputElement = <input
                className={inputClasses.join(' ')}
                {...props.elementConfig}
                value={props.value}
                onChange={props.changed} />;
            break;
        case ('textarea'):
            inputElement = <textarea
                className={inputClasses.join(' ')}
                {...props.elementConfig}
                value={props.value}
                onChange={props.changed} />;
            break;
        case ('select'):
            inputElement = <select
                className={inputClasses.join(' ')}
                {...props.elementConfig}
                value={props.value}
                onChange={props.changed}>
                {props.elementConfig.options.map(option => (
                    <option
                        key={option.value}
                        value={option.value}>{option.displayValue}</option>
                ))}
            </select>;
            break;
        default:
            inputElement = <input
                className={inputClasses.join(' ')}
                {...props.elementConfig}
                value={props.value}
                onChange={props.changed} />;
    }

    return (
        <div className={styles.Input}>
            {props.label && <label className={styles.Label}>{props.label}</label>}
            {inputElement}
        </div>
    )
};

export default input;

下面是我测试onChange的方法:

import React from 'react';
import { Redirect } from 'react-router-dom';
import thunk from 'redux-thunk';

import { configure, shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import configureStore from 'redux-mock-store';

import { Auth } from './Auth';
import Spinner from '../../components/UI/Spinner/Spinner';
import Button from '../../components/UI/Button/Button';
import Input from '../../components/UI/Input/Input';

configure({ adapter: new Adapter() });

const setup = () => {
    const props = {
        onAuth: jest.fn()
    }

    const enzymeWrapper = shallow(<Auth {...props} />);

    return {
        enzymeWrapper,
        props
    }
}

describe('<Auth />', () => {

    it('should create user when form is submitted', () => {
        const { enzymeWrapper: wrapper, props: reduxProps } = setup();
        const form = wrapper.find('form');
        const inputs = form.find(Input);
        const emailInput = inputs.at(0);
        const passwordInput = inputs.at(1);
        const email = "email@servidor.com";
        const password = "senha";

        // below the onChange doesn't works
        emailInput.simulate('change', {
            target: {
                value: email
            }
        });
        passwordInput.simulate('change', {
            target: {
                value: password
            }
        });
        // below the onChange doesn't works
        emailInput.find('input').simulate('change', {
            target: {
                value: email
            }
        });
        passwordInput.find('input').simulate('change', {
            target: {
                value: password
            }
        });
        // below the onChange works, but state doesn't change
        emailInput.props().changed({
            target: {
                value: email
            }
        }, 0);
        passwordInput.props().changed({
            target: {
                value: password
            }
        }, 1);

        expect(emailInput.props().value).toEqual(email);
        expect(passwordInput.props().value).toEqual(password);
    });
});

我的推理对吗?我如何测试onChange?

1 个答案:

答案 0 :(得分:1)

您的方向正确,只是缺少了几件事。

首先,React Hooks可能很难测试,但是您实际上并没有使用钩子(至少没有在发布的代码中使用钩子,所以不用担心:)

第二,您的测试缺少expect语句。在测试时,您想检查是否可行,并为此使用expect

因此,在这段代码之后:

emailInput.simulate('change', {
    target: {
        value: email
    }
});

您可能会遇到类似的事情:

expect(emailInput.value).toEqual(email);

您可以按照酶文档here中的示例进行操作。

此外,您可以查看expect here的文档。