Webdriver How to wait until the element is clickable in webdriver C#
Well taking a look into the Java source, tells me it is basically doing two things to determine if it's 'clickable':
https://code.google.com/p/selenium/source/browse/java/client/src/org/openqa/selenium/support/ui/ExpectedConditions.java
Firstly, it'll check if it's 'visible' by using the standard ExpectedConditions.visibilityOfElementLocated
, it'll then simply check if the element.isEnabled()
is true
or not.
This can be condensed slightly, this basically means (simplified, in C#):
- Wait until the element is returned from the DOM
- Wait until the element's
.Displayed
property is true (which is essentially whatvisibilityOfElementLocated
is checking for). - Wait until the element's
.Enabled
property is true (which is essentially what theelementToBeClickable
is checking for).
I would implement this like so (adding onto the current set of ExpectedConditions
, but there are multiple ways of doing it:
/// <summary>
/// An expectation for checking whether an element is visible.
/// </summary>
/// <param name="locator">The locator used to find the element.</param>
/// <returns>The <see cref="IWebElement"/> once it is located, visible and clickable.</returns>
public static Func<IWebDriver, IWebElement> ElementIsClickable(By locator)
{
return driver =>
{
var element = driver.FindElement(locator);
return (element != null && element.Displayed && element.Enabled) ? element : null;
};
}
Usable in something like:
var wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));
var clickableElement = wait.Until(ExpectedConditions.ElementIsClickable(By.Id("id")));
However, you might have a different idea of what clickable might mean, in which case, this solution may not work - but it is a direct translation of what the Java code is doing.
Selenium C# WebDriver: Wait until element is present
Alternatively you can use an implicit wait:
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
An implicit wait is to tell WebDriver to poll the DOM for a certain
amount of time when trying to find an element or elements if they are
not immediately available. The default setting is 0. Once set, the
implicit wait is set for the life of the WebDriver object instance.
Random errors using wait for element clickable method in Selenium
This is what I use in a framework I've created. It eats ElementClickInterceptedException
and StaleElementReferenceException
and keeps trying until the timeout or success. It got rid of a lot of issues like what you are talking about. There are other ways to do it specific to each page but I found that this works really well in a large number of scenarios.
/// <summary>
/// Clicks on an element
/// </summary>
/// <param name="locator">The locator used to find the element.</param>
/// <param name="timeOut">[Optional] How long to wait for the element (in seconds). The default timeOut is 10s.</param>
public void Click(By locator, int timeOut = 10)
{
DateTime now = DateTime.Now;
while (DateTime.Now < now.AddSeconds(timeOut))
{
try
{
new WebDriverWait(Driver, TimeSpan.FromSeconds(timeOut)).Until(ExpectedConditions.ElementToBeClickable(locator)).Click();
return;
}
catch (ElementClickInterceptedException)
{
// do nothing, loop again
}
catch (StaleElementReferenceException)
{
// do nothing, loop again
}
}
throw new Exception($"Unable to click element <{locator}> within {timeOut}s.");
}
WaitForElementClickable/ Visible - Selenium C#
As I understood your element is visible and clickable when loading element on the screen but overlaying you element, also maybe you need to wait javascript to complete to click successfully.
You need get "loading circles" locator. For that open chrome devtools trigger "loading circles" to appear and press F8(pause) then you can find html of loading element.
Wait until loading element is disappeared:
var wait = new WebDriverWait(Driver.Instance, TimeSpan.FromSeconds(8));
wait.until(ExpectedConditions.invisibilityOfElementLocated(loadingElementLocator);
Also you can check if javascript is complete :
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
bool jsLoaded = (bool)js.ExecuteScript("return (document.readyState == \"complete\" || document.readyState == \"interactive\")");
Here Java example:
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;
});
Here your updated code:
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;
});
}
How to use:
WaitForLoading(driver, 10);
myButton.Click();
How to use Selenium elements to wait, check, click on without finding the elements again?
There is an expected condition for visibility that accepts a WebElement:
https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html#visibilityOf-org.openqa.selenium.WebElement-
Until
also returns the element being waited for, so you can combine this into one line:
internal void ClickUpdateButton(TimeSpan timeout)
{
WebDriverWait wait = new WebDriverWait(_driver, timeout);
wait.Until(ExpectedConditions.visibilityOf(UpdateButton)).click();
}
However, in my frameworks I usually add a helper function that does this, as it get's used so much. You can also do similar things with wait until clickable, etc. and have methods that accept a WebElement or a By:
public WebElement waitThenClick(WebElement element)
{
WebDriverWait wait = new WebDriverWait(_driver, timeout);
return wait.Until(ExpectedConditions.visibilityOf(UpdateButton)).click();
}
Python Selenium: Wait until element is clickable - Element is found using find_elements
You need to take care of a couple of things here as follows:
As the searchBar element is a clickable element ideally you need you need to induce WebDriverWait for the element_to_be_clickable() as follows:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, "react-select-3-input"))).send_keys(address)
Again as the searchButton element is a clickable element you need you need to induce WebDriverWait for the element_to_be_clickable() as follows (in the worst case scenario assuming the searchButton gets enabled when search text is populated):
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CLASS_NAME, "sc-1mx0n6y-0"))).click()
Ideal dropdowns are html-select tags and ideally you should be using the Select class inducing WebDriverWait as follows:
Select(WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "cssSelector_select_element")))).select_by_visible_text("visible_text")
Finally, the
ID
andCLASS_NAME
values which you have used e.g. react-select-3-input, sc-1mx0n6y-0, css-19bqh2r, etc looks dynamic and may change when you would access the application afresh or in short intervals. So you may opt to lookout for some other static attributes.Note: You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Selenium Webdriver wait on element click?
In addition to prestomanifesto's solution I can offer a less than ideal solution to that I implemented to solve this issue. It turns out it is throwing an exception - No Response etc... - so I just surrounded it in a try catch then waited for the popup to close, which seems to work fine.
You can substitute whatever you want in your loop, just make sure to put a counter in so it won't loop forever.
try
{
element.Click();
}
catch
{
cnt++;
do
{
//wait for whatever
cnt++;
Thread.Sleep(1000);
// Wait for 30 seconds for popup to close
} while (!string.IsNullOrEmpty(browser.CurrentWindowHandle) && cnt < 30);
}
Related Topics
How to Implement Full Row Selecting in Gridview Without Select Button
How to Calculate the Average Rgb Color Values of a Bitmap
Getting the Index of a Particular Item in Array
Hide Form Instead of Closing When Close Button Clicked
Is a Reference Assignment Threadsafe
Edit Raw Pixel Data of Writeablebitmap
Why C# Won't Allow Field Initializer with Non-Static Fields
Running Async Methods in Parallel
How to Make Texture2D Readable via Script
How to Get All Cookies of a Cookiecontainer
Inheritance on a Constrained Generic Type Parameter