【问题标题】:wait.until(ExpectedConditions.visibilityOf Element1 OR Element2)wait.until(ExpectedConditions.visibilityOf Element1 OR Element2)
【发布时间】:2013-02-12 20:08:39
【问题描述】:

我想将wait.until(ExpectedConditions) 与两个元素一起使用。 我正在运行测试,我需要 WebDriver 等到 Element1 OR Element2 出现。然后我需要选择最先出现的人。我试过了:

WebDriverWait wait = new WebDriverWait(driver, 60); 
    wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//h2[@class='....']"))) || wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//h3[@class='... ']"))); 

        // Then I would need:

String result = driver.findElement(By.xpath("...")).getText() || driver.findElement(By.xpath("...")).getText();

总而言之,我需要等到两个元素中的任何一个出现。然后选择出现的人(他们不能同时出现) 请帮忙。

【问题讨论】:

    标签: java selenium


    【解决方案1】:

    现在有一个本地解决方案,or 方法,check the doc

    你这样使用它:

    driverWait.until(ExpectedConditions.or(
        ExpectedConditions.presenceOfElementLocated(By.cssSelector("div.something")),
        ExpectedConditions.presenceOfElementLocated(By.cssSelector("div.anything"))));
    

    【讨论】:

    • 我如何确保哪个元素的条件为真?
    • @Mak13 -- 使用 ExpectedConditions.and 而不是 ExpectedConditions.or。如果您想知道是哪一个,请在“或”测试之后立即检查这两个选项。
    【解决方案2】:

    这是我在 Helper 类中声明的方法,它就像一个魅力。只需创建您自己的 ExpectedCondition 并使其返回定位器找到的任何元素:

    public static ExpectedCondition<WebElement> oneOfElementsLocatedVisible(By... args)
    {
        final List<By> byes = Arrays.asList(args);
        return new ExpectedCondition<WebElement>()
        {
            @Override
            public Boolean apply(WebDriver driver)
            {
                for (By by : byes)
                {
                    WebElement el;
                    try {el = driver.findElement(by);} catch (Exception r) {continue;}
                    if (el.isDisplayed()) return el;
                }
                return false;
            }
        };
    }
    

    然后你可以这样使用它:

    Wait wait = new WebDriverWait(driver, Timeouts.WAIT_FOR_PAGE_TO_LOAD_TIMEOUT);
    WebElement webElement = (WebElement) wait.until(
            Helper.oneOfElementsLocatedVisible(
                    By.xpath(SERVICE_TITLE_LOCATOR), 
                    By.xpath(ATTENTION_REQUEST_ALREADY_PRESENTS_WINDOW_LOCATOR)
            )
    );
    

    这里SERVICE_TITLE_LOCATORATTENTION_REQUEST_ALREADY_PRESENTS_WINDOW_LOCATOR 是页面的两个静态定位器。

    【讨论】:

      【解决方案3】:

      如果您将“OR”放入 xpath,我认为您的问题有一个简单的解决方案。

      WebDriverWait wait = new WebDriverWait(driver, 60); 
      wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//h2[@class='....'] | //h3[@class='... ']"))); 
      

      然后,打印结果,例如:

      if(driver.findElements(By.xpath("//h2[@class='....']")).size()>0){
             driver.findElement(By.xpath("//h2[@class='....']")).getText();
      }else{
             driver.findElement(By.xpath("//h3[@class='....']")).getText();
      }
      

      【讨论】:

        【解决方案4】:

        你也可以像这样使用 CSSSelector:

        wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("h2.someClass, h3.otherClass")));
        

        将 someClass 和 otherClass 替换为 xpath 中 [...] 中的内容。

        【讨论】:

        • 这样做的好处是它回答了问题的一部分,Then I need to pick whoever shows up first. 因为.until() 返回找到的元素,例如WebElement e = wait.until(...);
        【解决方案5】:

        很遗憾,没有这样的命令。你可以通过 try and catch 来克服这个问题,或者我会建议你使用开源 Ruby 库Watir

        【讨论】:

        • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
        【解决方案6】:

        还有另一种等待方式,但它不使用预期条件,而是使用 lambda 表达式..

        wait.Until(x => driver.FindElements(By.Xpath("//h3[@class='... ']")).Count > 0 || driver.FindElements(By.Xpath("//h2[@class='... ']")).Count > 0); 
        

        【讨论】:

          【解决方案7】:

          如果要满足的条件数量不定,您可以利用 Java 的 ArrayList&lt;&gt; 等通用列表,如 here 所示,然后执行以下操作:

          //My example is waiting for any one of a list of URLs (code is java)
          
              public void waitUntilUrls(List<String> urls) {
                  if(null != urls && urls.size() > 0) {
                      System.out.println("Waiting at " + _driver.getCurrentUrl() + " for " + urls.size() + " urls");
                      List<ExpectedCondition<Boolean>> conditions = new ArrayList<>();
                      for (String url : urls) {
                          conditions.add(ExpectedConditions.urlContains(url));
                      }
          
                      WebDriverWait wait = new WebDriverWait(_driver, 30);
                      ExpectedCondition<Boolean>[] x = new ExpectedCondition[conditions.size()];
                      x = conditions.toArray(x);
                      wait.until(ExpectedConditions.or(x)); // "OR" selects from among your ExpectedCondition<Boolean> array
                  }
              }
          

          【讨论】:

            【解决方案8】:

            对此有一个简单的解决方案,使用显式等待:

            wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//*[@id='FirstElement' or @id='SecondElement']")));
            

            在此之前我尝试使用wait.until(ExpectedConditions.or(...,它与 2.53.0 之前的 selenium 版本不兼容。

            【讨论】:

              猜你喜欢
              • 2014-01-02
              • 1970-01-01
              • 2011-10-24
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-06-09
              • 2023-01-26
              相关资源
              最近更新 更多