What happened?
The "near" relative locator fails to locate elements in certain cases, like when a narrower object is directly above a wider object (see provided screenshot).

In this case, trying to locate " 'Rectangle 1' near 'Rectangle 2' " results in a NoSuchElementException exception even though the rectangles certainly look like they are within 50 px of each other.
I actually located the source of the issue:
|
// Ascii art time! |
|
// |
|
// +---+ |
|
// | 1 | |
|
// +---+ +---+ |
|
// | 2 | |
|
// +---+ |
|
// |
|
// As you can see, the right hand side of 1 is "left of" the left-most |
|
// edge of 2. The top edge of 2 is at the same level as the bottom |
|
// edge of 1. This means that 1 is "above" 2, and 2 is "below" one. |
|
|
|
// Distance from left edge to right edge |
|
var leftDistance = Math.abs(rect1.left - (rect2.left + rect2.width)); |
|
|
|
// Distance from right edge to left edge |
|
var rightDistance = Math.abs((rect1.left + rect1.width) - rect2.left); |
|
|
|
// Distance from top to bottom |
|
var topDistance = Math.abs(rect1.top - (rect2.top + rect2.height)); |
|
|
|
// Distance from bottom to top |
|
var bottomDistance = Math.abs((rect1.top + rect1.height) - rect2.top); |
|
|
|
var horizontallyClose = leftDistance <= distance || rightDistance <= distance; |
|
var verticallyClose = topDistance <= distance || bottomDistance <= distance; |
|
|
|
if (horizontallyClose && verticallyClose) { |
|
return true; |
|
} |
|
|
|
// Distance from centre points |
|
var x1 = rect1.left + (rect1.width / 2); |
|
var y1 = rect1.top + (rect1.height / 2); |
|
|
|
var x2 = rect2.left + (rect2.width / 2); |
|
var y2 = rect2.top + (rect2.height / 2); |
|
|
|
var xDistance = Math.abs(x1 - x2); |
|
var yDistance = Math.abs(y1 - y2); |
|
|
|
var dist = Math.sqrt(Math.pow(xDistance, 2) + Math.pow(yDistance, 2)); |
|
return dist <= distance; |
The algorithm to determine the proximity of object boundaries seems to perform some naive calculations, whereas what probably is desired is to calculate the shortest distance between the two rectangles' boundaries (or centres if they are overlapping).
So the code probably ought to look something like the example in this StackOverflow answer (https://stackoverflow.com/a/26178015).
I wrote that this issue is present in Selenium 4.6.0 for Python, but since the issue seems to stem from some JavaScript atoms, the issue is probably present in all versions of Selenium, but I did not check, since I only use Selenium for Python.
How can we reproduce the issue?
https://github.com/alpatron/SeleniumRelativeLocatorBug
Relevant log output
DevTools listening on ws://127.0.0.1:12320/devtools/browser/9ef7f89b-4fcb-40f3-9789-dbff1edade6b
Traceback (most recent call last):
File "C:\Users\Vikto\Desktop\SeleniumTests Big Boy\SeleniumRelativeLocatorBug\bug.py", line 8, in <module>
driver.find_element(
File "C:\Users\Vikto\Desktop\SeleniumTests Big Boy\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 848, in find_element
raise NoSuchElementException(f"Cannot locate relative element with: {by.root}")
selenium.common.exceptions.NoSuchElementException: Message: Cannot locate relative element with: {'id': 'rect1'}
Operating System
Windows 10 21H1
Selenium version
Python 4.6.0 (but should be present in all versions; see "What happened" section)
What are the browser(s) and version(s) where you see this issue?
Chrome 107
What are the browser driver(s) and version(s) where you see this issue?
ChromeDriver 107.0.5304.62
Are you using Selenium Grid?
No
What happened?
The "near" relative locator fails to locate elements in certain cases, like when a narrower object is directly above a wider object (see provided screenshot).

In this case, trying to locate " 'Rectangle 1' near 'Rectangle 2' " results in a
NoSuchElementExceptionexception even though the rectangles certainly look like they are within 50 px of each other.I actually located the source of the issue:
selenium/javascript/atoms/locators/relative.js
Lines 169 to 211 in abde4ce
The algorithm to determine the proximity of object boundaries seems to perform some naive calculations, whereas what probably is desired is to calculate the shortest distance between the two rectangles' boundaries (or centres if they are overlapping).
So the code probably ought to look something like the example in this StackOverflow answer (https://stackoverflow.com/a/26178015).
I wrote that this issue is present in Selenium 4.6.0 for Python, but since the issue seems to stem from some JavaScript atoms, the issue is probably present in all versions of Selenium, but I did not check, since I only use Selenium for Python.
How can we reproduce the issue?
Relevant log output
Operating System
Windows 10 21H1
Selenium version
Python 4.6.0 (but should be present in all versions; see "What happened" section)
What are the browser(s) and version(s) where you see this issue?
Chrome 107
What are the browser driver(s) and version(s) where you see this issue?
ChromeDriver 107.0.5304.62
Are you using Selenium Grid?
No