目前还没有内置的交互,但是 Serenity/JS 很容易扩展,因此您可以创建自定义交互(甚至可以将其作为拉取请求提交?)。
以下是我将采取的创建自定义交互的步骤。
1.研究量角器方式
首先,想一想您将如何使用普通的 Protractor 来实现此功能?
Protractor 的 API 文档建议以下选项:
// 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
假设我想要基于 Protractor 文档中的第二个示例进行 Serenity/JS、Screenplay 风格的交互:
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 Patternprotractor
样式的包装器,这意味着您可以使用它来访问特定于量角器的 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
请注意,除非修复了此缺陷,否则上述实现可能无法在具有HTML5 拖放功能的 Chromedriver 中运行。
或者,您可以安装html-dnd模块并实现一个剧本风格的任务,如下所示(您需要 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 社区 :-)
简