Closed lukeis closed 8 years ago
You appear to be missing some information in your report, as in where I can go to or
what page I can use to reproduce the same scenario.
Reported by arran.huxtable
on 2013-03-27 10:13:57
I don't have either, sorry. In the meantime, however, it looks like the cause of this
behaviour is the dropdown menu's animation. Between calling .click() and webdriver
actually clicks at the element's position, its position changes. Seems like that it
is an inherent defect of the webdriver (or is it possible to check if the intended
click location still belongs to the element to be clicked?)
I was able to work around this issue using the following predicate (need more testing
though):
private class ElementMotionlessPredicate implements Predicate<WebDriver> {
private By by;
private Point loc = new Point(-1, 1);
ElementMotionlessPredicate(By by) {
this.by = by;
}
@Override
public boolean apply(WebDriver webDriver) {
try {
WebElement element = driver.findElement(by);
if (element.isDisplayed()) {
Point newLoc = element.getLocation();
if (newLoc.equals(loc)) {
return true;
}
loc = newLoc;
}
} catch (NoSuchElementException e) {
;
} catch (StaleElementReferenceException e) {
;
}
return false;
}
};
Reported by discordia.primula
on 2013-03-29 01:53:03
Here are the HTML page and test class for it, exposing the behaviour described above.
1.html:
<html>
<head>
<style>
#t {
position: absolute;
left: 200px;
top: 10px;
}
td {
text-decoration: underline;
color: blue;
cursor: pointer;
}
</style>
<script language="javascript">
var offset = 10;
function refresh() {
var t = document.getElementById('t');
var top = parseInt(
document.defaultView
.getComputedStyle(t)
.top
.replace('px', '')
);
top += offset;
if (top > 300)
offset = -10;
else if (top < 10)
offset = 10;
t.style.top = top + 'px';
}
function onload() {
for (var i = 1; i < 10; i++) {
var e = document.getElementById('t'+i);
e.addEventListener('click', (function (i) {
return function () {
document.title = i;
}
})(i), false);
}
setInterval(refresh, 100);
}
</script>
</head>
<body onload="onload()">
<table id="t">
<tr><td id="t1">Menuitem 1</td></tr>
<tr><td id="t2">Menuitem 2</td></tr>
<tr><td id="t3">Menuitem 3</td></tr>
<tr><td id="t4">Menuitem 4</td></tr>
<tr><td id="t5">Menuitem 5</td></tr>
<tr><td id="t6">Menuitem 6</td></tr>
<tr><td id="t7">Menuitem 7</td></tr>
<tr><td id="t8">Menuitem 8</td></tr>
<tr><td id="t9">Menuitem 9</td></tr>
</table>
</body>
</html>
Test1.java:
import com.google.common.base.Predicate;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
public class Test1 {
WebDriver driver;
public Test1() {
}
@Before
public void setUp() throws Exception {
driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
driver.get("http://127.0.0.1:8000/1.html");
}
@After
public void tearDown() throws Exception {
}
private void waitForTitle(final String title) {
new WebDriverWait(driver, 5).until(new Predicate<WebDriver>() {
@Override
public boolean apply(WebDriver driver) {
return driver.getTitle().startsWith(title);
}
});
}
@Test
public void test1() {
for (int i = 9; i >= 1; i--) {
driver.findElement(By.id("t" + i)).click();
System.out.println("clicked " + i);
waitForTitle(Integer.toString(i));
}
}
}
Reported by discordia.primula
on 2013-03-29 03:13:49
Reported by barancev
on 2013-03-29 20:00:08
Yes, Selenium determines location and size of at element to be clicked, and emulates
click in the specified position on the page. If the element is actively moving the
click can miss it. It is expected behaviour.
Using a predicate like ElementMotionlessPredicate from the comment 2 is a correct way
to deal with such elements.
Reported by barancev
on 2013-05-13 21:39:35
WorkingAsIntended
Reported by luke.semerau
on 2015-09-17 18:17:02
Originally reported on Google Code with ID 5404
Reported by
discordia.primula
on 2013-03-27 02:15:48