Валидация ошибок формы

Валидация ошибок формы является критически важной частью автоматизированного тестирования веб-приложений. В контексте Protractor, который работает поверх WebDriverJS и тесно интегрирован с Angular, проверка ошибок ввода и сообщений об ошибках требует точного понимания работы локаторов, асинхронности и синхронизации с Angular-приложением.

Работа с элементами формы

Основная единица взаимодействия — элемент формы (ElementFinder). Для работы с ним используют методы поиска элементов:

let emailInput = element(by.css('input[type="email"]'));
let passwordInput = element(by.model('user.password'));
let submitButton = element(by.buttonText('Submit'));

Использование by.model или by.binding обеспечивает корректное взаимодействие с Angular-приложением, автоматически синхронизируя действия с зоной Angular.

Проверка наличия ошибки

Ошибки формы часто представлены через классы CSS (.ng-invalid, .error-message) или текстовые элементы рядом с полем. Protractor позволяет проверять их видимость и текстовое содержимое:

let emailError = element(by.css('.email-error'));

expect(emailError.isDisplayed()).toBeTruthy();
expect(emailError.getText()).toContain('Введите корректный email');

Метод isDisplayed() возвращает промис, который резолвится в true или false. Для точной проверки следует использовать await в асинхронных тестах:

expect(await emailError.isDisplayed()).toBe(true);

Валидация состояния полей

Angular добавляет специальные классы к элементам формы в зависимости от состояния:

  • .ng-valid — поле прошло валидацию
  • .ng-invalid — поле не прошло валидацию
  • .ng-dirty — значение поля изменено
  • .ng-touched — поле потеряло фокус

Проверка этих классов позволяет убедиться, что логика фронтенда корректно реагирует на ввод пользователя:

expect(await emailInput.getAttribute('class')).toContain('ng-invalid');
expect(await passwordInput.getAttribute('class')).toContain('ng-dirty');

Асинхронная валидация и ожидания

Некоторые ошибки появляются после асинхронной проверки, например, при проверке существующего email на сервере. Для этого применяют Explicit Waits через browser.wait и ExpectedConditions:

const EC = protractor.ExpectedConditions;
browser.wait(EC.visibilityOf(emailError), 5000, 'Ошибка email не появилась');
expect(await emailError.getText()).toBe('Email уже используется');

Использование ExpectedConditions обеспечивает стабильность теста и предотвращает ложные срабатывания до появления элемента.

Валидация нескольких ошибок одновременно

Форма может содержать несколько полей с ошибками. Protractor позволяет работать с массивами элементов через element.all:

let allErrors = element.all(by.css('.error-message'));
expect(await allErrors.count()).toBe(2);
expect(await allErrors.get(0).getText()).toContain('Введите имя');
expect(await allErrors.get(1).getText()).toContain('Введите email');

Методы count() и get(index) позволяют точно проверять количество и содержание ошибок на форме.

Пользовательские функции для проверки ошибок

Для упрощения повторного использования создаются утилитарные функции:

async function expectErrorMessage(inputElement, expectedMessage) {
    let errorElement = inputElement.element(by.xpath('following-sibling::div[contains(@class,"error-message")]'));
    await browser.wait(protractor.ExpectedConditions.visibilityOf(errorElement), 3000);
    expect(await errorElement.getText()).toBe(expectedMessage);
}

await expectErrorMessage(emailInput, 'Введите корректный email');

Такие функции повышают читаемость тестов и делают их поддерживаемыми.

Проверка ошибок при отправке формы

Ошибки часто отображаются только после попытки отправки формы. В этом случае последовательность действий выглядит так:

  1. Очистка или заполнение полей некорректными данными
  2. Клик по кнопке отправки
  3. Ожидание появления ошибок
  4. Проверка текста и состояния полей
await submitButton.click();
await browser.wait(EC.visibilityOf(emailError), 5000);
expect(await emailError.getText()).toBe('Введите корректный email');
expect(await emailInput.getAttribute('class')).toContain('ng-invalid');

Интеграция с Jasmine и async/await

Protractor тесно интегрируется с Jasmine. Использование async/await упрощает работу с промисами:

it('должен отображать ошибки при пустых полях', async () => {
    await submitButton.click();
    expect(await emailError.isDisplayed()).toBe(true);
    expect(await passwordInput.getAttribute('class')).toContain('ng-invalid');
});

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

Особенности работы с динамическими формами

Формы, где поля и ошибки добавляются динамически (например, повторяющиеся секции), требуют работы с ng-repeat или element.all(by.repeater(...)):

let dynamicErrors = element.all(by.repeater('field in formFields').column('field.error'));
expect(await dynamicErrors.count()).toBe(3);

Это позволяет проверять ошибки в любом количестве динамически создаваемых полей.

Валидация ошибок формы в Protractor требует сочетания корректного выбора элементов, управления асинхронностью, проверки CSS-классов и текста ошибок. Использование утилитарных функций и ExpectedConditions значительно повышает надежность и читаемость тестов, особенно в крупных Angular-приложениях.