Selenium WaitDriver不等待元素可点击

本文关键字:元素 等待 WaitDriver Selenium | 更新日期: 2023-09-27 18:07:22

当我点击一个按钮时,它会显示一个带有另一个按钮的表单,我想点击其中一个按钮。这里有一个视频(非常短的一个),请观看http://screencast.com/t/zyliSemW1s1

所以我点击"买票"按钮,就像这样:

button.Click();

然后等待下一个按钮可以点击。

我使用下一个代码:

WebDriverWait wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(15));
IWebElement element = wait.Until(ExpectedConditions.ElementToBeClickable(myButton));

之后,我点击了我等待的按钮:

element.Click();

我得到错误:元素在那个点是不可点击的

正如我所知,ExpectedConditions.ElementToBeClickable()方法等待2个条件:元素是可见的,元素是启用的。

当我在点击第二个按钮之前使用Thread.Sleep(3000)代码工作并且按钮是可点击的

我看到类似的问题,解决方案是等待这个按钮的处理程序:Selenium等待不't等待元素是可点击的

但是,如果我不知道是什么处理它,该怎么办?我认为它由jQuery处理,我使用下一个代码等待,直到它停止执行:

var ajaxIsComplete = (bool)
    ((IJavaScriptExecutor)Driver).ExecuteScript("return jQuery.active == 0");

如果返回"false",则等待并再次检查。

但它仍然不工作。

所以现在我的流是这样的:

  1. 我点击"购票"按钮
  2. 我一直等到jQuery停止执行
  3. 我使用ExpectedConditions.ElementToBeClickable()方法等待直到元素可点击
  4. 我点击元素,它返回一个错误,它是不可点击的。

请告诉我我的流程出了什么问题以及如何正确管理

:我正在添加按钮的HTML代码:

我点击这个:

<button class="btn btn-warning play-now" name="button" type="submit">Buy Tickets</button>

等这个:

<img alt="Credit Card" class="merchant" src="https://numgames-production.s3.amazonaws.com/uploads/merchant/image/21/CC_Offline.png?AWSAccessKeyId=AKIAJ2Q64HPERGHAJJUA&amp;Expires=1470984765&amp;Signature=Qj%2BFSQ3ElctkY6KTMfzp%2FedPjPo%3D">

Selenium WaitDriver不等待元素可点击

Denis,

正如在OP的评论中提到的,这里有一些小的扩展方法可以帮助你的任务:

public static void WaitForAjax(this IWebDriver driver, int timeoutSecs = 10, bool throwException = false)
{
    for (var i = 0; i < (timeoutSecs*10); i++)
    {
        var javaScriptExecutor = driver as IJavaScriptExecutor;
        var ajaxIsComplete = javaScriptExecutor != null && (bool)javaScriptExecutor.ExecuteScript("return jQuery.active == 0");
        if (ajaxIsComplete) return;
        Thread.Sleep(100);
    }
    if (throwException)
    {
        throw new Exception("WebDriver timed out waiting for AJAX call to complete");
    }
}
public static bool ElementExists(this IWebDriver driver, By condition)
{
    return ElementExists(driver, condition, new TimeSpan());
}
public static bool ElementExists(this IWebDriver driver, By condition, TimeSpan timeSpan)
{
    bool isElementPresent = false;
    if (timeSpan == default(TimeSpan))
    {
        timeSpan = TimeSpan.FromMilliseconds(15000);
    }
    var driverWait = new WebDriverWait(driver, (TimeSpan)timeSpan);
    driverWait.IgnoreExceptionTypes(typeof(WebDriverTimeoutException));
    isElementPresent = driverWait.Until(x => x.FindElements(condition).Any());
    return isElementPresent;
}
public static IWebElement FindElementAfterWait(this IWebDriver driver, By condition, int fromSeconds = 90)
{
    bool isElementPresent = false;
    IWebElement singleElement = null;
    var driverWait = new WebDriverWait(driver, TimeSpan.FromSeconds(fromSeconds));
    driverWait.IgnoreExceptionTypes(typeof(WebDriverTimeoutException));
    try
    {
        isElementPresent = driverWait.Until(ExpectedConditions.ElementExists(condition)) != null;
        if (isElementPresent)
        {
            singleElement = driver.FindElement(condition);
        }
    }
    catch
    {
        // log any errors
    }
    return singleElement;
}

用法:

bool elementExists = _driver.ElementExists(By.Id("submitButton"));
var submitButton = _driver.FindElementAfterWait(By.Id("submitButton"));
submitButton.Click();
_driver.WaitForAjax();
// then do other code stuff...

希望这些组合可以使您摆脱困境。

这是处理任何异步(AJAX)页面的典型问题。

你不需要使用任何"神奇"的方法,如睡眠,jquery。活动和预期条件。

Web页面通常是按照用户在操作结束时可以看到的方式构建的——比如出现一些消息,或者某个按钮被启用。我相信在你的情况下,这样的事情也发生在你点击"购买门票"之后-你需要注意到这一点,并在你的代码中等待它。

等待需要使用显式等待来执行您的特定情况。这是管理异步页面(包括还不能点击的元素)的唯一可靠的方法。

你可以在我的博客文章中看到更详细的概述-在Web自动化中处理AJAX的方法(Selenium)

与其使用ElementToBeClickable,不如使用presenceOfElementLocated。我认为你期望的元素不存在于DOM,所以尝试使用presenceOfElementLocated第一。一旦它出现在DOM上,然后使用ElementToBeClickable

 //   public void test() 
   {
        IWebDriver driver = new ChromeDriver();
        ClickSaveButton(driver,"MyButton",10); //Wait for 10 seconds
    }
 //Customized wait block 
public void ClickSaveButton(IWebDriver driver,String ElementID = "" int TimeOut)
    {
        Console.Error.WriteLine("Waiting....");
        try
        {
           driver.FindElement(By.Id(ElementID)).Click();
        }
        catch (Exception exception)
        {
            Thread.Sleep(1000);
            if (TimeOut > 0) ClickSaveButton(driver, TimeOut - 1);
        }
    }

我正面临这个问题,检查元素是否可点击,可见,定位(或它们的组合)等是不够的。Selenium仍然没有等待,并试图点击该元素。

我为我的案例找到的唯一解决方案是一个糟糕的实践,但作为一个变通的方法。我尝试使用try/Catch将元素放入循环中,如在Falgun contt response:

中找到的那样

StackExchange -如何在WebDriver中使用c#等待元素可点击