Drag and drop операции

Drag and drop (перетаскивание элементов) является одной из важных операций при автоматизированном тестировании веб-приложений. В Protractor для реализации этих действий используется модуль browser.actions(), предоставляющий богатый набор методов для взаимодействия с элементами на странице.


Методы для перетаскивания

1. mouseDown() и mouseUp() Эти методы имитируют нажатие и отпускание кнопки мыши. Чаще всего их используют вместе с mouseMove() для поэтапного перетаскивания.

Пример поэтапного перетаскивания:

let source = element(by.id('draggable'));
let target = element(by.id('droppable'));

browser.actions()
    .mouseMove(source)   // Наведение на исходный элемент
    .mouseDown()         // Нажатие кнопки мыши
    .mouseMove(target)   // Перемещение к целевому элементу
    .mouseUp()           // Отпускание кнопки мыши
    .perform();

2. dragAndDrop() Метод dragAndDrop(source, target) объединяет все этапы перетаскивания в одну операцию, что делает код более компактным и читаемым.

Пример использования:

let source = element(by.id('draggable'));
let target = element(by.id('droppable'));

browser.actions().dragAndDrop(source, target).perform();

Работа с координатами

Иногда требуется перетаскивание не к другому элементу, а на определённое смещение. Для этого используется mouseMove({x: offsetX, y: offsetY}).

Пример перетаскивания на смещение:

let elementToMove = element(by.css('.draggable'));

browser.actions()
    .mouseMove(elementToMove)
    .mouseDown()
    .mouseMove({x: 100, y: 50}) // Перемещение на 100px вправо и 50px вниз
    .mouseUp()
    .perform();

Проверка успешного перетаскивания

Для подтверждения корректности операции часто используется метод getText() или проверка атрибутов/классов элементов после перетаскивания:

let target = element(by.id('droppable'));

expect(target.getText()).toEqual('Dropped!');
expect(target.getAttribute('class')).toContain('ui-state-highlight');

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

Не все элементы корректно реагируют на стандартные методы dragAndDrop. В таких случаях применяются дополнительные подходы:

  1. Использование JavaScript для симуляции событий
browser.executeScript(`
    const source = arguments[0];
    const target = arguments[1];
    const dataTransfer = new DataTransfer();
    source.dispatchEvent(new DragEvent('dragstart', {dataTransfer}));
    target.dispatchEvent(new DragEvent('drop', {dataTransfer}));
    source.dispatchEvent(new DragEvent('dragend', {dataTransfer}));
`, source.getWebElement(), target.getWebElement());
  1. Разбиение перемещения на мелкие шаги Если mouseMove(target) не срабатывает, можно перемещать элемент по маленьким смещениям с промежуточными perform().

Отладка drag and drop

  1. Замедление действий — использование browser.sleep(ms) между этапами позволяет увидеть, как выполняется перетаскивание.
  2. Скриншоты — фиксируют состояние страницы после каждого этапа для диагностики проблем.
  3. Проверка координат — метод getLocation() возвращает текущие координаты элемента, что полезно для подтверждения перемещения.
element(by.id('draggable')).getLocation().then(location => {
    console.log(location); // {x: 150, y: 200}
});

Важные нюансы

  • Элементы должны быть видимыми и интерактивными, иначе действия с ними не будут выполняться.
  • Иногда полезно использовать browser.wait(ExpectedConditions.visibilityOf(element)) перед drag and drop.
  • При работе с фреймами требуется переключение контекста через browser.switchTo().frame().

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

  • Предпочтительно использовать dragAndDrop, если браузер и элемент поддерживают стандартные события.
  • Для сложных интерфейсов с нестандартной реализацией HTML5 Drag and Drop рекомендуется комбинировать JavaScript и Protractor actions.
  • В тестах важно проверять не только визуальный результат, но и состояние данных на фронтенде и бэкенде после перетаскивания.