Selenium implicit and explicit wait, timeout exception element not found - java

I am new to selenium (but experienced java developer).
I am using something like below:
WebElement searchBasket = pDriver.findElement(By.xpath("//a[contains(.,'Search&Baskets')]"));
WebElement searchproduct = pDriver.findElement(By.xpath("//a[contains(.,'Search a product')]"));
//if search an agreement is not show up, then click on other menu, then click it back
pWait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[contains(.,'Search&Baskets')]")));
pDriver.findElement(By.xpath("//a[contains(.,'Search&Baskets')]")).click();
// click on search an agreement
try {
pWait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[contains(.,'Search&Baskets')]")));
action = new Actions(pDriver);
action.moveToElement(searchBasket).build().perform();
pWait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[contains(.,'Search a product')]")));
searchproduct.click();
} catch (TimeoutException e) {
}
where pWait is:
WebDriverWait wait = new WebDriverWait(driver, 15);
however when I run the test case I get below error:
Unable to locate element: {"method":"xpath","selector":"//a[contains(.,'Search&Baskets')]"}
Command duration or timeout: 4 milliseconds
I thought it should have wait atleast 15 seconds before throwing this exception. From the log above it looks like it threw exception only in 4ms.
and i could see on console that as soon as it hit that line, it threw exception.
I have implicit waiting set as 0 and using explicit wait.
Am i missing anything here.
Also, in explicit and implicit wait, is it upto that much time OR exact that much time,
example if I set implicit wait as 10 sec, then does it mean wait for exact 10 sec OR wait upto 10 sec (if element found then proceed, even if element founf on 6th second)
is above same for explicit wait as well?
Please help

Let us analyze what is happening in our code.
We have defined two WebElements searchBasket and searchproduct as follows :
WebElement searchBasket = pDriver.findElement(By.xpath("//a[contains(.,'Search&Baskets')]"));
WebElement searchproduct = pDriver.findElement(By.xpath("//a[contains(.,'Search a product')]"));
We havn't tried to use those WebElements in our code at immediate basis, so had No Impact.
Next, we tried WebDriverWait for an WebElement as follows :
pWait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[contains(.,'Search&Baskets')]")));
Again we didn't capture the return type of the result, so had No Impact.
Now, within the try{} block we have again tried WebDriverWait:
pWait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[contains(.,'Search&Baskets')]")));
But again we havn't captured/acted on the return type of the result. That's why moving ahead when we did :
action.moveToElement(searchBasket).build().perform();
searchBasket referred to the WebElement which we have stored earlier as :
WebElement searchBasket = pDriver.findElement(By.xpath("//a[contains(.,'Search&Baskets')]"));
As this first search result (which was without WebDriverWait) may not have returned any WebElement at all and have returned Null.
Finally, the most important factor for the error Unable to locate element: {"method":"xpath","selector":"//a[contains(.,'Search&Baskets')]"} is, the
WebDriverWait instance was wait. Instead of using wait we have always tried to use pWait
So for all these reasons, WebDriverWait was never implemented properly in our code.
Mixing up ImplicitWait & ExplicitWait
The Selenium Documentation clearly mentions the following :
WARNING: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example setting an implicit wait of 10 seconds and an explicit wait of 15 seconds, could cause a timeout to occur after 20 seconds.

ExpectedConditions.elementToBeClickable invokes isDisplayed() and isEnabled() methods on EXISTING WebElement.
You are providing By as a parameter which means, the driver has to find your element first. It failed to do this.
Make sure your element is present by using wait until presenceOfElementLocatedBy(By by).
Example:
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.presenceOfElementLocatedBy(By.xpath("//a[contains(.,'Search&Baskets')]")));
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[contains(.,'Search&Baskets')]")));

Related

org.openqa.selenium.NoSuchElementException when navigating to child div Selenium Java

The current page is https://www.nintendo.co.uk/Games/Games-347085.html
I've run a Selenium test with driver.findElement for div.row-page-container and it works fine
but when I try to get the price value by going further into the red line below for the page-info I can't find how to access the class, it logs: org.openqa.selenium.NoSuchElementException: no such element
How can I get the price value, while avoiding XPath if possible?
Not sure why you do not want to have XPath.
But in case if you are looking for XPath based on Game name, that can get you it's price. You can use the below XPath
//p[text()='Animal Crossing: New Horizons']//following-sibling::p[#class='price-small']//span[#data-price]
or the below CSS should suffice as well
a[href*='Animal-Crossing-New-Horizons'] > p.price-small > span:nth-child(2)
It is based on href Animal-Crossing-New-Horizons
First of all using the correct xpath is an important step to remove the the NoSuchElementException.The xpath for identifying the element is
//p[text()='Animal Crossing: New Horizons']//following-sibling::p[#class='price-small']//span[#data-price]
Even if this doesn’t identify then there might be some timing issues with the webpage i.e.
the page is still being rendered and you've already finished your element search and obtained no element exception.
You can use FluentWait to overcome this problem.
Let’s say you have an element which sometimes appears in just 1 second and sometimes it takes minutes to appear. In that case it is better to define an explicit wait using FluentWait, as this will try to find an element again and again until it finds it or until the final timer runs out.
An instance of FluentWait can be defined to configure the maximum amount of time to wait for a condition as well as the frequency at which the condition must be checked.User can also configure the wait to ignore specific types of exceptions while waiting for an element, such as NoSuchElementExceptions on the page.
// Waiting 30 seconds for an element to be present on the page, checking
// for its presence once every 5 seconds.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS);
.pollingEvery(5, SECONDS) ;
.ignoring(NoSuchElementException.class);
Adding explicit wait might also do the trick:
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
. . .
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("element_xpath"))); element.click();

Selenium Wait for AJAX edit to text on page

I have an element on a web page that is updated by AJAX almost immeditely after page load. I know what I expect the change to be and want Selenium to wait for the change and capture it. I am trying to use an explicit wait for this. However, I am getting a timeoutException as Selenium is not detecting the change.
I know I am properly selecting the element and value as I have used print statements. I've solved the issue using
Java Thead.sleep(1000)
and then using
driver.findElement(By.id("balance-sms")).getText()
but this is not an acceptable solution.
private void modalSend(String newBalence){
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(modalSendButton)); //this wait works fine
modalSendButton.click(); //this results in a page refresh
//now check for the AJAX change to this element...normally takes about 1 second
wait.until(ExpectedConditions.textToBePresentInElement(driver.findElement(By.id("balance-sms")),newBalence));
//continue...
}
Try the locator using xpath and visibilityOfElementLocated with a few modifications :
//now check for the AJAX change to this element...normally takes about 1 second
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#id='balance-sms' and contains(text(),'" +newBalence +"')]")));
//continue...
Try with fluent wait like below instead of Thread.sleep
Wait wait = new FluentWait(WebDriver reference)
.withTimeout(timeout, SECONDS)
.pollingEvery(timeout, SECONDS)
.ignoring(Exception.class);

Performance issue with Headless Chrome [duplicate]

This question already has answers here:
Selenium Web Driver & Java. Element is not clickable at point (x, y). Other element would receive the click
(9 answers)
Closed 5 years ago.
My scripts are failing only when the headless mode is enabled. Please suggest me the ways what all I should look while coding.
Most of my scripts are failed due to TimedOut.
Is there anything I should specifically look for locators? I believe css wont help me in this case. Would there be something else related to locators?
In the continuous integration server, the execution is very slow. The limitations of Timed_Out seconds are fixed to 50. This didn't work for me and even for 100. Please suggest me how to handle when I'm restricted to utilize only upto 100seconds to TimeOut and it meets exception as it requires more seconds than this.
Here are few exceptions that I receive only when I enable headless,
1. WebDriverException: unknown error: Element <input type="radio" class="wizard-input" name="5a68a4c173bb-TOTAL-1" id="5a68a4c173bb-TOTAL-1" value="1"> is not clickable at point (496, 551). Other element would receive the click: <div class="navigation-bar">...</div>
Tried to apply wait condition and even scrolled and click.
2. TimeoutException: Expected condition failed: waiting for element to be clickable: By.cssSelector: div.icon.icon-add.add-contact-button (tried for 50 second(s) with 500 MILLISECONDS interval)
Tried to apply the conditions suggested by Marcel. As told it exceeds even 100seconds
Here are few examples of my code,
public void clickForwardButton(){
WaitTillElementToBeClickable("xpath", LoginData.Forward);
ScrollAndClickOnElement("xpath", LoginData.Forward);
} //The error seems to be like it wont scroll properly and hence I receive element not found exception
protected void WaitTillElementToBeClickable(String locatorType, String locatorValue) {
try {
WebDriverWait wait = new WebDriverWait(driver, TIME_OUT_IN_SECONDS);
if (locatorType.equalsIgnoreCase("cssSelector")) {
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector(locatorValue)));
} else if (locatorType.equalsIgnoreCase("xpath")) {
wait.until(ExpectedConditions.elementToBeClickable(By.xpath(locatorValue)));
} else if (locatorType.equalsIgnoreCase("id")) {
wait.until(ExpectedConditions.elementToBeClickable(By.id(locatorValue)));
}
} catch (Exception e) {
logger.error("Webdriver Locator Error" + e);
}
}
If you're not using WebDriverWait, give that a try
int seconds = 5;
WebDriverWait wait = new WebDriverWait(driver, seconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("yourID")));
You have to import OpenQA.Selenium.Support.UI to be able to use WebDriverWait.
Edit
Since the WebDriverWait method doesn't provide a solution, try adding an additional argument to your ChromeOptions to set the window size. Since the default headless window size is probably a lot smaller than your non-headless window size, it's worth a try. Additional benefit of setting a larger window size is reducing the need for scrolling.
ChromeOptions options = new ChromeOptions();
options.addArgument("headless");
options.addArgument("window-size=1920,1080");
// or
options.addArguments("headless", "window-size=1920,1080");

code, sometimes works some times doesnt. different error messages

i have the following issue, after perform the login, the system load the main page, its like 5 seconds doing it, so after that, the script should type over 3 fields and perform a tab to get more info, but the thing is that sometimes is working and sometimes does not, in 5 chances, only one worked, i do not know if its something about the time to get all fields or something like that, am using IE 9 cause the app only works on IE
Here´s the code:
`
System.setProperty("webdriver.ie.driver","C:\\Apps\\eclipse\\IEDriverServer.ex;
WebDriver driver = new InternetExplorerDriver();
driver.get("http://15.192.41.95/Cabina/asp/Login.asp");
WebElement text1 = driver.findElement(By.id("text1"));
text1.sendKeys("xxxx");
WebElement password1 = driver.findElement(By.id("password1"));
password1.sendKeys("xxxx");
WebElement aceptar = driver.findElement(By.id("ok1"));
aceptar.click();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.switchTo().frame(driver.findElement(By.name("menu")));
WebElement txtNumPolSol = driver.findElement (By.id("txtNumPolSol"));
txtNumPolSol.sendKeys("877885");
WebElement Text8 = driver.findElement(By.name("txtNumofic"));
Text8.sendKeys("228");
WebElement txtCveInc = driver.findElement(By.name("txtCveInc"));
txtCveInc.sendKeys("1");
WebElement clave = driver.findElement(By.id("txtCveInc"));
clave.sendKeys(Keys.TAB);
driver.switchTo().frame(driver.findElement(By.name("dest")));
WebElement txtNomrepo = driver.findElement(By.id("txtNomrepo"));
txtNomrepo.sendKeys("Jorge Villarreal");
driver.findElement(By.id("txtRelacion")).sendKeys("Conductor");
WebElement txtTelrepo = driver.findElement(By.id("txtTelrepo"));
txtTelrepo.sendKeys("83029090");`
Here the different issues i got:
1) Unable to find element with name == txtOficina
2) Element is no longer valid
3) Unable to find element with id == txtCveInc (the field is there)
4) Unable to find element with name == txtCveInc (the field is there)
The steps that the system to get the issues are:
1) Log in (so far so good)
2) The system load the main page (the page has frames and gets all fields in 5 secs...)
3) The script type over the txtNumPolSol, txtNumofic and txtCveInc (most of the issues are in the last two fields)
4) The script performs a tab
5) The system load the some information regarding the record and the script continue...
Note: Almost all the issues occur on step 3...
Thanks for your feedback!
This sounds like a timing problem. Your simulated user is proceeding faster than the page becomes ready. Depending on the timing of the page loading, different problems occur.
The solution is to add a wait after steps that trigger a DOM change than influences your next step, but doesn't cause WebDriver to wait before returning. Google 'webdriver wait for element' to get lots of ways to do it.
I was also facing the similar kind of problem but i tried to find the elements with Css_Selectors and X paths instead of ids, that worked for me
The key here is to add atleast 1 second of implicit wait after every action, i.e. send keys etc. It will allow 'driver.findElement' enough time to find the element. Though I would suggest keeping this code in a testBase or a reusable method.
driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
It will help in making your webtests less flaky.

Selenium Testing: Programming a more robust test

I am attempting to automate a task involving a JavaServer Page using the Selenium Webdriver. I have built a test that works about 90% of the time, meaning that the Webdriver makes it through all the tasks without any errors. During the test the browser executes the actions below:
opens a page
clicks on a link and switches windows
closes the original window
logs into a system
switches frames
clicks a link
fills out a form
submits the form
...more similar tasks
Unfortunatly, some of the time the Webdriver will randomly fail on one of the steps. This is because it could not find something, for example 'no frame found', 'unable to find element with link text...' and other similar errors. I am not sure why this happens sometimes and it appears to happen randomly at different stages in the test. I searched around for a solution and the best I could do was slow down the Webdriver with thread.sleep at various stages in the program. This seems like a very haphazard way to solve the problem to me and I am not even sure the problem is that the driver is moving too quickly. Even if I slow it down half a second I still sometimes get errors. I am a new user of Selenium and I do not know if this is usually a problem. Does anyone have a better way to address this problem? Am I overlooking something simple?
I did the same initially using thread sleep to develop my scripts. However, even though the scripts work while development, but it will be unrealiable on a production run as it fail inconsistently --which adds to the frustration. This is because thread sleep utilizes fixed waiting time and if elements do not get attached in time, it will fail the tests. singe31 has given a valid solution. Another solution would be by using fluentWait:
public void fluentWait(final By by)
{
FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(60, 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(by);
}
});
}
Here, the Selenium Webdriver will wait for at least 60 seconds to find an element until it throws of an TimeOutException. Otherwise, it will poll the DOM to find the element every 5 seconds and if the element is not found "NoSuchElementException" exception will be ignored.
Another problem which you are bound to face is, StaleStateReference or NoSuchElementException. You can check this link for solving that issue.
Hope it helps.
It's a common issue, instead of using Thread.sleep(duration) you should better create some utility method like
public WebElement waitForElementPresent(By by, int timeout) {
WebDriverWait wait = new WebDriverWait(driver, timeout);
WebElement element = null;
try {
element = wait.until(ExpectedConditions.presenceOfElementLocated(by));
} catch (TimeoutException e) {
e.printStackTrace();
}
return element;
}
This way if the element is already there you won't wait, and if it's loading it will wait until it finds it or until the timeout is triggered

Categories