Проверка CSS классов

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

Получение CSS-классов элемента

В Protractor для взаимодействия с элементами используется объект element совместно с локаторами из by. Чтобы получить список всех классов элемента, применяется метод getAttribute('class'):

let button = element(by.css('.submit-button'));
button.getAttribute('class').then(classes => {
    console.log(classes);
});

Метод getAttribute('class') возвращает строку, содержащую все классы элемента, разделённые пробелами. Для дальнейшей проверки удобно преобразовать эту строку в массив:

button.getAttribute('class').then(classes => {
    let classList = classes.split(' ');
    console.log(classList);
});

Такой подход позволяет выполнять точечные проверки на наличие определённого класса.

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

Для проверки, применён ли конкретный CSS-класс, используется метод expect библиотеки Jasmine (или аналогичные методы в других фреймворках):

let button = element(by.css('.submit-button'));

expect(button.getAttribute('class')).toContain('active');

Этот способ проверяет, что в списке классов присутствует active. Если класс отсутствует, тест завершится с ошибкой.

Проверка отсутствия класса

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

expect(button.getAttribute('class')).not.toContain('disabled');

Это важно при тестировании динамических состояний элементов, например, кнопки, которая становится активной после выполнения определённых действий.

Проверка нескольких классов одновременно

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

let expectedClasses = ['btn', 'btn-primary', 'active'];

button.getAttribute('class').then(classes => {
    let classList = classes.split(' ');
    let hasAllClasses = expectedClasses.every(c => classList.includes(c));
    expect(hasAllClasses).toBe(true);
});

Это гарантирует, что все ключевые классы присутствуют, и элемент отображается корректно в соответствии с макетом.

Проверка динамического изменения классов

В Angular-приложениях часто встречается динамическое добавление и удаление классов через директивы ngClass или условные выражения. Protractor позволяет проверять такие изменения в реальном времени:

let button = element(by.css('.submit-button'));
let toggleButton = element(by.css('.toggle'));

toggleButton.click().then(() => {
    expect(button.getAttribute('class')).toContain('active');
});

toggleButton.click().then(() => {
    expect(button.getAttribute('class')).not.toContain('active');
});

Метод click() возвращает промис, поэтому проверка класса выполняется после завершения действия, что гарантирует корректность результатов теста.

Утилита для повторного использования

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

function hasClass(element, className) {
    return element.getAttribute('class').then(classes => {
        return classes.split(' ').includes(className);
    });
}

// Использование
hasClass(button, 'active').then(isActive => {
    expect(isActive).toBe(true);
});

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

Особенности работы с Angular

Protractor автоматически ждёт завершения всех асинхронных операций Angular, что позволяет проверять классы, добавляемые через ngClass или реактивные события, без необходимости дополнительных ожиданий. Однако при работе с не-Angular страницами нужно использовать browser.wait или ExpectedConditions для синхронизации:

let EC = protractor.ExpectedConditions;
let button = element(by.css('.submit-button'));

browser.wait(EC.presenceOf(button), 5000);
expect(button.getAttribute('class')).toContain('visible');

Это предотвращает ошибки, связанные с попыткой проверить класс до того, как элемент появится или обновится на странице.

Практические рекомендации

  • Всегда разделять классы на массив для точной проверки отдельных значений.
  • Для динамических состояний использовать browser.wait или обработку промисов.
  • Создавать утилиты для повторяющихся проверок классов, чтобы уменьшить дублирование.
  • Проверять наличие нескольких классов одновременно только тогда, когда это критично для отображения и логики компонента.

Эффективная проверка CSS-классов позволяет убедиться, что интерфейс реагирует корректно на действия пользователя и отображает элементы в соответствии с дизайном и логикой приложения.