diff --git a/java/src/org/openqa/selenium/support/locators/BUILD.bazel b/java/src/org/openqa/selenium/support/locators/BUILD.bazel index e264a867bcc45..76e4332a568d7 100644 --- a/java/src/org/openqa/selenium/support/locators/BUILD.bazel +++ b/java/src/org/openqa/selenium/support/locators/BUILD.bazel @@ -13,8 +13,9 @@ java_library( "//java/test/org/openqa/selenium/support/locators:__pkg__", ], deps = [ - "//java/src/org/openqa/selenium:core", + "//java:auto-service", "//java/src/org/openqa/selenium/json", + "//java/src/org/openqa/selenium/remote", artifact("com.google.guava:guava"), ], ) diff --git a/java/src/org/openqa/selenium/support/locators/RelativeLocator.java b/java/src/org/openqa/selenium/support/locators/RelativeLocator.java index 1a6bab893d639..8018a38199a09 100644 --- a/java/src/org/openqa/selenium/support/locators/RelativeLocator.java +++ b/java/src/org/openqa/selenium/support/locators/RelativeLocator.java @@ -36,6 +36,7 @@ import java.util.Map; import static org.openqa.selenium.json.Json.MAP_TYPE; +import static org.openqa.selenium.support.locators.RelativeLocatorScript.FIND_ELEMENTS; /** * Used for finding elements by their location on a page, rather than their @@ -71,23 +72,6 @@ public class RelativeLocator { private static final Json JSON = new Json(); - private static final String FIND_ELEMENTS; - - static { - try { - String location = String.format( - "/%s/%s", - RelativeLocator.class.getPackage().getName().replace(".", "/"), - "findElements.js"); - - URL url = RelativeLocator.class.getResource(location); - - String rawFunction = Resources.toString(url, StandardCharsets.UTF_8); - FIND_ELEMENTS = String.format("return (%s).apply(null, arguments);", rawFunction); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } private static final int CLOSE_IN_PIXELS = 100; diff --git a/java/src/org/openqa/selenium/support/locators/RelativeLocatorScript.java b/java/src/org/openqa/selenium/support/locators/RelativeLocatorScript.java new file mode 100644 index 0000000000000..c2bb465cefaba --- /dev/null +++ b/java/src/org/openqa/selenium/support/locators/RelativeLocatorScript.java @@ -0,0 +1,51 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.openqa.selenium.support.locators; + +import com.google.common.io.Resources; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; + +class RelativeLocatorScript { + + static final String FIND_ELEMENTS; + + static { + try { + String location = String.format( + "/%s/%s", + RelativeLocator.class.getPackage().getName().replace(".", "/"), + "findElements.js"); + + URL url = RelativeLocator.class.getResource(location); + + String rawFunction = Resources.toString(url, StandardCharsets.UTF_8); + FIND_ELEMENTS = String.format("return (%s).apply(null, arguments);", rawFunction); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private RelativeLocatorScript() { + // Utility class. + } + +} diff --git a/java/src/org/openqa/selenium/support/locators/RelativeLocatorServerSide.java b/java/src/org/openqa/selenium/support/locators/RelativeLocatorServerSide.java new file mode 100644 index 0000000000000..dac168044646f --- /dev/null +++ b/java/src/org/openqa/selenium/support/locators/RelativeLocatorServerSide.java @@ -0,0 +1,74 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.openqa.selenium.support.locators; + +import com.google.auto.service.AutoService; +import com.google.common.collect.ImmutableMap; +import org.openqa.selenium.By; +import org.openqa.selenium.InvalidArgumentException; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.SearchContext; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.internal.Require; +import org.openqa.selenium.remote.JsonToWebElementConverter; +import org.openqa.selenium.remote.RemoteWebDriver; +import org.openqa.selenium.remote.locators.CustomLocator; + +import java.util.List; + +import static org.openqa.selenium.support.locators.RelativeLocatorScript.FIND_ELEMENTS; + +@AutoService(CustomLocator.class) +public class RelativeLocatorServerSide implements CustomLocator { + @Override + public String getLocatorName() { + return "relative"; + } + + @Override + public By createBy(Object usingParameter) { + Require.nonNull("Using", usingParameter); + return new RemoteRelative(usingParameter); + } + + private static class RemoteRelative extends By { + private final Object using; + + private RemoteRelative(Object usingParameter) { + using = usingParameter; + } + + @Override + public List findElements(SearchContext context) { + JavascriptExecutor js = getJavascriptExecutor(context); + + WebDriver driver = getWebDriver(context); + + if (driver instanceof RemoteWebDriver) { + Object converted = new JsonToWebElementConverter((RemoteWebDriver) driver).apply(using); + + @SuppressWarnings("unchecked") + List elements = (List) js.executeScript(FIND_ELEMENTS, ImmutableMap.of("relative", converted)); + return elements; + } + + throw new InvalidArgumentException("Unable to find element"); + } + } +} diff --git a/java/test/org/openqa/selenium/chrome/BUILD.bazel b/java/test/org/openqa/selenium/chrome/BUILD.bazel index 271f0d990bc08..e5a8542df5ac6 100644 --- a/java/test/org/openqa/selenium/chrome/BUILD.bazel +++ b/java/test/org/openqa/selenium/chrome/BUILD.bazel @@ -23,7 +23,7 @@ java_selenium_test_suite( artifact("org.mockito:mockito-core"), ], javacopts = [ - "--release", - "11", - ], + "--release", + "11", + ], ) diff --git a/java/test/org/openqa/selenium/support/locators/BUILD.bazel b/java/test/org/openqa/selenium/support/locators/BUILD.bazel index a94fbbdcd9aa2..7d94004a554e9 100644 --- a/java/test/org/openqa/selenium/support/locators/BUILD.bazel +++ b/java/test/org/openqa/selenium/support/locators/BUILD.bazel @@ -10,6 +10,9 @@ java_selenium_test_suite( "--release", "11", ], + tags = [ + "selenium-remote", + ], deps = [ "//java/src/org/openqa/selenium:core", "//java/src/org/openqa/selenium/remote", diff --git a/java/test/org/openqa/selenium/support/locators/RelativeLocatorTest.java b/java/test/org/openqa/selenium/support/locators/RelativeLocatorTest.java index f782f521ae1e2..f5704492b1243 100644 --- a/java/test/org/openqa/selenium/support/locators/RelativeLocatorTest.java +++ b/java/test/org/openqa/selenium/support/locators/RelativeLocatorTest.java @@ -19,8 +19,11 @@ import org.junit.Test; import org.openqa.selenium.By; +import org.openqa.selenium.ImmutableCapabilities; +import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.environment.webserver.Page; +import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.testing.JUnit4TestBase; import java.util.List;