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

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

问题描述

问题:

在我们的一项测试中,我们有长按/点击并按住我们使用以下方法解决的功能

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.

请注意量角器文档在解释操作时引用 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.

现在,要考虑的另一件事是default .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的代码用库存JavaScript替换了 goog ... 函数。

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

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

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