【问题标题】:Enzyme wrapper.update() causes ref input to no longer have value propEnzyme wrapper.update() 导致 ref 输入不再具有 value prop
【发布时间】:2020-03-21 19:41:29
【问题描述】:

这是一个包含模拟此问题的测试的代码沙箱。此代码沙箱中的测试失败,如以下问题所述:https://codesandbox.io/s/react-jest-and-enzyme-testing-c7vng


我正在尝试测试在 useEffect 中更新的 <input /> 的值。这是代码沙箱中的代码,它是我在项目中尝试做的事情的简化版本。

import React, { useEffect, useRef, useState } from "react";

const App = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    ref.current.value = "";
    console.log(typeof ref.current.value);
  }, [count]);

  const ref = useRef(null);

  const handleClick = () => {
    setCount(count + 1);
    console.log(count);
  };

  return (
    <div>
      <input ref={ref} type="text" />
      <button onClick={handleClick}>click me</button>
    </div>
  );
};

export default App;

我使用useRef来设置&lt;input /&gt;的值。

点击&lt;button /&gt; 时会调用useEffect&lt;button /&gt; 更新 useState countuseEffect 正在观看 count 的更新,它被称为副作用。

useEffect 中,我将ref.current.value 设置为一个空字符串,然后我记录typeof 这个值以验证它是一个字符串。

在测试中,我尝试模拟这种行为:

describe("App", () => {
  const wrapper = mount(<App />);
  wrapper.find("input").props().value = "hello";
  act(() =>
    wrapper
      .find("button")
      .props()
      .onClick()
  );
  console.log(wrapper.find("input").debug());
  wrapper.update();
  console.log(wrapper.find("input").debug());
  expect(wrapper.find("input").length).toBe(1);
  expect(wrapper.find("input").props().value).toBe("hello");
});

我将value 属性设置为'hello'。然后我调用&lt;button /&gt; onClick 道具,有效地点击它。然后我打电话给wrapper.update(),我也在debug() 之前和之后记录&lt;input /&gt; update()

update() 之前,&lt;input /&gt; 有一个包含'hello'value 属性。在 update() 之后,&lt;input /&gt; 没有 value 属性。这会导致测试失败,说&lt;input /&gt;value更新后未定义。

更新后输入的值不应该是''吗?

【问题讨论】:

    标签: javascript reactjs jestjs enzyme


    【解决方案1】:

    以下是当前方式的问题列表:

    • &lt;input ref={ref} type="text" /&gt; 描述了一个React Element 并且没有值属性

    • 属性值应该通过状态来控制,而不是直接改变

      wrapper.find("input").props().value = "hello";
      
    • 在 DOM 节点上设置值与设置 prop 值不同。使用 React 意味着您将 DOM 操作交给它。 useRef 允许在传递初始值 null 时访问底层 DOM 节点,并且尽管处于 App 状态,以下行会改变 DOM。

      ref.current.value = "";
      

    在某些情况下,尽管 App 处于状态,但还是方便地操作 DOM。然后测试应该处理 DOM 节点并检查对它的更改。

    describe("App", () => {
      const wrapper = mount(<App />);
      wrapper.find("input").getDOMNode().value = "hello";
      act(() =>
        wrapper
          .find("button")
          .props()
          .onClick()
      );
      wrapper.update();
      expect(wrapper.find("input").length).toBe(1);
      expect(wrapper.find("input").getDOMNode().value).toBe("");
    });
    

    如果您认为您的用例不需要对 DOMNode 进行如此多的直接控制。 input 元素值属性可以用状态来控制。例如,

    const App = () => {
      const [count, setCount] = useState(0);
      const [value, setValue] = useState("hello");
      useEffect(() => {
        setValue("");
      }, [count]);
    
      const handleClick = () => {
        setCount(count + 1);
      };
    
      return (
        <div>
          <input type="text" value={value} />
          <button onClick={handleClick}>click me</button>
        </div>
      );
    };
    
    export default App;
    

    【讨论】:

    • 感谢您的回答。至于wrapper.find("input").props().value = "hello";,据我所知,这是在 Enzyme 中测试 props 的推荐方式。
    • 这很有帮助。谢谢
    猜你喜欢
    • 2019-08-05
    • 2019-06-09
    • 2012-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-11
    • 1970-01-01
    • 2021-07-26
    相关资源
    最近更新 更多