Protractor中的自定义浏览器操作

ale*_*cxe 15 javascript selenium selenium-webdriver protractor

问题:

在我们的一个测试中,我们有一个"长按"/"点击并保持"功能,我们通过使用以下方法解决:

browser.actions().mouseDown(element).perform();
browser.sleep(5000);
browser.actions().mouseUp(element).perform();
Run Code Online (Sandbox Code Playgroud)

我们希望通过拥有sleep()动作链的一部分来理想地在一行中解决:

browser.actions().mouseDown(element).sleep(5000).mouseUp(element).perform();
Run Code Online (Sandbox Code Playgroud)

显然,这不起作用,因为没有"睡眠"动作.

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

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();
Run Code Online (Sandbox Code Playgroud)

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

问题:

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


Lou*_*uis 10

是的,您可以扩展操作框架.但是,严格地说,得到类似的东西:

browser.actions().mouseDown(element).sleep(5000).mouseUp(element).perform();
Run Code Online (Sandbox Code Playgroud)

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

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

返回的对象类webdriver.WebDriver.prototype.actionswebdriver.ActionSequence.实际上导致序列做任何事情的方法是webdriver.ActionSequence.prototype.perform.在默认实现中,此函数接受您调用时记录的命令,.sendKeys()或者使用与之关联.mouseDown()的驱动程序ActionSequence按顺序安排它们.所以添加.sleep方法不能这样做:

webdriver.ActionSequence.prototype.sleep = function (delay) {
    var driver = this.driver_;
    driver.sleep(delay);
    return this;
};
Run Code Online (Sandbox Code Playgroud)

否则,睡眠将无序发生.你要做的是记录你想要的效果,以便以后执行.

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

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

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();
Run Code Online (Sandbox Code Playgroud)

在我的实现中,.perform()我已经用goog...Selenium的代码替换了股票JavaScript使用的函数.