I am trying to write a generalized web driver wait to wait for elements to be clickable. But I found out online of Web Driver waits that are written specific to By.id or By.name.
Suppose Below are two WebElements
public WebElement accountNew() {
WebElement accountNew = driver.findElement(By.xpath("//input[#title='New']"));
waitForElementtobeClickable(accountNew);
return accountNew;
}
public WebElement accountName() {
WebElement accountName = driver.findElement(By.id("acc2"));
waitForElementtobeClickable(accountName);
return accountName;
}
Below is the generalized waitofrelementtobeclickable.
public static void waitForElementtobeClickable(WebElement element) {
try {
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(element));
System.out.println("Got the element to be clickable within 10 seconds" + element);
} catch (Exception e) {
WebDriverWait wait1 = new WebDriverWait(driver, 20);
wait1.until(ExpectedConditions.elementToBeClickable(element));
System.out.println("Got the element to be clickable within 20 seconds" + element);
e.printStackTrace();
}
}
but it doesn't seem to work. Any suggestions on how only one generalized code can be written for either xpath, or id, or class or Css can be written?
The problem is not in your function, its in your driver.findElement as you try to locate the element before it exist in the DOM. You can use implicit wait
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
This will wait up for 10 seconds for any element to exist in the DOM before when locating it.
Or locate your element using explicit wait
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//input[#title='New']")));
This will wait up to 10 seconds for your element to be visible.
You can (and should) use both of course.
You can change your code to something like that
public static WebElement waitForElementtobeClickable(By by) {
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(by));
System.out.println("Got the element to be clickable within 10 seconds" + element);
return element;
}
public WebElement accountNew() {
WebElement accountNew = waitForElementtobeClickable(By.xpath("//input[#title='New']"));
return accountNew;
}
You send your By locator to waitForElementtobeClickable and use elementToBeClickable(By) instead of elementToBeClickable(WebElement), so you can use xpath, id, class etc.
Related
I have trying so hard to search how to wait for specific element been load to the browser.
However, most of code are in python and C#, I am trying to convert but still cannot.
I cannot find ExpectedConditions please let me know which reference I need to imports, because I keep looking for is expectedCondidtion in namespace still cannot find it.
Can anyone share a code or link that how to use webdriverwait? because I still cannot understand.
I want to do is wait a element been load to the browser, and if element not in page will do something else.
Now I using is try and catch but, sometime internet slow cannot really wait for page fully load, direct show the exception of elelment is not in page.
Code :
WebDriverWait wait = new WebDriverWait(getDriver(), timeOut);
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("MainContent_lblLandmarkUPRN")));
You can use below function to wait until element is visible
public static IWebElement WaitforElement(this IWebDriver driver, By by, int timeoutInSeconds = 5, bool checkIsVisible = false)
{
IWebElement element;
driver.Sync();
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
wait.IgnoreExceptionTypes(typeof(StaleElementReferenceException));
try
{
if (checkIsVisible)
{
element = wait.Until(ExpectedConditions.ElementIsVisible(by));
element = wait.Until(ExpectedConditions.ElementToBeClickable(by));
}
else
{
element = wait.Until(ExpectedConditions.ElementExists(by));
}
}
catch (NoSuchElementException) { element = null; }
catch (WebDriverTimeoutException) { element = null; }
catch (TimeoutException) { element = null; }
catch (StaleElementReferenceException) { element = null; }return element;
}
I have an authentication popup before loading the website and while popup display on the webpage and a loader display running on the browser it means webpage not loaded completely.
And as per selenium if complete webpage not loaded initially, selenium not interact with elements
Need help on this.
Use following method with Java + Selenium :
public boolean isPageReady(WebDriver driver){
boolean readyStateComplete = false;
while (!readyStateComplete){
JavascriptExecutor executor = (JavascriptExecutor) driver;
readyStateComplete = executor.executeScript("return document.readyState") == "complete";
}
return readyStateComplete;
}
For C# + Selenium :
private void WaitUntilDocumentIsReady(TimeSpan timeout){
var javaScriptExecutor = WebDriver as IJavaScriptExecutor;
var wait = new WebDriverWait(WebDriver, timeout);
// Check if document is ready
Func<IWebDriver, bool> readyCondition = webDriver => javaScriptExecutor
.ExecuteScript("return (document.readyState == 'complete' && jQuery.active == 0)");
wait.Until(readyCondition);
}
You can wait until the page is completely loaded via JavaScript.
private void WaitUntilLoaded()
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
wait.Until((x) =>
{
return ((IJavaScriptExecutor)this.driver)
.ExecuteScript("return document.readyState").Equals("complete");
});
}
Another option is to wait for a specific element(s) to be visible on the page
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
wait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(
By.XPath("some Xpath")));
Source here: https://www.automatetheplanet.com/advanced-webdriver-tips-tricks-part-1/
I'm trying to use Fluent wait to perform two actions as below:
Click on search button
Check the result for the element
Right now I'm trying with the below code and it doesn't seem to work:
public SendMailPage waitForSometime() throws Exception {
FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(Duration.ofMinutes(2))
.pollingEvery(Duration.ofSeconds(10))
.ignoring(NoSuchElementException.class);
WebElement element = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
driver.findElement(By.xpath("//BUTTON[#type='submit'][text()='Search']")).click();
driver.findElement(By.xpath("xpath of the element i'm waiting to find"));
return driver.findElement(By.xpath("xpath of the element i'm waiting to find"));
}
});
element.isDisplayed();
return new SendMailPage();
}
Can someone guide me on how to fix this?
***UPDATED CODE: where waiting for a single element also doesn't work :
public SendMailPage assertMailSubject() throws Exception {
FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(Duration.ofMinutes(2))
.pollingEvery(Duration.ofSeconds(30))
.ignoring(NoSuchElementException.class);
WebElement element = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.xpath("the element that i am waiting for"));
}
}
);
return new SendMailPage();
}
I fixed both the problems:
The code was not working as the NoSuchElementException was from Java util instead of Selenium.
And for performing two actions, I just added by Search key action before the return statement.
Scenario - Valid login to www.homeshop18.com and then from the Digital Menu select "Samsung".
The results are displayed and now I need to choose another brand - Micromax from the Brand section (displayed at the left side of the page)
which requires scrolling and selecting Micromax.
Issue:
Though the xpath of Micromax is correct which is //*[#id='filter_1Option_12']//div[#class='ez-checkbox'] but I see during run time of the script - some other brand is getting selected instead of micromax.
Kindly advise.
//Class for valid login to www.homeshop18.com
public class HomeShop_Login_Test
{
#FindBy(xpath="//a[#id='signInHeaderLink']") WebElement SignIn_Link;
#FindBy(xpath=".//input[#id='emailId']") WebElement Email;
#FindBy(xpath=".//input[#id='existing_user_radio']") WebElement Existing_User_Radio;
#FindBy(xpath=".//input[#id='new_user_radio']") WebElement New_User_Radio;
#FindBy(xpath=".//input[#id='password']") WebElement Password;
#FindBy(xpath=".//a[#id='signin']") WebElement SignIn_Button;
#FindBy(xpath="//a[#title='Close']") WebElement Close_Home;
public void Login_Valid()
{
WebDriverWait wait = new WebDriverWait(driver, 30);
WebElement SignIn_Link = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//a[#id='signInHeaderLink']")));
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("arguments[0].click()", SignIn_Link);
Email.sendKeys("xxx#gmail.com");
boolean selected;
selected = New_User_Radio.isSelected();
if(selected)
{
Existing_User_Radio.click();
}
Password.sendKeys("xxx");
SignIn_Button.click();
}
//Class to choose Samsung from Digital menu
public class Browse_Samsung_Mobile
{
#FindBy(xpath="//*[#id='CategoryMenu1']//a[text()='Digital']") WebElement Digital_Menu;
#FindBy(xpath="//*[#id='CategoryMenu1']//a[#title='Samsung']") WebElement Samsung_SubMenu;
#FindBy(xpath="//*[#id='filter_1Option_19']//span[#class='selected_filter_img']") WebElement Micromax;
public void Browse_Samsung()
{
WebDriverWait wait = new WebDriverWait(driver, 30);
Actions act = new Actions(driver);
act.moveToElement(Digital_Menu).perform();
act.click(wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#id='CategoryMenu1']//a[#title='Samsung']")))).build().perform();
//WebElement Micromax = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//*[#id='filter_1Option_12']//span[#class='selected_filter_img']")));
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("arguments[0].click()", Micromax);
}
}
//class to call above two classes
public class Validate_Browse_Samsung_Mobile
{
WebDriver driver;
#Test
public void Validate_Browse()
{
driver = BrowserFactory.getBrowser("Firefox");
driver.get(DataProviderFactory.getConfig().getURL());
HomeShop_Login_Test login = PageFactory.initElements(driver, HomeShop_Login_Test.class);
login.Login_Valid();
Browse_Samsung_Mobile browse = PageFactory.initElements(driver, Browse_Samsung_Mobile.class);
browse.Browse_Samsung();
}
}
You should try with their name using title attribute as below :-
WebElement micromax = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("a[title ~= "Micromax"] input")));
You should use following XPath to choose proper check-box:
//a[#title="GSM Mobile Phones - Micromax"]/div/input
When I run my selenium rc script page is not loading completely because of change in the urls.
Earlier it was working fine when url was something link this
https://testersworld.com/
But now it changed to (updated the URL in the script before run)
https://testersworld.com/#login
Because of which when I run the script browser launches with specified url but fails to displayed login popup.
How to handle this https://testersworld.com/#login which gives login pop after page load. I used all methods of wait.
try this:
driver.manage().deleteAllCookies();
driver.get("https://testersworld.com/");
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
or
driver.manage().deleteAllCookies();
driver.get("https://testersworld.com/");
Thread.sleep(1000);
or
select locator on login page (e.g. input login(e-mail ) field):
String cssLocator=..blablabla...;
and use fluentWait mechanism:
public WebElement fluentWait(final By locator){
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(
new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(locator);
}
}
);
return foo; } ;
fluentWait(By.cssSelector(cssLocator));