Выполните перетаскивание в serenity-js

Я ищу способ выполнить перетаскивание с помощью serenity-js (http://serenity-js.org/), но я не могу найти ни одного примера. То, что я могу найти, - это транспортир, но, поскольку транспортир встроен в структуру serenity-js, мне было интересно, как заставить это работать. (Извините, я новичок в TS и javascript)

ОБНОВИТЬ:

Я реализовал обходной путь HTML5 от Яна Молака, но получил следующее сообщение об ошибке: введите здесь описание изображения

И это моя реализация задачи:

import { Execute, Target } from 'serenity-js/lib/screenplay-protractor';

import { PerformsTasks, Task } from 'serenity-js/lib/screenplay';

const dragAndDropScript = require('html-dnd').code; // tslint:disable-
line:no-var-requires

 export class DragAndDrop implements Task {

 static with(draggable: Target, dropzone: Target) {
    return new DragAndDrop(draggable, dropzone);
 }

 performAs(actor: PerformsTasks): PromiseLike<void> {
    return actor.attemptsTo(
        Execute.script(dragAndDropScript).withArguments(this.draggable, 
 this.dropzone)
    );
 }

 constructor(private draggable: Target, private dropzone: Target) {
 }
}

person Carlo Matulessy    schedule 17.10.2017    source источник


Ответы (1)


Для этого пока нет встроенного взаимодействия, но 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
comment
не могли бы посмотреть на это - stackoverflow.com/questions/57818817/ - person Pritam Maske; 13.09.2019