Skip to content

Commit

Permalink
[java][js][py] Add straight relative-by locators (#14482)
Browse files Browse the repository at this point in the history
Co-authored-by: Puja Jagani <[email protected]>
  • Loading branch information
AdamPDotty and pujagani authored Jan 16, 2025
1 parent 835c8a0 commit 960ff05
Show file tree
Hide file tree
Showing 13 changed files with 964 additions and 306 deletions.
101 changes: 72 additions & 29 deletions common/src/web/relative_locators.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

<html>
<html lang="en">
<head>
<title>Relative Locators</title>
<style>
Expand All @@ -10,57 +9,101 @@
td {
border: solid;
}
.small-rectangle {
#center {
width: 100px;
}
#rectangles {
position: relative;
}
#rectangles div {
position: absolute;
border: 1px solid black;
height: 50px;
width: 50px;
}
#a {
left: 25px;
top: 0;
}
#b {
left: 78px;
top: 30px;
}
#c {
left: 131px;
top: 60px;
}
#d {
left: 0;
top: 53px;
}
#e {
left: 53px;
top: 83px;
}
#f {
left: 106px;
top: 113px;
}
#proximity .small {
border: 1px solid black;
width: 100px;
height: 50px;
margin: 5px 25px;
}
.big-rectangle {
#proximity .big {
border: 1px solid black;
width: 150px;
height: 400px;
height: 400px;
}
#rect3 {
margin: 60px 25px;
}
</style>
</head>
<body>
<h1>Relative Locator Tests</h1>
<p id="above">This text is above.
<p id="mid">This is a paragraph of text in the middle.
<p id="below">This text is below.

<section id="paragraphs">
<p id="above">This text is above.</p>
<p id="mid">This is a paragraph of text in the middle.</p>
<p id="below">This text is below.</p>
</section>

<table>
<tr>
<td id="first">1</td>
<td id="second" style="width: 100px">2</td>
<td id="third">3</td>
<td id="topLeft">1</td>
<td id="top">2</td>
<td id="topRight">3</td>
</tr>
<tr>
<td id="fourth">4</td>
<td id="left">4</td>
<td id="center">5</td>
<td id="sixth">6</td>
<td id="right">6</td>
</tr>
<tr>
<td id="seventh">7</td>
<td id="eighth">8</td>
<td id="ninth">9</td>
<td id="bottomLeft">7</td>
<td id="bottom">8</td>
<td id="bottomRight">9</td>
</tr>
</table>

<div class="small-rectangle" id="rect1">
Rectangle 1
</div>
<div class="big-rectangle" id="rect2">
Rectangle 2, which is near Rectangle 1
</div>
<section id="rectangles">
<div id="a">El-A</div>
<div id="b">El-B</div>
<div id="c">El-C</div>
<div id="d">El-D</div>
<div id="e">El-E</div>
<div id="f">El-F</div>
</section>

<div class="small-rectangle" style="margin:60px 25px" id="rect3">
Rectangle 3
</div>
<div class="big-rectangle" id="rect4">
Rectangle 4, which is not near Rectangle 2 because it is more than 50 px away
</div>
<section id="proximity">
<div class="small" id="rect1">Rectangle 1</div>
<div class="big" id="rect2">Rectangle 2, which is near Rectangle 1</div>
<div class="small" id="rect3">Rectangle 3</div>
<div class="big" id="rect4">
Rectangle 4, which is not near Rectangle 2 because it is more than 50 px away
</div>
</section>

</body>
</html>
26 changes: 13 additions & 13 deletions dotnet/test/common/RelativeLocatorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ public void ShouldBeAbleToFindElementsAboveAnotherWithXpath()
{
driver.Url = (EnvironmentManager.Instance.UrlBuilder.WhereIs("relative_locators.html"));

IWebElement lowest = driver.FindElement(By.Id("seventh"));
IWebElement lowest = driver.FindElement(By.Id("bottomLeft"));

var elements = driver.FindElements(RelativeBy.WithLocator(By.XPath("//td[1]")).Above(lowest));

var values = elements.Select(element => element.GetDomAttribute("id"));
Assert.That(values, Is.EquivalentTo(new List<string> { "fourth", "first" }));
Assert.That(values, Is.EquivalentTo(new List<string> { "left", "topLeft" }));
}

[Test]
Expand All @@ -73,10 +73,10 @@ public void ShouldBeAbleToCombineFilters()
{
driver.Url = (EnvironmentManager.Instance.UrlBuilder.WhereIs("relative_locators.html"));

ReadOnlyCollection<IWebElement> seen = driver.FindElements(RelativeBy.WithLocator(By.TagName("td")).Above(By.Id("center")).RightOf(By.Id("second")));
ReadOnlyCollection<IWebElement> seen = driver.FindElements(RelativeBy.WithLocator(By.TagName("td")).Above(By.Id("center")).RightOf(By.Id("top")));

var elementIds = seen.Select(element => element.GetDomAttribute("id"));
Assert.That(elementIds, Is.EquivalentTo(new List<string>() { "third" }));
Assert.That(elementIds, Is.EquivalentTo(new List<string>() { "topRight" }));
}


Expand All @@ -85,10 +85,10 @@ public void ShouldBeAbleToCombineFiltersWithXpath()
{
driver.Url = (EnvironmentManager.Instance.UrlBuilder.WhereIs("relative_locators.html"));

ReadOnlyCollection<IWebElement> seen = driver.FindElements(RelativeBy.WithLocator(By.XPath("//td[1]")).Below(By.Id("second")).Above(By.Id("seventh")));
ReadOnlyCollection<IWebElement> seen = driver.FindElements(RelativeBy.WithLocator(By.XPath("//td[1]")).Below(By.Id("top")).Above(By.Id("bottomLeft")));

var values = seen.Select(element => element.GetDomAttribute("id"));
Assert.That(values, Is.EquivalentTo(new List<string> { "fourth" }));
Assert.That(values, Is.EquivalentTo(new List<string> { "left" }));
}

[Test]
Expand All @@ -97,10 +97,10 @@ public void ShouldBeAbleToCombineFiltersWithCssSelector()
driver.Url = (EnvironmentManager.Instance.UrlBuilder.WhereIs("relative_locators.html"));

ReadOnlyCollection<IWebElement> seen = driver.FindElements(
RelativeBy.WithLocator(By.CssSelector("td")).Above(By.Id("center")).RightOf(By.Id("second")));
RelativeBy.WithLocator(By.CssSelector("td")).Above(By.Id("center")).RightOf(By.Id("top")));

var values = seen.Select(element => element.GetDomAttribute("id"));
Assert.That(values, Is.EquivalentTo(new List<string> { "third" }));
Assert.That(values, Is.EquivalentTo(new List<string> { "topRight" }));
}

[Test]
Expand All @@ -120,7 +120,7 @@ public void ExerciseNearLocatorWithTagName()
// 5-8. Diagonally close (pythagoras sorting, with top row first
// because of DOM insertion order)
var values = seen.Select(element => element.GetDomAttribute("id"));
Assert.That(values, Is.EquivalentTo(new List<string> { "second", "eighth", "fourth", "sixth", "first", "third", "seventh", "ninth" }));
Assert.That(values, Is.EquivalentTo(new List<string> { "top", "bottom", "left", "right", "topLeft", "topRight", "bottomLeft", "bottomRight" }));
}

[Test]
Expand All @@ -140,7 +140,7 @@ public void ExerciseNearLocatorWithXpath()
// 5-8. Diagonally close (pythagoras sorting, with top row first
// because of DOM insertion order)
var values = seen.Select(element => element.GetDomAttribute("id"));
Assert.That(values, Is.EquivalentTo(new List<string> { "second", "eighth", "fourth", "sixth", "first", "third", "seventh", "ninth" }));
Assert.That(values, Is.EquivalentTo(new List<string> { "top", "bottom", "left", "right", "topLeft", "topRight", "bottomLeft", "bottomRight" }));
}

[Test]
Expand All @@ -160,7 +160,7 @@ public void ExerciseNearLocatorWithCssSelector()
// 5-8. Diagonally close (pythagoras sorting, with top row first
// because of DOM insertion order)
var values = seen.Select(element => element.GetDomAttribute("id"));
Assert.That(values, Is.EquivalentTo(new List<string> { "second", "eighth", "fourth", "sixth", "first", "third", "seventh", "ninth" }));
Assert.That(values, Is.EquivalentTo(new List<string> { "top", "bottom", "left", "right", "topLeft", "topRight", "bottomLeft", "bottomRight" }));
}

[Test]
Expand Down Expand Up @@ -218,11 +218,11 @@ public void NearLocatorShouldNotFindFarElements()
{
driver.Url = (EnvironmentManager.Instance.UrlBuilder.WhereIs("relative_locators.html"));

var rect3 = driver.FindElement(By.Id("rect3"));
var rect = driver.FindElement(By.Id("rect1"));

Assert.That(() =>
{
var rect2 = driver.FindElement(RelativeBy.WithLocator(By.Id("rect4")).Near(rect3));
var rect2 = driver.FindElement(RelativeBy.WithLocator(By.Id("rect4")).Near(rect));

}, Throws.TypeOf<NoSuchElementException>().With.Message.EqualTo("Unable to find element; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception"));
}
Expand Down
44 changes: 44 additions & 0 deletions java/src/org/openqa/selenium/support/locators/RelativeLocator.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,50 @@ public RelativeBy toRightOf(By locator) {
return simpleDirection("right", locator);
}

public RelativeBy straightAbove(WebElement element) {
Require.nonNull("Element to search straight above of", element);
return simpleDirection("straightAbove", element);
}

public RelativeBy straightAbove(By locator) {
Require.nonNull("Locator", locator);
assertLocatorCanBeSerialized(locator);
return simpleDirection("straightAbove", locator);
}

public RelativeBy straightBelow(WebElement element) {
Require.nonNull("Element to search straight below of", element);
return simpleDirection("straightBelow", element);
}

public RelativeBy straightBelow(By locator) {
Require.nonNull("Locator", locator);
assertLocatorCanBeSerialized(locator);
return simpleDirection("straightBelow", locator);
}

public RelativeBy straightLeftOf(WebElement element) {
Require.nonNull("Element to search straight to the left of", element);
return simpleDirection("straightLeft", element);
}

public RelativeBy straightLeftOf(By locator) {
Require.nonNull("Locator", locator);
assertLocatorCanBeSerialized(locator);
return simpleDirection("straightLeft", locator);
}

public RelativeBy straightRightOf(WebElement element) {
Require.nonNull("Element to search straight to the right of", element);
return simpleDirection("straightRight", element);
}

public RelativeBy straightRightOf(By locator) {
Require.nonNull("Locator", locator);
assertLocatorCanBeSerialized(locator);
return simpleDirection("straightRight", locator);
}

public RelativeBy near(WebElement element) {
Require.nonNull("Element to search near", element);
return near(element, CLOSE_IN_PIXELS);
Expand Down
Loading

0 comments on commit 960ff05

Please sign in to comment.