Java + Selenium:如何知道WebElement是否可以通过isDisplayed,isEnabled和findElement以外的方式进行点击?

时间:2017-08-30 13:46:49

标签: java html css selenium exception-handling

我知道通常可以测试WebElement是否可点击:

用这样的方法测试它:

public static boolean isElementFoundDisplayedEnabled(WebDriver driver, String accessor){

        return driver.findElements(By.xpath(accessor)).size() > 0 && driver.findElement(By.xpath(accessor)).isDisplayed() && driver.findElement(By.xpath(accessor)).isEnabled();
        //isDisplayed(): method avoids the problem of having to parse an element's "style" attribute to check hidden/visible. False when element is not present
        //isEnabled(): generally return true for everything but disabled input elements.
    }

这个函数有缺陷,它只检查Element在DOM级别是否可以点击,但如果由于某些css搞乱,该元素被隐藏/重叠,可以得到Exception:

  

org.openqa.selenium.WebDriverException:未知错误:元素不是   点击点(781,704)。其他元素将收到点击:

     ...

在这种情况下,仍然可以使用以下方法单击元素:

// Assume driver is a valid WebDriver instance that
// has been properly instantiated elsewhere.
WebElement element = driver.findElement(By.id("gbqfd"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", element);

但是,我有兴趣了解这一点,我们如何在不点击executor.executeScript的情况下进行检查,即WebElement没有被其他元素隐藏/重叠,并且完全可以点击。

有人可以稍微说清楚,我已经对这些进行了几个小时的研究并且无处可去。

4 个答案:

答案 0 :(得分:0)

我不是创建一个处理所有点击的功能的忠实粉丝,但是如果我被迫写一个,它看起来就像这样。里面的评论解释了发生了什么。

public static void clickElement(By locator) throws InterruptedException
{
    try
    {
        // first we try the standard wait for element to be clickable and click it
        new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(locator)).click();
    }
    catch (TimeoutException e)
    {
        // element never becomes present
    }
    catch (WebDriverException e)
    {
        // click is blocked by another element, retry for 10 seconds
        while (true)
        {
            Instant timeOut = Instant.now().plusSeconds(10);
            try
            {
                driver.findElement(locator).click();
                break;
            }
            catch (WebDriverException e2)
            {
                // ignore additional blocked click exceptions
            }

            if (Instant.now().isAfter(timeOut))
            {
                // element is still blocked after retries for 10 seconds, fallback to JSE click
                ((JavascriptExecutor) driver).executeScript("arguments[0].click();", driver.findElement(locator));
            }

            // slight pause between loops
            Thread.sleep(100);
        }
    }
}

有关您的功能的一些反馈...... 您应该传递By个实例而不是字符串,例如

By locator = By.id("myId");

这样,您的功能可以更灵活,并且不会硬编码到XPath。此外,您正在使用您的功能将页面抓取3次。刮一次页面,然后使用存储的元素进行可见和启用的检查,例如

public static boolean isElementFoundDisplayedEnabled(WebDriver driver, By locator)
{
    List<WebElement> e = driver.findElements(locator);

    return !e.isEmpty() && e.get(0).isDisplayed() && e.get(0).isEnabled();
}

答案 1 :(得分:0)

以下是您的问题的一些事实和见解:

  1. 我认为当Selenium已经拥有内置的isElementFoundDisplayedEnabled(WebDriver driver, String accessor)类时,方法WebDriverWait是一个开销。我将在回答的后半部分回复WebDriverWait
  2. 只有在显示此元素时,文档才会明确提及isDisplayed()。这种方法避免了必须解析元素&#34;样式&#34;属性。
  3. 文档提及isEnabled()仅检查当前是否启用的元素。除了禁用的输入元素之外,这通常会返回true。
  4. 因此,如果isElementFoundDisplayedEnabled(WebDriver driver, String accessor)WebElement,则必须覆盖函数clickable。因此,在某些情况下,您可能会遇到org.openqa.selenium.WebDriverException: unknown error: Element is not clickable at point (781, 704). Other element would receive the click
  5. 现在,当您看到Element is not clickable at point (781, 704)时,您已经提到了 JavascriptExecutor 点击并且有效。
  6. 因此要检查一个元素是否可点击,我们只需将<{>} WebDriverWait 设置为 ExpectedConditions < /强>
  7. 一个例子是:

    elementToBeClickable
  8. 文档明确提及Element is Clickable - it is Displayed and Enabled

  9. 仔细查看elementToBeClickable()方法,明确提到它返回 WebDriverWait wait2 = new WebDriverWait(driver, 10); WebElement ele = wait2.until(ExpectedConditions.elementToBeClickable(By.id("element_id")));

  10. 因此,您的问题的解决方案是 the (same) WebElement once it is clickable (visible and enabled) ,即 WebDriverWait

答案 2 :(得分:-1)

首先,您需要注意哪个属性具有隐藏或可见属性,并且基于此属性,您可以编写类似这样的内容。

示例:

 <input id ="email" style="margin-top: 0px; visibility: visible;" >

代码:

public Boolean isVisibleAndClickable(WebElement email, WebDriver driver ){

            Boolean flag = false;
    try{
            WebDriverWait wait = new WebDriverWait(driver, 10);
            wait.until(ExpectedConditions.elementToBeClickable(email));

            if(email.isDisplayed()){
            String style = email.getAttribute("style");
            if(style.contains("hidden")){
            System.out.println("Element is hidden");
            }
            else if(style.contains("visible")){
               System.out.println("Element is visible and clickable");
               flag = true;
           }else{
               System.out.println("Element is not displayed");
           }
           }
       } catch(Exception e){
         System.out.println("Exception occured waiting for the element"+e.getMessage());
     }

            return flag;
     }

答案 3 :(得分:-1)

您可以使用xpath contains函数,逻辑运算符和ancestor选项。例如:

.//一个[@ behavior.id =&#39;本身份识别码&#39;] /祖先:: DIV [含有(@class,&#39;类型类&#39)] /.//跨度

这条线找到了孩子们的跨越&#39;来自&#39;(@ class filter),为了找到这个div我开始找到&#39; a&#39;与behavior.id

为了提高可见性,我总是使用Wait或FluentWait选项:

public static WebElement xpathVisible(String xpath) {
    return new FluentWait<WebDriver>(driver)
            .withTimeout(IMPLICIT_TIMEOUT, TimeUnit.SECONDS)
            .pollingEvery(RETRY_TIME, TimeUnit.SECONDS)
            .ignoring(NoSuchElementException.class).until(ExpectedConditions
                    .elementToBeClickable(By.xpath(xpath)));
}

也许使用驱动程序的一些功能作为elementScrollBehavior从底部搜索元素是有用的:

capabilities.setCapability("elementScrollBehavior", 1); // 0- from Top,
                                                            // 1 - from
                                                            // bottom

我曾经使用过的东西是:

  1. 获得附近的遗产。
  2. 发送捷径为Keys.TAB或Keys.SHIFT + Keys.TAB。
  3. 从元素中取出任何属性,以检查您是否使用了正确的按钮。
  4. 发送Keys.Enter。