Selenium webdriver can't click on a link outside the page - java

I am having an issue with Selenium WebDriver. I try to click on a link that is outside the window page (you'd need to scroll up to see it). My current code is fairly standard:
menuItem = driver.findElement(By.id("MTP"));
menuItem.click();
// I also tried menuItem.sendKeys(Keys.RETURN);
I know I could scroll up, and it would work in this case. But in a case where you have a long list of items, you don't necessarily know how far you have to scroll down.
Is there any way to click on a link that is not on the visible part of the page (but that would be visible if you scroll)?
As a side note, I'm using Firefox, but I am planning to use IE7/8/9 and Chrome as well.
Any help would be greatly appreciated.
Edit: I'm afraid I can't give the source code, as the company I work for doesn't allow it, but I can give the code of the link I want to click on:
<div class="submenu">
<div id="MTP">Link title</div>
</div>
The exact same code works when the link is visible, only when it is not does it not work.
Edit2: Actually, oddly enough, it doesn't raise any exception and just goes to the next instruction. So basically, what happens is:
menuItem = driver.findElement(By.id("MTP")); // no exception
menuItem.click(); // no exception
//... some code ensuring we got to the next page: timeout reached
driver.findElement(By.id("smLH")).click(); // NoSuchElementException, as we're on the wrong page.

It is actually possible to scroll automatically to element. Although this is not a good solution in this case (there must be a way to get it working without scrolling) I will post it as a workaround. I hope someone will come up with better idea...
public void scrollAndClick(By by)
{
WebElement element = driver.findElement(by);
int elementPosition = element.getLocation().getY();
String js = String.format("window.scroll(0, %s)", elementPosition);
((JavascriptExecutor)driver).executeScript(js);
element.click();
}

I posted this same answer in another question so this is just a copy and paste.
I once had a combo box that wasn't in view that I needed to expand. What I did was use the Actions builder because the moveToElement() function will automatically scroll the object into view. Then it can be clicked on.
WebElement element = panel.findElement(By.className("tabComboBoxButton"));
Actions builder = new Actions(this.driver);
builder.moveToElement(element);
builder.click();
builder.build().perform();
(panel is simply a wrapped element in my POM)

Instead of move the scrollbar to the button position, which sometimes it didn't work for me, I send the enter key to the button
var element = driver.FindElement(By.Id("button"));
element.SendKeys(Keys.Enter);

I ran into a similar problem recently when there was a list of selectable objects in a JS dialog. Sometimes selenium would not select the correct object in the list. So i found this javascript suggestion:
WebElement target = driver.findElement(By.id("myId"));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", target);
Thread.sleep(500); //not sure why the sleep was needed, but it was needed or it wouldnt work :(
target.click();
That solved my issue

Hey you can use this for ruby
variable.element.location_once_scrolled_into_view
Store the element to find in variable

It might be occurring because your header element or the footer element might be blocking the view of the element you want to perform action on. Selenium tries to scroll to the element position when it has to perform some action on the element (I am using Selenium WebDriver v3.4.0).
Here is a workaround -
private WebElement scrollToElementByOffset(WebElement element, int offset) {
JavascriptExecutor jse = (JavascriptExecutor) driver;
jse.executeScript("window.scrollTo(" + element.getLocation().getX() + "," + (element.getLocation().getY()
+ offset) + ");");
return element;
}
The above function scrolls the view to the element and then scrolls further by the offset you provide. And you can call this method by doing something like -
WebElement webElement = driver.findElement(By.id("element1"));
scrollToElementByOffset(webElement, -200).click();
Now, this is just a workaround. I gladly welcome better solutions to this issue.

This solution worked like a charm for me:
public void click(By by) throws Exception{
WebElement element = driver.findElement(by);
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
Thread.sleep(500);
element.click();
}

This works for me (in c#)-
item = driver.findelement(by.....);
item.SendKeys(Keys.LeftControl);
item.Click();

Just an addition:
In my case the button was overlapped by another floating button.
Just resizing the browser window solved the problem!

I used the method below to solve a similar issue for Selenium Java:
public static void scrollToElementByElement(WebElement element) {
Coordinates coordinates = ((Locatable)element).getCoordinates();
coordinates.inViewPort();
coordinates.click(); //if needed
}
Then called on the method on my main test class

I have used below method to solve the problem of element not present in the visible area. The code scrolls down the webpage, till selenium operations can be performed on the element. Change the co ordinate of Y-axis and value of i as per requirement.
public void scrooling(By ele) throws InterruptedException {
for (int i = 0; i < 10; i++) {
try {
driver.findElement(ele);
break;
} catch (ElementNotVisibleException e) {
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollBy(0,400)");
System.out.println("inside ElementNotVisibleException block");
Thread.sleep(3000);
} catch (NoSuchElementException e) {
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollBy(0,400)");
System.out.println("inside NoSuchElementException block");
Thread.sleep(3000);
}
}
}

Related

How to click on a button until an element appears on a page in selenium

I have a page with a dynamic table that periodically updates with new data. What I am trying to do is to click on a button and reload the page let's say every 3 seconds until the element from that table appears.
I know the xpath of the element I want to appear, but I just can't make it work using the FluentWait. I tried configuring as seen in the code below, but when I'm calling the method it keeps clicking on the button extremly fast disregarding the pollingEvery configuration and without giving the page enough time to fully reload itself. Code can be checked out below.
What I am not sure about is the return statement. I don't fully grasp what should it be if I only need to click on a button until that element appears.
What am I missing?
public void clickButtonUntilElementIsDisplayed(WebElement elementToBeClicked, String xPathOfElementToBeDisplayed){
FluentWait<WebDriver> wait = new FluentWait<>(getDriver());
wait.pollingEvery(Duration.ofSeconds(5));
wait.withTimeout(Duration.ofSeconds(200));
wait.ignoring(NoSuchElementException.class);
Function<WebDriver,WebElement> clickUntilAppearance = webDriver -> {
while(webDriver.findElements(By.xpath(xPathOfElementToBeDisplayed)).isEmpty())
click(elementToBeClicked);
return webDriver.findElement(By.xpath(xPathOfElementToBeDisplayed));
};
wait.until(clickUntilAppearance);
}
The class in which this method can be found extends Page
The return type of the Functional Interface need to be changed. There are 2 cases in which the functional interface will keep looping.
Value returned is null.
It threw an Exception mentioned as part of ignoring
Don't use while. Use if condition. For every pollingEvery this Functional Interface would get executed.
Function<WebDriver,WebElement> clickUntilAppearance = webDriver -> {
List<WebElement> tableElements = webDriver.findElements(By.xpath(xPathOfElementToBeDisplayed));
if(tableElements.isEmpty()) {
click(elementToBeClicked);
return null;
} else {
return tableElements.get(0);
}
};
WebDriverWait w = new WebDriverWait(driver, 5);// 5seconds
w.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("element_location")));

Selenium in Java - can't go to the next page [duplicate]

I am trying to make some tests using selenium based Katalon Studio. In one of my tests I have to write inside a textarea. The problem is that I get the following error:
...Element MyElement is not clickable at point (x, y)... Other element would receive the click...
In fact my element is place inside some other diva that might hide it but how can I make the click event hit my textarea?
Element ... is not clickable at point (x, y). Other element would receive the click" can be caused for different factors. You can address them by either of the following procedures:
Element not getting clicked due to JavaScript or AJAX calls present
Try to use Actions Class:
WebElement element = driver.findElement(By.id("id1"));
Actions actions = new Actions(driver);
actions.moveToElement(element).click().build().perform();
Element not getting clicked as it is not within Viewport
Try to use JavascriptExecutor to bring the element within Viewport:
JavascriptExecutor jse1 = (JavascriptExecutor)driver;
jse1.executeScript("scroll(250, 0)"); // if the element is on top.
jse1.executeScript("scroll(0, 250)"); // if the element is at bottom.
Or
WebElement myelement = driver.findElement(By.id("id1"));
JavascriptExecutor jse2 = (JavascriptExecutor)driver;
jse2.executeScript("arguments[0].scrollIntoView()", myelement);
The page is getting refreshed before the element gets clickable.
In this case induce some wait.
Element is present in the DOM but not clickable.
In this case add some ExplicitWait for the element to be clickable.
WebDriverWait wait2 = new WebDriverWait(driver, 10);
wait2.until(ExpectedConditions.elementToBeClickable(By.id("id1")));
Element is present but having temporary Overlay.
In this case induce ExplicitWait with ExpectedConditions set to invisibilityOfElementLocated for the Overlay to be invisible.
WebDriverWait wait3 = new WebDriverWait(driver, 10);
wait3.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("ele_to_inv")));
Element is present but having permanent Overlay.
Use JavascriptExecutor to send the click directly on the element.
WebElement ele = driver.findElement(By.xpath("element_xpath"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", ele);
I assume, you've checked already that there is no any other component overlapping here (transparent advertisement-iframes or some other component of the DOM => seen quite often such things in input/textfield elements) and, when manually (slowly) stepping your code, it's working smoothly, then ajax calls might cause this behaviour.
To avoid thread.sleep, try sticking with EventFiringWebDriver and register a handle to it.
(Depending on your application's techstack you may work it for Angular, JQuery or wicket in the handler, thus requiring different implementations)
(Btw: This approach also got me rid of "StaleElementException" stuff lots of times)
see:
org.openqa.selenium.support.events.EventFiringWebDriver
org.openqa.selenium.support.events.WebDriverEventListener
driveme = new ChromeDriver();
driver = new EventFiringWebDriver(driveme);
ActivityCapture handle=new ActivityCapture();
driver.register(handle);
=> ActivityCapture implements WebDriverEventListener
e.g. javascriptExecutor to deal with Ajax calls in a wicket/dojo techstack
#Override
public void beforeClickOn(WebElement arg0, WebDriver event1) {
try {
System.out.println("After click "+arg0.toString());
//System.out.println("Start afterClickOn - timestamp: System.currentTimeMillis(): " + System.currentTimeMillis());
JavascriptExecutor executor = (JavascriptExecutor) event1;
StringBuffer javaScript = new StringBuffer();
javaScript.append("for (var c in Wicket.channelManager.channels) {");
javaScript.append(" if (Wicket.channelManager.channels[c].busy) {");
javaScript.append(" return true;");
javaScript.append(" }");
;
;
;
javaScript.append("}");
javaScript.append("return false;");
//Boolean result = (Boolean) executor.executeScript(javaScript.toString());
WebDriverWait wait = new WebDriverWait(event1, 20);
wait.until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return !(Boolean) executor.executeScript(javaScript.toString());
}
});
//System.out.println("End afterClickOn - timestamp: System.currentTimeMillis(): " + System.currentTimeMillis());
} catch (Exception ex) {
//ex.printStackTrace();
}
}
As #DebanjanB said, your button (or another element) could be temporarily covered by another element, but you can wait and click it even if you don't know which element is covering the button.
To do this, you can define your own ExpectedCondition with the click action:
public class SuccessfulClick implements ExpectedCondition<Boolean> {
private WebElement element;
public SuccessfulClick(WebElement element) { //WebElement element
this.element = element;
}
#Override
public Boolean apply(WebDriver driver) {
try {
element.click();
return true;
} catch (ElementClickInterceptedException | StaleElementReferenceException | NoSuchElementException e) {
return false;
}
}
}
and then use this:
WebDriverWait wait10 = new WebDriverWait(driver, 10);
wait10.until(elementToBeClickable(btn));
wait10.until(new SuccessfulClick(btn));
Try Thread.Sleep()
Implicit - Thread.Sleep()
So this isn’t actually a feature of Selenium WebDriver, it’s a common feature in most programming languages though.
But none of that matter.
Thread.Sleep() does exactly what you think it does, it’s sleeps the thread. So when your program runs, in the majority of your cases that program will be some automated checks, they are running on a thread.
So when we call Thread.Sleep we are instructing our program to do absolutely nothing for a period of time, just sleep.
It doesn’t matter what our application under test is up to, we don’t care, our checks are having a nap time!
Depressingly though, it’s fairly common to see a few instances of Thread.Sleep() in Selenium WebDriver GUI check frameworks.
What tends to happen is a script will be failing or failing sporadically, and someone runs it locally and realises there is a race, that sometimes WedDriver is losing. It could be that an application sometimes takes longer to load, perhaps when it has more data, so to fix it they tell WebDriver to take a nap, to ensure that the application is loaded before the check continues.
Thread.sleep(5000);
The value provided is in milliseconds, so this code would sleep the check for 5 seconds.
I was having this problem, because I had clicked into a menu option that expanded, changing the size of the scrollable area, and the position of the other items. So I just had my program click back on the next level up of the menu, then forward again, to the level of the menu I was trying to access. It put the menu back to the original positioning so this "click intercepted" error would no longer happen.
The error didn't happen every time I clicked an expandable menu, only when the expandable menu option was already all the way at the bottom of its scrollable area.

Element is not clickable at point (x,y)

I have the following exception:
org.openqa.selenium.WebDriverException: Element is not clickable at
point (1057.38330078125, 673.13330078125). Other element would receive
the click:
button id="ID4b6a687af6934e35b6f355f6305dc481"
data-layout="hbox" class="hux-ui-button" type="button"
role="button">
As you can see, I try to click on the Button "Speichern". But strangely the error says he can´t click on the position but the other element IS the Button I want to click on.
Do you know why and how I can work around this?
xpath = //span[text()='Speichern'
FF = 43.0
Selenium = 2.49.
Well, you told the driver to click on the span, not the button. Try modifying your xpath to point to the button. I THINK this would work:
//span[text()='Speichern']/..
It does assume that there is only the one element with that text, and looks for the parent, which is your button.
Exception clearly states you are going to click on span while button element would receive the click, So you need to click on button instead of span as below :-
driver.findElement(By.cssSelector("button.hux-ui-button")).click();
or
driver.findElement(By.xpath(".//span[text()='Speichern']/parent::button")).click();
Edited :- If still you are facing same issue try using JavascriptExecutor to perform click as below :-
WebElement el = driver.findElement(By.xpath(".//span[text()='Speichern']/parent::button"));
((JavascriptExecutor)driver).executeScript("arguments[0].click()", el);
Sooo ... I just asked one Pro-Programmer ;).
I had to updated my singelton with this:
public static Optional<JavascriptExecutor> getExecutor() {
WebDriver checkdriver = Driver.getWebInstance();
final JavascriptExecutor executor;
if (checkdriver instanceof JavascriptExecutor ){
executor = (JavascriptExecutor)checkdriver;
}
else
{
executor = null;
}
return Optional.ofNullable(executor);
}
and added this in the actual page object:
WebElement el = Driver.getInstance().findElement(By.xpath(".//span[text()='Speichern']/parent::button"));
Driver.getExecutor().ifPresent( (executor) -> executor.executeScript("arguments[0].click()", el) );
now it works. Thx :)

selenium dynamically click li item

I am trying to dynamically search an "li" tag item and double-click on this website: www.jstree.com (the right-top hierarchy tree sample). The code does find the WebElement but does not do anything. I am trying as follows. Can someone please point to what I am doing wrong? I am using Firefox 35.0.1 and selenium 2.44.0.
driver.get(baseUrl + "http://www.jstree.com/");
WebElement we = driver.findElement(By.xpath("/html/body/div/div/div[1]/div[1]/div[2]/div[1]/ul/li[1]/ul"));
Actions action = new Actions(driver);
List<WebElement> liItems = we.findElements(By.tagName("li"));
for(WebElement liItem:liItems)
{
System.out.println(liItem.getText());
if(liItem.getText().startsWith("initially open"))
{
System.out.println("Found it...");
liItem.click();
action.moveToElement(liItem).doubleClick().build().perform();
break;
}
}
I ended up doing this:
Modified the selector to make sure ONLY the expected elements are returned. It helps a lot in terms of execution time and reducing the number of unwanted loopings. And, then find the element in run time and use Action() on that to perform double click. I also update the Selenium binding as #alecxe suggested to work with latest Firefox
public void DemoTest() throws InterruptedException {
List<WebElement> liItems = driver.findElements(By.xpath("//*[contains(text(),'initially open')]"));
for(WebElement liItem:liItems)
{
Actions actions = new Actions(driver);
actions.moveToElement(liItem).doubleClick().build().perform();
}
}

How to access a Button with Selenium, when the button seems to be generated from JavaScript

I try to run some tests on a webpage. I'm a beginner and until now everything went pretty smooth.
I'm changing some values in a webform and now want to press the "Save & Exit" button.
But when I look at the available source with the webdriver (driver.getPageSource();) , I don't see a button, only the below JavaScript. I shortened the script to one button - the one button I would like to click.
function getToolbarCfg() {
return [{ btnId: 2, icon:'images/obj16/tsave_.gif', text:'Save & Exit', qtip:'Save Record and Exit', handler:function() { cwc.getCenterWindow().tpzExecute('2',null,'detail'); } }];
Any help is appreciated.
You can have the WebDriver wait explicitly for an element to appear.
public static IWebElement WaitForElementToAppear(IWebDriver driver, int waitTime, By waitingElement)
{
IWebElement wait = new WebDriverWait(driver, TimeSpan.FromSeconds(waitTime)).Until(ExpectedConditions.ElementExists(waitingElement));
return wait;
}
Read up on Selenium's WebDriver Wait Documentation for a good explanation of explicit and implicit waits.
EDIT:
You could alternatively do this:
public static IWebElement WaitForElementToAppear(IWebDriver driver, int waitTime, By waitingElement)
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(waitTime));
var element = wait.Until(d =>
{
var elem = driver.FindElement(waitingElement);
if (elem.Enabled)
return elem;
else return null;
});
return element;
}
This will ping the element every .5 seconds until whatever waitTime is defined or to be OR until the element is present.
Found the solution:
The button is executing a JavaScript when clicked. One can directly call that JavaScript function with the Selenium WebDriver.
((JavascriptExecutor) driver).executeScript("cwc.getCenterWindow().tpzExecute('3',null,'detail');");
Hope this answer helps people having the same troubles.

Categories