Работа с мультиселектами

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


Определение мультиселекта

Мультиселект на странице обычно представлен тегом <select> с атрибутом multiple:

<select id="colors" multiple>
  <option value="red">Красный</option>
  <option value="green">Зелёный</option>
  <option value="blue">Синий</option>
</select>

В HTML этот атрибут позволяет пользователю выбирать сразу несколько значений. В Protractor для работы с такими элементами используется объект element и методы взаимодействия с option внутри селекта.


Выбор одного и нескольких значений

Для одиночного выбора можно использовать метод .click() на нужной опции:

let colorsSelect = element(by.id('colors'));
let redOption = colorsSelect.element(by.css('option[value="red"]'));

redOption.click();

Для множественного выбора необходимо учитывать, что клики должны симулировать нажатие клавиши Ctrl или Command для поддержки множественного выбора в браузерах. В Protractor это делается через browser.actions():

let greenOption = colorsSelect.element(by.css('option[value="green"]'));
let blueOption = colorsSelect.element(by.css('option[value="blue"]'));

browser.actions()
  .keyDown(protractor.Key.CONTROL)
  .click(redOption)
  .click(greenOption)
  .click(blueOption)
  .keyUp(protractor.Key.CONTROL)
  .perform();

Ключевые моменты:

  • keyDown(protractor.Key.CONTROL) удерживает клавишу Ctrl.
  • click(option) выбирает конкретную опцию.
  • keyUp(protractor.Key.CONTROL) отпускает клавишу Ctrl после выбора.

Проверка выбранных значений

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

expect(redOption.isSelected()).toBe(true);
expect(greenOption.isSelected()).toBe(true);
expect(blueOption.isSelected()).toBe(true);

Также можно получить список всех выбранных опций:

colorsSelect.all(by.css('option:checked')).getText().then(function(selectedValues) {
  console.log(selectedValues); // ['Красный', 'Зелёный', 'Синий']
});

Снятие выбора

Снятие выбора в мультиселекте аналогично выбору: удерживаем Ctrl и кликаем по уже выбранной опции:

browser.actions()
  .keyDown(protractor.Key.CONTROL)
  .click(greenOption) // снимает выбор
  .keyUp(protractor.Key.CONTROL)
  .perform();

expect(greenOption.isSelected()).toBe(false);

Работа с динамическими мультиселектами

Если мультиселект формируется динамически через JavaScript, важно дождаться появления опций перед выбором:

let EC = protractor.ExpectedConditions;

browser.wait(EC.presenceOf(colorsSelect.element(by.css('option[value="red"]'))), 5000);

redOption.click();

Использование ExpectedConditions гарантирует, что тест не упадёт из-за попытки взаимодействия с ещё не загруженным элементом.


Универсальная функция для выбора нескольких опций

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

async function selectMultipleOptions(selectElement, values) {
  let options = await selectElement.all(by.tagName('option'));
  await browser.actions().keyDown(protractor.Key.CONTROL).perform();
  for (let value of values) {
    let option = options.find(async opt => (await opt.getAttribute('value')) === value);
    await option.click();
  }
  await browser.actions().keyUp(protractor.Key.CONTROL).perform();
}

Вызов функции:

await selectMultipleOptions(colorsSelect, ['red', 'blue']);

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


Особенности в разных браузерах

  • Chrome: поддерживает стандартное управление с Ctrl и Shift.
  • Firefox: иногда требуется отдельное ожидание после keyDown, иначе выбор может не примениться.
  • MacOS: вместо Ctrl часто используется Command (protractor.Key.META).

Учитывать эти нюансы важно при кросс-браузерном тестировании, чтобы тесты оставались стабильными.


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

  1. Отдельный блок beforeEach для инициализации элементов.
  2. Использование функций-утилит для выбора/снятия значений.
  3. Всегда проверять состояние опций через .isSelected() после взаимодействия.
  4. Оборачивать динамические элементы в ExpectedConditions.

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