Для этого пока нет встроенного взаимодействия, но Serenity/ JS довольно легко расширить, поэтому вы можете создать собственное взаимодействие (и, возможно, даже отправить его как запрос на вытягивание?).
Ниже приведены шаги, которые я предприму для создания пользовательского взаимодействия.
1. Исследуйте транспортир
Для начала подумайте, как бы вы реализовали эту функциональность, используя старый добрый Protractor?
документация API Protractor предлагает следующие варианты:
// Dragging one element to another.
browser.actions().
mouseDown(element1).
mouseMove(element2).
mouseUp().
perform();
// You can also use the `dragAndDrop` convenience action.
browser.actions().
dragAndDrop(element1, element2).
perform();
// Instead of specifying an element as the target, you can specify an offset
// in pixels. This example double-clicks slightly to the right of an element.
browser.actions().
mouseMove(element).
mouseMove({x: 50, y: 0}).
doubleClick().
perform();
Как видите, все приведенные выше примеры основаны на browser.actions()
API, поэтому нам нужно найти способ получить его.
Но прежде чем погрузиться в это, давайте попробуем спроектировать наше новое взаимодействие снаружи внутрь и подумаем об интерфейсе, который мы хотели бы иметь.
2. Определите DSL, который вы хотели бы использовать
Допустим, я хотел иметь Serenity/JS, взаимодействие в стиле сценария на основе второго примера из документации Protractor:
browser.actions().
dragAndDrop(element1, element2).
perform();
предоставление следующего интерфейса:
actor.attemptsTo(
DragAndDrop(element1).onto(element2);
)
Это означает, что я мог бы определить DSL моего взаимодействия следующим образом:
import { Target } from 'serenity-js/lib/screenplay-protractor';
export const DragAndDrop = (draggable: Target) => ({
onto: (dropzone: Target) => ...
})
Это даст мне синтаксис DragAndDrop(draggable).onto(dropzone)
, который я хотел иметь.
Следующий шаг — вызов DragAndDrop(draggable).onto(dropzone)
для возврата фактического взаимодействия.
3. Определите взаимодействие
Вы можете определить взаимодействие, используя следующий сокращенный синтаксис:
import { Interaction } from 'serenity-js/lib/screenplay-protractor';
Interaction.where(`#actor drags ${draggable} onto ${dropzone}`, actor => {
// interaction body
});
Serenity/JS предоставляет "возможность" для BrowseTheWeb
а>. Эта возможность представляет собой оболочку в стиле Screenplay Pattern вокруг объекта protractor
, что означает что вы можете использовать его для доступа к API-интерфейсам транспортира.
Итак, при условии, что вы дали своему актеру возможность BrowseTheWeb
:
import { Actor, BrowseTheWeb } from 'serenity-js/lib/screenplay-protractor';
const Alice = Actor.named('Alice').whoCan(BrowseTheWeb.using(protractor.browser));
вы можете получить к нему доступ в своем interaction body
:
Interaction.where(`#actor drags ${draggable} onto ${dropzone}`, actor => {
return BrowseTheWeb.as(actor).actions().
dragAndDrop(..., ...).
perform();
});
Еще один недостающий шаг заключается в том, что метод транспортира browser.actions.dragAndDrop(..., ...)
предполагает, что вы предоставите экземпляр WebElement
, а не специфичный для Serenity/JS Target
.
Это означает, что нам нужно решить Target
, прежде чем мы передадим его:
Interaction.where(`#actor drags ${draggable} onto ${dropzone}`, actor => {
const browse = BrowseTheWeb.as(actor),
draggableElement = browse.locate(draggable),
dropzoneElement = browse.locate(dropzone);
return browse.actions().
dragAndDrop(draggableElement, dropzoneElement).
perform();
});
4. Собираем все вместе
Учитывая все вышеизложенное, результирующая реализация может выглядеть следующим образом:
import { Actor, BrowseTheWeb, Interaction, Target } from 'serenity-js/lib/screenplay-protractor';
export const DragAndDrop = (draggable: Target) => ({
onto: (dropzone: Target) => Interaction.where(
`#actor drags ${draggable} onto ${dropzone}`,
actor => {
const browse = BrowseTheWeb.as(actor),
draggableElement = browse.locate(draggable),
dropzoneElement = browse.locate(dropzone);
return browse.actions().
dragAndDrop(draggableElement, dropzoneElement).
perform();
})
})
Перетаскивание HTML5 и Chrome
Обратите внимание, что приведенная выше реализация может не работать в Chromedriver с перетаскиванием HTML5, если этот дефект исправлен.
Кроме того, вы можете установить модуль html-dnd и реализовать задачу в стиле Screenplay как следует (вам понадобится Serenity/JS 1.9.3 или новее):
import { Execute, Target, Task } from 'serenity-js/lib/screenplay-protractor';
const dragAndDropScript = require('html-dnd').code; // tslint:disable-line:no-var-requires
export const DragAndDrop = (draggable: Target) => ({
onto: (dropzone: Target) => Task.where(`#actor drags ${draggable} onto ${dropzone}`,
Execute.script(dragAndDropScript).withArguments(draggable, dropzone),
),
});
Надеюсь, это поможет, и спасибо за присоединение к сообществу Serenity/JS :-)
Ян
person
Jan Molak
schedule
18.10.2017