Тестирование checkbox и radio

Enzyme предоставляет мощные инструменты для тестирования компонентов React, в том числе для работы с элементами формы, такими как checkbox и radio. Эти элементы представляют собой важные части пользовательского интерфейса, которые требуют особого внимания при написании тестов, чтобы гарантировать корректное взаимодействие с пользователем и правильную обработку данных формы.

Основные элементы управления

Checkbox и Radio — это два типа элементов формы, которые позволяют пользователю выбрать одно или несколько значений. В отличие от обычных текстовых полей, которые используют значения, передаваемые напрямую, эти элементы взаимодействуют с состоянием компонента через события изменения. Важно правильно моделировать эти события в тестах для имитации поведения пользователя.

Проверка состояния checkbox

Когда компонент содержит несколько флажков (checkbox), важно убедиться, что:

  1. Пользователь может выбирать и снимать выбор с каждого флажка.
  2. Состояние флажков корректно обновляется в состоянии компонента.
it('должен правильно переключать состояние checkbox', () => {
  const wrapper = mount(<MyComponent />);
  const checkbox = wrapper.find('input[type="checkbox"]');

  // Начальное состояние
  expect(checkbox.prop('checked')).toBe(false);

  // Переключаем состояние
  checkbox.simulate('change', { target: { checked: true } });

  // Проверяем новое состояние
  expect(checkbox.prop('checked')).toBe(true);

  // Снимаем выбор
  checkbox.simulate('change', { target: { checked: false } });
  expect(checkbox.prop('checked')).toBe(false);
});

В данном примере мы используем simulate для вызова события изменения (change) на элементе checkbox. Важно передать правильные параметры в объект события, чтобы правильно имитировать поведение пользователя.

Проверка состояния radio

Для элементов типа radio, где из набора выбирается только один элемент, тестирование отличается. Нужно убедиться, что:

  1. Выбран только один радио-кнопка.
  2. При выборе одного элемента остальные автоматически становятся невыбранными.
it('должен правильно переключать состояние radio', () => {
  const wrapper = mount(
    <form>
      <input type="radio" name="group" value="option1" />
      <input type="radio" name="group" value="option2" />
    </form>
  );

  const radioButtons = wrapper.find('input[type="radio"]');

  // Проверяем, что изначально все не выбраны
  expect(radioButtons.at(0).prop('checked')).toBe(false);
  expect(radioButtons.at(1).prop('checked')).toBe(false);

  // Выбираем первый радиокнопку
  radioButtons.at(0).simulate('change', { target: { checked: true } });

  // Проверяем, что первый радиокнопка выбран, второй — нет
  expect(radioButtons.at(0).prop('checked')).toBe(true);
  expect(radioButtons.at(1).prop('checked')).toBe(false);

  // Выбираем второй радиокнопку
  radioButtons.at(1).simulate('change', { target: { checked: true } });

  // Проверяем, что второй радиокнопка выбран, первый — нет
  expect(radioButtons.at(0).prop('checked')).toBe(false);
  expect(radioButtons.at(1).prop('checked')).toBe(true);
});

Как и в случае с checkbox, для radio используется метод simulate для имитации события change. Важно отслеживать, что при выборе одного элемента из группы радио-кнопок остальные должны быть сброшены.

Взаимодействие с состоянием компонента

Тестирование checkbox и radio требует проверки того, как изменения в пользовательском интерфейсе влияют на состояние компонента. Для этого можно использовать состояние компонента и тестировать его изменения после симуляции событий.

class MyComponent extends React.Component {
  state = {
    checkboxChecked: false,
    radioValue: ''
  };

  handleCheckboxChange = event => {
    this.setState({ checkboxChecked: event.target.checked });
  };

  handleRadioChange = event => {
    this.setState({ radioValue: event.target.value });
  };

  render() {
    return (
      <form>
        <input
          type="checkbox"
          checked={this.state.checkboxChecked}
          onCha nge={this.handleCheckboxChange}
        />
        <input
          type="radio"
          name="group"
          value="option1"
          checked={this.state.radioValue === 'option1'}
          onCha nge={this.handleRadioChange}
        />
        <input
          type="radio"
          name="group"
          value="option2"
          checked={this.state.radioValue === 'option2'}
          onCha nge={this.handleRadioChange}
        />
      </form>
    );
  }
}

В тестах важно убедиться, что состояние компонента изменяется правильно после того, как пользователь взаимодействует с флажками или радио-кнопками. Например:

it('должен обновлять состояние при изменении checkbox', () => {
  const wrapper = mount(<MyComponent />);
  const checkbox = wrapper.find('input[type="checkbox"]');

  // Проверка начального состояния
  expect(wrapper.state().checkboxChecked).toBe(false);

  // Симулируем изменение checkbox
  checkbox.simulate('change', { target: { checked: true } });

  // Проверка, что состояние обновилось
  expect(wrapper.state().checkboxChecked).toBe(true);
});

it('должен обновлять состояние при изменении radio', () => {
  const wrapper = mount(<MyComponent />);
  const radio1 = wrapper.find('input[type="radio"]').at(0);
  const radio2 = wrapper.find('input[type="radio"]').at(1);

  // Проверка начального состояния
  expect(wrapper.state().radioValue).toBe('');

  // Выбираем первый радио
  radio1.simulate('change', { target: { value: 'option1' } });

  // Проверка, что состояние обновилось
  expect(wrapper.state().radioValue).toBe('option1');

  // Выбираем второй радио
  radio2.simulate('change', { target: { value: 'option2' } });

  // Проверка, что состояние обновилось
  expect(wrapper.state().radioValue).toBe('option2');
});

Тестирование в комбинации с другими библиотеками

Часто компоненты с флажками и радио используются в сочетании с другими библиотеками, такими как Formik или React Hook Form, для управления состоянием формы. В этих случаях тестирование становится более сложным, так как необходимо учитывать внешний слой управления состоянием формы. Однако подходы к тестированию остаются теми же: симуляция событий и проверка обновлений состояния.

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

  1. Симуляция пользовательских событий: Всегда используйте метод simulate для имитации событий, таких как change, чтобы протестировать изменения состояния элементов формы.
  2. Проверка состояний: Для тестов, где состояние компонента зависит от выбора флажков или радио, убедитесь, что проверяете не только визуальное состояние (например, через атрибут checked), но и внутреннее состояние компонента.
  3. Группы радио: Когда тестируете группу радио-кнопок, помимо проверки их отдельных состояний, обязательно проверяйте, что только одна кнопка из группы может быть выбрана в данный момент времени.

Правильное тестирование checkbox и radio помогает выявить ошибки на ранних этапах разработки и улучшить пользовательский опыт в приложении.