我可以扩展WebElement的.click方法吗?

时间:2016-11-15 13:38:32

标签: java selenium

有没有办法扩展WebElement的.click方法?

我想为它添加一些代码来解决我们在内部网站上遇到的一些问题。

我想补充一下:

WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.elementToBeClickable(pageElement));

现在我知道有些人可能会说只是使用隐式等待。我已经考虑过了,但我编写的一些页面需要10-30秒才能加载。有些页面加载速度非常快,但是显示的按钮是基于点击其他按钮的条件,我进入了一个我知道按钮应该在5秒内加载的情况。我宁愿不在每个按钮上等待30秒。这可能会发生几百次,我不希望脚本花费那么长时间。

有没有办法为点击事件添加显式等待?

2 个答案:

答案 0 :(得分:0)

尝试FluentWait,这将每5秒检查一次元素。

Wait wait = new FluentWait(driver).withTimeout(30, TimeUnit.SECONDS).pollingEvery(5, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);

答案 1 :(得分:0)

实际上并不需要覆盖.click(),正如@lauda在评论中所述,这不是一个好习惯。您不需要添加大量代码来等待元素可点击,因此声称它将添加数千行代码是不正确的。您可以使用一行代码轻松完成此操作...因此无需额外的代码行。话虽如此......你应该少关注它会添加和考虑的代码行数:

  1. 维护有多容易?
  2. 我是否在代码库中添加了不必要的复杂性?
  3. 它会更具可读性吗?
  4. ......依旧......
  5. 代表性按钮的示例点击方法

    public void clickButtonX()
    {
        new WebDriverWait(driver, timeOutInSeconds).until(ExpectedConditions.elementToBeClickable(buttonXLocator)).click();
    }
    

    你在课堂顶部声明了这些

    private By buttonXLocator = By.id("buttonXId");
    private int timeOutInSeconds = 10;
    

    话虽如此......我不认为这是正确的做法。使用页面对象模型,您应该让每个页面类句柄等待页面完成加载...然后您不必在单击它们之前等待按钮加载。在动态加载按钮的情况下,触发动态加载的操作应等待加载完成。

    package sandbox;
    
    import org.openqa.selenium.By;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.support.ui.ExpectedConditions;
    import org.openqa.selenium.support.ui.WebDriverWait;
    import common.Functions;
    
    public class _PageTemplate
    {
        private WebDriver driver;
        private By dynamicPageLoadLocator = By.id("someId");
        private By buttonXLocator = By.id("buttonXId");
        private By dynamicLinkLocator = By.id("dynamicLinkId");
        private By dynamicSectionElementLocator = By.id("dynamicSectionId");
    
        public _PageTemplate(WebDriver webDriver) throws IllegalStateException
        {
            Functions.waitForPageLoad(driver);
    
            // see if we're on the right page
            if (!driver.getCurrentUrl().contains("samplePage.jsp"))
            {
                throw new IllegalStateException("This is not the XXXX Sample page. Current URL: " + driver.getCurrentUrl());
            }
    
            // for dynamic pages, wait for a specific element to signal the dynamic load is complete
            new WebDriverWait(driver, 10).until(ExpectedConditions.presenceOfElementLocated(dynamicPageLoadLocator));
        }
    
        public void clickButtonX()
        {
            // no wait needed here
            driver.findElement(buttonXLocator).click();
        }
    
        public void clickDynamicLink()
        {
            // clicking this link triggers part of the page to change, reload, etc. ...
            driver.findElement(dynamicLinkLocator).click();
            // ... so after the click, we wait for the dynamic part of the page to finish by locating an element that is inside the dynamically
            // loaded portion and wait for it to be visible
            new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfElementLocated(dynamicSectionElementLocator));
        }
    }
    

    这是在某些Utils类或其他任何内容中声明的。

    /**
     * Waits for the browser to signal that the DOM is loaded. For dynamic pages, an extra wait may be necessary.
     */
    public static void waitForPageLoad(WebDriver driver)
    {
        new WebDriverWait(driver, 30).until(new ExpectedCondition<Boolean>()
        {
            public Boolean apply(WebDriver webDriver)
            {
                return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
            }
        });
    }
    

    现在有了这个框架,我们不再需要为每个按钮添加代码,以确保在点击之前它可用。我建议你采用这种方法来处理所有代码。只在需要的地方等待,而不是到处等待。

    1. 等待页面加载
    2. 触发动态页面更改后,等待页面更改完成
    3. 如果你只是做这两件事,你只会在非常特定的地方等待而不需要它们(在调试时减少复杂性和混乱等)。