量角器中的自定义浏览器操作 [英] Custom browser actions in Protractor

查看:19
本文介绍了量角器中的自定义浏览器操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:

在我们的一项测试中,我们有一个"长按"/"单击并按住" 功能,我们通过使用来解决:

In one of our tests we have a "long click"/"click and hold" functionality that we solve by using:

browser.actions().mouseDown(element).perform();
browser.sleep(5000);
browser.actions().mouseUp(element).perform();

理想情况下,我们希望通过将 sleep() 作为动作链的一部分在一行中解决:

Which we would like to ideally solve in one line by having sleep() a part of the action chain:

browser.actions().mouseDown(element).sleep(5000).mouseUp(element).perform();

显然,这行不通,因为有 没有睡眠"动作.

Clearly, this would not work since there is no "sleep" action.

另一个实际例子可能是类人打字".例如:

Another practical example could be the "human-like typing". For instance:

browser.actions().mouseMove(element).click()
   .sendKeys("t").sleep(50)  // we should randomize the delays, strictly speaking
   .sendKeys("e").sleep(10)
   .sendKeys("s").sleep(20)
   .sendKeys("t")
   .perform();

请注意,这些只是示例,问题是通用的.

问题:

是否可以扩展 browser.actions() 动作序列并引入自定义动作?

Is it possible to extend browser.actions() action sequences and introduce custom actions?

推荐答案

是的,您可以扩展操作框架.但是,严格来说,得到如下内容:

Yes, you can extend the actions framework. But, strictly speaking, getting something like:

browser.actions().mouseDown(element).sleep(5000).mouseUp(element).perform();

意味着弄乱 Selenium 的胆量.所以,YMMV.

means messing with Selenium's guts. So, YMMV.

请注意,Protractor 文档是指webdriver.WebDriver.prototype.actions 在解释操作时,我认为这意味着它不会修改或添加 Selenium 提供的内容.

Note that the Protractor documentation refers to webdriver.WebDriver.prototype.actions when explaining actions, which I take to mean that it does not modify or add to what Selenium provides.

webdriver.WebDriver.prototype.actions返回的对象类是webdriver.ActionSequence.实际使序列执行任何操作的方法是 webdriver.ActionSequence.prototype.perform.在默认实现中,此函数采用调用 .sendKeys().mouseDown() 时记录的命令,并具有 ActionSequence 的驱动程序 是关联的,按顺序安排它们.所以添加一个 .sleep 方法不能这样做:

The class of object returned by webdriver.WebDriver.prototype.actions is webdriver.ActionSequence. The method that actually causes the sequence to do anything is webdriver.ActionSequence.prototype.perform. In the default implementation, this function takes the commands that were recorded when you called .sendKeys() or .mouseDown() and has the driver to which the ActionSequence is associated schedule them in order. So adding a .sleep method CANNOT be done this way:

webdriver.ActionSequence.prototype.sleep = function (delay) {
    var driver = this.driver_;
    driver.sleep(delay);
    return this;
};

否则,睡眠会乱序.你要做的是记录你想要的效果,以便稍后执行.

Otherwise, the sleep would happen out of order. What you have to do is record the effect you want so that it is executed later.

现在,要考虑的另一件事是默认的 .perform() 只期望执行 webdriver.Command,这是要发送到浏览器的命令.睡觉不是这样的命令之一.因此,必须修改 .perform() 以处理我们将使用 .sleep() 记录的内容.在下面的代码中,我选择让 .sleep() 记录一个函数并修改 .perform() 以处理除 webdriver.Command<之外的函数/代码>.

Now, the other thing to consider is that the default .perform() only expects to execute webdriver.Command, which are commands to be sent to the browser. Sleeping is not one such command. So .perform() has to be modified to handle what we are going to record with .sleep(). In the code below I've opted to have .sleep() record a function and modified .perform() to handle functions in addition to webdriver.Command.

这就是整件事情的样子,一旦放在一起.我首先给出了一个使用股票 Selenium 的示例,然后添加了补丁和一个使用修改后代码的示例.

Here is what the whole thing looks like, once put together. I've first given an example using stock Selenium and then added the patches and an example using the modified code.

var webdriver = require('selenium-webdriver');
var By = webdriver.By;
var until = webdriver.until;
var chrome = require('selenium-webdriver/chrome');

// Do it using what Selenium inherently provides.

var browser = new chrome.Driver();

browser.get("http://www.google.com");

browser.findElement(By.name("q")).click();
browser.actions().sendKeys("foo").perform();
browser.sleep(2000);
browser.actions().sendKeys("bar").perform();
browser.sleep(2000);

// Do it with an extended ActionSequence.

webdriver.ActionSequence.prototype.sleep = function (delay) {
    var driver = this.driver_;
    // This just records the action in an array. this.schedule_ is part of
    // the "stock" code.
    this.schedule_("sleep", function () { driver.sleep(delay); });
    return this;
};

webdriver.ActionSequence.prototype.perform = function () {
    var actions = this.actions_.slice();
    var driver = this.driver_;
    return driver.controlFlow().execute(function() {
        actions.forEach(function(action) {
            var command = action.command;
            // This is a new test to distinguish functions, which 
            // require handling one way and the usual commands which
            // require a different handling.
            if (typeof command === "function")
                // This puts the command in its proper place within
                // the control flow that was created above
                // (driver.controlFlow()).
                driver.flow_.execute(command);
            else
                driver.schedule(command, action.description);
        });
    }, 'ActionSequence.perform');
};

browser.get("http://www.google.com");

browser.findElement(By.name("q")).click();
browser.actions().sendKeys("foo")
    .sleep(2000)
    .sendKeys("bar")
    .sleep(2000)
    .perform();
browser.quit();

在我的 .perform() 实现中,我将 Selenium 代码使用的 goog... 函数替换为常用 JavaScript.

In my implementation of .perform() I've replaced the goog... functions that Selenium's code uses with stock JavaScript.

这篇关于量角器中的自定义浏览器操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆