Selenium Chrome webdriver can't find elements after content is reloaded - selenium

I'm testing a page where the div reloads with a form that has multiple textboxesand buttons. However after the div is reloaded the webdriver can't find any of the elements on the screen. I've tried different waits but it never finds the elements. However, when I try to find an element that didn't change (i.e. a top nav element) it finds it fine.
Driver.Instance.FindElement(By.Id("igtxttxt_CAge")).Click();
var wait = new WebDriverWait(Driver.Instance, TimeSpan.FromSeconds(10));
wait.Until(d => d.SwitchTo().ActiveElement().GetAttribute("id") == "igtxttxt_CAge");
Is there something I can do for when the div content is refreshed?
Error received:
no such element: Unable to locate element:
{"method":"id","selector":"igtxttxt_CAge"}
(Session info: chrome=56.0.2924.76)
(Driver info: chromedriver=2.27.440174

I found the answer to this question. I didn't realize until I looked at the HTML content that the Driver contained that the page I was loading was loaded in an iFrame.
Once I added this code:
Driver.Instance.SwitchTo().Frame("frame_Calculator");
Then the rest of my code worked as expected:
Driver.Instance.FindElement(By.Id("igtxttxt_CAge")).Click();
((IJavaScriptExecutor)Driver.Instance).ExecuteScript("$('#igtxttxt_CAge').trigger('focus')");

In your given scenario, I think fluentwait is better candidate than webdriverwait. You can try the following code. It will ignore all such no element not found exceptions while the webdriver waits.
FluentWait fluentWait = new FluentWait<>(webDriver) {
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(200, TimeUnit.MILLISECONDS);
.ignoring(NoSuchElementException.class, TimeoutException.class)
.ignoring(StaleElementReferenceException.class);
}
And the you can use it until your element is clickable or visible.
fluentWait.until(ExpectedConditions.visibilityOf(By.Id("igtxttxt_CAge")));
fluentWait.until(ExpectedConditions.elementToBeClickable(By.Id("igtxttxt_CAge")));
Hope this will help. here is a difference between webdriverwait and fluentwait.

Related

Selenium - move page to front

I am performing a web page scrape and update using Selenium and phantomJS webdriver. At one stage, completing one page can bring up either page_A or page_B. The page I want is page_B. If page_A appears, I can locate the elements:
<li class="menu_item">
<a class="menu_item_anchor_selected" href="#page_a">Page_A</a>
</li>
<li class="menu_item">
<a class="menu_item_anchor" href="#page_b">Page_B</a>
</li>
and I can then extract the target from the anchor to page_B. However, once loaded by the driver, every element on page_B remains invisible.
public class fill_page_B (WebDriver driver, String target) throws Exception
{
String currentUrl = driver.getCurrentUrl;
String page_B_Url = currentUrl + target;
driver.get (page_B_Url);
// prove that page_B actually loaded
String page = driver.getPageSource ();
System.println (page);
WebElement we = driver.findElement (By.id ("MyId"));
// ignore test for we exists; it does
WebDriver wait = new WebDriverWait (driver, 60); // should be long enough!
wait.until (ExpectedConditions.visibilityOf (we)); // fails
. . .
}
I have tried using:
driver.manage().window().maximize();
and other tricks to ensure the window hasn't shrunk to make the required control outside the viewable window and other, similar tricks to make sure it hasn't migrated off the screen entirely.
I have also tried:
JavascriptExecutor jse = (JavascriptExecutor) driver;
jse.executeScript ("arguments[0].checked=true;", we);
to force the element to be visible. This approach however merely threw an Exception "cannot click on option element. Executing JavaScript click function returned an unexpected error etc."
However, when I ran my application again, this time using an Internet Explorer driver, I noticed that when I got page_B (and proved it by displaying the page contents in the system log), page_A was still visible. I did try resizing page_A (which was previously maximized) before getting page_B, but this made no difference; everything on page_B remained invisible and unclickable.
Any suggestions as to how Selenium could deal with this?

Why By.Id can't find some elements from web page who had property id and is unique

I have the HTML code:
<button type="submit" id="login-signin" class="pure-button puree-button-primary puree-spinner-button" name="verifyPassword" value="Sign in" data-ylk="elm:btn;elmt:next;slk:next"> Sign in </button>
I write a test case who checks login to Yahoo mail.
My question is:
Why driver.findElemnt(By.id("login-signin")) Can't find this element in DOM.
The only solution is to use xpath selector:
WebElement login = driver.findElement(By.xpath("//button[#id='login-signin']"));
Fantastic, today with ChromeDriver and selenium 2.47.1 run locally my test is successfully.
I tried on many browsers and I don't know in which browsers I have errors.
There is error stale element reference: while enter password on yahoo site
A stale element reference exception is thrown in one of two cases, the first being more common than the second:
1. The element has been deleted entirely.
2. The element is no longer attached to the DOM.
Either put some wait using Thread.sleep(3000) so it get reattach with DOM
Note: This is not recommended
Or Refresh the page to relocate the element using
driver.navigate().refresh();
The Best way to use FluentWait to avoid this kind of exception in following way
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class)
.ignoring(StaleElementReferenceException.class);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("login-passwd")));
although above 3 things will work.
Try below code, same working fine at my end:
driver.get("https://login.yahoo.com/config/login");
driver.manage().timeouts().implicitlyWait(45, TimeUnit.SECONDS);
driver.findElement(By.id("login-username")).sendKeys("abc#yahoo.com");
driver.findElement(By.id("login-signin")).click();
//driver.navigate().refresh();
//Thread.sleep(5000);
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class)
.ignoring(StaleElementReferenceException.class);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("login-passwd")));
driver.findElement(By.id("login-passwd")).sendKeys("****");
driver.findElement(By.id("login-signin")).click();
Reason 1:
Waiting for the element to be loaded. Use
WebDriverWait wait = new WebDriverWait(driver, 4000);
wait.until(ExpectedConditions.visibilityOfElementLocated((By.id("login-sigin"))));
Reason 2:
Check to see if is in any frame.
If yes use following code:
driver.switchTo.frame("frameName");
before using
driver.findElement(By.id("login-sigin"));
Hope any one of above solution will work out.
I just had a look on the HTML code.
Did you copy this from your code? There is a 'n' missing in your id (login-signin).
Otherwise you could use findElement(By.name/xpath/cssSelector/...) In this special case I would use the element name.

How to click a button created using <span> tag for Selenium webdriver?

I have span tag which looks like a button on html tag
<span class="middle">Next</span>
I tried using
xpath=driver.findElement(By.xpath(".//*[#id='modal-actions-panel']/div[2]/a/span/span/span")); // by considering fixed id as reference
Using absolute
xpath=driver.findElement(By.xpath("html/body/div[4]/div[2]/a/span/span/span")); // took this from firebug
and Using
driver.findElement(By.cssSelector("span[class='middle']"));
No success!! It is throwing below exception :
Exception in thread "main" org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"xpath","selector":"//span[contains(., \"Next\")]"}
Command duration or timeout: 30.12 seconds
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
For all the ways I tried it is showing the same exception with change in selector details. Can someone please help me out in finding solution so that I can find Next button that is in span tag and click it.
Next button is in iFrame: Below is the part of html covering required span tag.
Next
I also tried with :
driver.switchTo().frame("iframe-applicationname_ModalDialog_0");
WebElement el = driver.findElement(By.cssSelector("span.middle"));
But throwing below error :
Caused by: org.openqa.selenium.ElementNotVisibleException: Element is not currently visible and so may not be interacted with
Kindly let me know if needed something that I'm missing..
I think this element is inside a frame or iframe, if it is then you need to switch that frame or iframe before finding element as below :-
driver.switchTo().frame("iframe-applicationname_ModalDialog_0");
WebElement el = driver.findElement(By.cssSelector("span.middle"));
el.click();
//Now after all your stuff done inside frame need to switch to default content
driver.switchTo().defaultContent();
Edited1 :- If you are getting exception as element is not currently visible need to implement WebDriverWait to wait until element visible as below :-
WebDriverWait wait = new WebDriverWait(driver, 10);
//Find frame or iframe and switch
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt("iframe-applicationname_ModalDialog_0"));
//Now find the element
WebElement el = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(".//span[#class = 'middle' and contains(text(), 'Next')]")));
el.click();
//Once all your stuff done with this frame need to switch back to default
driver.switchTo().defaultContent();
Edited2 :- If unfortunately it's not getting visible try to click on it using JavascriptExecutor as below :-
WebDriverWait wait = new WebDriverWait(driver, 10);
//Find frame or iframe and switch
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt("iframe-applicationname_ModalDialog_0"));
//Now find the element
WebElement el = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(".//span[#class = 'middle' and contains(text(), 'Next')]")));
//Now click using JavascriptExecutor
((JavascriptExecutor)driver).executeScript("arguments[0].click()" el);
//Once all your stuff done with this frame need to switch back to default
driver.switchTo().defaultContent();
Try this....
driver.findElement(By.xpath("//span[contains(#class,'middle') and contains(text(), 'Next')]"))
I tried it and it worked for me:
WebElement actionBtn=driver2.findElement(
By.xpath("//span[contains(#class,'v-menubar-menuitem-caption')
and contains(text(), 'Actions')]")
);
actionBtn.click();
Try this
new WebDriverWait(driver, 30).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//span[contains(#class,'middle') and contains(text(), 'Next')]"))).click();

Element is not clickable when another element covers it

I am writing a test that at some point navigates to another page. The first thing that page is will be to run a javascript that pops up a span with a message. After some seconds, that span will dissapear.
I am trying to click a link that will go below the span and chromedriver does not seem to allow that.
System.InvalidOperationException: unknown error: Element is not
clickable at point (165, 177). Other element would receive the click:
...
This is really an expected behavior and also a bit impresssive.
Can I click the link without waiting for the span to dissapear?
I have no suggestion how to click the element as long as the massage is displayed but you could skip waiting for it to disappear by removing it on your own using javascript and webDriver.executeScript:
How to make a DIV visible and invisible with JavaScript
I would suggest you to use "smart" wait that will verify that the window has disappeared.
It's implemented using WebDriverWait and ExpectedConditions.
Example in Java:
WebDriverWait wait = new WebDriverWait(driver, 10); //timeout after 10 seconds
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.ByCssSelector("CSS_POP_UP_SELECTOR")));
Or, you can try to use the following script to make element visible:
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("document.getElementById('BUTTON_ELEMENT_ID').style.display='block';");
Or, to try and hide the message:
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("document.getElementById('BUTTON_ELEMENT_ID').style.display='none';");
If you want your elements to keep their size when the not visible/visible, instead of 'display' change the 'visibility':
document.getElementById('BUTTON_ELEMENT_ID').style.visibility = 'hidden';
document.getElementById('BUTTON_ELEMENT_ID').style.visibility = 'visible';

Test dynamically loaded content with Selenium Web Driver

I am working on a system that has a web based frontend that I am testing with Selenium. On one page the content is dynamically loaded when scrolling down (maybe you know that from Facebook's friend-list), because it is one of the requirements.
Scrolling down with Selenium Webdriver (I use Chrome) should be no problem via Javascript. But there is a problem with the dynamically added content. How can I make the Webdriver find those elements?
I tried the following to scroll down until no more content is loaded:
int oldSize = 0;
int newSize = 0;
do {
driver.executeScript("window.scrollTo(0,document.body.scrollHeight)");
newSize = driver.findElementsBy(By.cssSelector("selector").size();
} while(newSize > oldSize);
But though the page scrolls down the first time and some now content is loaded correctly, they will not be found by the drivers' findElementsBy(By) function.
Has someone ever faced this problem?? I'd be very glad if someone could help me figuring a solution for that!
Regards, Benjamin
I would recommend using WebDriverWait with ExpectedConditons.
//scroll down with Javascript first
WebDriverWait wait = new WebDriverWait(driver, 30);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("selector")));
//interact with your element
element.click()
Take a look at the guidance provided by Selenium Official page:
http://seleniumhq.org/docs/04_webdriver_advanced.html
try using fluent wait in particular. The main feature is:
An implementation of the Wait interface that may have its timeout and polling interval configured on the fly.
Each FluentWait instance defines the maximum amount of time to wait for a condition, as well as the frequency with which to check the condition. Furthermore, the user may configure the wait to ignore specific types of exceptions whilst waiting, such as NoSuchElementExceptions when searching for an element on the page.
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; } ;
The method described returns you web element you can operate with.
So the approach be the following:
1) you need to find the selectors of elements you expect to be rendered after scrolling
e.g.
String cssSelector = "blablabla"
2) scroll down with js
3)
WebElement neededElement = fluentWait(cssSelector);
neededElement.click();
//neededElement.getText().trim();
you can get more info about fluent wait here
I think the problem is waiting for the dynamic content to finish loading. Try to wait 3 seconds just before findElementsBy? In C# the code would be Thread.Sleep(3000);