Java Selenium-确定网页是否已在Angular 2+;
我有一个Selenium测试套件,它对许多web应用程序运行Selenium集成测试,有些是用Angular2+编写的,有些是用AngularJS编写的 我们使用自定义的Java Selenium-确定网页是否已在Angular 2+;,java,angular,selenium,selenium-webdriver,Java,Angular,Selenium,Selenium Webdriver,我有一个Selenium测试套件,它对许多web应用程序运行Selenium集成测试,有些是用Angular2+编写的,有些是用AngularJS编写的 我们使用自定义的ExpectedCondition和WebDriverWait使测试用例等待AngularJS应用程序完成加载,以避免等待任意时间: private static ExpectedCondition<Boolean> angularIsFinished() { return new ExpectedCondi
ExpectedCondition
和WebDriverWait
使测试用例等待AngularJS应用程序完成加载,以避免等待任意时间:
private static ExpectedCondition<Boolean> angularIsFinished() {
return new ExpectedCondition<Boolean>() {
public Boolean apply(final WebDriver driver) {
Object result = null;
while(result == null || result.toString().equals("undefined")) {
result = ((JavascriptExecutor)driver).executeScript("return typeof angular;");
try {
Thread.sleep(200L);
} catch (final InterruptedException ex) {
logger.error("Error while trying to sleep", ex);
}
}
final String script = " var el = document.querySelector(\"body\");\n" +
" var callback = arguments[arguments.length - 1];\n" +
" angular.element(el).injector().get('$browser').notifyWhenNoOutstandingRequests(callback);";
((JavascriptExecutor)driver).executeAsyncScript(script);
return true;
}
public String toString() {
return "Wait for AngularJS";
}
};
}
private static ExpectedCondition angularIsFinished(){
返回新的ExpectedCondition(){
公共布尔应用(最终WebDriver){
对象结果=空;
while(result==null | | result.toString().equals(“未定义”)){
结果=((JavascriptExecutor)驱动程序);
试一试{
线程。睡眠(200L);
}捕获(最终中断例外){
logger.error(“尝试睡眠时出错”,例如);
}
}
最终字符串script=“var el=document.querySelector(\“body\”);\n+
“var callback=arguments[arguments.length-1];\n”+
“angular.element(el.injector().get('$browser')。notifyWhenNoOutstandingRequests(回调);”;
((JavascriptExecutor)驱动程序);
返回true;
}
公共字符串toString(){
返回“等待AngularJS”;
}
};
}
但是,返回角度的类型对于Angular 2+应用程序,code>将始终返回未定义的
。有没有类似于AngularJS的方法可以用来确定Angular2+应用程序何时完成加载
提到使用NgZone
作为一种可能的解决方案,但是如何通过通过JavascriptExecutor
执行的脚本来处理这个问题呢?查看我提出的两种可能的解决方案:
首先,我们有一个选项,找到一个可测试性列表,然后向所有可测试性添加回调,然后等待其中一个将站点标记为可测试(这意味着您的脚本将在任何一个可测试性成为可测试性后继续,而不是等待所有可测试性成为可测试性)
private static ExpectedCondition angular2istable(){
返回(预期条件)驱动程序->{
JavascriptExecutor jsexec=((JavascriptExecutor)驱动程序);
Object result=jsexec.executeAsyncScript(“window.seleniumCallback=arguments[arguments.length-1];\n”+
“如果(window.getAllAngularTestabilities()){\n”+
“window.getAllAngularTestabilities().forEach(函数(可测试性){\n”+
“可测试性.whenStable(window.seleniumCallback(true))\n”+
“}\n”+
“”;\n“+
“}其他{\n”+
“window.seleniumCallback(false)\n”+
"}"
);
返回Boolean.parseBoolean(result.toString());
};
}
第二个选项是专门检查角根元素的可测试性状态:
private static ExpectedCondition angular2ElementIsTestable(final WebElement element) {
return (ExpectedCondition<Boolean>) driver -> {
JavascriptExecutor jsexec = ((JavascriptExecutor) driver);
Object result = jsexec.executeAsyncScript(
"window.seleniumCallback = arguments[arguments.length -1];\n" +
"var element = arguments[0];\n" +
"if (window.getAngularTestability && window.getAngularTestability(element)) {\n" +
" window.getAngularTestability(element).whenStable(window.seleniumCallback(true));\n" +
"} else {\n" +
" window.seleniumCallback(false)\n" +
"}"
, element);
return Boolean.parseBoolean(result.toString());
};
}
private static ExpectedCondition angular2elementistable(最终WebElement){
返回(预期条件)驱动程序->{
JavascriptExecutor jsexec=((JavascriptExecutor)驱动程序);
对象结果=jsexec.executeAsyncScript(
“window.seleniumCallback=参数[arguments.length-1];\n”+
“变量元素=参数[0];\n”+
“如果(window.getAngularTestability&&window.getAngularTestability(元素)){\n”+
“window.getAngularTestability(元素).whenStable(window.seleniumCallback(true));\n”+
“}其他{\n”+
“window.seleniumCallback(false)\n”+
"}"
,元素);
返回Boolean.parseBoolean(result.toString());
};
}
如果要测试站点的特定区域,第二个选项更具针对性,因此更可靠
第三种选择是编写更复杂的东西,跟踪所有可测试性的状态,然后只有在所有可测试性都为真时才触发真正的回调。我还没有这方面的实现。您可以通过调用例如document.querySelector('app-root')
来检查它?或任意组件选择器
或者调用document.readyState
?在完全加载wep页面后,它应该有结果'complete'
,无论网页是否基于角度。多亏了,我能够使用窗口执行类似于量角器的操作。getAllAngularTestabilities
函数。以下是我运行的脚本,用于确定Angular 2+页面是否加载:
var testability = window.getAllAngularTestabilities()[0];
var callback = arguments[arguments.length - 1];
testability.whenStable(callback);
以下是对AngularJS和Angular2+都有效的完整的ExpectedCondition
:
private static ExpectedCondition<Boolean> angularIsFinished() {
return new ExpectedCondition<Boolean>() {
public Boolean apply(final WebDriver driver) {
Object result = null;
boolean isAngular2Plus = false;
while(result == null || result.toString().equals("undefined")) {
result = ((JavascriptExecutor)driver).executeScript("return typeof angular;");
if (result == null || result.toString().equals("undefined")) {
result = ((JavascriptExecutor)driver).executeScript("return typeof window.getAngularTestability;");
if (result != null && !result.toString().equals("undefined")) {
isAngular2Plus = true;
}
}
try {
Thread.sleep(200L);
} catch (final InterruptedException ex) {
logger.error("Error while trying to sleep", ex);
}
}
final String script;
if (isAngular2Plus) {
script =" var testability = window.getAllAngularTestabilities()[0];\n" +
" var callback = arguments[arguments.length - 1];\n" +
" testability.whenStable(callback);";
} else {
script =" var el = document.querySelector(\"body\");\n" +
" var callback = arguments[arguments.length - 1];\n" +
" angular.element(el).injector().get('$browser').notifyWhenNoOutstandingRequests(callback);";
}
((JavascriptExecutor) driver).executeAsyncScript(script);
return true;
}
public String toString() {
return "Wait for AngularJS";
}
};
}
private static ExpectedCondition angularIsFinished(){
返回新的ExpectedCondition(){
公共布尔应用(最终WebDriver){
对象结果=空;
布尔值isAngular2Plus=false;
while(result==null | | result.toString().equals(“未定义”)){
结果=((JavascriptExecutor)驱动程序);
if(result==null | | result.toString().equals(“未定义”)){
结果=((JavascriptExecutor)driver.executeScript(“返回窗口的类型。getAngularTestability;”);
if(result!=null&&!result.toString().equals(“未定义”)){
isAngular2Plus=true;
}
}
试一试{
线程。睡眠(200L);
}捕获(最终整数)
private static ExpectedCondition<Boolean> angularIsFinished() {
return new ExpectedCondition<Boolean>() {
public Boolean apply(final WebDriver driver) {
Object result = null;
boolean isAngular2Plus = false;
while(result == null || result.toString().equals("undefined")) {
result = ((JavascriptExecutor)driver).executeScript("return typeof angular;");
if (result == null || result.toString().equals("undefined")) {
result = ((JavascriptExecutor)driver).executeScript("return typeof window.getAngularTestability;");
if (result != null && !result.toString().equals("undefined")) {
isAngular2Plus = true;
}
}
try {
Thread.sleep(200L);
} catch (final InterruptedException ex) {
logger.error("Error while trying to sleep", ex);
}
}
final String script;
if (isAngular2Plus) {
script =" var testability = window.getAllAngularTestabilities()[0];\n" +
" var callback = arguments[arguments.length - 1];\n" +
" testability.whenStable(callback);";
} else {
script =" var el = document.querySelector(\"body\");\n" +
" var callback = arguments[arguments.length - 1];\n" +
" angular.element(el).injector().get('$browser').notifyWhenNoOutstandingRequests(callback);";
}
((JavascriptExecutor) driver).executeAsyncScript(script);
return true;
}
public String toString() {
return "Wait for AngularJS";
}
};
}