Многошаговые формы

Многошаговые формы (multi-step forms) встречаются во многих веб-приложениях: регистрация пользователей, оформление заказов, анкеты и опросы. Тестирование таких форм требует тщательного подхода, так как данные на каждом шаге могут сохраняться локально, на сервере или в сессии, а переход между шагами сопровождается проверкой валидации и асинхронными запросами.

Навигация по шагам формы

Каждый шаг формы может представлять отдельный компонент или быть частью одного HTML-документа с динамическим показом/скрытием блоков. Cypress позволяет работать с этими сценариями через цепочку команд:

cy.get('form')
  .within(() => {
    cy.get('input[name="firstName"]').type('Иван');
    cy.get('input[name="lastName"]').type('Иванов');
    cy.get('button.next').click();
  });

cy.get('form')
  .within(() => {
    cy.get('input[name="email"]').type('ivan@example.com');
    cy.get('button.next').click();
  });

Ключевое здесь — точное определение области действия (within), чтобы каждая команда работала только с элементами текущего шага.

Валидация и асинхронные проверки

На каждом шаге формы часто выполняется валидация:

  • Синхронная — проверка обязательных полей, формата данных, длины строк.
  • Асинхронная — проверка уникальности email, номера телефона, кодов купонов через API-запросы.

Cypress предоставляет механизм ожидания (cy.wait(), cy.intercept()), чтобы корректно обработать асинхронные проверки:

cy.intercept('POST', '/api/check-email').as('checkEmail');

cy.get('input[name="email"]').type('ivan@example.com');
cy.get('button.next').click();
cy.wait('@checkEmail').its('response.statusCode').should('eq', 200);

Использование cy.intercept() позволяет не только дождаться ответа сервера, но и контролировать его содержимое, что важно для тестирования граничных условий.

Передача данных между шагами

Данные, введённые на одном шаге, могут использоваться на последующих. Для проверки правильной передачи данных необходимо:

  • Проверять отображение на последующих шагах.
  • Сохранять значения в алиасы (cy.wrap() и as()) или использовать переменные в контексте теста:
cy.get('input[name="firstName"]').type('Иван').as('firstNameValue');
cy.get('button.next').click();

cy.get('@firstNameValue').then((firstName) => {
  cy.get('span.first-name-display').should('contain', firstName);
});

Такой подход повышает надёжность теста и позволяет отслеживать корректность данных на каждом этапе.

Обработка динамических элементов

Многошаговые формы часто включают динамические поля: новые input появляются после выбора определённого значения. Cypress обеспечивает удобные инструменты для работы с такими элементами:

cy.get('select[name="country"]').select('Россия');
cy.get('input[name="region"]').should('be.visible').type('Москва');

Важно использовать ожидания видимости (should('be.visible')), чтобы убедиться, что динамический элемент полностью отрендерен перед взаимодействием.

Повторная проверка ошибок

На каждом шаге формы могут появляться ошибки валидации. Cypress позволяет проверять их текст и состояние:

cy.get('button.next').click();
cy.get('.error-message').should('contain', 'Поле обязательно для заполнения');

Рекомендуется проверять не только наличие сообщения, но и правильность CSS-классов или атрибутов (aria-invalid), чтобы убедиться в соответствии UX-требованиям.

Полное прохождение формы

Для комплексного тестирования создаётся сценарий, который проходит все шаги формы, включая корректные и некорректные данные, с проверкой всех промежуточных условий:

cy.get('input[name="firstName"]').type('Иван');
cy.get('input[name="lastName"]').type('Иванов');
cy.get('button.next').click();

cy.get('input[name="email"]').type('ivan@example.com');
cy.get('button.next').click();

cy.get('input[name="password"]').type('Password123!');
cy.get('button.submit').click();

cy.url().should('include', '/success');
cy.get('.success-message').should('contain', 'Регистрация завершена');

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

Рекомендации по структуре тестов

  • Использовать Page Object или функции-обёртки для повторяющихся шагов.
  • Разделять тесты по сценариям: позитивные, негативные, проверка граничных условий.
  • Контролировать сетевые запросы через cy.intercept(), чтобы тесты были стабильными и не зависели от внешних сервисов.
  • Использовать алиасы и переменные для данных, используемых на нескольких шагах, для читаемости и повторного использования.

Многошаговые формы — пример сценариев, где Cypress проявляет свои сильные стороны в работе с асинхронностью, динамическими элементами и валидацией. Правильное структурирование тестов и контроль каждого шага позволяют создавать надёжные и поддерживаемые автоматические проверки.