这是一个具有AngularJS ng-click属性的div,可在单击div时设置一个变量。
<div id="id"
ng-click="foo.bar = true;">
Set bar variable on foo object to true
</div>
这是一些使用Selenium单击div元素的Java代码。
By upload = By.id("id");
driver.findElement(uploadCensus).click();
当我运行Java代码时,AngularJS会永久挂起。我认为单击div时未设置foo.bar,因此这是一些直接设置变量的代码。
By upload = By.id("id");
((JavascriptExecutor) driver)
.executeScript("foo.bar = true;",
driver.findElement(upload));
Stacktrace
未知错误:未定义foo(会话信息:chrome = 56.0.2924.87) (驱动程序信息:chromedriver = 2.25.426923 (0390b88869384d6eb0d5d09729679f934aab9eed),平台= Windows NT 6.1.7601 SP1 x86_64)(警告:服务器未提供任何堆栈跟踪信息)命令持续时间或超时:51毫秒 内部版本信息:版本:'2.53.0',版本:'35ae25b',时间:'2016-03-15 17:00:58'系统信息:主机:'WV-VC104-027',ip:'{ip}',操作系统名称: 'Windows 7',os.arch:'amd64',os.version:'6.1',java.version: '1.8.0_151'驱动程序信息:org.openqa.selenium.chrome.ChromeDriver 功能[{applicationCacheEnabled = false,rotatable = false, mobileEmulationEnabled = false,networkConnectionEnabled = false, chrome = {chromedriverVersion = 2.25.426923 (0390b88869384d6eb0d5d09729679f934aab9eed), userDataDir = C:\ Users {user} \ AppData \ Local \ Temp \ scoped_dir5600_4225}, takeHeapSnapshot = true,pageLoadStrategy = normal, databaseEnabled = false,handlesAlerts = true,hasTouchScreen = false, 版本= 56.0.2924.87,平台= XP,browserConnectionEnabled = false, nativeEvents = true,acceptSslCerts = true,locationContextEnabled = true, webStorageEnabled = true,browserName = chrome,takesScreenshot = true, javascriptEnabled = true,cssSelectorsEnabled = true}]会话ID: a7734312eff62fe452a53895b221a58d
当我尝试设置foo.bar
时,无法获得对该变量的引用,因为它不是全局定义的,并且埋在AngularJS源代码中。我试图缩小索引并寻找变量,但似乎找不到它。我想通过foo.bar
手动设置JavascriptExecutor
变量,但是无法获得对该变量的引用。我将如何找到然后设置变量?
如果这似乎是触发此ng-click
的错误方法,那么我可以公开征求意见。我确信Protractor可以解决此问题,但是这个AngularJS应用程序已部署在企业环境中,并且已经尝试了数月的业务来批准该技术。我被硒困住了。帮助...
答案 0 :(得分:1)
只需直接回答您的问题[请勿用于您的情况:)]
Angular具有隔离变量作用域。因此,您需要获取作用域并在其中设置变量。
angular.element("#id").scope().foo.bar = true;
但是不要在您的情况下使用它。在系统级别测试应用程序时,必须像在用户一样对它们进行测试。
推荐答案:等待Java中的角度测试性
无论量角器可以处理什么,您的Java测试也可以。两者都是硒绑定的包装。最终,所有硒化代码都在您测试的同一浏览器中执行。
waitForAngularMethod
是您在测试中丢失的最不可避免的方法。好事是您可以在紧急等待内使用JavaScriptExecutor执行相同类型的javascript。
如果您是JavaScript爱好者,则可以在量角器中引用waitForangular方法的实现。这只是一个简单的验证检查,请等待使用回调。
您的Java代码,用于为waitforangular创建期望的condrion
String waitForAngularJs ="Your javascript goes here"; // as it is lengthy read it from file and store here.
ExpectedCondition<Boolean> waitForAngular= new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor) driver).executeAsyncScript(waitForAngularJs).equals(true);
}
};
WebDriverWait wait = new WebDriverWait(driver, 60);
wait.until(waitForAngular);
等待有角度的Javascript(已针对您的Java执行进行了修改。但我没有对其进行检查):
该方法需要两个属性,即根定位符挂钩和回调。我已将callback设置为一个简单的函数,返回true并使用[ng-app]
的根定位符进行钩子。
var testCallback = function() {
return true;
};
// Wait for angular1 testability first and run waitForAngular2 as a callback
var waitForAngular1 = function(callback) {
if (window.angular) {
var hooks = window.angular.element('[ng-app]');
if (!hooks){
callback(); // not an angular1 app
}
else{
if (hooks.$$testability) {
hooks.$$testability.whenStable(callback);
} else if (hooks.$injector) {
hooks.$injector.get('$browser')
.notifyWhenNoOutstandingRequests(callback);
} else if (!rootSelector) {
throw new Error(
'Could not automatically find injector on page: "' +
window.location.toString() + '". Consider using config.rootEl');
} else {
throw new Error(
'root element (' + rootSelector + ') has no injector.' +
' this may mean it is not inside ng-app.');
}
}
}
else {callback();} // not an angular1 app
};
// Wait for Angular2 testability and then run test callback
var waitForAngular2 = function() {
if (window.getAngularTestability) {
if (rootSelector) {
var testability = null;
var el = document.querySelector(rootSelector);
try{
testability = window.getAngularTestability(el);
}
catch(e){}
if (testability) {
testability.whenStable(testCallback);
return;
}
}
// Didn't specify root element or testability could not be found
// by rootSelector. This may happen in a hybrid app, which could have
// more than one root.
var testabilities = window.getAllAngularTestabilities();
var count = testabilities.length;
// No angular2 testability, this happens when
// going to a hybrid page and going back to a pure angular1 page
if (count === 0) {
testCallback();
return;
}
var decrement = function() {
count--;
if (count === 0) {
testCallback();
}
};
testabilities.forEach(function(testability) {
testability.whenStable(decrement);
});
}
else {testCallback();} // not an angular2 app
};
if (!(window.angular) && !(window.getAngularTestability)) {
// no testability hook
throw new Error(
'both angularJS testability and angular testability are undefined.' +
' This could be either ' +
'because this is a non-angular page or because your test involves ' +
'client-side navigation, which can interfere with Protractor\'s ' +
'bootstrapping. See http://git.io/v4gXM for details');
} else {waitForAngular1(waitForAngular2);} // Wait for angular1 and angular2
// Testability hooks sequentially
为什么我们需要等待背后的角度和逻辑
为什么我们需要它,因为angular使用html模板,两种方式的数据绑定,ajax请求和路由。因此,在页面导航之后,我们必须等待所有此操作(请求和承诺)完成。否则html不会像您的情况那样响应预期。
检查角度可比性
即检查角度的可比性。为此,角度本身提供了一种方法。
要基于元素进行检查,
window.getAngularTestability(el).whenStable(callback); //Here el is element to be valiated.
要检查所有可证明性,
window.getAllAngularTestabilities();
testabilities.forEach(function(testability) {
testability.whenStable(callback);
});
等待所有http待处理的请求完成
在检查角度可比性之前,我们可以确保没有任何HTTP请求待处理,并带有以下几行内容。
angular.element(document).injector().get('$http').pendingRequest.length