From 72e3a61001af990eafe607e719ed5b21f82671c0 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 18 Jul 2024 13:30:21 +0700 Subject: [PATCH 1/2] [java] custom duration for Actions constructor (#14085) Co-authored-by: Titus Fortner Co-authored-by: Puja Jagani --- .../openqa/selenium/interactions/Actions.java | 16 +++- .../interactions/ActionDurationTest.java | 82 +++++++++++++++++++ 2 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 java/test/org/openqa/selenium/interactions/ActionDurationTest.java diff --git a/java/src/org/openqa/selenium/interactions/Actions.java b/java/src/org/openqa/selenium/interactions/Actions.java index bdec7bf3b94e3..ac6671e75d978 100644 --- a/java/src/org/openqa/selenium/interactions/Actions.java +++ b/java/src/org/openqa/selenium/interactions/Actions.java @@ -54,9 +54,15 @@ public class Actions { private PointerInput activePointer; private KeyInput activeKeyboard; private WheelInput activeWheel; + private Duration actionDuration; public Actions(WebDriver driver) { + this(driver, Duration.ofMillis(250)); + } + + public Actions(WebDriver driver, Duration duration) { this.driver = Require.nonNull("Driver", driver); + this.actionDuration = duration; } /** @@ -215,7 +221,7 @@ public Actions release(WebElement target) { */ public Actions scrollToElement(WebElement element) { WheelInput.ScrollOrigin scrollOrigin = WheelInput.ScrollOrigin.fromElement(element); - return tick(getActiveWheel().createScroll(0, 0, 0, 0, Duration.ofMillis(250), scrollOrigin)); + return tick(getActiveWheel().createScroll(0, 0, 0, 0, this.actionDuration, scrollOrigin)); } /** @@ -229,7 +235,7 @@ public Actions scrollToElement(WebElement element) { public Actions scrollByAmount(int deltaX, int deltaY) { WheelInput.ScrollOrigin scrollOrigin = WheelInput.ScrollOrigin.fromViewport(); return tick( - getActiveWheel().createScroll(0, 0, deltaX, deltaY, Duration.ofMillis(250), scrollOrigin)); + getActiveWheel().createScroll(0, 0, deltaX, deltaY, this.actionDuration, scrollOrigin)); } /** @@ -249,7 +255,7 @@ public Actions scrollFromOrigin(WheelInput.ScrollOrigin scrollOrigin, int deltaX int x = scrollOrigin.getxOffset(); int y = scrollOrigin.getyOffset(); return tick( - getActiveWheel().createScroll(x, y, deltaX, deltaY, Duration.ofMillis(250), scrollOrigin)); + getActiveWheel().createScroll(x, y, deltaX, deltaY, this.actionDuration, scrollOrigin)); } /** @@ -548,6 +554,10 @@ public WheelInput getActiveWheel() { return this.activeWheel; } + public Duration getActionDuration() { + return this.actionDuration; + } + /** * Generates a composite action containing all actions so far, ready to be performed (and resets * the internal builder state, so subsequent calls to this method will contain fresh sequences). diff --git a/java/test/org/openqa/selenium/interactions/ActionDurationTest.java b/java/test/org/openqa/selenium/interactions/ActionDurationTest.java new file mode 100644 index 0000000000000..f9d603390eedf --- /dev/null +++ b/java/test/org/openqa/selenium/interactions/ActionDurationTest.java @@ -0,0 +1,82 @@ +// 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.interactions; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.Duration; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.testing.JupiterTestBase; + +@Tag("UnitTests") +class ActionDurationTest extends JupiterTestBase { + @Test + void shouldScrollToElementWithCustomDuration() { + driver.get( + appServer.whereIs("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html")); + WebElement iframe = driver.findElement(By.tagName("iframe")); + + assertFalse(inViewport(iframe)); + + new Actions(driver, Duration.ofMillis(111)).scrollToElement(iframe).perform(); + + assertTrue(inViewport(iframe)); + } + + @Test + void shouldScrollFromViewportByGivenAmountWithCustomDuration() { + driver.get( + appServer.whereIs("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html")); + WebElement footer = driver.findElement(By.tagName("footer")); + int deltaY = footer.getRect().y; + + new Actions(driver, Duration.ofMillis(111)).scrollByAmount(0, deltaY).perform(); + + assertTrue(inViewport(footer)); + } + + @Test + void shouldBeDefaultActionDuration250ms() { + Actions actions = new Actions(driver); + assertEquals(Duration.ofMillis(250), actions.getActionDuration()); + } + + @Test + void shouldBeCustomDuration110ms() { + Actions actions = new Actions(driver, Duration.ofMillis(110)); + assertEquals(Duration.ofMillis(110), actions.getActionDuration()); + } + + private boolean inViewport(WebElement element) { + + String script = + "for(var e=arguments[0],f=e.offsetTop,t=e.offsetLeft,o=e.offsetWidth,n=e.offsetHeight;\n" + + "e.offsetParent;)f+=(e=e.offsetParent).offsetTop,t+=e.offsetLeft;\n" + + "return" + + " f\n" + + "window.pageYOffset&&t+o>window.pageXOffset"; + + return (boolean) ((JavascriptExecutor) driver).executeScript(script, element); + } +} From f3724e661adb896a11160bb0816a42ce60df6916 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 18 Jul 2024 14:10:09 +0700 Subject: [PATCH 2/2] [java] Consistent UTF-8 Encoding and Code Enhancements (#14218) * made the use of UTF8 encoding consistent throughout * replaced for loop with enchanced for in DockerOptions * removed unnecessary unboxing in test noErrorNoCry * applied format.sh --------- Co-authored-by: Diego Molina --- .../distributor/local/LocalDistributor.java | 6 +--- .../grid/node/docker/DockerOptions.java | 4 +-- java/src/org/openqa/selenium/net/Urls.java | 8 ++--- .../selenium/remote/http/FormEncodedData.java | 2 +- .../org/openqa/selenium/ReferrerTest.java | 7 +--- .../selenium/docker/v1_41/ListImagesTest.java | 34 ++++++++----------- .../org/openqa/selenium/grid/MainTest.java | 7 +--- .../codec/w3c/W3CHttpResponseCodecTest.java | 2 +- .../remote/http/FormEncodedDataTest.java | 15 +++----- 9 files changed, 29 insertions(+), 56 deletions(-) diff --git a/java/src/org/openqa/selenium/grid/distributor/local/LocalDistributor.java b/java/src/org/openqa/selenium/grid/distributor/local/LocalDistributor.java index aacb21ec965c8..01eded126079d 100644 --- a/java/src/org/openqa/selenium/grid/distributor/local/LocalDistributor.java +++ b/java/src/org/openqa/selenium/grid/distributor/local/LocalDistributor.java @@ -878,11 +878,7 @@ protected Node getNodeFromURI(URI uri) { model.getSnapshot().stream() .filter(node -> node.getExternalUri().equals(uri)) .findFirst(); - if (nodeStatus.isPresent()) { - return nodes.get(nodeStatus.get().getNodeId()); - } else { - return null; - } + return nodeStatus.map(status -> nodes.get(status.getNodeId())).orElse(null); } finally { readLock.unlock(); } diff --git a/java/src/org/openqa/selenium/grid/node/docker/DockerOptions.java b/java/src/org/openqa/selenium/grid/node/docker/DockerOptions.java index d5bff8e52725b..8c752c8ae39fd 100644 --- a/java/src/org/openqa/selenium/grid/node/docker/DockerOptions.java +++ b/java/src/org/openqa/selenium/grid/node/docker/DockerOptions.java @@ -207,8 +207,8 @@ protected List getDevicesMapping() { config.getAll(DOCKER_SECTION, "devices").orElseGet(Collections::emptyList); List deviceMapping = new ArrayList<>(); - for (int i = 0; i < devices.size(); i++) { - String deviceMappingDefined = devices.get(i).trim(); + for (String device : devices) { + String deviceMappingDefined = device.trim(); Matcher matcher = linuxDeviceMappingWithDefaultPermissionsPattern.matcher(deviceMappingDefined); diff --git a/java/src/org/openqa/selenium/net/Urls.java b/java/src/org/openqa/selenium/net/Urls.java index 6aa6b1a40d6a2..3981aa4dbdb98 100644 --- a/java/src/org/openqa/selenium/net/Urls.java +++ b/java/src/org/openqa/selenium/net/Urls.java @@ -19,12 +19,12 @@ import java.io.IOException; import java.io.UncheckedIOException; -import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.regex.Pattern; import org.openqa.selenium.internal.Require; @@ -42,11 +42,7 @@ private Urls() { * @see URLEncoder#encode(java.lang.String, java.lang.String) */ public static String urlEncode(String value) { - try { - return URLEncoder.encode(value, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new UncheckedIOException(e); - } + return URLEncoder.encode(value, StandardCharsets.UTF_8); } public static URL fromUri(URI uri) { diff --git a/java/src/org/openqa/selenium/remote/http/FormEncodedData.java b/java/src/org/openqa/selenium/remote/http/FormEncodedData.java index f7adbd6c8ef45..7d920e23d4694 100644 --- a/java/src/org/openqa/selenium/remote/http/FormEncodedData.java +++ b/java/src/org/openqa/selenium/remote/http/FormEncodedData.java @@ -90,6 +90,6 @@ private static String read(Reader reader, Charset charSet, char delimiter, Atomi builder.append(c); } - return URLDecoder.decode(builder.toString(), charSet.toString()); + return URLDecoder.decode(builder.toString(), charSet); } } diff --git a/java/test/org/openqa/selenium/ReferrerTest.java b/java/test/org/openqa/selenium/ReferrerTest.java index 17e1a1f430e69..0fd58d08b02df 100644 --- a/java/test/org/openqa/selenium/ReferrerTest.java +++ b/java/test/org/openqa/selenium/ReferrerTest.java @@ -31,7 +31,6 @@ import com.google.common.net.HostAndPort; import java.io.IOException; import java.io.UncheckedIOException; -import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URLEncoder; import java.nio.file.Files; @@ -169,11 +168,7 @@ void basicHistoryNavigationWithADirectProxy() { } private static String encode(String url) { - try { - return URLEncoder.encode(url, UTF_8.name()); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException("UTF-8 should always be supported!", e); - } + return URLEncoder.encode(url, UTF_8); } private void performNavigation(WebDriver driver, String firstUrl) { diff --git a/java/test/org/openqa/selenium/docker/v1_41/ListImagesTest.java b/java/test/org/openqa/selenium/docker/v1_41/ListImagesTest.java index 6189290666d35..f84d0122f5f60 100644 --- a/java/test/org/openqa/selenium/docker/v1_41/ListImagesTest.java +++ b/java/test/org/openqa/selenium/docker/v1_41/ListImagesTest.java @@ -21,8 +21,8 @@ import static org.openqa.selenium.json.Json.MAP_TYPE; import static org.openqa.selenium.remote.http.Contents.utf8String; -import java.io.UnsupportedEncodingException; import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.Set; import org.junit.jupiter.api.Test; @@ -41,26 +41,22 @@ void shouldReturnImageIfTagIsPresent() { HttpHandler handler = req -> { String filters = req.getQueryParameter("filters"); - try { - String decoded = URLDecoder.decode(filters, "UTF-8"); - Map raw = new Json().toType(decoded, MAP_TYPE); + String decoded = URLDecoder.decode(filters, StandardCharsets.UTF_8); + Map raw = new Json().toType(decoded, MAP_TYPE); - Map rawRef = (Map) raw.get("reference"); - assertThat(rawRef.get("selenium/standalone-firefox:latest")).isEqualTo(true); + Map rawRef = (Map) raw.get("reference"); + assertThat(rawRef.get("selenium/standalone-firefox:latest")).isEqualTo(true); - return new HttpResponse() - .addHeader("Content-Type", "application/json") - .setContent( - utf8String( - "[{\"Containers\":-1,\"Created\":1581716253," - + "\"Id\":\"sha256:bc24341497a00a3afbf04c518cb4bf98834d933ae331d1c5d3cd6f52c079049e\"," - + "\"Labels\":{\"authors\":\"SeleniumHQ\"},\"ParentId\":\"\"," - + "\"RepoDigests\":null," - + "\"RepoTags\":[\"selenium/standalone-firefox:latest\"]," - + "\"SharedSize\":-1,\"Size\":765131593,\"VirtualSize\":765131593}]")); - } catch (UnsupportedEncodingException ignore) { - return null; - } + return new HttpResponse() + .addHeader("Content-Type", "application/json") + .setContent( + utf8String( + "[{\"Containers\":-1,\"Created\":1581716253," + + "\"Id\":\"sha256:bc24341497a00a3afbf04c518cb4bf98834d933ae331d1c5d3cd6f52c079049e\"," + + "\"Labels\":{\"authors\":\"SeleniumHQ\"},\"ParentId\":\"\"," + + "\"RepoDigests\":null," + + "\"RepoTags\":[\"selenium/standalone-firefox:latest\"]," + + "\"SharedSize\":-1,\"Size\":765131593,\"VirtualSize\":765131593}]")); }; Reference reference = Reference.parse("selenium/standalone-firefox:latest"); diff --git a/java/test/org/openqa/selenium/grid/MainTest.java b/java/test/org/openqa/selenium/grid/MainTest.java index 26558dcbc6086..aabe07c74d84c 100644 --- a/java/test/org/openqa/selenium/grid/MainTest.java +++ b/java/test/org/openqa/selenium/grid/MainTest.java @@ -21,7 +21,6 @@ import java.io.ByteArrayOutputStream; import java.io.PrintStream; -import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -38,11 +37,7 @@ public void init() { } private PrintStream toPrintStream(ByteArrayOutputStream baos) { - try { - return new PrintStream(baos, true, StandardCharsets.UTF_8.name()); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } + return new PrintStream(baos, true, StandardCharsets.UTF_8); } @Test diff --git a/java/test/org/openqa/selenium/remote/codec/w3c/W3CHttpResponseCodecTest.java b/java/test/org/openqa/selenium/remote/codec/w3c/W3CHttpResponseCodecTest.java index df480c356a99c..b7d1e846b1674 100644 --- a/java/test/org/openqa/selenium/remote/codec/w3c/W3CHttpResponseCodecTest.java +++ b/java/test/org/openqa/selenium/remote/codec/w3c/W3CHttpResponseCodecTest.java @@ -52,7 +52,7 @@ void noErrorNoCry() { Response decoded = new W3CHttpResponseCodec().decode(response); - assertThat(decoded.getStatus().intValue()).isEqualTo(ErrorCodes.SUCCESS); + assertThat(decoded.getStatus()).isEqualTo(ErrorCodes.SUCCESS); assertThat(decoded.getState()).isEqualTo("success"); assertThat(decoded.getValue()).isEqualTo("cheese"); } diff --git a/java/test/org/openqa/selenium/remote/http/FormEncodedDataTest.java b/java/test/org/openqa/selenium/remote/http/FormEncodedDataTest.java index e165f602ea2d1..063446a56c624 100644 --- a/java/test/org/openqa/selenium/remote/http/FormEncodedDataTest.java +++ b/java/test/org/openqa/selenium/remote/http/FormEncodedDataTest.java @@ -27,7 +27,6 @@ import com.google.common.collect.ImmutableMap; import com.google.common.net.MediaType; -import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Arrays; @@ -133,15 +132,11 @@ private HttpRequest createRequest(String key, String value, String... others) { if (!isFirst) { content.append("&"); } - try { - content.append(URLEncoder.encode(iterator.next(), UTF_8.toString())); - - String next = iterator.next(); - if (next != null) { - content.append("=").append(URLEncoder.encode(next, UTF_8.toString())); - } - } catch (UnsupportedEncodingException e) { - fail(e.getMessage()); + content.append(URLEncoder.encode(iterator.next(), UTF_8)); + + String next = iterator.next(); + if (next != null) { + content.append("=").append(URLEncoder.encode(next, UTF_8)); } if (isFirst) { isFirst = false;