toHaveValue возвращает значение null, в то время как входное значение равно 0

#reactjs #jestjs #react-testing-library #jest-dom

Вопрос:

Я работаю над тестовым кодом для своего проекта React. Что я хочу проверить, так это «если тип ввода-число, он запрещает вставку текста». Ниже приведен тестовый код, который я написал.

 it("disallow a text input", () => {
  const input = screen.getByLabelText(label0); // it has 0 as initial value
  const dummyText = "imyourfather";

  // typing a text won't change the value of input
  userEvent.type(input, dummyText);
  screen.debug();
  expect(input).toHaveValue(0); // FAILED -> return null
});
 

То, что я ожидал здесь, — это получить начальное значение 0 , в результате toHaveValue . Но на самом деле он возвращается null .

Вы можете подумать: «Да, вы пытались вставить текст в ввод, набранный цифрами, вот почему он возвращает значение null», но самое забавное, что debug() он console.log(input.value) возвращается 0 , как я и ожидал.

 <!-- the result of debug() -->
<div
  class="ui input"
>
  <input
    id="form-field-number01"
    required=""
    type="number"
    value="0"
  />
</div>
 

А также, если вы вручную попытаетесь вставить текстовое значение в вводимые числа в браузере, оно фактически покажет начальное значение 0. Кто-нибудь знает, почему toHaveValue и debug показывают разные результаты?

Комментарии:

1. Как вы можете видеть из вашего собственного журнала отладки, начальное значение-это не 0 «но "0" «. Это строка, а не число

2. @lbsn даже когда все работает хорошо и возвращает целое 0 число , он показывает вам "0" debug() результат, потому что он написан в html-форме. и даже если фактический результат таков "0" , это не имеет смысла, что вы получаете null в результате.

Ответ №1:

После некоторого копания выясняется, что это действительно ожидаемое поведение toHaveValue в случае <input type="number"> .

Во-первых, входное значение при вводе строки (в случае type="number" ) на самом деле является пустой строкой:

Алгоритм очистки значений выглядит следующим образом: если значение элемента не является допустимым числом с плавающей запятой, вместо этого установите его в пустую строку.

В то время screen.debug() как будет выводиться дерево DOM, вы можете проверить фактическое value свойство, зарегистрировав его после ввода фиктивного текста:

 userEvent.type(input, dummyText);
console.log('--> Value: ', input.value);
console.log('--> Value type: ', typeof input.value);
 

Теперь функция, используемая jest-dom для получения входного значения, выглядит следующим образом:

 function getInputValue(inputElement) {
  switch (inputElement.type) {
    case 'number':
      return inputElement.value === '' ? null : Number(inputElement.value)
    case 'checkbox':
      return inputElement.checked
    default:
      return inputElement.value
  }
}
 

Как вы можете видеть, в случае type="number" , если пустая строка будет разрешена null . Не знаю, в чем причина этого.

Что касается вашего конкретного случая, вы можете проверить элемент ввода, чтобы в качестве значения не было вашего фиктивного текста или чтобы отображалось пустое значение:

 expect(input).not.toHaveValue(dummyText);
expect(input).toHaveDisplayValue("");
 

Комментарии:

1. вау. Я даже не заботился о самой спецификации ввода. такое милое объяснение. большое спасибо 🙂