WebDriver does not use latest page source - selenium

I'm running into problems when executing Selenium 2.18 WebDriver tests against an Oracle SSXA-based site, which translates to tons of popups, Ajax-loaded content and iframes. For a given page, based on manual observation, the page is initially loaded with an empty sslw_doc_content_id span (no text). About a second later, the span still exists and contains text.
To check that this page has loaded, I'm using a WebDriverWait with a Predicate that checks that the sslw_doc_content_id span has non-empty text:
new Predicate<WebDriver>() {
#Override
public boolean apply(final WebDriver input) {
return StringUtils.isNotEmpty(input.findElement(By.id("sslw_doc_content_id")).getText());
}
}
Somehow, WebDriver always finds the WebElement but always returns an empty string when calling WebElement.getText(). And so this predicate always evaluates to false.
Inspecting the page with Chrome or Firefox shows that the element exists and does have text. When debugging the predicate, I've observed that input.getPageSource() contains the span with no text on its first invocation, but that input.getPageSource() contains the span with some text on its second invocation (after the page has been ajax-refreshed).
Why doesn't WebDriver consider the refreshed page source on the second invocation?
Thanks!

You can try loop:
int seconds = 0;
for (int seconds =0; seconds<30; seconds++) {
if (apply(driver)){
break;
}
Thread.sleep(1000);
}
The above loop will check every second if text is there and do it for 30 seconds. If it finds it, it will escape the loop. You can still add one more check after:
if (!apply(driver)){
throw new RuntimeException("Expected text still not there");
}
Or another approach, which I am using: Whenewer I have page to load for long time, I select element which is loaded among the last on the page and check its presence the same way:
for (int seconds =0; seconds<30; seconds++){
try{
driver.findElement(By.id("lastelementonpage"));
}catch (Exception e){
Thread.sleep(1000);
}
}

It turns out that WebDriver does not allow access to hidden elements, and this span was hidden.
http://code.google.com/p/selenium/wiki/FrequentlyAskedQuestions#Q:_Why_is_it_not_possible_to_interact_with_hidden_elements?
I've resorted to using the JavaScript-based solution described in the above link.

Related

Wait for element for certain amount of time

I have been experiencing one issue during test automation implementation. Particularly test checks if a hamburger menu is displayed.
So far I defined the element and subelement, and I need to really wait just one second, and not to waste time If I know that element will not be displayed after several seconds.
WebDriverWait wait = new WebDriverWait(getDriver(), 1);
WebElement hamMenu = el.findElement(By.xpath(HAMBURGER_MENU_GENERAL_XPATH));
How to implement the method findElement in the way it will try to find the element in one sec? I do not wish to stay longer... Thanks
Try this -
WebElement elem = new WebDriverWait(driver, 1).until(ExpectedConditions.visibilityOfElementLocated(By.xpath(HAMBURGER_MENU_GENERAL_XPATH)));
If I summarize your requirement is as follows :
Check if a hamburger menu is displayed only for 1 second : You need WebDriverWait with proper ExpectedConditions
Element may/not not be displayed after several seconds : You need to wrapup your code in a try-catch {} block to be able to proceed further in absence of the hamburger.
Youe effective code can be :
try {
WebElement hamburger = new WebDriverWait(getDriver(), 1).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("HAMBURGER_MENU_GENERAL_XPATH")));
System.out.println("Hamburger is displayed in 1 sec");
//rest of your code
} catch (NoSuchElementException e){
System.out.println("Hamburger wasn't displayed in 1 sec");
//rest of your code
}
I got it. Thanks for all hints. This will wait just only for short time which is intended.
public boolean isHamMenuDisplayed(){
getDriver().manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
if (el.findElements(By.xpath(HAMBURGER_MENU_GENERAL_XPATH)).size() == 0)
return false;
else
return true;}

Click Next link until pagination Next action is disabled in selenium webdriver

I want to verify elements in a row inside a table in by navigating each page through pagination.I am able to navigate to each page and assert element but the probelm is at last page the loop still continues even though the Next link is grayed out.
When Next link is disabled
<span>
<a class="next_btn inactive">NEXT ></a>
</span>
When Next link is enabled
<span>
<a class="next_btn" href="home.do?action=Next&start=10&end=20&sort=&
type=00&status=&fromDate=04/02/2017&toDate=05/02/2017&school=&
district=0009">NEXT ></a>
</span>
Actual Code
public void submissionType() throws Exception {
driver.findElement(By.linkText("NEXT >"));
while(true) {
processPage();
if (pagination.isDisplayed() && pagination.isEnabled()){
pagination.click();
Thread.sleep(100L);
} else
break;
}
}
private void processPage() {
String statusColumn="//td[#class='gridDetail'][2]";
List<WebElement> list = table.findElements(By.xpath(statusColumn));
for (WebElement checkbox : list) {
String columnName=checkbox.getText();
Asserts.assertThat(columnName,"File");
}
}
Instead of identifying the element with By.linkText("NEXT >"), try identifying it with By.cssSelector("a.next_btn").
When you use this approach, then when the object becomes disabled, its class name would change, and hence your object would no longer get identified and your loop would break.
Edit: Add try block and Catch NoSuchElement exception to avoid exceptions.
I know you already accepted an answer but one of the statements is not correct. The locator, By.cssSelector("a.next_btn"), will find both the enabled and disabled button so it will not cause the loop to break.
Looking at your code, I would offer a few suggestions/corrections.
.isEnabled() only really works on INPUT tags so testing for that doesn't really accomplish anything here.
Using Thread.sleep() is not a good practice. You can google some explanations but basically the problem is that it's an inflexible wait. If the element you are waiting for becomes available in 15ms, you are still going to wait 10s or whatever your sleep is set to. Using an explicit wait (WebDriverWait) is a best practice.
I would clean up your functions and write them like
public void submissionType()
{
WebDriverWait wait = new WebDriverWait(driver, 10);
By nextButtonLocator = By.cssSelector("a.next_btn:not(.inactive)");
List<WebElement> nextButton = driver.findElements(nextButtonLocator);
while (!nextButton.isEmpty())
{
processPage();
nextButton.get(0).click();
wait.until(ExpectedConditions.stalenessOf(nextButton.get(0))); // wait until the page transitions
nextButton = driver.findElements(nextButtonLocator);
}
}
private void processPage()
{
for (WebElement checkbox : table.findElements(By.xpath("//td[#class='gridDetail'][2]")))
{
Asserts.assertThat(checkbox.getText(), "File");
}
}

Waiting for elements with Selenium WebDriver

I am automating a web page that essentially has a button which, each time it is pressed, creates a new text field.
I am using the FindBy annotation with PageFactory to find the list of text fields.
I have a synchronization problem when I press the button several times, thus creating several text fields, and then try to write into one of them. Stepping through the debugger it works fine, but out of the debugger there is a delay before the FindBy finds all the text fields.
My current workaround performs sleeps until the required number of text fields are found but I find this quite unsatisfactory. Any suggestions how the synchronization could best be done?
#FindBy(how= How.XPATH, using="//*[contains(#id, 'TextField')]")
private List<WebElement> textFields;
:
:
public void enterText(Integer index, String text){
int attempts = 0;
// Check every 10th of a second for 10 seconds if all the textFields have been found
while ((textFields.size() <= index) && attempts < 100){
Thread.sleep(100);
}
textFields.get(index).sendKeys("blah blah");
}
First of all use Implicit wait for all element present in script.
This wait is wait for all element present in the script
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
Initiate above just after get.("URL");
Now for specific element which need additional time you can use below code:-
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));
Refer below:-
http://toolsqa.com/selenium-webdriver/wait-commands/
Hope it will help you :)

First character is missing inconstantly while sending string to the ExtJS input via sendKeys()

I randomly face the issue of missing first character in the ExtJS5 input field, while sending string via sendKeys method.
System info:
Ubuntu 14.04 -> docker containers with selenium grid (2.48.2)
Browser Firefox
Code is simple. I just get input web element, wait if it's clickable (i.e. isEnabled and isDisplayed), clear and send string:
wait.until(ExpectedConditions.elementToBeClickable(input)).clear();
input.sendKeys(value);
input element is simple too:
<input id="textfield-1455-inputEl" data-ref="inputEl" type="text" role="textbox" size="1" name="name" class="x-form-field x-form-required-field x-form-text x-form-text-default x-form-focus x-field-form-focus x-field-default-form-focus" autocomplete="off" componentid="textfield-1455"/>
I've noticed that issue occurs only for the first sendKeys() executing on the page:
Enter the page, wait for page load, work with first input
Enter the page, wait for page load, choose Enable into corresponding select box in order to enable input field, work with input field (image with this example is attached)
Enter the page, wait for page load, click button add in order to add the needed input field, work with input field
Other occurrences of the sendKeys on the page are stable.
I've looked for similar questions. It does not seem the issue with special characters (Missing characters example: 46-> 6; coverTest -> overTest; 1 -> nothing);
Also, I don't think it's an issue with missing characters due to remote webdriver infrastructure. The tests fail randomly but in exact places.
I know that I can use sendKeys(), then check the value of the input and repeat the sending action. However, it's the last option.
Is there any additional check needed for ExtJS input (any attribute in DOM) in order to be sure that input field is ready?
Appreciate your help.
Some times it happens with me. Try clicking on to the field first, but it's a wild guess assuming there can be some focus related issues.
Your sequence could be somewhat like this:
wait.until(ExpectedConditions.elementToBeClickable(input)).click();
input.clear();
input.sendKeys(value);
Weird thing is that I actually faced a situation, where I clicked it twice before sending values and it worked somehow :P
Another thing to try could be using a non-native javascript executor.
JavascriptExecutor myExecutor = ((JavascriptExecutor) driver);
myExecutor.executeScript("arguments[0].value='6';", input);
Sorry man, if the system would have been in front of me I'd have tried much more things.
I was struggling with sendKeys failing my self, but the following works pretty consistently. The method findVisibleElement is a custom wrapper for driver.until....
protected static boolean sendKeysByChar(By by, String input)
{
WebElement field = driver.findVisibleElement(by).base();
field.click();
field.clear();
for (int i = 0; i < input.length(); i++) {
String current = driver.findElement(by).getAttribute("value");
String nextChar = String.valueOf(input.charAt(i));
while (current.length() <= i || !current.endsWith(nextChar)) {
field.sendKeys(nextChar);
current = driver.findElement(by).getAttribute("value");
}
}
field = driver.findElement(by); // Refresh element
if (field.getAttribute("value").equals(input)) { return true; }
log.warn("Send keys by char failed.");
return false;
}

Selecting multiple elements with Selenium

I'm creating List of all available elements with below Xpath.
IList<IWebElement> test= Driver.FindElements(By.XPath("//*[#id='middle-container']//div[#class='middle-section match-list']//div[contains(#class,'title')]//span[contains(text(),'" + Event.Trim() + "')]//..//..//..//..//div[contains(#class,'drop-down-content')]//table[contains(#class,'hidden-xs')]//tr//td[contains(#class,'bettype')]//a[#class='bet']`//span"));
So all the elements available in that Xpath need to be clicked. Running foreach loop:
foreach (var item in availableSports)
{
item.Click();
}
}
My problem is let's say if test contains more than, I think, 10 elements, it is stopping the click event after around 8 to 9 clicks, and raising this error:
StaleElementReferenceException
So just wondering how can I write the method which will continue click until last available element without fail.
You are getting StaleElementReferenceException because something has changed in the DOM after you performed the FindElements operation.
You have mentioned that you are clicking on the items in the list. Does this click action reload the page or navigate to a different page. In both cases the DOM has changed. Hence the Exception.
You can handle this(hopefully) with the following logic. I am a JAVA guy and the following code is in JAVA. But I think you get the idea.
IList<IWebElement> test= Driver.FindElements(By.XPath("//*[#id='middle-container']//div[#class='middle-section match-list']//div[contains(#class,'title')]//span[contains(text(),'" + Event.Trim() + "')]//..//..//..//..//div[contains(#class,'drop-down-content')]//table[contains(#class,'hidden-xs')]//tr//td[contains(#class,'bettype')]//a[#class='bet']`//span"));
// Instead of using the for each loop, get the size of the list and iterate through it
for (int i=0; i<test.length; i++) {
try {
test.get(i).click();
} catch (StaleElementReferenceException e) {
// If the exception occurs, find the elements again and click on it
test = test= Driver.FindElements(By.XPath("//*[#id='middle-container']//div[#class='middle-section match-list']//div[contains(#class,'title')]//span[contains(text(),'" + Event.Trim() + "')]//..//..//..//..//div[contains(#class,'drop-down-content')]//table[contains(#class,'hidden-xs')]//tr//td[contains(#class,'bettype')]//a[#class='bet']`//span"));
test.get(i).click();
}
}
Hope this helps you.