C# 自定义单击中的多个wait.untill

C# 自定义单击中的多个wait.untill,c#,selenium,xunit,C#,Selenium,Xunit,我创建了一个自定义的click方法,它在单击元素之前会一直等到元素可单击为止。该方法运行良好,但我需要添加更多的wait.Until,以使click方法更稳定 这就是我所拥有的 public static void WaitAndJsClick(this Browser browser, IWebElement element, int seconds = 30) { var LoadingProgressBar = "(//*[@class='progress-bar'])[2]";

我创建了一个自定义的click方法,它在单击元素之前会一直等到元素可单击为止。该方法运行良好,但我需要添加更多的
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));
}
现在,正如您所看到的,我在单击之前等待三个元素“不可见”,单击之后,它再次等待元素“不可见”

我的问题是,我该如何改进这一点?这是一个好的解决方案吗?
它看起来很混乱,但工作非常好。

等等。忽略异常类型(typeof(NoSuchElementException))在这里没有意义。如果确实要忽略某些异常,请在实例化此新Wait对象之后立即执行此方法在这里没有意义。如果您真的想忽略一些异常,请在实例化这个新的Wait对象之后立即执行此方法。我遇到了一个类似的问题,这就是我为确保这种情况下的稳定性所做的

    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;
            }
        }
    }
private const int retryintervalinMillingSeconds=2000;
私有常量int ajaxreqtimeoutinems=20000;
public void WaitForAjax()
{
var stopwatch=stopwatch.StartNew();
while(stopwatch.elapsedmillesons
然后,我用WaitForAjax()调用替换了所有等待微调器和进度条的调用

从技术上讲,您可以删除休眠,只需在预期条件下使用javascript ajaxComplete即可返回true


希望这有帮助

我也遇到过类似的问题,这就是我为确保此类情况的稳定性所做的

    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;
            }
        }
    }
private const int retryintervalinMillingSeconds=2000;
私有常量int ajaxreqtimeoutinems=20000;
public void WaitForAjax()
{
var stopwatch=stopwatch.StartNew();
while(stopwatch.elapsedmillesons
然后,我用WaitForAjax()调用替换了所有等待微调器和进度条的调用

从技术上讲,您可以删除休眠,只需在预期条件下使用javascript ajaxComplete即可返回true


希望这有帮助

我不太喜欢等待一大堆东西的通用方法。我认为当事情出错时,它会使事情变得更加混乱和难以调试。我会为你需要等待的每个“东西”写一个函数。。。进度条、微调器、加载消息等,然后在需要时调用它们

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

现在,等待每件“事情”的代码只存在于一个地方(如下所示),并且更易于维护。

我不太喜欢等待一堆东西的通用方法。我认为当事情出错时,它会使事情变得更加混乱和难以调试。我会为你需要等待的每个“东西”写一个函数。。。进度条、微调器、加载消息等,然后在需要时调用它们

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

现在,等待每件“事情”的代码只存在于一个地方(如下所示),并且更易于维护。

谢谢,Ajax加载实际上是我最大的问题。我现在就试试看没问题。让我知道进展如何。谢谢,Ajax加载实际上是我最大的问题。我现在就试试看没问题。让我知道它是如何进行的。也许你不必等待加载微调器不可见,而可以等待元素可单击?@NicolasG.Duvivier是的。我已经有这种情况了。问题是,在加载微调器消失之前,元素可单击,因此Selenium无法“获取”按钮:(对不起,我没有注意到你的代码。当SPENE已经存在时,它是否认为元素是可点击的,或者是因为自旋者出现了一点滞后,然后等待已经被执行了?)NeOLasas.Duvivier-Yes,这就是问题所在,也是我需要等待三个元素先消失的原因。这是一种仅在需要微调器时才使用的方法吗?也许您可以不等待加载微调器不可见,而只等待元素可单击?@NicolasG.Duvivier是的。我已经有了这种情况。问题是,在加载微调器消失之前元素可单击,因此Selenium无法“获取”按钮:(对不起,我没有注意到你的代码。当SPENE已经存在时,它是否认为元素是可点击的,或者是因为自旋者出现了一点滞后,然后等待已经被执行了?)NeOLasas.Duvivier-Yes,这就是问题所在,也是我需要等待三个元素先消失的原因。这是一种你只在期待一个微调器时才使用的方法吗?完全同意!这是我第一次这样做的,不幸的是,负责框架的人说,阅读这个微调器会变得一团糟