Enzyme wrapper.update () приводит к тому, что входные данные ref больше не имеют значения prop - PullRequest
2 голосов
/ 21 марта 2020

Вот песочница кода, которая содержит тест, имитирующий эту проблему. Тест в этой изолированной программной среде кода не проходит, как описано в этом вопросе: https://codesandbox.io/s/react-jest-and-enzyme-testing-c7vng

Я пытаюсь проверить значение <input />, которое обновляется внутри useEffect. Это код из песочницы кода, которая является упрощенной версией того, что я пытаюсь сделать в проекте.

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, чтобы установить значение <input />.

useEffect вызывается при нажатии <button />. <button /> обновляет useState count. useEffect наблюдает за обновлениями 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 prop в 'hello'. Затем я вызываю <button /> onClick опору, эффективно нажимая на нее. Затем я звоню wrapper.update(), и я также debug() записываю <input /> до и после update().

До, update(), <input /> имеет value реквизит, содержащий 'hello'. После update(), <input /> не имеет value проп. Это приводит к сбою теста, говоря, что <input /> value не определен после обновления.

Разве значение ввода не должно быть '' после обновления?

1 Ответ

1 голос
/ 24 марта 2020

Вот список проблем с текущим способом:

  • <input ref={ref} type="text" /> описывает Элемент реагирования и не имеет значения prop

  • Значением проп следует управлять через состояние и не изменять его напрямую

    wrapper.find("input").props().value = "hello";
    
  • Установка значения на DOM-узле отличается от установки значения проп. Использование React означает, что вы уступили DOM-манипуляциям с ним. useRef разрешает доступ к базовому узлу DOM, когда ему передано начальное значение null, и следующая строка изменяет DOM, несмотря на состояние App.

    ref.current.value = "";
    

In Для определенного сценария ios целесообразно манипулировать 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;
...