gpt4 book ai didi

javascript - 使用 Enzyme 测试点击监听器

转载 作者:行者123 更新时间:2023-12-02 23:31:24 27 4
gpt4 key购买 nike

我有一个有状态组件,它在挂载时附加了一个 dom 事件监听器。如果用户单击给定元素,则另一个给定元素将有条件地出现和消失。我想为此编写一个测试,但是当我使用 enzyme 这样做时,出现错误:

sampleComponent.js:

import React from 'react';

class SampleComponent extends React.Component {
constructor() {
super();
this.state = {
onClick: false,
};
this.handleClick = this.handleClick.bind(this);
}

componentDidMount() {
document.addEventListener('mousedown', this.handleClick);
}

componentWillUnmount() {
document.removeEventListener('mousedown', this.handleClick);
}

handleClick(event) {
if (this.divRef && this.divRef.contains(event.target)) {
this.setState(prevState => ({ onClick: !prevState.onClick }));
}
}

render() {
return (
<div
ref={(node) => { this.divRef = node; }}
test-attr="div"
>
{
this.state.onClick && <p test-attr="p">clicked!</p>
}
</div>
);
}
}

export default SampleComponent;

sampleComponent.test.js:

import React from 'react';
import { shallow } from 'enzyme';
import SampleComponent from './sampleComponent';

test('renders component without errors', () => {
const wrapper = shallow(<SampleComponent />);
const div = wrapper.find('[test-attr="div"]');
const p = wrapper.find('[test-attr="p"]');
div.simulate('click');
expect(p.length).toEqual(1);
});

错误:

Error: 
expect(received).toEqual(expected)

Expected value to equal:
1
Received:
0
Expected :1
Actual :0

为什么我的点击模拟无法正确更新我的组件状态?谢谢!

最佳答案

根据设计, enzyme 不支持事件监听器,因为它们是 Javascript implementation and not a React implementation 。因此,您必须执行一些 JavaScript 和 Jest 技巧才能模仿事件监听器。

在这种情况下,您实际上不需要测试事件处理程序,因为您只是操纵状态。绕过事件监听器,您可以手动操作 onClick 类属性,并对状态和 DOM 如何相应变化进行断言——这将是一个更加以 React 为中心的测试。然而,即使这样也有点困难,因为 onClick 需要一个真实的 DOM 节点。因此,一种更简单的方法是直接使用 wrapper.setState({ ... }) 操作状态,并对 DOM 更改进行断言。

顺便说一句,我更喜欢使用className而不是data-attributes,因为它们对于样式更有用测试并且它们不会用大量不必要和/或未使用的属性污染 DOM。

下面的示例涵盖了所有 3 个选项。

  • ClickHandlerEvent.test.js(模拟事件)
  • ClickHandlerHandleClick.test.js(模仿handleClick)
  • ClickHandler.test.js(操作状态)

工作示例(单击测试选项卡 - 位于浏览器右侧 - 运行所有测试):

Edit Click Listener Testing

<小时/>

components/ClickHandler/index.js(组件)

import React, { Fragment, Component } from "react";
import ClickBox from "../ClickBox";

class ClickHandler extends Component {
state = {
isVisible: false
};

componentDidMount = () => {
document.addEventListener("mousedown", this.handleClick);
};

componentWillUnmount = () => {
document.removeEventListener("mousedown", this.handleClick);
};

handleClick = ({ target }) => {
this.setState({
isVisible: this.wrapperRef && this.wrapperRef.contains(target)
});
};

render = () => {
const { isVisible } = this.state;

return (
<div className="wrapper" ref={node => (this.wrapperRef = node)}>
<ClickBox>
<p className="instruction">
(click <strong>{isVisible ? "outside" : "inside"}</strong> the box
to <strong>{isVisible ? "hide" : "show"}</strong> the message)
</p>
<h2 className="message">
{isVisible ? (
<Fragment>
Hello <strong>World</strong>!
</Fragment>
) : null}
</h2>
</ClickBox>
</div>
);
};
}

export default ClickHandler;
<小时/>

选项 1

components/ClickHandler/__tests__/ClickHandlerEvent.test.js(模拟事件)

import React, { Fragment } from "react";
import { mount } from "enzyme";
import ClickHandler from "../index";

const initialState = {
isVisible: false
};

// elevating the event listener to the test
const eventListener = {};
document.addEventListener = (evt, cb) => (eventListener[evt] = cb);

describe("Click Handler", () => {
let wrapper;
beforeAll(() => {
wrapper = mount(
<Fragment>
<ClickHandler />
<div className="outside" />
</Fragment>
);
wrapper.setState({ ...initialState });
});

afterAll(() => {
wrapper.unmount();
});

it("renders without errors and the message should be hidden", () => {
expect(wrapper.find("div.wrapper")).toHaveLength(1);
expect(wrapper.find("h2.message").text()).toEqual("");
});

it("displays a message when a click is inside of the box", () => {
// manually triggering the event listener with a node
// inside of "ClickHandler"
eventListener.mousedown({
target: wrapper
.find("ClickHandler")
.getDOMNode()
.getElementsByClassName("instruction")[0]
});

expect(wrapper.find("ClickHandler").state("isVisible")).toBeTruthy();
expect(wrapper.find("h2.message").text()).toEqual("Hello World!");
});

it("hides the message when the click is outside of the box", () => {
// manually triggering the event listener with a node
// outside of "ClickHandler"
eventListener.mousedown({
target: wrapper.find("div.outside").getDOMNode()
});

expect(wrapper.find("ClickHandler").state("isVisible")).toBeFalsy();
expect(wrapper.find("h2.message").text()).toEqual("");
});
});
<小时/>

选项 2

components/ClickHandler/__tests__/ClickHandlerHandleClick.test.js(模仿handleClick)

import React, { Fragment } from "react";
import { mount } from "enzyme";
import ClickHandler from "../index";

const initialState = {
isVisible: false
};

describe("Click Handler", () => {
let wrapper;
beforeAll(() => {
wrapper = mount(
<Fragment>
<ClickHandler />
<div className="outside" />
</Fragment>
);
wrapper.setState({ ...initialState });
});

afterAll(() => {
wrapper.unmount();
});

it("renders without errors and the message should be hidden", () => {
expect(wrapper.find("div.wrapper")).toHaveLength(1);
expect(wrapper.find("h2.message").text()).toEqual("");
});

it("displays a message when a click is inside of the box", () => {
// manually triggering the handleClick class property with a
// node inside of "ClickHandler"
wrapper
.find("ClickHandler")
.instance()
.handleClick({
target: wrapper
.find("ClickHandler")
.getDOMNode()
.getElementsByClassName("instruction")[0]
});

expect(wrapper.find("ClickHandler").state("isVisible")).toBeTruthy();
expect(wrapper.find("h2.message").text()).toEqual("Hello World!");
});

it("hides the message when the click is outside of the box", () => {
// manually triggering the handleClick class property with a
// node outside of "ClickHandler"
wrapper
.find("ClickHandler")
.instance()
.handleClick({
target: wrapper.find("div.outside").getDOMNode()
});

expect(wrapper.find("ClickHandler").state("isVisible")).toBeFalsy();
expect(wrapper.find("h2.message").text()).toEqual("");
});
});
<小时/>

选项 3

components/ClickHandler/__tests__/ClickHandler.test.js(操作状态)

import React from "react";
import { mount } from "enzyme";
import ClickHandler from "../index";

const initialState = {
isVisible: false
};

describe("Click Handler", () => {
let wrapper;
beforeAll(() => {
wrapper = mount(<ClickHandler />);
wrapper.setState({ ...initialState });
});

afterAll(() => {
wrapper.unmount();
});

it("renders without errors and the message should be hidden", () => {
expect(wrapper.find("div.wrapper")).toHaveLength(1);
expect(wrapper.find("h2.message").text()).toEqual("");
});

it("displays a message when a click is inside of the box", () => {
// manually manipulating state
wrapper.setState({ isVisible: true });
expect(wrapper.find("h2.message").text()).toEqual("Hello World!");
});

it("hides the message when the click is outside of the box", () => {
// manually manipulating state
wrapper.setState({ isVisible: false });
expect(wrapper.find("h2.message").text()).toEqual("");
});
});

关于javascript - 使用 Enzyme 测试点击监听器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56485252/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com