jjzjj

javascript - 如果 Angular 正在做......从 Selenium 中检测东西

coder 2025-02-22 原文

为什么 driver.findElement(<some static element ng-if=simplebool>static text</some>).getText()曾经返回“”吗?

我有一个 Angular 应用程序,我正在 osx 上通过 java 通过 chromedriver 使用 selenium 进行测试。

我有一些标记如下:

<h1 id="my-unique-id" ng-if="model.shouldDisplayThisAttribute">static text</h1>

我经常得到:

assert(driver.findElement(By.id("my-unique-id").getText().contains("static text");

产量:

java.lang.AssertionError: Not true that <""> contains <"static text">

喜欢,30% 的时间。

我不明白该元素的 .getText() 如何计算为“”,所以我假设 angular 是 $digesting 或 $compiling 页面。没关系。没关系。没关系。

我想知道 Angular 什么时候完成了 $compiling、$digesting 和 $watching,这样我就可以查看页面,看看是什么。

如果我添加:

(function() 
   function angularAppearsToBeIdle(callback) {
     var untilNextDigest,
        isIdle = angular.element(document.body).scope().$watch(function () {
           clearTimeout(untilNextDigest);
           untilNextDigest = setTimeout(function () {
           isIdle();
           callback('done');
         }, 100);
      });
    }
 angularAppearsToBeIdle(console.log.bind(console));
}());

在我的页面上,我在预期的时间看到了 console.log 消息。

如果我将其粘贴到控制台中:

(function() {
   function angularAppearsToBeIdle(callback) {
       var untilNextDigest,
       isIdle = angular.element(document.body).scope().$watch(function () {
           clearTimeout(untilNextDigest);
           untilNextDigest = setTimeout(function () {
               isIdle();
               callback('done');
           }, 100);
       });
   }
   angularAppearsToBeIdle(console.log.bind(console));
}());

我得到“未定义”。

最终,我想做的是来自 Java 的:

@Test
public void clickOnSomethingThatIsProbablyNotGoingToChange(driver.findElement(By.id("some-id"));

private WebElement idleElement() {

    new WebDriverWait(driver, 30).until(new Predicate<WebDriver>() {
        @Override
        public boolean apply(WebDriver input) {
            Object result = ((JavascriptExecutor) driver).executeScript("return window.angularAppearsToBeIdle;");
            return result.equals("idle");
        }
   }

我已经尝试了以下方法,但是没有 Selenium 做这样的事情的例子:

public void waitForAngular() {

    ((JavascriptExecutor) driver).executeScript(
            " window.angularAppearsToBeIdle = 'not idle'; ");

    ((JavascriptExecutor) driver).executeScript(
            " window.signalThatAngularAppearsToBeIdle = function(signal) { " +
            " var untilNextDigest, " +
            " isIdle = angular.element(document.body).scope().$watch(function () { " +
            "    clearTimeout(untilNextDigest); " +
            "    untilNextDigest = setTimeout(function () { " +
            "       isIdle(); " +
            "       signal = 'idle'; " +
            "    }, 100); " +
            "  }); " +
            " } ");

    driver.manage().timeouts().setScriptTimeout(10, TimeUnit.SECONDS);

    ((JavascriptExecutor) driver).executeAsyncScript(
            " var callback = arguments[arguments.length - 1]; " +
                    " signalThatAngularAppearsToBeIdle(callback) "
            ,
            " window.angularAppearsToBeIdle ");

    new WebDriverWait(driver, 30).until(new Predicate<WebDriver>() {
        @Override
        public boolean apply(WebDriver input) {
            Object result = ((JavascriptExecutor) driver).executeScript("return window.angularAppearsToBeIdle;");
            return result.equals("idle");

        }
    });

如果 Angular 正在忙着做事,我如何从 Selenium 检测到?

最佳答案

您需要编写一个自定义的 ExpectedCondition 来查询 angular 以查看它是否已完成。这是我之前准备的:

    public static ExpectedCondition angularHasFinishedProcessing() {
        return new ExpectedCondition<Boolean>() {
            @Override
            public Boolean apply(WebDriver driver) {
                String hasAngularFinishedScript = "var callback = arguments[arguments.length - 1];\n" +
                        "var el = document.querySelector('html');\n" +
                        "if (!window.angular) {\n" +
                        "    callback('false')\n" +
                        "}\n" +
                        "if (angular.getTestability) {\n" +
                        "    angular.getTestability(el).whenStable(function(){callback('true')});\n" +
                        "} else {\n" +
                        "    if (!angular.element(el).injector()) {\n" +
                        "        callback('false')\n" +
                        "    }\n" +
                        "    var browser = angular.element(el).injector().get('$browser');\n" +
                        "    browser.notifyWhenNoOutstandingRequests(function(){callback('true')});\n" +
                        "}";

                JavascriptExecutor javascriptExecutor = (JavascriptExecutor) driver;
                String isProcessingFinished = javascriptExecutor.executeAsyncScript(hasAngularFinishedScript).toString();

                return Boolean.valueOf(isProcessingFinished);
            }
        };
    }

这是假设您已经在 html 元素上定义了 ng-app。如果您在 DOM 的其他地方定义它,您将需要更新上面的代码。这几乎是从 Protractor 中偷来的,它正在检查是否有任何未完成的 ajax 请求,并检查 Angular 是否认为它处于可测试状态。

重要的部分是将此 JavaScript 片段作为异步脚本执行,因为 Angular 使用 promise 在准备就绪时触发回调。如果您不将其作为异步脚本运行,它将无法运行。

您还需要在驱动程序对象上设置脚本超时,这是 selenium 在抛出超时异常之前等待回调完成的时间量。您可以按如下方式设置:

driver.manage().timeouts().setScriptTimeout(15, TimeUnit.SECONDS);

然后就像将这个 ExpectedCondition 插入等待一样简单:

WebDriverWait wait = new WebDriverWait(driver, 15, 100);
wait.until(angularHasFinishedProcessing());

希望这对您有所帮助。

关于javascript - 如果 Angular 正在做......从 Selenium 中检测东西,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32345603/

有关javascript - 如果 Angular 正在做......从 Selenium 中检测东西的更多相关文章

  1. ruby - 难道Lua没有和Ruby的method_missing相媲美的东西吗? - 2

    我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/

  2. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  3. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  4. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

  5. ruby-on-rails - 如果我将 ruby​​ 版本 2.5.1 与 rails 版本 2.3.18 一起使用会怎样? - 2

    如果我使用ruby​​版本2.5.1和Rails版本2.3.18会怎样?我有基于rails2.3.18和ruby​​1.9.2p320构建的rails应用程序,我只想升级ruby的版本,而不是rails,这可能吗?我必须面对哪些挑战? 最佳答案 GitHub维护apublicfork它有针对旧Rails版本的分支,有各种变化,它们一直在运行。有一段时间,他们在较新的Ruby版本上运行较旧的Rails版本,而不是最初支持的版本,因此您可能会发现一些关于需要向后移植的有用提示。不过,他们现在已经有几年没有使用2.3了,所以充其量只能让更

  6. 「Python|Selenium|场景案例」如何定位iframe中的元素? - 2

    本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决

  7. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

    我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

  8. ruby - 我正在学习编程并选择了 Ruby。我应该升级到 Ruby 1.9 吗? - 2

    我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or

  9. ruby - 如果它是标点符号,我怎么能从字符串中删除最后一个字符,在 ruby​​ 中? - 2

    啊,正则表达式有点困惑。我正在尝试删除字符串末尾所有可能的标点符号:ifstr[str.length-1]=='?'||str[str.length-1]=='.'||str[str.length-1]=='!'orstr[str.length-1]==','||str[str.length-1]==';'str.chomp!end我相信有更好的方法来做到这一点。有什么指点吗? 最佳答案 str.sub!(/[?.!,;]?$/,'')[?.!,;]-字符类。匹配这5个字符中的任何一个(注意,。在字符类中并不特殊)?-前一个字符或组

  10. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

随机推荐