代码之家  ›  专栏  ›  技术社区  ›  Ixi11

WaitForElementClickable/可见-硒C#

  •  1
  • Ixi11  · 技术社区  · 7 年前

    • 等待元素可见(当前已实现,但仍在使用 预期条件 已经过时了 可能是 已更改)
    • 等待被点击的元素(当我的测试运行时,它面临一个“加载循环”的问题,我按下按钮,在窗口加载之前,有一个加载程序需要1到4秒,然后它消失。我的目标是强制Selenium等待“XXX”时间,当加载完成时,然后继续处理。

    public static IWebElement WaitForElementVisible(this IWebDriver driver, By by, int timeoutInSeconds = 6)
        {
            IWebElement element;
            driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(0);
            try
            {
                WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
                element = wait.Until(ExpectedConditions.ElementIsVisible(by));
                driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(Configuration.ElementTimeout);
                return element;
    
            }
            catch (WebDriverTimeoutException e)
            {
                Console.WriteLine(e.ToString());
            }
            driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(Configuration.ElementTimeout);
            return null;
        }
    

    基于不同的主题,我已经开始写一些东西,但不幸的是,它只是复制。。。

    //编辑

    我添加了加载程序代码的外观:

        <div class="Loader__background" style="display: block; position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); z-index: 10;">
       <div class="Loader__foreground" style="display: table; width: 100%; height: 100%; text-align: center; z-index: 20; color: white;">
          <div class="Loader__message" style="display: table-cell; vertical-align: middle;">
             <div mode="indeterminate" value="0" min="0" max="100" style="position: relative; display: inline-block; width: 280px; height: 280px;">
                <div style="width: 280px; height: 280px; display: inline-block; transition: transform 10s linear 0ms; transform: rotate(1800deg);">
                   <svg viewBox="0 0 280 280" style="width: 280px; height: 280px; position: relative;">
                      <circle cx="140" cy="140" r="137.5" fill="none" stroke-width="5" stroke-miterlimit="20" style="stroke: rgb(0, 188, 212); stroke-linecap: round; transition: all 750ms ease-in-out 0ms; stroke-dasharray: 604.757, 863.938; stroke-dashoffset: -259.181;"></circle>
                   </svg>
                </div>
             </div>
          </div>
       </div>
    </div>
    

    我还将@sers Java advice转移到C:

    public static IWebElement WaitForElementClickable(this IWebDriver driver, By by, int timeoutInSeconds)
        {
            new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds)).Until(d =>
            {
                Boolean ajaxComplete;
                Boolean jsReady;
                Boolean loaderHidden = false;
    
                IJavaScriptExecutor js = (IJavaScriptExecutor)d;
                jsReady = (Boolean)js.ExecuteScript("return (document.readyState == \"complete\" || document.readyState == \"interactive\")"); ;
    
                try
                {
                    ajaxComplete = (Boolean)js.ExecuteScript("var result = true; try { result = (typeof jQuery != 'undefined') ? jQuery.active == 0 : true } catch (e) {}; return result;");
                }
                catch (Exception)
                {
                    ajaxComplete = true;
                }
                try
                {
                    loaderHidden = !d.FindElement(by).Displayed;
                }
                catch (Exception) { }
    
                return ajaxComplete && jsReady && loaderHidden;
            });
        }
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Sers    7 年前

    据我所知,当在屏幕上加载元素但覆盖元素时,您的元素是可见的且可单击的,也可能需要等待javascript完成才能成功单击。

    你需要得到“加载圆”定位器。打开的chrome devtools会触发“loading circles”并按F8(暂停),然后您可以找到loading元素的html。

    等待加载元素消失:

    var wait = new WebDriverWait(Driver.Instance, TimeSpan.FromSeconds(8));
    wait.until(ExpectedConditions.invisibilityOfElementLocated(loadingElementLocator);
    

    IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
    bool jsLoaded = (bool)js.ExecuteScript("return (document.readyState == \"complete\" || document.readyState == \"interactive\")");
    

    这里是Java示例:

    new WebDriverWait(driver, timeoutSec).until(d ->
    {
        boolean ajaxComplete;
        boolean jsReady;
        boolean loaderHidden = false;
    
        JavascriptExecutor js = (JavascriptExecutor) d;
        jsReady = (boolean) js.executeScript("return (document.readyState == \"complete\" || document.readyState == \"interactive\")");;
    
        try {
            ajaxComplete = (boolean) js.executeScript("var result = true; try { result = (typeof jQuery != 'undefined') ? jQuery.active == 0 : true } catch (e) {}; return result;");
        } catch (Exception ignored) {
            ajaxComplete = true;
        }
    
        try {
            loaderHidden = !d.findElement(loadElementLocator).isDisplayed();
        } catch (Exception ignored) {}
    
        return ajaxComplete && jsReady && loaderHidden;
    });
    

    这里是您的更新代码:

    public static void WaitForLoading(IWebDriver driver, int timeoutInSeconds)
        {
            new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds)).Until(d =>
            {
                Boolean ajaxComplete;
                Boolean jsReady;
                Boolean loaderHidden = false;
    
                IJavaScriptExecutor js = (IJavaScriptExecutor)d;
                jsReady = (Boolean)js.ExecuteScript("return (document.readyState == \"complete\" || document.readyState == \"interactive\")"); ;
    
                try
                {
                    ajaxComplete = (Boolean)js.ExecuteScript("var result = true; try { result = (typeof jQuery != 'undefined') ? jQuery.active == 0 : true } catch (e) {}; return result;");
                }
                catch (Exception)
                {
                    ajaxComplete = true;
                }
                try
                {
                    loaderHidden = !d.FindElement(By.ClassName("Loader__background")).Displayed;
                }
                catch (Exception) { }
    
                return ajaxComplete && jsReady && loaderHidden;
            });
        }
    

    WaitForLoading(driver, 10);
    myButton.Click();
    
        2
  •  1
  •   Guy    7 年前

    这个 ExpectedConditions 在.NET中绑定已过时,但它已移动到 DotNetSeleniumExtras

    “ExpectedConditions”已过时:“ExpectedConditions” .NET绑定中的实现已弃用,将被删除 在未来的版本中。这部分代码已经迁移到 ( https://github.com/DotNetSeleniumTools/DotNetSeleniumExtras

    使用 预期条件

    using WaitHelpers = SeleniumExtras.WaitHelpers;
    
    wait.Until(WaitHelpers.ExpectedConditions.ElementIsVisible(by));
    

    你也可以使用 预期条件

    IWebElement webElement = wait.Until(WaitHelpers.ExpectedConditions.ElementToBeClickable(by));
    webElement.Click();
    

    另一种选择是等待加载程序出现,然后消失,然后继续

    wait.Until(WaitHelpers.ExpectedConditions.ElementIsVisible(by));   
    wait.Until(WaitHelpers.ExpectedConditions.InvisibilityOfElementLocated(by));