Selenium-确定网页是否已在Angular 2+中完成加载

时间:2019-03-21 15:05:40

标签: java angular selenium selenium-webdriver

我有一个Selenium测试套件,它针对许多Web应用程序运行Selenium集成测试,其中一些是用Angular 2+编写的,而另一些是用AngularJS编写的。

我们使用带有ExpectedCondition的自定义WebDriverWaitprivate 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"; } }; } 来使测试用例等待AngularJS应用完成加载,以避免等待任意时间:

return typeof angular;

但是,undefined对于Angular 2+应用程序将始终返回NgZone。可以使用与AngularJS的notifyWhenNoOutstandingRequests类似的方法来确定Angular 2+应用何时完成加载吗?

This question提到使用JavascriptExecutor作为一种可能的解决方案,但是您如何通过通过 ID PFT area 1 alnfru_00001 alnfru Yukon_Delta 2 alnfru_00002 alnfru Yukon_Delta 3 alnfru_00003 alnfru Yukon_Delta 4 alnfru_00004 alnfru Yukon_Delta 5 alnfru_00001 alnfru Yukon_Delta 6 alnfru_00002 alnfru Yukon_Delta 7 alnfru_00003 alnfru Yukon_Delta 8 alnfru_00004 alnfru Yukon_Delta 9 alnfru_00005 alnfru Yukon_Delta.................................... 18 alnfru_00001 alnfru Yukon_Delta 19 alnfru_00002 alnfru Yukon_Delta 20 alnfru_00003 alnfru Yukon_Delta 21 alnfru_00004 alnfru Yukon_Delta 22 alnfru_00001 alnfru Yukon_Delta 23 alnfru_00002 alnfru Yukon_Delta 24 alnfru_00003 alnfru Yukon_Delta 25 alnfru_00004 alnfru Yukon_Delta The data frame should look like this ID PFT area 1 alnfru_00001 alnfru Yukon_Delta 2 alnfru_00002 alnfru Yukon_Delta 3 alnfru_00003 alnfru Yukon_Delta 4 alnfru_00004 alnfru Yukon_Delta 5 alnfru_00005 alnfru Yukon_Delta 6 alnfru_00006 alnfru Yukon_Delta 7 alnfru_00007 alnfru Yukon_Delta 8 alnfru_00008 alnfru Yukon_Delta 9 alnfru_00009 alnfru Yukon_Delta.................................... 18 alnfru_00010 alnfru Yukon_Delta 19 alnfru_00011 alnfru Yukon_Delta 20 alnfru_00012 alnfru Yukon_Delta 21 alnfru_00013 alnfru Yukon_Delta 22 alnfru_00014 alnfru Yukon_Delta 23 alnfru_00015 alnfru Yukon_Delta 24 alnfru_00016 alnfru Yukon_Delta 25 alnfru_00017 alnfru Yukon_Delta 执行的脚本来处理呢?

3 个答案:

答案 0 :(得分:1)

您可以通过致电例如document.querySelector('app-root')?或任意组件选择器...

或者打电话给document.readyState呢?完整载入wep页面后,结果应该为'complete',并且网页是否基于角度都没关系。

答案 1 :(得分:0)

针对Protractor code,我提出了两种可能的解决方案:

首先,我们有一个选项,可以在其中找到可测试性列表,然后为所有可添加性添加回调,然后等待其中一个将站点标记为可测试性(这确实意味着您的脚本将在任何一种可测性都已经成为可测性,它不会等待所有可测性都变为可测性。

private static ExpectedCondition angular2IsTestable() {
    return (ExpectedCondition<Boolean>) driver -> {
        JavascriptExecutor jsexec = ((JavascriptExecutor) driver);
        Object result = jsexec.executeAsyncScript("window.seleniumCallback = arguments[arguments.length -1];\n" +
                        "if (window.getAllAngularTestabilities()) {\n" +
                        "    window.getAllAngularTestabilities().forEach(function (testability) {\n" +
                        "            testability.whenStable(window.seleniumCallback(true))\n" +
                        "        }\n" +
                        "    );\n" +
                        "} else {\n" +
                        "    window.seleniumCallback(false)\n" +
                        "}"
        );

        return 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());
    };
}

第二个选项更具针对性,因此如果要测试站点的特定区域,则更可靠。

第三个选择是编写一些更复杂的东西,以跟踪所有可测试性的状态,然后仅在所有条件变为真时才触发真正的回调。我还没有实现方案。

答案 2 :(得分:0)

由于@Ardesco's answer,我可以使用window.getAllAngularTestabilities函数来完成类似于量角器的工作。这是我用来确定Angular 2+页面是否加载的脚本:

var testability = window.getAllAngularTestabilities()[0];
var callback = arguments[arguments.length - 1];
testability.whenStable(callback);

这是完整的ExpectedCondition看起来对AngularJS和Angular 2+都适用的样子:

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";
        }
    };
}
相关问题