多个wait.untill里面的自定义点击

时间:2017-07-14 12:48:24

标签: c# selenium xunit

我创建了一个自定义单击方法,在单击元素之前等待元素可单击。该方法运行良好,但我需要添加更多wait.Until以使click方法更稳定。

这就是我所拥有的。

public static void WaitAndJsClick(this Browser browser, IWebElement element, int seconds = 30)
{
    var LoadingProgressBar = "(//*[@class='progress-bar'])[2]";
    var loading = "loading";
    var spinner = "spinner";

    var wait = new WebDriverWait(browser.Driver, new TimeSpan(0, 0, seconds));
    wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.ClassName(loading)));
    wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.ClassName(spinner)));
    wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.XPath(LoadingProgressBar)));
    wait.Until(ExpectedConditions.ElementToBeClickable(element));

    element.JsClick(browser);   // Click

    wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.ClassName(loading)));
    wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.ClassName(spinner)));
    wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.XPath(LoadingProgressBar)));
    wait.IgnoreExceptionTypes(typeof(NoSuchElementException));
}

现在你可以看到,我等待三个元素是"隐形"在点击之前,点击之后它再次等待元素"隐形"

我的问题是,我怎么能改善这个?这是一个很好的解决方案吗? 它看起来像一团糟,但工作得非常好。

3 个答案:

答案 0 :(得分:1)

我遇到了类似的问题,这就是我为确保此类案件的稳定所做的工作。

    private const int RetryIntervalInMilliSeconds = 2000;
    private const int AjaxReqTimeoutInMilliSeconds = 20000;

    public void WaitForAjax()
    {
        var stopwatch = Stopwatch.StartNew();
        while (stopwatch.ElapsedMilliseconds < AjaxReqTimeoutInMilliSeconds)
        {
            try
            {
                Thread.Sleep(RetryIntervalInMilliSeconds);
                var ajaxIsComplete = (bool)browser.ExecuteJavascript("return window.jQuery && jQuery.active == 0");
                if (ajaxIsComplete)
                {
                    break;
                }
            }
            catch
            {
                return;
            }
        }
    }

然后我用调用WaitForAjax()替换了所有等待旋转器和进度条的调用。

您可以在技术上删除睡眠,只需在expectedCondition中使用javascript ajaxComplete即可返回true。

希望这有帮助

答案 1 :(得分:1)

我不是等待一堆东西的通用方法的忠实粉丝。我认为当出现问题时,它会使事情变得更加混乱和难以调试。我会为每个&#34;事情写一个函数&#34;你需要等待......进度条,微调器,加载信息等,然后在需要时调用它们。

public static void WaitForLoading(this Browser browser)
{
    new WebDriverWait(browser.Driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.InvisibilityOfElementLocated(By.ClassName("loading")));
}
public static void WaitForProgressBar(this Browser browser)
{
    new WebDriverWait(browser.Driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.InvisibilityOfElementLocated(By.XPath("(//*[@class='progress-bar'])[2]")));
}
public static void WaitForSpinner(this Browser browser)
{
    new WebDriverWait(browser.Driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.InvisibilityOfElementLocated(By.ClassName("spinner")));
}

然后,当您需要在单击元素后等待进度条时,您可以执行类似这样的操作

element.JsClick(browser);
WaitForProgressBar(browser);

现在你的代码等待每个&#34;事情&#34;只存在于一个地方(跟DRY principle之后)并且更容易维护。

答案 2 :(得分:0)

wait.IgnoreExceptionTypes(typeof(NoSuchElementException));在这里毫无意义。如果您确实要忽略某些异常,请在实例化此新Wait对象后立即执行此方法