Как я могу использовать метод Enzyme React Test .find? - PullRequest
0 голосов
/ 03 февраля 2019

Я пытаюсь освоить тестирование Enzyme + Jest в компонентах React, и у меня возникает ошибка при использовании метода .find в Enzyme.

Ошибка

Method “simulate” is meant to be run on 1 node. 0 found instead.

      19 |         onAddNew={onAddNew} />);
      20 |
    > 21 |      component.find('button.btn-primary').simulate('click');
         |                                           ^
      22 |      expect(onAddNew).toHaveBeenCalledTimes(1);

Я проверил рендеринг html и могу видеть кнопку и имя класса точно так, как я написал в методе find.

enter image description here

В соответствии с этим ссылка , я могу написать селектор энзима как div.className.Я думал, что мы можем написать селекторы фермента как селекторы JQuery.Итак, я использовал button.btn-primary или button.btn btn-primary, но это не работает.

Однако, если я использовал .find('Button'), он может найти его.Это показывает ошибку, что он нашел 2 узла, потому что у меня есть 2 кнопки в компоненте.Означает ли это, что метод .find выполняет поиск по компонентам React, а не по документу DOM?Если да, как я могу написать селектор, чтобы найти кнопку Primary?Есть ли способ найти его без использования first () или (0)?

Пожалуйста, смотрите следующие коды как подробно:

workoutAdd.test.js

import React from 'react';
import { shallow } from 'enzyme';
import WorkoutAdd from '../workoutAdd';

it('renders without crashing', () => {
    const 
        onChange = jest.fn(),
        onChangeDate = jest.fn(),
        onAddNew = jest.fn(),
        toggle = jest.fn(),
        item = {};

    const component = shallow(<WorkoutAdd
        toggle={toggle}
        modal={true}
        item={item}
        onChange={onChange}
        onChangeDate={onChangeDate}
        onAddNew={onAddNew} />);

     component.find('button.btn-primary').simulate('click');
     expect(onAddNew).toHaveBeenCalledTimes(1);
});

Компонент - workoutAdd.js

import React, { Component } from 'react';
import {
    Modal, ModalBody, ModalHeader, ModalFooter, Button
    , Form, FormGroup, Label, Input
} from 'reactstrap';
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";

export default class WorkoutAdd extends Component {

    render() {
        const {
            modal,
            toggle,
            item,
            onChange,
            onChangeDate,
            onAddNew } = this.props;
        return (
            <Modal isOpen={modal} toggle={toggle} centered>
                <ModalHeader toggle={toggle}>Add New Workout</ModalHeader>
                <ModalBody>
                    <Form>
                        <FormGroup>
                            <Label for="Date">Date</Label><br />                            
                            <DatePicker
                                name="date"
                                id="Date"
                                className="form-control"
                                selected={item.date}
                                onChange={onChangeDate}
                                dateFormat="dd/MM/yyyy"
                                maxDate={new Date()}
                            />                            
                        </FormGroup>
                        <FormGroup>
                            <Label for="WorkoutType">Type</Label>
                            <Input
                                type="select"
                                name="workoutType"
                                onChange={onChange}
                                value={item.workoutType}
                                id="WorkoutType">
                                <option>Running</option>
                                <option>Cycling</option>
                            </Input>
                        </FormGroup>
                        <FormGroup>
                            <Label for="Calories">Calories</Label>
                            <Input
                                type="number"
                                name="calories"
                                id="Calories"
                                value={item.calories}
                                onChange={onChange}
                                placeholder="Calories burnt"
                            />
                        </FormGroup>
                    </Form>
                </ModalBody>
                <ModalFooter>
                    <Button color="primary" onClick={onAddNew}>Save</Button>{' '}
                    <Button color="secondary" onClick={toggle}>Cancel</Button>
                </ModalFooter>
            </Modal>
        )
    }
}

ОБНОВЛЕНО Ответы

Код, который я использовал в вопросе (button.btn-primary) не работает, потому что я использую компонент Bootstrap для рендеринга Button.Если для рендеринга вашей кнопки используется традиционный HTML-код кнопки, она будет работать.

Существует множество способов выполнить это требование.
Метод 1

console.log(component.debug()); является ключевой утилитой для анализа того, как Enzyme отображает и видит компонент.

component.find("Button").at(0).simulate('click'), как упомянуто Мэттом.Однако вы не можете изменить положение кнопок / добавить новые кнопки, и тест не пройден.

Метод 2

component.find('Button[color="primary"]').simulate('click');

или

component.find('Button').find({ color: 'primary' }).simulate('click');

Вы можете использовать вышеуказанные коды, чтобы найти правильную кнопку с любым атрибутом / пропеллером.Используя их, ваши тестовые коды не связаны с реализацией компонента.Вам больше не нужно беспокоиться о положении кнопки.Сказав это, если у вас есть 2 кнопки с «основной», вам нужно будет найти другой способ уникальной идентификации кнопки.

1 Ответ

0 голосов
/ 03 февраля 2019

Поскольку вы монтируете только shallow, это будет Button.btn-primary или Button.btn.btn-primary.Вы можете подтвердить это, написав console.log(component.debug()); внутри вашего it теста, и он распечатает структуру DOM так, как enzyme ее увидит.

Если вы хотите, вы также можете обобщить ваш .find() до component.find("Button").at(0).simulate('click') или в терминах непрофессионала «найти компонент Button в позиции 0 и смоделировать щелчок».Или просто component.find(".btn-primary").simulate('click').У вас есть много возможностей найти элемент DOM, и он становится личным предпочтением (хотя я бы предпочел более конкретный селектор, особенно если вы когда-либо mount компонент).

Как примечание,будьте осторожны с обобщенным импортом: import WorkoutAdd from '../workoutAdd'; может разрешить до workAdd.test.js вместо workoutAdd.js, если они находятся в одной папке.Так что если вы когда-нибудь столкнетесь с проблемами, в которых шутит expected a string (for built-in components) or a class/function (for composite components), то вы поймете, почему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...