Работа с текстовыми полями: type, clear, selectAll

При тестировании React-компонентов, содержащих текстовые поля (input, textarea), ключевой задачей является имитация поведения пользователя: ввод текста, очистка поля или выделение всего содержимого. React Testing Library предоставляет для этого удобные утилиты, встроенные в модуль user-event, позволяющий моделировать действия максимально близко к реальному взаимодействию.


Основные методы

1. type

Метод type используется для ввода текста в текстовое поле. Он эмулирует печать пользователя, учитывая каждый введённый символ. В отличие от простого изменения значения через fireEvent.change, type вызывает все соответствующие события (keydown, keypress, input, keyup), что делает тесты более реалистичными.

Пример использования:

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import TextInput from './TextInput';

test('ввод текста в input', async () => {
  render(<TextInput />);
  const input = screen.getByRole('textbox');

  await userEvent.type(input, 'Привет');
  
  expect(input).toHaveValue('Привет');
});

Особенности type:

  • Позволяет эмулировать ввод текста с клавиатуры, включая задержку между нажатиями клавиш ({delay: 100}).
  • Поддерживает имитацию нажатий специальных клавиш ({enter}, {backspace}, {tab}).
  • Реально срабатывают события, что позволяет тестировать onChange и другие обработчики.

2. clear

Метод clear полностью очищает содержимое текстового поля. Важно понимать, что clear вызывает события так же, как если бы пользователь удалял текст вручную, что позволяет тестам корректно реагировать на изменения состояния.

Пример использования:

test('очистка input', async () => {
  render(<TextInput value="Тестовое значение" />);
  const input = screen.getByRole('textbox');

  await userEvent.clear(input);

  expect(input).toHaveValue('');
});

Особенности clear:

  • Работает как последовательное удаление символов, эмулируя клавишу backspace.
  • Подходит для тестирования форм, где требуется проверка валидации после очистки поля.
  • Можно комбинировать с type для проверки последовательного ввода и удаления текста.

3. selectAll

Метод selectAll позволяет выделить весь текст в поле ввода, аналогично действиям пользователя с Ctrl+A или Cmd+A. Это особенно полезно при реализации функциональности замены текста или проверки поведения при вставке нового значения поверх выделенного.

Пример использования:

test('выделение всего текста и замена', async () => {
  render(<TextInput value="Старый текст" />);
  const input = screen.getByRole('textbox');

  await userEvent.selectOptions(input); // selectAll нет в user-event v14, используется комбинация selectText
  await userEvent.type(input, 'Новый текст');

  expect(input).toHaveValue('Новый текст');
});

Особенности selectAll:

  • Полезно для проверки редактирования и замены текста.
  • Часто используется вместе с type, чтобы заменить полностью старое значение новым.
  • Требует внимания к версии user-event: в последних версиях выделение текста может выполняться через input.select() перед вводом текста.

Комбинированное использование

Эффективное тестирование текстовых полей обычно сочетает три метода:

test('комбинация type, clear и selectAll', async () => {
  render(<TextInput value="Исходный текст" />);
  const input = screen.getByRole('textbox');

  // Очистка поля
  await userEvent.clear(input);
  expect(input).toHaveValue('');

  // Ввод нового текста
  await userEvent.type(input, 'Первый ввод');
  expect(input).toHaveValue('Первый ввод');

  // Выделение и замена текста
  input.select();
  await userEvent.type(input, 'Замена текста');
  expect(input).toHaveValue('Замена текста');
});

Такой подход позволяет моделировать реальные сценарии взаимодействия пользователя: редактирование, удаление, выделение и вставку текста.


Советы по написанию тестов

  • Использовать userEvent вместо fireEvent для имитации действий пользователя, так как это обеспечивает корректное срабатывание всех событий.
  • Не изменять value напрямую через свойство input.value, если цель — проверить реакцию компонентов на действия пользователя.
  • Комбинировать методы для воспроизведения сложных сценариев, например, ввод с заменой текста.
  • Учитывать асинхронность: многие методы userEvent возвращают промис, поэтому необходимо использовать await.

Работа с текстовыми полями через type, clear и selectAll обеспечивает тестам высокую реалистичность и позволяет проверять компонент так, как его видит реальный пользователь. Это повышает качество тестирования форм, поиска, чатов и других интерфейсов, где важен ввод текста.