From 32b433f598d943a997cc8c63d92cab7c663a8217 Mon Sep 17 00:00:00 2001 From: JustasMonkev Date: Fri, 12 Mar 2021 19:15:30 +0200 Subject: [PATCH 1/2] added new methods for RelativeBy(withXpath,withCssSelector) and added tests for these methods --- .../support/locators/RelativeLocator.java | 12 +++ .../support/locators/RelativeLocatorTest.java | 87 ++++++++++++++++++- 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/java/client/src/org/openqa/selenium/support/locators/RelativeLocator.java b/java/client/src/org/openqa/selenium/support/locators/RelativeLocator.java index 88e41d37da25d..221e0834b5f69 100644 --- a/java/client/src/org/openqa/selenium/support/locators/RelativeLocator.java +++ b/java/client/src/org/openqa/selenium/support/locators/RelativeLocator.java @@ -72,6 +72,7 @@ public class RelativeLocator { private static final Json JSON = new Json(); private static final String FIND_ELEMENTS; + static { try { String location = String.format( @@ -87,6 +88,7 @@ public class RelativeLocator { throw new UncheckedIOException(e); } } + private static final int CLOSE_IN_PIXELS = 100; /** @@ -97,6 +99,16 @@ public static RelativeBy withTagName(String tagName) { return new RelativeBy(By.tagName(tagName)); } + public static RelativeBy withXpath(String xpathExpression) { + Require.nonNull("xpath to look for", xpathExpression); + return new RelativeBy(By.xpath(xpathExpression)); + } + + public static RelativeBy withCssSelector(String cssSelector) { + Require.nonNull("css selector to look for", cssSelector); + return new RelativeBy(By.cssSelector(cssSelector)); + } + public static class RelativeBy extends By implements By.Remotable { private final Object root; private final List> filters; diff --git a/java/client/test/org/openqa/selenium/support/locators/RelativeLocatorTest.java b/java/client/test/org/openqa/selenium/support/locators/RelativeLocatorTest.java index c43eb9e7f4fd2..28e6158888a9a 100644 --- a/java/client/test/org/openqa/selenium/support/locators/RelativeLocatorTest.java +++ b/java/client/test/org/openqa/selenium/support/locators/RelativeLocatorTest.java @@ -28,11 +28,14 @@ import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.openqa.selenium.support.locators.RelativeLocator.withTagName; +import static org.openqa.selenium.support.locators.RelativeLocator.withXpath; +import static org.openqa.selenium.support.locators.RelativeLocator.withCssSelector; + public class RelativeLocatorTest extends JUnit4TestBase { @Test - public void shouldBeAbleToFindElementsAboveAnother() { + public void shouldBeAbleToFindElementsAboveAnotherWithTagName() { driver.get(appServer.whereIs("relative_locators.html")); WebElement lowest = driver.findElement(By.id("below")); @@ -43,6 +46,30 @@ public void shouldBeAbleToFindElementsAboveAnother() { assertThat(ids).containsExactly("mid", "above"); } + @Test + public void shouldBeAbleToFindElementsAboveAnotherWithXpath() { + driver.get(appServer.whereIs("relative_locators.html")); + + WebElement lowest = driver.findElement(By.id("below")); + + List elements = driver.findElements(withXpath("//p").above(lowest)); + List ids = elements.stream().map(e -> e.getAttribute("id")).collect(Collectors.toList()); + + assertThat(ids).containsExactly("mid", "above"); + } + + @Test + public void shouldBeAbleToFindElementsAboveAnotherwithCssSelector() { + driver.get(appServer.whereIs("relative_locators.html")); + + WebElement lowest = driver.findElement(By.id("below")); + + List elements = driver.findElements(withCssSelector("p").above(lowest)); + List ids = elements.stream().map(e -> e.getAttribute("id")).collect(Collectors.toList()); + + assertThat(ids).containsExactly("mid", "above"); + } + @Test public void shouldBeAbleToCombineFilters() { driver.get(appServer.whereIs("relative_locators.html")); @@ -54,11 +81,67 @@ public void shouldBeAbleToCombineFilters() { } @Test - public void exerciseNearLocator() { + public void shouldBeAbleToCombineFiltersWithXpath() { + driver.get(appServer.whereIs("relative_locators.html")); + + List seen = driver.findElements(withXpath("//td").above(By.id("center")).toRightOf(By.id("second"))); + + List ids = seen.stream().map(e -> e.getAttribute("id")).collect(Collectors.toList()); + assertThat(ids).containsExactly("third"); + } + + @Test + public void shouldBeAbleToCombineFiltersWithCssSelector() { + driver.get(appServer.whereIs("relative_locators.html")); + + List seen = driver.findElements(withCssSelector("td").above(By.id("center")).toRightOf(By.id("second"))); + + List ids = seen.stream().map(e -> e.getAttribute("id")).collect(Collectors.toList()); + assertThat(ids).containsExactly("third"); + } + + @Test + public void exerciseNearLocatorWithTagName() { driver.get(appServer.whereIs("relative_locators.html")); List seen = driver.findElements(withTagName("td").near(By.id("center"))); + // Elements are sorted by proximity and then DOM insertion order. + // Proximity is determined using distance from center points, so + // we expect the order to be: + // 1. Directly above (short vertical distance, first in DOM) + // 2. Directly below (short vertical distance, later in DOM) + // 3. Directly left (slight longer distance horizontally, first in DOM) + // 4. Directly right (slight longer distance horizontally, later in DOM) + // 5-8. Diagonally close (pythagorus sorting, with top row first + // because of DOM insertion order) + List ids = seen.stream().map(e -> e.getAttribute("id")).collect(Collectors.toList()); + assertThat(ids).containsExactly("second", "eighth", "fourth", "sixth", "first", "third", "seventh", "ninth"); + } + @Test + public void exerciseNearLocatorWithXpath() { + driver.get(appServer.whereIs("relative_locators.html")); + + List seen = driver.findElements(withXpath("//td").near(By.id("center"))); + + // Elements are sorted by proximity and then DOM insertion order. + // Proximity is determined using distance from center points, so + // we expect the order to be: + // 1. Directly above (short vertical distance, first in DOM) + // 2. Directly below (short vertical distance, later in DOM) + // 3. Directly left (slight longer distance horizontally, first in DOM) + // 4. Directly right (slight longer distance horizontally, later in DOM) + // 5-8. Diagonally close (pythagorus sorting, with top row first + // because of DOM insertion order) + List ids = seen.stream().map(e -> e.getAttribute("id")).collect(Collectors.toList()); + assertThat(ids).containsExactly("second", "eighth", "fourth", "sixth", "first", "third", "seventh", "ninth"); + } + @Test + public void exerciseNearLocatorWithCssSelector() { + driver.get(appServer.whereIs("relative_locators.html")); + + List seen = driver.findElements(withCssSelector("td").near(By.id("center"))); + // Elements are sorted by proximity and then DOM insertion order. // Proximity is determined using distance from center points, so // we expect the order to be: From 7a0191900acb60c31bf253ce77de44c8010eb14e Mon Sep 17 00:00:00 2001 From: JustasMonkev Date: Sat, 20 Mar 2021 19:01:33 +0200 Subject: [PATCH 2/2] updates regarding shs96c comments --- .../support/locators/RelativeLocator.java | 20 ++++++---- .../support/locators/RelativeLocatorTest.java | 37 ++++++++++++------- 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/java/client/src/org/openqa/selenium/support/locators/RelativeLocator.java b/java/client/src/org/openqa/selenium/support/locators/RelativeLocator.java index 221e0834b5f69..2af069e4f0e68 100644 --- a/java/client/src/org/openqa/selenium/support/locators/RelativeLocator.java +++ b/java/client/src/org/openqa/selenium/support/locators/RelativeLocator.java @@ -94,19 +94,25 @@ public class RelativeLocator { /** * Start of a relative locator, finding elements by tag name. */ - public static RelativeBy withTagName(String tagName) { + + public static RelativeBy with(By by) { + Require.nonNull("By to look for", by); + return new RelativeBy(by); + } + + public static By tagName(String tagName) { Require.nonNull("Tag name to look for", tagName); - return new RelativeBy(By.tagName(tagName)); + return By.tagName(tagName); } - public static RelativeBy withXpath(String xpathExpression) { + public static By xpath(String xpathExpression) { Require.nonNull("xpath to look for", xpathExpression); - return new RelativeBy(By.xpath(xpathExpression)); + return By.xpath(xpathExpression); } - public static RelativeBy withCssSelector(String cssSelector) { - Require.nonNull("css selector to look for", cssSelector); - return new RelativeBy(By.cssSelector(cssSelector)); + public static By cssSelector(String cssSelectorExpression) { + Require.nonNull("css selector to look for", cssSelectorExpression); + return By.cssSelector(cssSelectorExpression); } public static class RelativeBy extends By implements By.Remotable { diff --git a/java/client/test/org/openqa/selenium/support/locators/RelativeLocatorTest.java b/java/client/test/org/openqa/selenium/support/locators/RelativeLocatorTest.java index 28e6158888a9a..95f1db0470ce1 100644 --- a/java/client/test/org/openqa/selenium/support/locators/RelativeLocatorTest.java +++ b/java/client/test/org/openqa/selenium/support/locators/RelativeLocatorTest.java @@ -40,22 +40,24 @@ public void shouldBeAbleToFindElementsAboveAnotherWithTagName() { WebElement lowest = driver.findElement(By.id("below")); - List elements = driver.findElements(withTagName("p").above(lowest)); + List elements = driver.findElements(with(tagName("p")).above(lowest)); List ids = elements.stream().map(e -> e.getAttribute("id")).collect(Collectors.toList()); assertThat(ids).containsExactly("mid", "above"); + } @Test public void shouldBeAbleToFindElementsAboveAnotherWithXpath() { driver.get(appServer.whereIs("relative_locators.html")); - WebElement lowest = driver.findElement(By.id("below")); + WebElement lowest = driver.findElement(By.id("seventh")); - List elements = driver.findElements(withXpath("//p").above(lowest)); - List ids = elements.stream().map(e -> e.getAttribute("id")).collect(Collectors.toList()); + List seen = driver.findElements(with(xpath("//td[1]")).above(lowest)); - assertThat(ids).containsExactly("mid", "above"); + List ids = seen.stream().map(e -> e.getAttribute("id")).collect(Collectors.toList()); + + assertThat(ids).containsExactly("fourth", "first"); } @Test @@ -64,19 +66,21 @@ public void shouldBeAbleToFindElementsAboveAnotherwithCssSelector() { WebElement lowest = driver.findElement(By.id("below")); - List elements = driver.findElements(withCssSelector("p").above(lowest)); + List elements = driver.findElements(with(cssSelector("p")).above(lowest)); List ids = elements.stream().map(e -> e.getAttribute("id")).collect(Collectors.toList()); assertThat(ids).containsExactly("mid", "above"); + } @Test public void shouldBeAbleToCombineFilters() { driver.get(appServer.whereIs("relative_locators.html")); - List seen = driver.findElements(withTagName("td").above(By.id("center")).toRightOf(By.id("second"))); + List seen = driver.findElements(with(tagName("td")).above(By.id("center")).toRightOf(By.id("second"))); List ids = seen.stream().map(e -> e.getAttribute("id")).collect(Collectors.toList()); + assertThat(ids).containsExactly("third"); } @@ -84,19 +88,23 @@ public void shouldBeAbleToCombineFilters() { public void shouldBeAbleToCombineFiltersWithXpath() { driver.get(appServer.whereIs("relative_locators.html")); - List seen = driver.findElements(withXpath("//td").above(By.id("center")).toRightOf(By.id("second"))); + List seen = driver.findElements(with(xpath("//td[1]")).below(By.id("second")).above(By.id("seventh"))); List ids = seen.stream().map(e -> e.getAttribute("id")).collect(Collectors.toList()); - assertThat(ids).containsExactly("third"); + + assertThat(ids).containsExactly("fourth"); + } @Test public void shouldBeAbleToCombineFiltersWithCssSelector() { driver.get(appServer.whereIs("relative_locators.html")); - List seen = driver.findElements(withCssSelector("td").above(By.id("center")).toRightOf(By.id("second"))); + + List seen = driver.findElements(with(cssSelector("td")).above(By.id("center")).toRightOf(By.id("second"))); List ids = seen.stream().map(e -> e.getAttribute("id")).collect(Collectors.toList()); + assertThat(ids).containsExactly("third"); } @@ -104,7 +112,7 @@ public void shouldBeAbleToCombineFiltersWithCssSelector() { public void exerciseNearLocatorWithTagName() { driver.get(appServer.whereIs("relative_locators.html")); - List seen = driver.findElements(withTagName("td").near(By.id("center"))); + List seen = driver.findElements(with(tagName("td")).near(By.id("center"))); // Elements are sorted by proximity and then DOM insertion order. // Proximity is determined using distance from center points, so @@ -118,11 +126,12 @@ public void exerciseNearLocatorWithTagName() { List ids = seen.stream().map(e -> e.getAttribute("id")).collect(Collectors.toList()); assertThat(ids).containsExactly("second", "eighth", "fourth", "sixth", "first", "third", "seventh", "ninth"); } + @Test public void exerciseNearLocatorWithXpath() { driver.get(appServer.whereIs("relative_locators.html")); - List seen = driver.findElements(withXpath("//td").near(By.id("center"))); + List seen = driver.findElements(with(xpath("//td")).near(By.id("center"))); // Elements are sorted by proximity and then DOM insertion order. // Proximity is determined using distance from center points, so @@ -134,13 +143,15 @@ public void exerciseNearLocatorWithXpath() { // 5-8. Diagonally close (pythagorus sorting, with top row first // because of DOM insertion order) List ids = seen.stream().map(e -> e.getAttribute("id")).collect(Collectors.toList()); + assertThat(ids).containsExactly("second", "eighth", "fourth", "sixth", "first", "third", "seventh", "ninth"); } + @Test public void exerciseNearLocatorWithCssSelector() { driver.get(appServer.whereIs("relative_locators.html")); - List seen = driver.findElements(withCssSelector("td").near(By.id("center"))); + List seen = driver.findElements(with(cssSelector("td")).near(By.id("center"))); // Elements are sorted by proximity and then DOM insertion order. // Proximity is determined using distance from center points, so