问题:
在我们的一个测试中,我们使用以下方法解决了"long click"/"click and hold" functionality:
gravity_vertical
我们希望通过让browser.actions().mouseDown(element).perform();
browser.sleep(5000);
browser.actions().mouseUp(element).perform();
成为行动链的一部分来理想地解决这一问题:
sleep()
显然,由于存在no "sleep" action,这不起作用。
另一个实际例子可能是"类似人类的打字"。例如:
browser.actions().mouseDown(element).sleep(5000).mouseUp(element).perform();
请注意,这些只是示例,问题是通用的。
问题:
是否可以扩展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();
操作序列并引入自定义操作?
答案 0 :(得分:10)
是的,你可以扩展行动框架。但是,严格来说,得到类似的东西:
browser.actions().mouseDown(element).sleep(5000).mouseUp(element).perform();
意味着搞乱Selenium的胆量。所以,YMMV。
请注意,Protractor documentation在解释操作时会引用webdriver.WebDriver.prototype.actions
,我认为这意味着它不会修改或添加Selenium提供的内容。
webdriver.WebDriver.prototype.actions
返回的对象类为webdriver.ActionSequence
。实际上导致序列执行任何操作的方法是webdriver.ActionSequence.prototype.perform
。在默认实现中,此函数采用您调用.sendKeys()
或.mouseDown()
时记录的命令,并使ActionSequence
关联的驱动程序按顺序排列。因此,添加.sleep
方法不能这样做:
webdriver.ActionSequence.prototype.sleep = function (delay) {
var driver = this.driver_;
driver.sleep(delay);
return this;
};
否则,睡眠会发生乱序。您需要做的是记录您想要的效果,以便以后执行。
现在,要考虑的另一件事是默认.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();
在我.perform()
的实现中,我已将Selenium代码使用的goog...
函数替换为股票JavaScript。
答案 1 :(得分:4)
这就是我所做的(基于完美的@Louis答案)。
将以下内容放入量角器配置中的onPrepare()
:
// extending action sequences
protractor.ActionSequence.prototype.sleep = function (delay) {
var driver = this.driver_;
this.schedule_("sleep", function () { driver.sleep(delay); });
return this;
};
protractor.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;
if (typeof command === "function")
driver.flow_.execute(command);
else
driver.schedule(command, action.description);
});
}, 'ActionSequence.perform');
};
protractor.ActionSequence.prototype.clickAndHold = function (elm) {
return this.mouseDown(elm).sleep(3000).mouseUp(elm);
};
现在,您可以使用sleep()
和clickAndHold()
个浏览器操作。用法示例:
browser.actions().clickAndHold(element).perform();
答案 2 :(得分:3)
我认为可以扩展browser.actions()
功能但目前高于我的技能水平,所以我将列出解决此问题的路线。我建议设置一个" HelperFunctions.js "包含所有这些全局助手函数的页面对象。在该文件中,您可以列出您的browser
函数,并在多个测试中引用它,并将所有代码放在一个位置。
这是" HelperFunctions.js"的代码。我建议设置的文件:
var HelperFunctions = function() {
this.longClick = function(targetElement) {
browser.actions().mouseDown(targetElement).perform();
browser.sleep(5000);
browser.actions().mouseUp(targetElement).perform();
};
};
module.exports = new HelperFunctions();
然后在您的测试中,您可以像这样引用Helper文件:
var HelperFunctions = require('../File_Path_To/HelperFunctions.js');
describe('Example Test', function() {
beforeEach(function() {
this.helperFunctions = HelperFunctions;
browser.get('http://www.example.com/');
});
it('Should test something.', function() {
var Element = element(by.className('targetedClassName'));
this.helperFunctions.longClick(Element);
});
});
在我的测试套件中,我设置了一些帮助文件,并在我的所有测试中引用它们。
答案 3 :(得分:2)
我对硒或量角器知之甚少,但我会试一试。
这假定
browser.actions().mouseDown(element).mouseUp(element).perform();
是您的问题的有效语法,如果是这样,那么这可能会成功
browser.action().sleep = function(){
browser.sleep.apply(this, arguments);
return browser.action()
}