WaitForElementClickable/Visible-Selenium C#

WaitForElementClickable/Visible-Selenium C#,c#,selenium,selenium-webdriver,selenium-chromedriver,C#,Selenium,Selenium Webdriver,Selenium Chromedriver,我需要实施和修改我当前的方法来完成这两件事: 等待可见元素-(当前已实现,但仍使用已过时且可能已更改的ExpectedCondition) 等待可点击的元素-(当我的测试运行时,它面临“加载循环”的问题,我按下按钮,在加载窗口之前,有一个加载程序需要1到4秒,然后它消失。我的目标是强制Selenium等待“XXX”加载完成的时间和时间,然后继续该过程 当前代码: public static IWebElement WaitForElementVisible(this IWebDriver d

我需要实施和修改我当前的方法来完成这两件事:

  • 等待可见元素-(当前已实现,但仍使用已过时且可能已更改的ExpectedCondition
  • 等待可点击的元素-(当我的测试运行时,它面临“加载循环”的问题,我按下按钮,在加载窗口之前,有一个加载程序需要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>

.NET绑定中的
ExpectedConditions
已过时,但已移动到
DotNetSeleniumExtras

“ExpectedConditions”已过时:“ExpectedConditions” .NET绑定中的实现已弃用,将被删除 这部分代码已迁移到 GitHub上的DotNetSeleniumExtras存储库 ()'

使用
ExpectedConditions
从那里,它将消除警告

using WaitHelpers = SeleniumExtras.WaitHelpers;

wait.Until(WaitHelpers.ExpectedConditions.ElementIsVisible(by));
您还可以使用
ExpectedConditions
等待元素可单击

IWebElement webElement = wait.Until(WaitHelpers.ExpectedConditions.ElementToBeClickable(by));
webElement.Click();
另一个选项是等待加载程序出现,然后消失,然后继续

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

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

你需要得到“加载圈”定位器。打开ChromeDevTools会触发“加载圈”出现,然后按F8(暂停),然后你可以找到加载元素的html

等待加载元素消失:

var wait = new WebDriverWait(Driver.Instance, TimeSpan.FromSeconds(8));
wait.until(ExpectedConditions.invisibilityOfElementLocated(loadingElementLocator);
您还可以检查javascript是否完整:

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();

我已经用“循环加载”DOM(b)代码更新了我的帖子,该代码已从JAVA转移到C。我想你可能有权使用js定位器,但我还是不太明白我在做什么。我应该在代码中的什么地方设置循环加载器?编译器还认为我的方法不会返回任何东西。我添加了加载器的定位器:
By.ClassName(“loader\uu background”)
,尝试将其设为方法void并在单击之前调用,将其用作等待加载完成。另外,如果加载出现在每个可以实现
WebDriverEventListener
listener并在
beforeFindBy
中调用此方法的地方。我应该添加的地方:using WaitHelpers=SeleniumExtras.WaitHelpers?IDE未编译+我无法添加任何内容以检测it@Ixi11它的“使用”,把它和其余的“使用”放在顶部。
WaitForLoading(driver, 10);
myButton.Click();