如何使用酶反应测试.find方法?

时间:2019-02-03 16:09:14

标签: javascript reactjs jestjs enzyme

我正在尝试学习React组件中的酶+笑话测试,并且在酶中使用.find方法时遇到错误。

错误

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

根据此link,我可以将酶选择器写为div.className。我以为我们可以将Enzyme选择器编写为JQuery选择器。因此,我使用了button.btn-primarybutton.btn btn-primary,但是它不起作用。

但是,如果我使用.find('Button')可以找到它。它显示了一个错误,它发现了2个节点,因为组件中有2个Button。这是否意味着.find方法在React Components而不是渲染的DOM文档上执行搜索?如果是,如何编写选择器以找到“主要”按钮?有没有找到方法而无需使用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);
});

组件-ExerciseAdd.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。如果您使用的是传统的Button html来呈现按钮,那么它将起作用。

有很多方法可以满足此要求。
方法1

console.log(component.debug());是分析酶如何渲染和查看组件的关键实用工具。

component.find("Button").at(0).simulate('click'),如Matt所述。 但是,您无法移动按钮的位置/添加新按钮,测试将失败。

方法2

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

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

您可以使用上述代码找到具有任何属性/属性的右键。通过使用这些,您的测试代码不会耦合到组件的实现。您无需再担心按钮的位置。话虽如此,如果您有2个带有“主要”按钮的按钮,则需要寻找另一种唯一识别按钮的方法。

1 个答案:

答案 0 :(得分:1)

由于您仅shallow个安装,因此它将是Button.btn-primaryButton.btn.btn-primary。您可以通过在console.log(component.debug());测试内部编写it来确认这一点,并且它将打印出DOM结构,如enzyme所见。

如果需要,还可以将.find()概括为component.find("Button").at(0).simulate('click')或用外行的术语“在位置0找到Button组件并模拟点击”。或者简单地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)的问题,那么您就会知道原因。