Selenium webdriver - mouseover and dropdown menu - mouse inside/outside the browser issue - java

Specs:
Windows 7;
selenium 2.39.0;
Java - Eclipse
I'm currently using Selenium to test a webApp through three different browsers (Chrome, IE9 and Firefox).
The webApp has a menu bar, and there are located dropdown menus (classic).
I need to set the mouse over one item of that menu bar and wait for a dropdown menu to appear, then I need to click in one of the dropdown menu items.
My code:
WebElement div_menu = driver.findElement(By.xpath("//div[text() = 'Trigger of the dropdown menu']"));
WebDriverWait wait = new WebDriverWait(driver, 300);
Actions builder = new Actions(driver);
builder.moveToElement(div_menu).build().perform();
WebElement item_to_click = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("Link_inside_the_dropdown_menu")));
item_to_click.click();
The funny stuff occurs when I start the test. (FYI Browsers come up one by one, that is to say, all tests are performed for one browser before going on with other one, not threaded.)
If the mouse pointer is over the browser (because they are started not full maximized) at the time the tests are performed, then here are the results:
Chrome: div_menu seems to get the mouseover (because of a css style change), but for too short, so that dropdown menu never appears
IE9: throws this exception: org.openqa.selenium.ElementNotVisibleException: Cannot click on element, but mainly, div_menu gets the mouseover, so dropdown menu is displayed. In spite of this, item_to_click it's not clicked at all (btw, I don't think the exception is the issue cause). And besides, it's like an invisible mouse keep laying over the div_menu, because when I move the real mouse, dropdown menu blinks as if div_menu lose the hover and get it back every time I stop moving the real mouse.
Firefox: Works as it's supposed to.
Now, let's see what happens when I left the mouse outside the browser window.
Chrome: works
IE9: works
Firefox: div_menu seems to get the mouseover (because of a css style change), but for too short, so that dropdown menu never appears
As you can see, the code is the same for the three of the browsers. The funny variable here is the mouse_in_browser and mouse_out_browser.
I can't imagine what the problem could be.
If you need any extra info, please don't hesitate.
Thank you very much in advance!

I managed to get Firefox to work no matters where the physical mouse is.
I initialized it this way:
//Firefox initialization
FirefoxProfile profile = new FirefoxProfile();
//explicitly enable native events(this is mandatory on Linux system, since they
//are not enabled by default
profile.setEnableNativeEvents(true);
WebDriver driver = new FirefoxDriver(profile);
This did the trick for me regarding Firefox. Not yet the others two.
Source: Selenium WebDriver mouse actions moveToElement doesn't raise mouseout event on Firefox Linux

Related

Wait until elementToBeClickable is not the solution for other element would receive the click exception

Yesterday I ask question how to deal with: "Element is not clickable at point - other element would receive the click" exception in Selenium WebDriver.
I receive several answers with this solution:
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id(...));
Yes, it has sense but in practice it doesn't work.
Below is piece of my code:
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].scrollIntoView();", categoryItem);
Thread.sleep(1000);
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(categoryItem));
categoryItem.click();
List<WebElement> selects = driver.findElements(By.tagName("select"));
Select ticketsSelect = new Select(selects.get(3));
ticketsSelect.selectByValue("2");
By addToBasket = By.xpath("//div[contains(text(),'Add to Basket')]");
Thread.sleep(1000);
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(addToBasket));
driver.findElement(addToBasket).click();
I had to put 1 second sleep before each wait until element to be clickable because without this it still throw exception that other element would receive the click.
My question is why WebDriver clicks this element if element is not clickable ?
ElementToBeClickable – An expectation for checking an element is visible and enabled such that you can click it.
But it seems that it doesn't imply that this element is not "hidden" under some other element, even if it's a transparent part of another tag. In my experience, this exception is mostly occur when you are trying to interact with a page, which currently loads, and you have typical loading div overlapping the whole page with loading icon, or in other cases when you have an open modal, which also often cover page with overlays transparent overlay, to prevent user from interacting with a page.
In this answer you can see that you basically have two options:
You can send a click event via JavaScript call. It will always work, but it's not something you want to do. If you want to test your page, you should always trigger real click events.
Wait. There is not much you can do. Something you just need to wait till your page fully loads. In a way maybe this will show you the slow parts of your application, which you can improve in a future

Waiting for an Element to Be Clickable using Selenium WebDriverWait Does Not Work

There's a menu item that I want to click.
However just before this click, in my test flow I have a modal open, which prevents clicking on the menu item. Also, when closed, the modal will fade instead of disappearing instantly.
What I do is close the menu item and then place a wait for the menu item to be clickable, before performing the click:
WebDriverWait wait = new WebDriverWait(getDriver(), time);
wait.withMessage(message);
try {
wait.until(ExpectedConditions.elementToBeClickable(locator));
} catch (Exception e) {
Logging.logException(e);
}
clickOn(locator);
However this does not work, as I'm running each time into the following exception:
org.openqa.selenium.WebDriverException: unknown error: Element is not clickable at point (158, 565). Other element would receive the click: <div class="globalpopup with-data slideout">...</div>
I also have Selenium set-up to take a screenshot each time an exception occurs and in the screenshot I can clearly see that the modal is in the process of fading out.
So the close button for it has been clicked, but at this point I'm thinking the wait should come into effect and pause execution until the modal fully disappears and the menu item can be clicked. Which does not happen.
Now I usually fix this by adding a bit of sleep time, as it's quite predictable how long it takes the modal to fade out. However I'd really like to figure out a more elegant solution, which can apply in all situations.
My understanding is that elementToBeClickable does not account for when the element is covered by another element, which I find quite silly. Is there a way to simulate such a wait (notCoveredByOtherElement), as it's exactly what I'd need?
P.S. I'm using Selenium 2.53. Have not tried v3 yet, although I'd happily make the effort to start switching to it if someone can confirm that this case is handled properly in this new version.
I also faced this issue number of time and tried some solution which always worked for me.
1-Updated chrome driver to latest one 2.23
2-Get the coordinate then click on the link or button
3-Try to click using Y coordinates
// Find an element
WebElement elementToClick = driver.findElement(By.xpath("Your xpath"));
// Scroll the browser to the element's Y position
((JavascriptExecutor)driver).executeScript("window.scrollTo(0,"+elementToClick.getLocation().y+")");
// Click the element
elementToClick.click();
// Find an element
WebElement elementToClick = driver.findElement(By.xpath("Your xpath"));
// Scroll the browser to the element's Y position
((JavascriptExecutor)driver).executeScript("window.scrollTo(0,"+elementToClick.getLocation().y+")");
// Click the element
elementToClick.click();
I have documented all in below link kindly check
Solutions for Element is not clickable in Selenium

Mouseover function with Selenium Webdriver does not work with Opera 39 and works inconsistently with Chrome 53

I'm trying to write Webdriver tests where I need to hover the mouse cursor over an element to trigger a drop down menu, and then click a button from the drop down menu. I've been writing my code following the suggestion from How to perform mouseover function in Selenium WebDriver using Java?. So for example, my code might look like this :
Actions action = new Actions(webdriver);
WebElement hoverElem = webdriver.findElement(By.xpath("//html/body/div[13]/ul/li[4]/a"));
WebElement clickElem = webdriver.findElement(By.xpath("//html/body/div[3]/li[12]/a"));
action.moveToElement(hoverElem).moveToElement(clickElem).click().build().perform();
My code runs perfectly when I test it in Firefox, but in Chrome it's inconsistent; sometimes it will work perfectly, and then the next time I run the test it will fail. In Opera it never works. When the code fails, it looks like the drop down menu appears for a split second on the screen, then disappears before WebDriver can click on the button on the drop down menu. I'm not sure how I can fix this problem. How can I get this to work with all 3 browsers?
As a reference, I'm using selenium-2.53.0, Chrome 53.0.2785.101 64-bit, and Opera 39.0.2256.71 64-bit.
In case anyone finds this in the future and is confused about why the mouse-over function works inconsistently with Chrome, Opera, or Internet Explorer, here is why:
The code I have above is correct. The problem is that for whatever reason, mouse over with Chrome, Opera, and IE doesn't work if the mouse cursor is on the browser window while the test is running (this may be an issue within the driver for each of these browsers).
To get around this, you need to ensure the mouse cursor is outside of the browser window while you run tests. I did this by leaving a pixel or two of space on the bottom of the screen when maximizing the browser window, and then using the java.awt.Robot class to move the mouse cursor to the bottom of the screen where the mouse would not interfere with the tests.
Below is an example for my monitor (which is 1680 x 1050, so I leave 40 pixels of space at the bottom of the screen):
driver.manage().window().setPosition(new Point(0, 0));
org.openqa.selenium.Dimension d = new org.openqa.selenium.Dimension(1680, 1010);
driver.manage().window().setSize(d);
To move the cursor out of the way:
Robot robot = new Robot();
robot.mouseMove(0, 1050);
You can call the above whenever you need to reset the mouse cursor to the bottom, for whatever reason.

Difference between clicking with Selenium and clicking with Robot

Is there a difference between testing perspective and not usability, on clicking elements with selenium like this:driver.findElement(By.id("foobar")).click();
instead of using coordinates and the robot class.
Example: If an element is not clickable because of a bug, robot will not be able to click it. Will selenium be able to click it ?
Selenium tries as much as possible to emulate what a regular user can and cannot do. When you use findElement(...).click() Selenium will raise an exception if operation cannot be performed. For instance, if an element exists in the DOM but is not displayed, an exception will be raised. And note that Selenium's .click() will try to scroll elements. If you ask it to click an element that is not visible but could be visible by scroll it, Selenium will scroll to bring it into view.
Also note that Selenium will usually take the element's coordinates and perform a click at those coordinates. So the idea that a moving element will always be hit by findElement(...).click() (expressed in this answer) is incorrect. Using findElement minimizes the window between which the coordinates are acquired and the click event is sent, but it does not completely eliminate it. The reason that Selenium works with coordinates is, again, to reproduce what a user would do. The user would see the element, move the mouse to the coordinates of the element, and click on it. If the element has an transparent overlay over it, then the overlay will get the click, rather than the element. This works because Selenium clicks at the coordinates rather than send a click directly to the element that you selected with findElement.
If you are using Robot to perform the click, the stakes are roughly the same as above, with a few caveats:
Trying to click moving elements is more of an issue because the window of time between acquiring the coordinates and performing the click is greater.
Robot does not know how the DOM is structured so won't scroll elements for you.
Rogério Peixoto pointed out that you can use JavaScript to perform the click. This will cause the event handler for click to be called for the element, irrespective of whether a user would be in fact able to access the element. This can allow clicking on elements that are not otherwise clickable but I would not do this unless there are overriding reasons to do so. I've gone over the difference between Selenium's click and the JavaScript click in this answer.
If an element is not clickable because of a bug, robot will not be able to click it. Will selenium be able to click it?
It depends on what the bug is that is preventing the click. I would suggest that you use element.click() in almost all cases because it's more maintainable. For coordinate clicks, what if the element moves? Then you have to update your script with the new position where element.click() will just work. Another issue with coordinate clicking, what if your element moves and another one is in its place? That will likely cause your script to fail but will be very hard to track down. An example might be an unexpected popup that covers the element to be clicked. Now your coordinate click will hit the popup and eventually cause an error/failure. If you do element.click() you will at least get an error that another element would receive the click. You can then track down what is getting in the way from debugging.
Selenium clicks in my experience click an element within a browser window, where as Robot click seem to click whatever is on the desktop at the time. Personally I would recommend you try to use Selenium clicks where possible as you can specify the window in which you are clicking.
Using this:
driver.findElement(By.id("foobar")).click();
Means that you will click the element with the foobar id regardless where it is.
If you use coordinates, you won't be able to click the element if they change their position.
Updating answer due to your updated question:
I'm not quite sure where you're trying to get with this.
In Selenium, if the element is visible it will receive the click event, if not you'll have an exception.
You could force click it with javascript:
WebElement element = driver.findElement(By.id("foobar"));
((JavascriptExecutor)driver).executeScript("arguments[0].click();", element);
But it won't trigger the an eventual javascript event registered to that button, you would have to fire it manually.

Selenium fails to click

selenium.click([xpath to object])
Selenium click method seems to be screwed up for me. It recognises the button I want to click and thinks it clicks it. But nothing happens on the screen. The next line involves clicking another button on the next screen. It fails because it cant locate the button because the first click hasn't actually happened.
[EDIT]
It looks like It just fails to click after the screen changes. It will click the log in button fine, and load the new screen. The next click fails, but if i give it a gentle push(IE click the button for it) all the followin clicks in the script run fine. So it seems to be a problem with a click after a screen change?
I had a similar problem and this code worked for me:
mouseOver(locator);
mouseDownAt(locator, "10,10");
mouseUpAt(locator, "10,10");
I wrapped it up in a clickButton() method and use it instead of click()
you can try this:
WebElement element = driver.findElement(By.id("button"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", element);
If you're doing it on Internet Explorer, there is a known bug that its window must be foremost. Some people get past this with doing another event which makes the window get focus like clicking twice or maximising, etc. etc.

Categories