Wait until element is clickable does not timeout correctly - selenium

I'm having some problem handling timeouts as it doesn't seem to be working in every situation. I have defined the timeout as follows:
wait = new FluentWait<WebDriver>(driver)
.withTimeout(Duration.ofSeconds(60))
.pollingEvery(Duration.ofSeconds(1))
.ignoring(NoSuchElementException.class);
Now, when I want to wait until an element is present on the page, I use this piece of code :
wait.until(ExpectedConditions.presenceOfElementLocated(locator));
It works in most of the situation (wait for the element and timeout after 60 seconds) but lately we've been having trouble with some of the pages that get stuck loading (there's a message waiting for ... at the bottom left of the page). When this happens, I realize that this piece of code doesn't work properly. It doesn't timeout after 60 seconds but after 10 minutes.
Edit: Actually, trying to investigate my problem a little more, I realized it really comes from another line of code that also contains the wait:
wait.until(ExpectedConditions.elementToBeClickable(locator));
Basically, I click on a link that redirects to another page, wait for a button to be present, wait for the button to be clickable, and click on the button. So it detects the button is present but then it waits for it to be clickable and doesn't time out after 60 seconds.
So when I define my driver, I added the following line:
driver.manage().timeouts().pageLoadTimeout(60, TimeUnit.SECONDS);
In the console, I see the following line:
Timed out receiving message from renderer: 60.000
But how do I catch this exception? I tried to surround my wait with a try/catch but it doesn't work.
try {
wait.until(ExpectedConditions.elementToBeClickable(locator));
} catch (Exception e) {
logger.info("TEST");
throw new TimeoutException("element " + locator.toString() + " not found on the page");
}
How can I do it? Thanks.

You need to take care of a couple of things as follows:
Waiting until an element is present on the page ideally won't help much if your usecase is either to get any of the attributes, e.g. classname, innerHTML, etc of an element or to invoke click() on an element.
Instead depending on your usecase you need to use either visibilityOfElementLocated() or elementToBeClickable().
You can find a couple of detailed discussion in:
WebDriverWait not working as expected
Java Wrapper method for waiting for element to be available for Apache Cordova Webview driven App
Selenium: Check for the presence of element
The reason for the line of code wait.until(ExpectedConditions.presenceOfElementLocated(locator)) doesn't times out after 60 seconds but after 10 minutes may be due to the reason that, along with WebDriverWait you have also configured Implicit Wait and as per the documentation mixing up Implicit Wait and Explicit Wait can cause unpredictable wait times
To configure pageLoadTimeout you can use the following code block:
Code Block:
System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().timeouts().pageLoadTimeout(2, TimeUnit.SECONDS);
try{
driver.get("https://www.booking.com/hotel/in/the-taj-mahal-palace-tower.html?label=gen173nr-1FCAEoggJCAlhYSDNiBW5vcmVmaGyIAQGYATG4AQbIAQzYAQHoAQH4AQKSAgF5qAID;sid=338ad58d8e83c71e6aa78c67a2996616;dest_id=-2092174;dest_type=city;dist=0;group_adults=2;hip_dst=1;hpos=1;room1=A%2CA;sb_price_type=total;srfid=ccd41231d2f37b82d695970f081412152a59586aX1;srpvid=c71751e539ea01ce;type=total;ucfs=1&#hotelTmpl");
}catch(WebDriverException e){
System.out.println("WebDriverException occured");
}
driver.quit();
Console Output:
INFO: Detected dialect: W3C
[1563377008.449][SEVERE]: Timed out receiving message from renderer: 1.999
[1563377008.450][SEVERE]: Timed out receiving message from renderer: -0.001
[1563377008.461][SEVERE]: Timed out receiving message from renderer: -0.012
[1563377010.466][SEVERE]: Timed out receiving message from renderer: 1.998
[1563377010.467][SEVERE]: Timed out receiving message from renderer: -0.001
[1563377010.476][SEVERE]: Timed out receiving message from renderer: -0.010
WebDriverException occured
You can find a relevant detailed discussion in pageLoadTimeout in Selenium not working

Related

Jmeter/Selenium "stale element reference exception error

I have 10 threads on Jmeter all going into the same website but each thread has different accounts. I keep getting the Stale Element Reference Exception error on 1-3 threads per each test. The weird thing is that the threads that fail are different each time I run a test, and they all have the exact same path/code (besides the login credentials). What can I do to fix it?
When the a thread fails, it says "This site can't be reached" "examplewebsite.com took too long to respond" in the UI
enter image description here
Looking at Stale element reference page:
The stale element reference error is a WebDriver error that occurs because the referenced web element is no longer attached to the DOM.
So it means that you're trying to interact with the element which no longer exists.
Given This site can't be reached error it might be the case your application is overloaded or has another problem preventing proper displaying/rendering controls
You could try taking a screenshot in case of failure and/or printing the page source to jmeter.log file, this way you will have more information regarding what's going on when the page cannot be opened or element cannot be found/interacted with.
Example code:
try
{
WDS.browser.get('examplewebsite.com')
wait.until(conditions.presenceOfElementLocated(pkg.By.linkText('some-link')))
}
catch (err)
{
WDS.log.error(err.message)
var screenshot = WDS.browser.getScreenshotAs(pkg.OutputType.FILE)
screenshot.renameTo(new java.io.File('screenshot.png'))
WDS.log.info('Page source:')
WDS.log.info(WDS.browser.getPageSource())
exception = err
}
finally
{
throw (exception)
}
More information: The WebDriver Sampler: Your Top 10 Questions Answered

Is there a change in the handling of unhandled alert in ChromeDriver and Chrome with Selenium?

I have a test that has been running fine for months. One thing it does is cause an alert and then verify the alert text. This is running with Selenium, Java and Chrome Driver 76.0.3809.68.
Lately it has been giving me the error:
"No such alert".
What happens is it clicks a button and waits for an alert if there:
try {
button.click();
} catch (UnhandledAlertException ex) {
// nothing
}
// then here goes code to accept the alert and get the text
when stepping through I see the alert. When I run it, I see the alert but it disappears. I did read something in the (Chrome Driver) release notes about unexpected alerts but it was a bit vague.
We have a global page which sets the options for Chrome, but everyone uses it and I don't want to screw up for other people. I did do it locally (did not git push) and it worked when I set the options before creating the driver.
Then I tried to do this, which does not seem to work. Should it, or once the web page is retrieved, can you not change options?
// Somewhere after web page retrieved this gets called:
public void setIgnoreAlert() {
ChromeDriver cd = (ChromeDriver) driver;
ChromeOptions cap = new ChromeOptions();
cap.setCapability(CapabilityType.UNEXPECTED_ALERT_BEHAVIOUR, UnexpectedAlertBehaviour.IGNORE);
Capabilities other = cap;
cd.getCapabilities().merge(other);
}
Which I was really hoping would work, but did not. Do you have to set the behavior before the Chrome instance comes up? That is, can you not set it as I did above? Any other suggestions on how to set it after the Chrome instance is up?
--- added later to answer question
This is done immediately after the try-catch block with button.click():
The method configPage.getAndHandleAlertPopUp() does the following:
public String getAndHandleAlertPopUp() {
Alert alert = driver.switchTo().alert();
String alertPopup = alert.getText();
alert.accept();
return alertPopup;
}
You saw it right. As per the User Prompts section within WebDriver - W3C Recommendation:
The common denominator for user prompts is that they are modal windows requiring users to interact with them before the event loop is unpaused and control is returned to the current top-level browsing context.
By default user prompts are not handled automatically unless a user prompt handler has been defined. When a user prompt appears, it is the task of the subsequent command to handle it. If the subsequent requested command is not one listed in this chapter, an unexpected alert open error will be returned.
User prompts that are spawned from beforeunload event handlers, are dismissed implicitly upon navigation or close window, regardless of the defined user prompt handler.
A user prompt has an associated user prompt message that is the string message shown to the user, or null if the message length is 0.
As per the discussion in ChromeDriver should return user prompt (or alert) text in unhandled alert error response:
When a user prompt handler is triggered, the W3C Specification states that the error response should return an "annotated unexpected alert open error" which includes an optional dictionary containing the text of the user prompt. ChromeDriver should supply the optional information.
Clearly, ChromeDriver was not compliant with this standard as the #Test were annotated with #NotYetImplemented as follows:
#Test
#NotYetImplemented(CHROME)
#NotYetImplemented(CHROMIUMEDGE)
#Ignore(value = HTMLUNIT, reason = "https://github.com/SeleniumHQ/htmlunit-driver/issues/57")
#NotYetImplemented(value = MARIONETTE,
reason = "https://bugzilla.mozilla.org/show_bug.cgi?id=1279211")
#NotYetImplemented(EDGE)
public void testIncludesAlertTextInUnhandledAlertException() {
driver.get(alertPage("cheese"));
driver.findElement(By.id("alert")).click();
wait.until(alertIsPresent());
assertThatExceptionOfType(UnhandledAlertException.class)
.isThrownBy(driver::getTitle)
.withMessageContaining("cheese")
.satisfies(ex -> assertThat(ex.getAlertText()).isEqualTo("cheese"));
}
Now this feature have been implemented with ChromeDriver v76.0:
Resolved issue 2869: ChromeDriver should return user prompt (or alert) text in unhandled alert error response [Pri-2]
So you have to handle the alert as a mandatory measure.
A bit more of your code code block for ...then here goes code to accept the alert and get the text... would have helped us to debug the issue in a better way. However here are the options:
Induce WebDriverWait for alertIsPresent() as follows:
new WebDriverWait(driver, 10).until(ExpectedConditions.alertIsPresent());
Your code trials was perfect perhaps as you have passed the CapabilityType.UNEXPECTED_ALERT_BEHAVIOUR, UnexpectedAlertBehaviour.IGNORE in a structured way:
public void setIgnoreAlert() {
ChromeOptions opt = new ChromeOptions();
opt.setCapability(CapabilityType.UNEXPECTED_ALERT_BEHAVIOUR, UnexpectedAlertBehaviour.IGNORE);
}
Another perspective would be to disable the beforeunload event handlers and you can find a couple of related discussions in:
How to disable a “Reload site? Changes you made may not be saved” popup for (python) selenium tests in chrome?
How to handle below Internet Explorer popup “Are you sure you want to leave this page?” through Selenium
Note: Once the WebDriver and Web Browser instances are initialized you won't be able to change the configuration on the run. Even if you are able to extract the Session ID, Cookies and other capabilities and session attributes from the Browsing Session still you won't be able to alter those attributes of the WebDriver.
You can find a detailed discussion in How can I reconnect to the browser opened by webdriver with selenium?

Alert handling fails in latest IE version

OS: Windows 10 Enterprise
Selenium Version: 3.3.1
Browser: Internet Explorer 11
Browser Version: 11.953.14393.0
I was running the same test script for last 3 months. Suddenly last week it started failing in verifying the alert text. One difference I could find is now if the same alert is displayed within a short time span there is a warning with checkbox. Warning message is don't let this page create more messages.
Alert alert = driver.switchTo().alert();
alertText = alert.getText();
alert.getText() should return the text.
Is there any way to disable this warning message in IE11 ? If not how can I handle this in Selenium Webdriver.?
Here is the link to handle alerts in Selenium.
Link to help
To point you specific piece of code, take a look at Lines 41 to 53 in code of article.
Hope this helps.
The problem you have now is that alert is coming for very less time, which you can handle by checking whether the alert is present or not.
Try this code it might help.
WebDriverWait wait = new WebDriverWait(driver, 10);
try {
wait.until(ExpectedConditions.alertIsPresent());
driver.switchTo().alert().accept();
} catch (Exception e) {
throw e;
}
Let me know if it works.

Selenium:How can I delay the closing of a browser let's say for 5 sec

I have run all my Tests successfully and I have used the driver.close command at the end but I want to delay the closing of a browser for 5 or 10 sec which means once all tests gets executed then browser waits for like 5 sec and then gets close. Is it possible to do this and how?
Just add a "sleep" before calling close().
In Python:
import time
time.sleep(5)
driver.close()
In Java:
Thread.sleep(2000);
driver.close();
Using Selenium 2.x api (not 3.x), you can do it like so, and you wont have to change the test methods signature to throw a InterruptedException :
Sleeper.sleepTight(2000);
Usually, I start the web browser in the tests #Before annotated method and then in the #After annotated method I will stick that sleeper and then a driver.close. Sometimes, just before the sleep, I will navigate the page to a success page and display that just before the browser closes.

Extending Selenium: How to call commands?

I read about user extensions and extending selenium but am wondering how to call a command from within a custom command I'm creating.
I added a file similar to the following to Selenium core extensions (user-extensions.js) in Selenium IDE Options.
// selenium-action-example.js
Selenium.prototype.doExample = function() {
this.doOpen("/"); // doesn't waitForPageToLoad like the command does
// These two commands are equivalent to the clickAndWait command. NOT!
// For proof, see the filterForRemoteControl function:
// http://code.google.com/p/selenium/source/browse/trunk/ide/src/extension/content/formats/formatCommandOnlyAdapter.js?r=8284#68
this.doClick("css=a#example");
this.doWaitForPageToLoad(); // doesn't wait at all
this.doClick("link=Example");
this.doWaitForElementPresent("example"); // error! undefined function
this.doClick("example");
};
In other words, how can I wait for things between clicks within a custom action?
Your command
this.doWaitForPageToLoad(); // doesn't wait at all
Doesn't wait as you have not specified wait time in brackets. You should write it as
this.doWaitForPageToLoad(30000); // time in milliseconds
Tour another Command
this.doWaitForElementPresent("example"); // error! undefined function
as no function is there in Selenium. whenever it waits for an element it checks that element is present or not so you should wait for time until it is visible/present.
Using For loop and ispresent commands you can do it.
Regards
Waiting for an page load does not to work in current versions of Selenium. As far as I can see, this is because the doWaitForPageToLoad defers the waiting until the end of the current Selenium IDE command, i.e. waiting for a page load stops the test execution until the page has loaded, but not the execution of the actual javascript function that this was executed in.
You will have to split your function in two at this point.