Skip to content

Commit 6449881

Browse files
committed
Allow the remote server to handle relative locators
This avoids the need to send a large amount of JS across the wire, and should make using the relative locators with the Selenium server more efficient.
1 parent 2835393 commit 6449881

File tree

7 files changed

+137
-21
lines changed

7 files changed

+137
-21
lines changed

java/src/org/openqa/selenium/support/locators/BUILD.bazel

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ java_library(
1313
"//java/test/org/openqa/selenium/support/locators:__pkg__",
1414
],
1515
deps = [
16-
"//java/src/org/openqa/selenium:core",
16+
"//java:auto-service",
1717
"//java/src/org/openqa/selenium/json",
18+
"//java/src/org/openqa/selenium/remote",
1819
artifact("com.google.guava:guava"),
1920
],
2021
)

java/src/org/openqa/selenium/support/locators/RelativeLocator.java

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.util.Map;
3737

3838
import static org.openqa.selenium.json.Json.MAP_TYPE;
39+
import static org.openqa.selenium.support.locators.RelativeLocatorScript.FIND_ELEMENTS;
3940

4041
/**
4142
* Used for finding elements by their location on a page, rather than their
@@ -71,23 +72,6 @@
7172
public class RelativeLocator {
7273

7374
private static final Json JSON = new Json();
74-
private static final String FIND_ELEMENTS;
75-
76-
static {
77-
try {
78-
String location = String.format(
79-
"/%s/%s",
80-
RelativeLocator.class.getPackage().getName().replace(".", "/"),
81-
"findElements.js");
82-
83-
URL url = RelativeLocator.class.getResource(location);
84-
85-
String rawFunction = Resources.toString(url, StandardCharsets.UTF_8);
86-
FIND_ELEMENTS = String.format("return (%s).apply(null, arguments);", rawFunction);
87-
} catch (IOException e) {
88-
throw new UncheckedIOException(e);
89-
}
90-
}
9175

9276
private static final int CLOSE_IN_PIXELS = 100;
9377

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium.support.locators;
19+
20+
import com.google.common.io.Resources;
21+
22+
import java.io.IOException;
23+
import java.io.UncheckedIOException;
24+
import java.net.URL;
25+
import java.nio.charset.StandardCharsets;
26+
27+
class RelativeLocatorScript {
28+
29+
static final String FIND_ELEMENTS;
30+
31+
static {
32+
try {
33+
String location = String.format(
34+
"/%s/%s",
35+
RelativeLocator.class.getPackage().getName().replace(".", "/"),
36+
"findElements.js");
37+
38+
URL url = RelativeLocator.class.getResource(location);
39+
40+
String rawFunction = Resources.toString(url, StandardCharsets.UTF_8);
41+
FIND_ELEMENTS = String.format("return (%s).apply(null, arguments);", rawFunction);
42+
} catch (IOException e) {
43+
throw new UncheckedIOException(e);
44+
}
45+
}
46+
47+
private RelativeLocatorScript() {
48+
// Utility class.
49+
}
50+
51+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium.support.locators;
19+
20+
import com.google.auto.service.AutoService;
21+
import com.google.common.collect.ImmutableMap;
22+
import org.openqa.selenium.By;
23+
import org.openqa.selenium.InvalidArgumentException;
24+
import org.openqa.selenium.JavascriptExecutor;
25+
import org.openqa.selenium.SearchContext;
26+
import org.openqa.selenium.WebDriver;
27+
import org.openqa.selenium.WebElement;
28+
import org.openqa.selenium.internal.Require;
29+
import org.openqa.selenium.remote.JsonToWebElementConverter;
30+
import org.openqa.selenium.remote.RemoteWebDriver;
31+
import org.openqa.selenium.remote.locators.CustomLocator;
32+
33+
import java.util.List;
34+
35+
import static org.openqa.selenium.support.locators.RelativeLocatorScript.FIND_ELEMENTS;
36+
37+
@AutoService(CustomLocator.class)
38+
public class RelativeLocatorServerSide implements CustomLocator {
39+
@Override
40+
public String getLocatorName() {
41+
return "relative";
42+
}
43+
44+
@Override
45+
public By createBy(Object usingParameter) {
46+
Require.nonNull("Using", usingParameter);
47+
return new RemoteRelative(usingParameter);
48+
}
49+
50+
private static class RemoteRelative extends By {
51+
private final Object using;
52+
53+
private RemoteRelative(Object usingParameter) {
54+
using = usingParameter;
55+
}
56+
57+
@Override
58+
public List<WebElement> findElements(SearchContext context) {
59+
JavascriptExecutor js = getJavascriptExecutor(context);
60+
61+
WebDriver driver = getWebDriver(context);
62+
63+
if (driver instanceof RemoteWebDriver) {
64+
Object converted = new JsonToWebElementConverter((RemoteWebDriver) driver).apply(using);
65+
66+
@SuppressWarnings("unchecked")
67+
List<WebElement> elements = (List<WebElement>) js.executeScript(FIND_ELEMENTS, ImmutableMap.of("relative", converted));
68+
return elements;
69+
}
70+
71+
throw new InvalidArgumentException("Unable to find element");
72+
}
73+
}
74+
}

java/test/org/openqa/selenium/chrome/BUILD.bazel

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ java_selenium_test_suite(
2323
artifact("org.mockito:mockito-core"),
2424
],
2525
javacopts = [
26-
"--release",
27-
"11",
28-
],
26+
"--release",
27+
"11",
28+
],
2929
)

java/test/org/openqa/selenium/support/locators/BUILD.bazel

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ java_selenium_test_suite(
1010
"--release",
1111
"11",
1212
],
13+
tags = [
14+
"selenium-remote",
15+
],
1316
deps = [
1417
"//java/src/org/openqa/selenium:core",
1518
"//java/src/org/openqa/selenium/remote",

java/test/org/openqa/selenium/support/locators/RelativeLocatorTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@
1919

2020
import org.junit.Test;
2121
import org.openqa.selenium.By;
22+
import org.openqa.selenium.ImmutableCapabilities;
23+
import org.openqa.selenium.WebDriver;
2224
import org.openqa.selenium.WebElement;
2325
import org.openqa.selenium.environment.webserver.Page;
26+
import org.openqa.selenium.remote.RemoteWebDriver;
2427
import org.openqa.selenium.testing.JUnit4TestBase;
2528

2629
import java.util.List;

0 commit comments

Comments
 (0)