javascript - 如何使用 Enzyme React Test .find 方法?

标签 javascript reactjs jestjs enzyme

我正在尝试学习 React 组件中的 Enzyme + Jest 测试,但我在使用 Enzyme 中的 .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 ,我可以将 enzyme 选择器写成 div.className。我认为我们可以将 Enzyme 选择器编写为 JQuery 选择器。因此,我使用了 button.btn-primarybutton.btn btn-primary,但它不起作用。

但是,如果我使用 .find('Button') 它可以找到它。它显示一个错误,它找到了 2 个节点,因为我在组件中有 2 个按钮。这是否意味着 .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);
});

组件 - 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 来呈现您的按钮,它会起作用。

有很多方法可以达到这个要求。
方法一

console.log(component.debug()); 是分析 Enzyme 如何呈现和查看组件的关键实用程序。

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

方法二

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

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

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

最佳答案

因为您只是安装,所以它应该是Button.btn-primaryButton.btn.btn-primary。您可以通过在 it 测试中写入 console.log(component.debug()); 来确认这一点,它会打印出 DOM 结构如 enzyme 所见。

如果需要,您还可以将 .find() 概括为 component.find("Button").at(0).simulate('click') 或通俗地说“在位置 0 找到一个 Button 组件并模拟点击”。或者简单地 component.find(".btn-primary").simulate('click')。您有多种选择来查找 DOM 元素,这成为个人偏好(尽管我更喜欢更具体的选择器,尤其是当您mount 组件时)。

作为旁注,请注意广义导入: import WorkoutAdd from '../workoutAdd'; 如果它们在同一个文件夹。因此,如果您遇到开 Jest 说 需要字符串(对于内置组件)或类/函数(对于复合组件) 的问题,那么您就会知道原因。

关于javascript - 如何使用 Enzyme React Test .find 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54504815/

相关文章:

javascript - 如何使用 AngularJS 制作基于单选按钮值的下拉列表?

javascript - jQuery:可排序:列表为空时的占位符

javascript - 在eslint中配置公共(public)文件路径

javascript - addEventListener 方法是文档对象的一部分吗?

javascript - 更改 Prop 时某些图像无法加载

javascript - 如何使用 Jest + Puppeteer 测试警报显示?

javascript - Jest 快照为每个测试文件返回相同的代码

reactjs - 更新 Redux 存储以从数组中删除某些内容不会重新渲染

reactjs - 集成测试 - redux/react + nock.js

javascript - Jest Mock React 组件仅在某些测试中