From 86fd063330bf57786975f28af0c3b5d988c6a600 Mon Sep 17 00:00:00 2001 From: Sandeep Suryaprasad <26169602+sandeepsuryaprasad@users.noreply.github.com> Date: Thu, 2 May 2024 14:08:57 +0530 Subject: [PATCH 001/723] [py] removed unused logger object from `firefox/webdriver.py` (#13892) [py] removed unused logger object from firefox/webdriver.py Co-authored-by: Diego Molina --- py/selenium/webdriver/firefox/webdriver.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/py/selenium/webdriver/firefox/webdriver.py b/py/selenium/webdriver/firefox/webdriver.py index d048b01ea5c1d..c04c2d4a7b458 100644 --- a/py/selenium/webdriver/firefox/webdriver.py +++ b/py/selenium/webdriver/firefox/webdriver.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. import base64 -import logging import os import warnings import zipfile @@ -29,8 +28,6 @@ from .remote_connection import FirefoxRemoteConnection from .service import Service -logger = logging.getLogger(__name__) - class WebDriver(RemoteWebDriver): """Controls the GeckoDriver and allows you to drive the browser.""" From a0a39148452e35e8f4652ce29e2baba90b9a88d0 Mon Sep 17 00:00:00 2001 From: Diego Molina Date: Thu, 2 May 2024 10:57:01 +0200 Subject: [PATCH 002/723] [java] Improving logging to understand why "Value must be set" is raised. --- .../grid/node/config/DriverServiceSessionFactory.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/java/src/org/openqa/selenium/grid/node/config/DriverServiceSessionFactory.java b/java/src/org/openqa/selenium/grid/node/config/DriverServiceSessionFactory.java index b1ff2cec5b07f..7a803437b9c4a 100644 --- a/java/src/org/openqa/selenium/grid/node/config/DriverServiceSessionFactory.java +++ b/java/src/org/openqa/selenium/grid/node/config/DriverServiceSessionFactory.java @@ -33,6 +33,7 @@ import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; +import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Stream; import org.openqa.selenium.Capabilities; @@ -329,10 +330,11 @@ private Capabilities setBrowserBinary(Capabilities options, String browserPath) .setCapability(vendorOptionsCapability, vendorOptions) .setCapability("browserVersion", null); } catch (Exception e) { - LOG.warning( + LOG.log( + Level.WARNING, String.format( - "Exception while setting the browser binary path. %s: %s", - options, e.getMessage())); + "Exception while setting the browser binary path. Options: %s", options), + e); } } } From c114dbd53059c65596a3dbeefc82257ff7063878 Mon Sep 17 00:00:00 2001 From: Puja Jagani Date: Thu, 2 May 2024 16:23:09 +0530 Subject: [PATCH 003/723] [js] Ensure 'selectVisibleByText' method is same as other languages (#13899) --- common/src/web/select_space.html | 14 +++ .../node/selenium-webdriver/lib/select.js | 104 ++++++++++++++---- .../selenium-webdriver/lib/test/fileserver.js | 1 + .../selenium-webdriver/test/select_test.js | 37 +++++++ 4 files changed, 133 insertions(+), 23 deletions(-) create mode 100644 common/src/web/select_space.html diff --git a/common/src/web/select_space.html b/common/src/web/select_space.html new file mode 100644 index 0000000000000..9e237e5eca9ce --- /dev/null +++ b/common/src/web/select_space.html @@ -0,0 +1,14 @@ + + + +Multiple Selection test page + + + elements`) } }) + + this.element.getAttribute('multiple').then((multiple) => { + this.multiple = multiple !== null && multiple !== 'false' + }) } /** @@ -254,30 +258,46 @@ class Select { async selectByVisibleText(text) { text = typeof text === 'number' ? text.toString() : text - const normalized = text - .trim() // strip leading and trailing white-space characters - .replace(/\s+/, ' ') // replace sequences of whitespace characters by a single space + const xpath = './/option[normalize-space(.) = ' + escapeQuotes(text) + ']' - /** - * find option element using xpath - */ - const formatted = /"/.test(normalized) - ? 'concat("' + normalized.split('"').join('", \'"\', "') + '")' - : `"${normalized}"` - const dotFormat = `[. = ${formatted}]` - const spaceFormat = `[normalize-space(text()) = ${formatted}]` + const options = await this.element.findElements(By.xpath(xpath)) - const selections = [ - `./option${dotFormat}`, - `./option${spaceFormat}`, - `./optgroup/option${dotFormat}`, - `./optgroup/option${spaceFormat}`, - ] + for (let option of options) { + await this.setSelected(option) + if (!(await this.isMultiple())) { + return + } + } - const optionElement = await this.element.findElement({ - xpath: selections.join('|'), - }) - await this.setSelected(optionElement) + let matched = Array.isArray(options) && options.length > 0 + + if (!matched && text.includes(' ')) { + const subStringWithoutSpace = getLongestSubstringWithoutSpace(text) + let candidates + if ('' === subStringWithoutSpace) { + candidates = await this.element.findElements(By.tagName('option')) + } else { + const xpath = './/option[contains(., ' + escapeQuotes(subStringWithoutSpace) + ')]' + candidates = await this.element.findElements(By.xpath(xpath)) + } + + const trimmed = text.trim() + + for (let option of candidates) { + const optionText = await option.getText() + if (trimmed === optionText.trim()) { + await this.setSelected(option) + if (!(await this.isMultiple())) { + return + } + matched = true + } + } + } + + if (!matched) { + throw new Error(`Cannot locate option with text: ${text}`) + } } /** @@ -293,7 +313,7 @@ class Select { * @returns {Promise} */ async isMultiple() { - return (await this.element.getAttribute('multiple')) !== null + return this.multiple } /** @@ -457,4 +477,42 @@ class Select { } } -module.exports = { Select } +function escapeQuotes(toEscape) { + if (toEscape.includes(`"`) && toEscape.includes(`'`)) { + const quoteIsLast = toEscape.lastIndexOf(`"`) === toEscape.length - 1 + const substrings = toEscape.split(`"`) + + // Remove the last element if it's an empty string + if (substrings[substrings.length - 1] === '') { + substrings.pop() + } + + let result = 'concat(' + + for (let i = 0; i < substrings.length; i++) { + result += `"${substrings[i]}"` + result += i === substrings.length - 1 ? (quoteIsLast ? `, '"')` : `)`) : `, '"', ` + } + return result + } + + if (toEscape.includes('"')) { + return `'${toEscape}'` + } + + // Otherwise return the quoted string + return `"${toEscape}"` +} + +function getLongestSubstringWithoutSpace(text) { + let words = text.split(' ') + let longestString = '' + for (let word of words) { + if (word.length > longestString.length) { + longestString = word + } + } + return longestString +} + +module.exports = { Select, escapeQuotes } diff --git a/javascript/node/selenium-webdriver/lib/test/fileserver.js b/javascript/node/selenium-webdriver/lib/test/fileserver.js index aa270d54f91d8..337c1b9205137 100644 --- a/javascript/node/selenium-webdriver/lib/test/fileserver.js +++ b/javascript/node/selenium-webdriver/lib/test/fileserver.js @@ -94,6 +94,7 @@ const Pages = (function () { addPage('scrollingPage', 'scrollingPage.html') addPage('selectableItemsPage', 'selectableItems.html') addPage('selectPage', 'selectPage.html') + addPage('selectSpacePage', 'select_space.html') addPage('simpleTestPage', 'simpleTest.html') addPage('simpleXmlDocument', 'simple.xml') addPage('sleepingPage', 'sleep') diff --git a/javascript/node/selenium-webdriver/test/select_test.js b/javascript/node/selenium-webdriver/test/select_test.js index b6dc61377f067..b4681ee7ed715 100644 --- a/javascript/node/selenium-webdriver/test/select_test.js +++ b/javascript/node/selenium-webdriver/test/select_test.js @@ -20,6 +20,7 @@ const assert = require('node:assert') const { Select, By } = require('..') const { Pages, suite } = require('../lib/test') +const { escapeQuotes } = require('../lib/select') let singleSelectValues1 = { name: 'selectomatic', @@ -87,6 +88,42 @@ suite( } }) + it('Should be able to select by visible text with spaces', async function () { + await driver.get(Pages.selectSpacePage) + + const elem = await driver.findElement(By.id('selectWithoutMultiple')) + const select = new Select(elem) + await select.selectByVisibleText(' five') + let selectedElement = await select.getFirstSelectedOption() + selectedElement.getText().then((text) => { + assert.strictEqual(text, ' five') + }) + }) + + it('Should convert an unquoted string into one with quotes', async function () { + assert.strictEqual(escapeQuotes('abc'), '"abc"') + assert.strictEqual(escapeQuotes('abc aqewqqw'), '"abc aqewqqw"') + assert.strictEqual(escapeQuotes(''), '""') + assert.strictEqual(escapeQuotes(' '), '" "') + assert.strictEqual(escapeQuotes(' abc '), '" abc "') + }) + + it('Should add double quotes to a string that contains a single quote', async function () { + assert.strictEqual(escapeQuotes("f'oo"), `"f'oo"`) + }) + + it('Should add single quotes to a string that contains a double quotes', async function () { + assert.strictEqual(escapeQuotes('f"oo'), `'f"oo'`) + }) + + it('Should provide concatenated strings when string to escape contains both single and double quotes', async function () { + assert.strictEqual(escapeQuotes(`f"o'o`), `concat("f", '"', "o'o")`) + }) + + it('Should provide concatenated strings when string ends with quote', async function () { + assert.strictEqual(escapeQuotes(`'"`), `concat("'", '"')`) + }) + it('Should select by multiple index', async function () { await driver.get(Pages.formPage) From ad53a19918039f0a7b944b43b47e3a1cea357cbe Mon Sep 17 00:00:00 2001 From: Alex Rodionov Date: Fri, 3 May 2024 06:34:30 -0700 Subject: [PATCH 004/723] Revert "[bazel] Update rules_jvm_external to 6.1" This reverts commit ef96a7b18482a753f413596e265085e608f159e3. --- MODULE.bazel | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MODULE.bazel b/MODULE.bazel index d8249a99f7121..93578f833b573 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -124,6 +124,16 @@ use_repo(pip, "py_dev_requirements") register_toolchains("@pythons_hub//:all") +# https://github.com/bazelbuild/rules_jvm_external/pull/1079 +archive_override( + module_name = "rules_jvm_external", + integrity = "sha256-yS8Qes1PLbYbe10b1WSgl0Auqn/1Wlxg8O3wSr7a/Sg=", + patch_strip = 1, + patches = ["//java:rules_jvm_external_javadoc.patch"], + strip_prefix = "rules_jvm_external-f572a26116c7ef71d8842dd056c2605782f7be8d", + urls = ["https://github.com/bazelbuild/rules_jvm_external/archive/f572a26116c7ef71d8842dd056c2605782f7be8d.tar.gz"], +) + java_toolchains = use_extension("@rules_java//java:extensions.bzl", "toolchains") use_repo( java_toolchains, From 17d927b596898f666b0377ab40afe05434c6d8df Mon Sep 17 00:00:00 2001 From: Alex Rodionov Date: Fri, 3 May 2024 06:39:10 -0700 Subject: [PATCH 005/723] [bazel] Only use credential helper for RBE --- .bazelrc.remote | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bazelrc.remote b/.bazelrc.remote index ac8b6f12232fa..075c9efafbcdf 100644 --- a/.bazelrc.remote +++ b/.bazelrc.remote @@ -43,7 +43,7 @@ test:remote --test_env=PATH=/bin:/usr/bin:/usr/local/bin test:remote --test_env=HOME=/home/dev # Make sure we sniff credentials properly -build:remote --credential_helper=%workspace%/scripts/credential-helper.sh +build:remote --credential_helper=gypsum.cluster.engflow.com=%workspace%/scripts/credential-helper.sh # Use pinned browsers when running remotely build:remote --//common:pin_browsers From 5fe3362dfcbf62730fe7c63bab2d8f9e629845e9 Mon Sep 17 00:00:00 2001 From: joerg1985 <16140691+joerg1985@users.noreply.github.com> Date: Fri, 3 May 2024 23:47:13 +0200 Subject: [PATCH 006/723] [grid] flatten combined routes to improve routing (#13856) Co-authored-by: Diego Molina --- .../openqa/selenium/remote/http/Route.java | 20 ++++++++++++++++--- .../selenium/remote/http/RouteTest.java | 7 +++++-- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/java/src/org/openqa/selenium/remote/http/Route.java b/java/src/org/openqa/selenium/remote/http/Route.java index 5503136befb43..047ed4247e7f8 100644 --- a/java/src/org/openqa/selenium/remote/http/Route.java +++ b/java/src/org/openqa/selenium/remote/http/Route.java @@ -27,8 +27,8 @@ import static org.openqa.selenium.remote.http.HttpMethod.POST; import static org.openqa.selenium.remote.http.UrlPath.ROUTE_PREFIX_KEY; +import java.util.ArrayList; import java.util.Collections; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.function.Function; @@ -292,7 +292,7 @@ private HttpRequest transform(HttpRequest request) { // Don't forget to register our prefix Object rawPrefixes = request.getAttribute(ROUTE_PREFIX_KEY); if (!(rawPrefixes instanceof List)) { - rawPrefixes = new LinkedList<>(); + rawPrefixes = Collections.emptyList(); } List prefixes = Stream.concat(((List) rawPrefixes).stream(), Stream.of(prefix)) @@ -321,7 +321,21 @@ private static class CombinedRoute extends Route { private CombinedRoute(Stream routes) { // We want later routes to have a greater chance of being called so that we can override // routes as necessary. - List routables = routes.collect(Collectors.toList()); + List routables = + routes + .flatMap( + route -> { + // flatten a nested CombinedRoute + if (route instanceof CombinedRoute) { + List nestedRoutes = + new ArrayList<>(((CombinedRoute) route).allRoutes); + // reverse to have the identical behaviour like not flattened + Collections.reverse(nestedRoutes); + return nestedRoutes.stream(); + } + return Stream.of(route); + }) + .collect(Collectors.toList()); Collections.reverse(routables); allRoutes = List.copyOf(routables); Require.stateCondition(!allRoutes.isEmpty(), "At least one route must be specified."); diff --git a/java/test/org/openqa/selenium/remote/http/RouteTest.java b/java/test/org/openqa/selenium/remote/http/RouteTest.java index 6d25f5542502d..799db1405efec 100644 --- a/java/test/org/openqa/selenium/remote/http/RouteTest.java +++ b/java/test/org/openqa/selenium/remote/http/RouteTest.java @@ -152,8 +152,11 @@ void laterRoutesOverrideEarlierRoutesToFacilitateOverridingRoutes() { HttpHandler handler = Route.combine( Route.get("/hello").to(() -> req -> new HttpResponse().setContent(utf8String("world"))), - Route.get("/hello") - .to(() -> req -> new HttpResponse().setContent(utf8String("buddy")))); + Route.combine( + Route.get("/hello") + .to(() -> req -> new HttpResponse().setContent(utf8String("world"))), + Route.get("/hello") + .to(() -> req -> new HttpResponse().setContent(utf8String("buddy"))))); HttpResponse response = handler.execute(new HttpRequest(GET, "/hello")); assertThat(string(response)).isEqualTo("buddy"); From 970557de27ba8097e11ad7d623a5bb30d28feb1b Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 4 May 2024 06:03:26 +0700 Subject: [PATCH 007/723] [Java] Java language level aids (#13834) * Improvements from Java 11 API have been incorporated into the code. * removed unnecessary values boxing * remove unnecessary values unboxing * fix for file java/test/org/openqa/selenium/environment/webserver/Utf8Handler.java format * Format script --------- Co-authored-by: Diego Molina Co-authored-by: Diego Molina --- .../openqa/selenium/ExecutingJavascriptTest.java | 2 +- java/test/org/openqa/selenium/ProxyTest.java | 6 +++--- .../environment/webserver/Utf8Handler.java | 4 +--- .../grid/distributor/AddingNodesTest.java | 8 ++++---- .../org/openqa/selenium/json/JsonOutputTest.java | 2 +- java/test/org/openqa/selenium/json/JsonTest.java | 16 ++++++++-------- .../selenium/remote/DesiredCapabilitiesTest.java | 6 +----- .../codec/w3c/W3CHttpResponseCodecTest.java | 8 ++++---- 8 files changed, 23 insertions(+), 29 deletions(-) diff --git a/java/test/org/openqa/selenium/ExecutingJavascriptTest.java b/java/test/org/openqa/selenium/ExecutingJavascriptTest.java index 22bd5a7804e19..0a80cdd803157 100644 --- a/java/test/org/openqa/selenium/ExecutingJavascriptTest.java +++ b/java/test/org/openqa/selenium/ExecutingJavascriptTest.java @@ -407,7 +407,7 @@ void testShouldBeAbleToExecuteABigChunkOfJavascriptCode() throws IOException { driver.get(pages.javascriptPage); Path jqueryFile = InProject.locate("common/src/web/js/jquery-3.5.1.min.js"); - String jquery = new String(Files.readAllBytes(jqueryFile), US_ASCII); + String jquery = Files.readString(jqueryFile, US_ASCII); assertThat(jquery.length()) .describedAs("The javascript code should be at least 50 KB.") .isGreaterThan(50000); diff --git a/java/test/org/openqa/selenium/ProxyTest.java b/java/test/org/openqa/selenium/ProxyTest.java index 6944be1f3c123..77f016e9d7314 100644 --- a/java/test/org/openqa/selenium/ProxyTest.java +++ b/java/test/org/openqa/selenium/ProxyTest.java @@ -117,7 +117,7 @@ void testManualProxy() { assertThat(proxy.getHttpProxy()).isEqualTo("http.proxy:1234"); assertThat(proxy.getSslProxy()).isEqualTo("ssl.proxy"); assertThat(proxy.getSocksProxy()).isEqualTo("socks.proxy:65555"); - assertThat(proxy.getSocksVersion()).isEqualTo(Integer.valueOf(5)); + assertThat(proxy.getSocksVersion()).isEqualTo(5); assertThat(proxy.getSocksUsername()).isEqualTo("test1"); assertThat(proxy.getSocksPassword()).isEqualTo("test2"); assertThat(proxy.getNoProxy()).isEqualTo("localhost,127.0.0.*"); @@ -184,7 +184,7 @@ void manualProxyFromMap() { assertThat(proxy.getHttpProxy()).isEqualTo("http.proxy:1234"); assertThat(proxy.getSslProxy()).isEqualTo("ssl.proxy"); assertThat(proxy.getSocksProxy()).isEqualTo("socks.proxy:65555"); - assertThat(proxy.getSocksVersion()).isEqualTo(Integer.valueOf(5)); + assertThat(proxy.getSocksVersion()).isEqualTo(5); assertThat(proxy.getSocksUsername()).isEqualTo("test1"); assertThat(proxy.getSocksPassword()).isEqualTo("test2"); assertThat(proxy.getNoProxy()).isEqualTo("localhost,127.0.0.*"); @@ -209,7 +209,7 @@ void longSocksVersionFromMap() { Proxy proxy = new Proxy(proxyData); - assertThat(proxy.getSocksVersion()).isEqualTo(Integer.valueOf(5)); + assertThat(proxy.getSocksVersion()).isEqualTo(5); } @Test diff --git a/java/test/org/openqa/selenium/environment/webserver/Utf8Handler.java b/java/test/org/openqa/selenium/environment/webserver/Utf8Handler.java index 4e0bb13dc527e..1e684874a4760 100644 --- a/java/test/org/openqa/selenium/environment/webserver/Utf8Handler.java +++ b/java/test/org/openqa/selenium/environment/webserver/Utf8Handler.java @@ -17,8 +17,6 @@ package org.openqa.selenium.environment.webserver; -import static java.nio.charset.StandardCharsets.UTF_8; - import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Files; @@ -51,7 +49,7 @@ public HttpResponse execute(HttpRequest req) throws UncheckedIOException { return new HttpResponse() .setHeader("Content-Type", "text/html; charset=UTF-8") - .setContent(Contents.utf8String(new String(Files.readAllBytes(target), UTF_8))); + .setContent(Contents.utf8String(Files.readString(target))); } catch (IOException e) { throw new UncheckedIOException(e); } diff --git a/java/test/org/openqa/selenium/grid/distributor/AddingNodesTest.java b/java/test/org/openqa/selenium/grid/distributor/AddingNodesTest.java index 2e1b8755eabc8..482f577d05d22 100644 --- a/java/test/org/openqa/selenium/grid/distributor/AddingNodesTest.java +++ b/java/test/org/openqa/selenium/grid/distributor/AddingNodesTest.java @@ -153,7 +153,7 @@ void shouldBeAbleToRegisterALocalNode() throws URISyntaxException { wait.until(obj -> distributor.getStatus().hasCapacity()); NodeStatus status = getOnlyElement(distributor.getStatus().getNodes()); - assertEquals(1, getStereotypes(status).get(CAPS).intValue()); + assertEquals(1, getStereotypes(status).get(CAPS)); } @Test @@ -192,7 +192,7 @@ void shouldBeAbleToRegisterACustomNode() throws URISyntaxException { wait.until(obj -> distributor.getStatus().hasCapacity()); NodeStatus status = getOnlyElement(distributor.getStatus().getNodes()); - assertEquals(1, getStereotypes(status).get(CAPS).intValue()); + assertEquals(1, getStereotypes(status).get(CAPS)); } } @@ -231,7 +231,7 @@ void shouldBeAbleToRegisterNodesByListeningForEvents() throws URISyntaxException wait.until(obj -> distributor.getStatus().hasCapacity()); NodeStatus status = getOnlyElement(distributor.getStatus().getNodes()); - assertEquals(1, getStereotypes(status).get(CAPS).intValue()); + assertEquals(1, getStereotypes(status).get(CAPS)); } } @@ -323,7 +323,7 @@ void distributorShouldUpdateStateOfExistingNodeWhenNodePublishesStateChange() wait.until(obj -> distributor.getStatus().hasCapacity()); NodeStatus nodeStatus = getOnlyElement(distributor.getStatus().getNodes()); - assertEquals(1, getStereotypes(nodeStatus).get(CAPS).intValue()); + assertEquals(1, getStereotypes(nodeStatus).get(CAPS)); // Craft a status that makes it look like the node is busy, and post it on the bus. NodeStatus status = node.getStatus(); diff --git a/java/test/org/openqa/selenium/json/JsonOutputTest.java b/java/test/org/openqa/selenium/json/JsonOutputTest.java index f85897e35b981..10d246d431b8f 100644 --- a/java/test/org/openqa/selenium/json/JsonOutputTest.java +++ b/java/test/org/openqa/selenium/json/JsonOutputTest.java @@ -419,7 +419,7 @@ void shouldConvertUnhandledAlertException() { @Test void shouldConvertDatesToMillisecondsInUtcTime() { String jsonStr = convert(new Date(0)); - assertThat(valueOf(jsonStr).intValue()).isZero(); + assertThat(valueOf(jsonStr)).isZero(); } @Test diff --git a/java/test/org/openqa/selenium/json/JsonTest.java b/java/test/org/openqa/selenium/json/JsonTest.java index 23e484e237f1d..ad5e0c0ef1007 100644 --- a/java/test/org/openqa/selenium/json/JsonTest.java +++ b/java/test/org/openqa/selenium/json/JsonTest.java @@ -61,9 +61,9 @@ void canReadBooleans() { @Test void canReadANumber() { - assertThat((Number) new Json().toType("42", Number.class)).isEqualTo(Long.valueOf(42)); - assertThat((Integer) new Json().toType("42", Integer.class)).isEqualTo(Integer.valueOf(42)); - assertThat((Double) new Json().toType("42", Double.class)).isEqualTo(Double.valueOf(42)); + assertThat((Number) new Json().toType("42", Number.class)).isEqualTo(42L); + assertThat((Integer) new Json().toType("42", Integer.class)).isEqualTo(42); + assertThat((Double) new Json().toType("42", Double.class)).isEqualTo(42.0); } @Test @@ -285,7 +285,7 @@ void canHandleValueBeingAnArray() { assertThat(response.getSessionId()).isEqualTo("bar"); assertThat(((List) converted.getValue())).hasSize(2); - assertThat(response.getStatus().intValue()).isEqualTo(1512); + assertThat(response.getStatus()).isEqualTo(1512); } @Test @@ -426,7 +426,7 @@ void decodingResponseWithNumbersInValueObject() { void shouldRecognizeNumericStatus() { Response response = new Json().toType("{\"status\":0,\"value\":\"cheese\"}", Response.class); - assertThat(response.getStatus().intValue()).isZero(); + assertThat(response.getStatus()).isZero(); assertThat(response.getState()).isEqualTo(new ErrorCodes().toState(0)); String value = (String) response.getValue(); assertThat(value).isEqualTo("cheese"); @@ -437,7 +437,7 @@ void shouldRecognizeStringStatus() { Response response = new Json().toType("{\"status\":\"success\",\"value\":\"cheese\"}", Response.class); - assertThat(response.getStatus().intValue()).isZero(); + assertThat(response.getStatus()).isZero(); assertThat(response.getState()).isEqualTo(new ErrorCodes().toState(0)); String value = (String) response.getValue(); assertThat(value).isEqualTo("cheese"); @@ -450,7 +450,7 @@ void shouldConvertInvalidSelectorError() { .toType( "{\"state\":\"invalid selector\",\"message\":\"invalid xpath selector\"}", Response.class); - assertThat(response.getStatus().intValue()).isEqualTo(32); + assertThat(response.getStatus()).isEqualTo(32); assertThat(response.getState()).isEqualTo(new ErrorCodes().toState(32)); } @@ -459,7 +459,7 @@ void shouldRecognizeStringState() { Response response = new Json().toType("{\"state\":\"success\",\"value\":\"cheese\"}", Response.class); assertThat(response.getState()).isEqualTo("success"); - assertThat(response.getStatus().intValue()).isZero(); + assertThat(response.getStatus()).isZero(); String value = (String) response.getValue(); assertThat(value).isEqualTo("cheese"); } diff --git a/java/test/org/openqa/selenium/remote/DesiredCapabilitiesTest.java b/java/test/org/openqa/selenium/remote/DesiredCapabilitiesTest.java index 856f273356468..ba401b0a9af5e 100644 --- a/java/test/org/openqa/selenium/remote/DesiredCapabilitiesTest.java +++ b/java/test/org/openqa/selenium/remote/DesiredCapabilitiesTest.java @@ -133,10 +133,6 @@ void canCompareCapabilities() { } private String createString(int length) { - StringBuilder outputBuffer = new StringBuilder(length); - for (int i = 0; i < length; i++) { - outputBuffer.append("x"); - } - return outputBuffer.toString(); + return "x".repeat(Math.max(0, length)); } } 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 11c4007194978..df480c356a99c 100644 --- a/java/test/org/openqa/selenium/remote/codec/w3c/W3CHttpResponseCodecTest.java +++ b/java/test/org/openqa/selenium/remote/codec/w3c/W3CHttpResponseCodecTest.java @@ -78,7 +78,7 @@ void shouldBeAbleToHandleGatewayTimeoutError() { Response decoded = new W3CHttpResponseCodec().decode(response); - assertThat(decoded.getStatus().intValue()).isEqualTo(ErrorCodes.UNHANDLED_ERROR); + assertThat(decoded.getStatus()).isEqualTo(ErrorCodes.UNHANDLED_ERROR); assertThat(decoded.getValue()).isEqualTo(responseString); } @@ -104,7 +104,7 @@ void shouldBeAbleToHandleBadGatewayError() { Response decoded = new W3CHttpResponseCodec().decode(response); - assertThat(decoded.getStatus().intValue()).isEqualTo(ErrorCodes.UNHANDLED_ERROR); + assertThat(decoded.getStatus()).isEqualTo(ErrorCodes.UNHANDLED_ERROR); assertThat(decoded.getValue()).isEqualTo(responseString); } @@ -120,7 +120,7 @@ void decodingAnErrorWithoutAStacktraceIsDecodedProperlyForNonCompliantImplementa Response decoded = new W3CHttpResponseCodec().decode(response); assertThat(decoded.getState()).isEqualTo("unsupported operation"); - assertThat(decoded.getStatus().intValue()).isEqualTo(METHOD_NOT_ALLOWED); + assertThat(decoded.getStatus()).isEqualTo(METHOD_NOT_ALLOWED); assertThat(decoded.getValue()).isInstanceOf(UnsupportedCommandException.class); assertThat(((WebDriverException) decoded.getValue()).getMessage()).contains("I like peas"); @@ -140,7 +140,7 @@ void decodingAnErrorWithoutAStacktraceIsDecodedProperlyForConformingImplementati Response decoded = new W3CHttpResponseCodec().decode(response); assertThat(decoded.getState()).isEqualTo("unsupported operation"); - assertThat(decoded.getStatus().intValue()).isEqualTo(METHOD_NOT_ALLOWED); + assertThat(decoded.getStatus()).isEqualTo(METHOD_NOT_ALLOWED); assertThat(decoded.getValue()).isInstanceOf(UnsupportedCommandException.class); assertThat(((WebDriverException) decoded.getValue()).getMessage()).contains("I like peas"); From fe2edbdebab6d1685e6eb084c49a716b579d5cb4 Mon Sep 17 00:00:00 2001 From: Viet Nguyen Duc Date: Sat, 4 May 2024 12:31:22 +0000 Subject: [PATCH 008/723] [grid][java]: apply protocol version in relay session factory (#13880) Signed-off-by: Viet Nguyen Duc --- .../openqa/selenium/grid/node/relay/RelaySessionFactory.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java/src/org/openqa/selenium/grid/node/relay/RelaySessionFactory.java b/java/src/org/openqa/selenium/grid/node/relay/RelaySessionFactory.java index 5818335af3cdd..889afb5bb958a 100644 --- a/java/src/org/openqa/selenium/grid/node/relay/RelaySessionFactory.java +++ b/java/src/org/openqa/selenium/grid/node/relay/RelaySessionFactory.java @@ -159,6 +159,9 @@ public Either apply(CreateSessionRequest sess ClientConfig clientConfig = ClientConfig.defaultConfig().readTimeout(sessionTimeout).baseUrl(serviceUrl); + if (!serviceProtocolVersion.isEmpty()) { + clientConfig = clientConfig.version(serviceProtocolVersion); + } HttpClient client = clientFactory.createClient(clientConfig); Command command = new Command(null, DriverCommand.NEW_SESSION(capabilities)); From 7b83fc135b7e4c023195da960ad592d882a3fe8f Mon Sep 17 00:00:00 2001 From: Oleksandr Kulychok Date: Mon, 6 May 2024 11:02:50 +0300 Subject: [PATCH 009/723] [java][sm] Configure Selenium Manager environment from System Properties (#13858) * [java][sm] Configure Selenium Manager environment from System Properties * Running format script --------- Co-authored-by: Diego Molina Co-authored-by: Diego Molina --- .../selenium/manager/SeleniumManager.java | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/java/src/org/openqa/selenium/manager/SeleniumManager.java b/java/src/org/openqa/selenium/manager/SeleniumManager.java index 75af5188e20ae..04daa88acb256 100644 --- a/java/src/org/openqa/selenium/manager/SeleniumManager.java +++ b/java/src/org/openqa/selenium/manager/SeleniumManager.java @@ -28,6 +28,7 @@ import java.nio.file.Paths; import java.time.Duration; import java.util.List; +import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import org.openqa.selenium.Beta; @@ -62,6 +63,7 @@ public class SeleniumManager { private static final String CACHE_PATH_ENV = "SE_CACHE_PATH"; private static final String BETA_PREFIX = "0."; private static final String EXE = ".exe"; + private static final String SE_ENV_PREFIX = "SE_"; private static volatile SeleniumManager manager; private final String managerPath = System.getenv("SE_MANAGER_PATH"); @@ -119,8 +121,21 @@ private static Result runCommand(Path binary, List arguments) { String output; int code; try { + ExternalProcess.Builder processBuilder = ExternalProcess.builder(); + + Properties properties = System.getProperties(); + for (String name : properties.stringPropertyNames()) { + if (name.startsWith(SE_ENV_PREFIX)) { + // read property with 'default' value due to concurrency + String value = properties.getProperty(name, ""); + if (!value.isEmpty()) { + processBuilder.environment(name, value); + } + } + } ExternalProcess process = - ExternalProcess.builder().command(binary.toAbsolutePath().toString(), arguments).start(); + processBuilder.command(binary.toAbsolutePath().toString(), arguments).start(); + if (!process.waitFor(Duration.ofHours(1))) { LOG.warning("Selenium Manager did not exit, shutting it down"); process.shutdown(); @@ -240,13 +255,13 @@ private Level getLogLevel() { } private Path getBinaryInCache(String binaryName) throws IOException { - String cachePath = DEFAULT_CACHE_PATH.replace(HOME, System.getProperty("user.home")); - // Look for cache path as env - String cachePathEnv = System.getenv(CACHE_PATH_ENV); - if (cachePathEnv != null) { - cachePath = cachePathEnv; - } + // Look for cache path as system property or env + String cachePath = System.getProperty(CACHE_PATH_ENV, ""); + if (cachePath.isEmpty()) cachePath = System.getenv(CACHE_PATH_ENV); + if (cachePath == null) cachePath = DEFAULT_CACHE_PATH; + + cachePath = cachePath.replace(HOME, System.getProperty("user.home")); // If cache path is not writable, SM will be extracted to a temporal folder Path cacheParent = Paths.get(cachePath); From 8e3e26e0a21e393d6a14855e27e74e4684523786 Mon Sep 17 00:00:00 2001 From: Viet Nguyen Duc Date: Mon, 6 May 2024 11:58:27 +0000 Subject: [PATCH 010/723] [java][grid]: Set test name to video file name in dynamic grid (#13907) * [java][grid]: Set test name to video file name in dynamic grid Signed-off-by: Viet Nguyen Duc * Revert unexpected changes Signed-off-by: Viet Nguyen Duc --------- Signed-off-by: Viet Nguyen Duc --- .../node/docker/DockerSessionFactory.java | 57 +++++++++++++------ 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/java/src/org/openqa/selenium/grid/node/docker/DockerSessionFactory.java b/java/src/org/openqa/selenium/grid/node/docker/DockerSessionFactory.java index dd0ed03d6fde0..d7aa7eec721fe 100644 --- a/java/src/org/openqa/selenium/grid/node/docker/DockerSessionFactory.java +++ b/java/src/org/openqa/selenium/grid/node/docker/DockerSessionFactory.java @@ -301,23 +301,34 @@ private Container createBrowserContainer(int port, Capabilities sessionCapabilit } private Map getBrowserContainerEnvVars(Capabilities sessionRequestCapabilities) { - Optional screenResolution = - ofNullable(getScreenResolution(sessionRequestCapabilities)); Map envVars = new HashMap<>(); - if (screenResolution.isPresent()) { - envVars.put("SE_SCREEN_WIDTH", String.valueOf(screenResolution.get().getWidth())); - envVars.put("SE_SCREEN_HEIGHT", String.valueOf(screenResolution.get().getHeight())); - } - Optional timeZone = ofNullable(getTimeZone(sessionRequestCapabilities)); - timeZone.ifPresent(zone -> envVars.put("TZ", zone.getID())); // Passing env vars set to the child container + setEnvVarsToContainer(envVars); + // Capabilities set to env vars with higher precedence + setCapsToEnvVars(sessionRequestCapabilities, envVars); + return envVars; + } + + private void setEnvVarsToContainer(Map envVars) { Map seEnvVars = System.getenv(); seEnvVars.entrySet().stream() .filter( entry -> entry.getKey().startsWith("SE_") || entry.getKey().equalsIgnoreCase("LANGUAGE")) .forEach(entry -> envVars.put(entry.getKey(), entry.getValue())); - return envVars; + } + + private void setCapsToEnvVars( + Capabilities sessionRequestCapabilities, Map envVars) { + Optional screenResolution = + ofNullable(getScreenResolution(sessionRequestCapabilities)); + screenResolution.ifPresent( + dimension -> { + envVars.put("SE_SCREEN_WIDTH", String.valueOf(dimension.getWidth())); + envVars.put("SE_SCREEN_HEIGHT", String.valueOf(dimension.getHeight())); + }); + Optional timeZone = ofNullable(getTimeZone(sessionRequestCapabilities)); + timeZone.ifPresent(zone -> envVars.put("TZ", zone.getID())); } private Container startVideoContainer( @@ -357,17 +368,31 @@ private Container startVideoContainer( private Map getVideoContainerEnvVars( Capabilities sessionRequestCapabilities, String containerIp) { Map envVars = new HashMap<>(); + // Passing env vars set to the child container + setEnvVarsToContainer(envVars); + // Capabilities set to env vars with higher precedence + setCapsToEnvVars(sessionRequestCapabilities, envVars); envVars.put("DISPLAY_CONTAINER_NAME", containerIp); - Optional screenResolution = - ofNullable(getScreenResolution(sessionRequestCapabilities)); - screenResolution.ifPresent( - dimension -> { - envVars.put("SE_SCREEN_WIDTH", String.valueOf(dimension.getWidth())); - envVars.put("SE_SCREEN_HEIGHT", String.valueOf(dimension.getHeight())); - }); + Optional testName = ofNullable(getTestName(sessionRequestCapabilities)); + testName.ifPresent(name -> envVars.put("SE_VIDEO_FILE_NAME", String.format("%s.mp4", name))); return envVars; } + private String getTestName(Capabilities sessionRequestCapabilities) { + Optional testName = ofNullable(sessionRequestCapabilities.getCapability("se:name")); + if (testName.isPresent()) { + String name = testName.get().toString(); + if (!name.isEmpty()) { + name = name.replaceAll(" ", "_").replaceAll("[^a-zA-Z0-9_-]", ""); + if (name.length() > 251) { + name = name.substring(0, 251); + } + return name; + } + } + return null; + } + private TimeZone getTimeZone(Capabilities sessionRequestCapabilities) { Optional timeZone = ofNullable(sessionRequestCapabilities.getCapability("se:timeZone")); if (timeZone.isPresent()) { From 72562d8d88e9f2e2492c461910e6dd6124e0e954 Mon Sep 17 00:00:00 2001 From: Viet Nguyen Duc Date: Mon, 6 May 2024 12:39:29 +0000 Subject: [PATCH 011/723] [grid][java]: session-timeout set connection timeout in RemoteNode (#13854) * [grid][java]: add session-timeout to all kind of Nodes Signed-off-by: Viet Nguyen Duc * [grid][java]: fix code as suggestions Signed-off-by: Viet Nguyen Duc * [java][grid]: update test CustomNode can get/set sessionTimeout Signed-off-by: Viet Nguyen Duc --------- Signed-off-by: Viet Nguyen Duc --- .../openqa/selenium/grid/data/NodeStatus.java | 23 ++++++++++++++++++- .../selenium/grid/distributor/AddNode.java | 1 + .../selenium/grid/distributor/GridModel.java | 2 ++ .../distributor/local/LocalDistributor.java | 1 + .../org/openqa/selenium/grid/node/Node.java | 10 +++++++- .../selenium/grid/node/k8s/OneShotNode.java | 5 +++- .../selenium/grid/node/local/LocalNode.java | 8 ++++++- .../selenium/grid/node/remote/RemoteNode.java | 11 ++++++--- .../selenium/redis/GridRedisClient.java | 1 + .../selenium/grid/data/NodeStatusTest.java | 1 + .../grid/distributor/AddingNodesTest.java | 12 ++++++++-- .../selector/DefaultSlotSelectorTest.java | 1 + .../openqa/selenium/grid/node/NodeTest.java | 4 ++++ 13 files changed, 71 insertions(+), 9 deletions(-) diff --git a/java/src/org/openqa/selenium/grid/data/NodeStatus.java b/java/src/org/openqa/selenium/grid/data/NodeStatus.java index d2f31d6a858ff..47753585ec989 100644 --- a/java/src/org/openqa/selenium/grid/data/NodeStatus.java +++ b/java/src/org/openqa/selenium/grid/data/NodeStatus.java @@ -42,6 +42,7 @@ public class NodeStatus { private final Set slots; private final Availability availability; private final Duration heartbeatPeriod; + private final Duration sessionTimeout; private final String version; private final Map osInfo; @@ -52,6 +53,7 @@ public NodeStatus( Set slots, Availability availability, Duration heartbeatPeriod, + Duration sessionTimeout, String version, Map osInfo) { this.nodeId = Require.nonNull("Node id", nodeId); @@ -62,6 +64,7 @@ public NodeStatus( this.slots = unmodifiableSet(new HashSet<>(Require.nonNull("Slots", slots))); this.availability = Require.nonNull("Availability", availability); this.heartbeatPeriod = heartbeatPeriod; + this.sessionTimeout = sessionTimeout; this.version = Require.nonNull("Grid Node version", version); this.osInfo = Require.nonNull("Node host OS info", osInfo); } @@ -73,6 +76,7 @@ public static NodeStatus fromJson(JsonInput input) { Set slots = null; Availability availability = null; Duration heartbeatPeriod = null; + Duration sessionTimeout = null; String version = null; Map osInfo = null; @@ -87,6 +91,10 @@ public static NodeStatus fromJson(JsonInput input) { heartbeatPeriod = Duration.ofMillis(input.read(Long.class)); break; + case "sessionTimeout": + sessionTimeout = Duration.ofMillis(input.read(Long.class)); + break; + case "nodeId": nodeId = input.read(NodeId.class); break; @@ -119,7 +127,15 @@ public static NodeStatus fromJson(JsonInput input) { input.endObject(); return new NodeStatus( - nodeId, externalUri, maxSessions, slots, availability, heartbeatPeriod, version, osInfo); + nodeId, + externalUri, + maxSessions, + slots, + availability, + heartbeatPeriod, + sessionTimeout, + version, + osInfo); } public boolean hasCapability(Capabilities caps, SlotMatcher slotMatcher) { @@ -162,6 +178,10 @@ public Duration getHeartbeatPeriod() { return heartbeatPeriod; } + public Duration getSessionTimeout() { + return sessionTimeout; + } + public String getVersion() { return version; } @@ -212,6 +232,7 @@ private Map toJson() { toReturn.put("slots", slots); toReturn.put("availability", availability); toReturn.put("heartbeatPeriod", heartbeatPeriod.toMillis()); + toReturn.put("sessionTimeout", sessionTimeout.toMillis()); toReturn.put("version", version); toReturn.put("osInfo", osInfo); diff --git a/java/src/org/openqa/selenium/grid/distributor/AddNode.java b/java/src/org/openqa/selenium/grid/distributor/AddNode.java index 95e8a33c304ee..904faaab6f1ec 100644 --- a/java/src/org/openqa/selenium/grid/distributor/AddNode.java +++ b/java/src/org/openqa/selenium/grid/distributor/AddNode.java @@ -65,6 +65,7 @@ public HttpResponse execute(HttpRequest req) { status.getNodeId(), status.getExternalUri(), registrationSecret, + status.getSessionTimeout(), status.getSlots().stream().map(Slot::getStereotype).collect(Collectors.toSet())); distributor.add(node); diff --git a/java/src/org/openqa/selenium/grid/distributor/GridModel.java b/java/src/org/openqa/selenium/grid/distributor/GridModel.java index c2b3d05898702..3aa27085e1f81 100644 --- a/java/src/org/openqa/selenium/grid/distributor/GridModel.java +++ b/java/src/org/openqa/selenium/grid/distributor/GridModel.java @@ -367,6 +367,7 @@ private NodeStatus rewrite(NodeStatus status, Availability availability) { status.getSlots(), availability, status.getHeartbeatPeriod(), + status.getSessionTimeout(), status.getVersion(), status.getOsInfo()); } @@ -508,6 +509,7 @@ private void amend(Availability availability, NodeStatus status, Slot slot) { newSlots, availability, status.getHeartbeatPeriod(), + status.getSessionTimeout(), status.getVersion(), status.getOsInfo())); } finally { 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 332ea7ef6a695..f9581b1fff016 100644 --- a/java/src/org/openqa/selenium/grid/distributor/local/LocalDistributor.java +++ b/java/src/org/openqa/selenium/grid/distributor/local/LocalDistributor.java @@ -314,6 +314,7 @@ private void register(NodeStatus status) { status.getNodeId(), status.getExternalUri(), registrationSecret, + status.getSessionTimeout(), capabilities); add(remoteNode); diff --git a/java/src/org/openqa/selenium/grid/node/Node.java b/java/src/org/openqa/selenium/grid/node/Node.java index 5fb0877d8fcc7..5d54bb3e2981d 100644 --- a/java/src/org/openqa/selenium/grid/node/Node.java +++ b/java/src/org/openqa/selenium/grid/node/Node.java @@ -28,6 +28,7 @@ import com.google.common.collect.ImmutableMap; import java.io.IOException; import java.net.URI; +import java.time.Duration; import java.util.Map; import java.util.ServiceLoader; import java.util.Set; @@ -116,13 +117,16 @@ public abstract class Node implements HasReadyState, Routable { protected final Tracer tracer; private final NodeId id; private final URI uri; + private final Duration sessionTimeout; private final Route routes; protected boolean draining; - protected Node(Tracer tracer, NodeId id, URI uri, Secret registrationSecret) { + protected Node( + Tracer tracer, NodeId id, URI uri, Secret registrationSecret, Duration sessionTimeout) { this.tracer = Require.nonNull("Tracer", tracer); this.id = Require.nonNull("Node id", id); this.uri = Require.nonNull("URI", uri); + this.sessionTimeout = Require.positive("Session timeout", sessionTimeout); Require.nonNull("Registration secret", registrationSecret); RequiresSecretFilter requiresSecret = new RequiresSecretFilter(registrationSecret); @@ -246,6 +250,10 @@ public TemporaryFilesystem getDownloadsFilesystem(UUID uuid) throws IOException public abstract HealthCheck getHealthCheck(); + public Duration getSessionTimeout() { + return sessionTimeout; + } + public boolean isDraining() { return draining; } diff --git a/java/src/org/openqa/selenium/grid/node/k8s/OneShotNode.java b/java/src/org/openqa/selenium/grid/node/k8s/OneShotNode.java index 22b79969eefd1..d293d1c6ba78c 100644 --- a/java/src/org/openqa/selenium/grid/node/k8s/OneShotNode.java +++ b/java/src/org/openqa/selenium/grid/node/k8s/OneShotNode.java @@ -109,12 +109,13 @@ private OneShotNode( EventBus events, Secret registrationSecret, Duration heartbeatPeriod, + Duration sessionTimeout, NodeId id, URI uri, URI gridUri, Capabilities stereotype, WebDriverInfo driverInfo) { - super(tracer, id, uri, registrationSecret); + super(tracer, id, uri, registrationSecret, Require.positive(sessionTimeout)); this.heartbeatPeriod = heartbeatPeriod; this.events = Require.nonNull("Event bus", events); @@ -169,6 +170,7 @@ public static Node create(Config config) { eventOptions.getEventBus(), secretOptions.getRegistrationSecret(), nodeOptions.getHeartbeatPeriod(), + nodeOptions.getSessionTimeout(), new NodeId(UUID.randomUUID()), serverOptions.getExternalUri(), nodeOptions @@ -376,6 +378,7 @@ public NodeStatus getStatus() { : new Session(sessionId, getUri(), stereotype, capabilities, Instant.now()))), isDraining() ? DRAINING : UP, heartbeatPeriod, + getSessionTimeout(), getNodeVersion(), getOsInfo()); } diff --git a/java/src/org/openqa/selenium/grid/node/local/LocalNode.java b/java/src/org/openqa/selenium/grid/node/local/LocalNode.java index 79f687448cf91..2283e8573042d 100644 --- a/java/src/org/openqa/selenium/grid/node/local/LocalNode.java +++ b/java/src/org/openqa/selenium/grid/node/local/LocalNode.java @@ -154,7 +154,12 @@ protected LocalNode( List factories, Secret registrationSecret, boolean managedDownloadsEnabled) { - super(tracer, new NodeId(UUID.randomUUID()), uri, registrationSecret); + super( + tracer, + new NodeId(UUID.randomUUID()), + uri, + registrationSecret, + Require.positive(sessionTimeout)); this.bus = Require.nonNull("Event bus", bus); @@ -906,6 +911,7 @@ public NodeStatus getStatus() { slots, availability, heartbeatPeriod, + getSessionTimeout(), getNodeVersion(), getOsInfo()); } diff --git a/java/src/org/openqa/selenium/grid/node/remote/RemoteNode.java b/java/src/org/openqa/selenium/grid/node/remote/RemoteNode.java index 913909b9a93ff..ae7cc8e1af9fb 100644 --- a/java/src/org/openqa/selenium/grid/node/remote/RemoteNode.java +++ b/java/src/org/openqa/selenium/grid/node/remote/RemoteNode.java @@ -22,6 +22,7 @@ import static org.openqa.selenium.grid.data.Availability.DRAINING; import static org.openqa.selenium.grid.data.Availability.UP; import static org.openqa.selenium.net.Urls.fromUri; +import static org.openqa.selenium.remote.http.ClientConfig.defaultConfig; import static org.openqa.selenium.remote.http.Contents.asJson; import static org.openqa.selenium.remote.http.Contents.reader; import static org.openqa.selenium.remote.http.HttpMethod.DELETE; @@ -35,6 +36,7 @@ import java.io.Reader; import java.io.UncheckedIOException; import java.net.URI; +import java.time.Duration; import java.util.Collection; import java.util.Map; import java.util.Objects; @@ -60,6 +62,7 @@ import org.openqa.selenium.json.Json; import org.openqa.selenium.json.JsonInput; import org.openqa.selenium.remote.SessionId; +import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.remote.http.Filter; import org.openqa.selenium.remote.http.HttpClient; import org.openqa.selenium.remote.http.HttpHandler; @@ -83,13 +86,15 @@ public RemoteNode( NodeId id, URI externalUri, Secret registrationSecret, + Duration sessionTimeout, Collection capabilities) { - super(tracer, id, externalUri, registrationSecret); + super(tracer, id, externalUri, registrationSecret, sessionTimeout); this.externalUri = Require.nonNull("External URI", externalUri); this.capabilities = ImmutableSet.copyOf(capabilities); - this.client = - Require.nonNull("HTTP client factory", clientFactory).createClient(fromUri(externalUri)); + ClientConfig clientConfig = + defaultConfig().readTimeout(this.getSessionTimeout()).baseUrl(fromUri(externalUri)); + this.client = Require.nonNull("HTTP client factory", clientFactory).createClient(clientConfig); this.healthCheck = new RemoteCheck(); diff --git a/java/src/org/openqa/selenium/redis/GridRedisClient.java b/java/src/org/openqa/selenium/redis/GridRedisClient.java index 3a8011d7d5a94..045d25e0e4a23 100644 --- a/java/src/org/openqa/selenium/redis/GridRedisClient.java +++ b/java/src/org/openqa/selenium/redis/GridRedisClient.java @@ -144,6 +144,7 @@ public Optional getNode(NodeId id) { node.getSlots(), node.getAvailability(), node.getHeartbeatPeriod(), + node.getSessionTimeout(), node.getVersion(), node.getOsInfo()); return Optional.of(resultNode); diff --git a/java/test/org/openqa/selenium/grid/data/NodeStatusTest.java b/java/test/org/openqa/selenium/grid/data/NodeStatusTest.java index f5ed2ca76e2fa..4926f08e02c9e 100644 --- a/java/test/org/openqa/selenium/grid/data/NodeStatusTest.java +++ b/java/test/org/openqa/selenium/grid/data/NodeStatusTest.java @@ -56,6 +56,7 @@ void ensureRoundTripWorks() throws URISyntaxException { Instant.now()))), UP, Duration.ofSeconds(10), + Duration.ofSeconds(300), "4.0.0", ImmutableMap.of( "name", "Max OS X", diff --git a/java/test/org/openqa/selenium/grid/distributor/AddingNodesTest.java b/java/test/org/openqa/selenium/grid/distributor/AddingNodesTest.java index 482f577d05d22..0649e1bbee235 100644 --- a/java/test/org/openqa/selenium/grid/distributor/AddingNodesTest.java +++ b/java/test/org/openqa/selenium/grid/distributor/AddingNodesTest.java @@ -164,6 +164,7 @@ void shouldBeAbleToRegisterACustomNode() throws URISyntaxException { bus, new NodeId(UUID.randomUUID()), externalUrl.toURI(), + Duration.ofSeconds(300), c -> new Session( new SessionId(UUID.randomUUID()), sessionUri, stereotype, c, Instant.now())); @@ -193,6 +194,7 @@ void shouldBeAbleToRegisterACustomNode() throws URISyntaxException { NodeStatus status = getOnlyElement(distributor.getStatus().getNodes()); assertEquals(1, getStereotypes(status).get(CAPS)); + assertEquals(Duration.ofSeconds(300), status.getSessionTimeout()); } } @@ -345,6 +347,7 @@ void distributorShouldUpdateStateOfExistingNodeWhenNodePublishesStateChange() Instant.now()))), UP, Duration.ofSeconds(10), + status.getSessionTimeout(), status.getVersion(), status.getOsInfo()); @@ -374,8 +377,12 @@ static class CustomNode extends Node { private Session running; protected CustomNode( - EventBus bus, NodeId nodeId, URI uri, Function factory) { - super(DefaultTestTracer.createTracer(), nodeId, uri, registrationSecret); + EventBus bus, + NodeId nodeId, + URI uri, + Duration sessionTimeout, + Function factory) { + super(DefaultTestTracer.createTracer(), nodeId, uri, registrationSecret, sessionTimeout); this.bus = bus; this.factory = Objects.requireNonNull(factory); @@ -468,6 +475,7 @@ public NodeStatus getStatus() { new Slot(new SlotId(getId(), UUID.randomUUID()), CAPS, Instant.now(), sess)), UP, Duration.ofSeconds(10), + getSessionTimeout(), getNodeVersion(), getOsInfo()); } diff --git a/java/test/org/openqa/selenium/grid/distributor/selector/DefaultSlotSelectorTest.java b/java/test/org/openqa/selenium/grid/distributor/selector/DefaultSlotSelectorTest.java index 9cec975cb7361..d05e9d1c5f81b 100644 --- a/java/test/org/openqa/selenium/grid/distributor/selector/DefaultSlotSelectorTest.java +++ b/java/test/org/openqa/selenium/grid/distributor/selector/DefaultSlotSelectorTest.java @@ -229,6 +229,7 @@ private NodeStatus createNode(List stereotypes, int count, int cur ImmutableSet.copyOf(slots), UP, Duration.ofSeconds(10), + Duration.ofSeconds(300), "4.0.0", ImmutableMap.of( "name", "Max OS X", diff --git a/java/test/org/openqa/selenium/grid/node/NodeTest.java b/java/test/org/openqa/selenium/grid/node/NodeTest.java index 9f6d4c50b404a..b1c50ed0dc65a 100644 --- a/java/test/org/openqa/selenium/grid/node/NodeTest.java +++ b/java/test/org/openqa/selenium/grid/node/NodeTest.java @@ -158,6 +158,7 @@ public HttpResponse execute(HttpRequest req) throws UncheckedIOException { new NodeId(UUID.randomUUID()), uri, registrationSecret, + local.getSessionTimeout(), ImmutableSet.of(caps)); } @@ -172,6 +173,7 @@ void shouldRefuseToCreateASessionIfNoFactoriesAttached() { new NodeId(UUID.randomUUID()), uri, registrationSecret, + local.getSessionTimeout(), ImmutableSet.of()); Either response = @@ -223,6 +225,7 @@ public boolean test(Capabilities capabilities) { new NodeId(UUID.randomUUID()), uri, registrationSecret, + local.getSessionTimeout(), ImmutableSet.of(caps)); ImmutableCapabilities wrongCaps = new ImmutableCapabilities("browserName", "burger"); @@ -346,6 +349,7 @@ public HttpResponse execute(HttpRequest req) throws UncheckedIOException { new NodeId(UUID.randomUUID()), uri, registrationSecret, + local.getSessionTimeout(), ImmutableSet.of(caps)); Either response = From 4b415384eae4ac156353726b473df35540625b88 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 7 May 2024 04:09:01 +0700 Subject: [PATCH 012/723] [java] type casting and numeric improvements (#13909) * replaced condition controll flow with switch * remove casting from double to int division operation with integer ergument is equal to cast to int Math.floor() * remove division by 1 in tests * replaced manual calculation of hashcode with Long.hashCode() * removed redundand toString method call * removed cast to string in string concat * applying code formatting --- .../selenium/devtools/CdpClientGenerator.java | 29 +++++++++++-------- .../support/AbstractFindByBuilder.java | 2 +- .../org/openqa/selenium/support/Color.java | 2 +- .../selenium/bidi/input/DefaultMouseTest.java | 2 +- .../selenium/bidi/input/DragAndDropTest.java | 2 +- .../interactions/DefaultMouseTest.java | 2 +- .../selenium/interactions/PenPointerTest.java | 6 ++-- 7 files changed, 25 insertions(+), 20 deletions(-) diff --git a/java/src/org/openqa/selenium/devtools/CdpClientGenerator.java b/java/src/org/openqa/selenium/devtools/CdpClientGenerator.java index dccb9eb0e7339..ad43ee1d5a91c 100644 --- a/java/src/org/openqa/selenium/devtools/CdpClientGenerator.java +++ b/java/src/org/openqa/selenium/devtools/CdpClientGenerator.java @@ -913,18 +913,23 @@ public TypeDeclaration toTypeDeclaration() { fromJson.getBody().get().addStatement(String.format("return new %s(%s);", name, getMapper())); MethodDeclaration toJson = classDecl.addMethod("toJson").setPublic(true); - if (type.equals("object")) { - toJson.setType("java.util.Map"); - toJson.getBody().get().addStatement(String.format("return %s;", propertyName)); - } else if (type.equals("number")) { - toJson.setType(Number.class); - toJson.getBody().get().addStatement(String.format("return %s;", propertyName)); - } else if (type.equals("integer")) { - toJson.setType(Integer.class); - toJson.getBody().get().addStatement(String.format("return %s;", propertyName)); - } else { - toJson.setType(String.class); - toJson.getBody().get().addStatement(String.format("return %s.toString();", propertyName)); + switch (type) { + case "object": + toJson.setType("java.util.Map"); + toJson.getBody().get().addStatement(String.format("return %s;", propertyName)); + break; + case "number": + toJson.setType(Number.class); + toJson.getBody().get().addStatement(String.format("return %s;", propertyName)); + break; + case "integer": + toJson.setType(Integer.class); + toJson.getBody().get().addStatement(String.format("return %s;", propertyName)); + break; + default: + toJson.setType(String.class); + toJson.getBody().get().addStatement(String.format("return %s.toString();", propertyName)); + break; } MethodDeclaration toString = classDecl.addMethod("toString").setPublic(true); diff --git a/java/src/org/openqa/selenium/support/AbstractFindByBuilder.java b/java/src/org/openqa/selenium/support/AbstractFindByBuilder.java index 791e982ed59c8..645d17dafa5c7 100644 --- a/java/src/org/openqa/selenium/support/AbstractFindByBuilder.java +++ b/java/src/org/openqa/selenium/support/AbstractFindByBuilder.java @@ -109,7 +109,7 @@ protected void assertValidFindBy(FindBy findBy) { throw new IllegalArgumentException( String.format( "You must specify at most one location strategy. Number found: %d (%s)", - finders.size(), finders.toString())); + finders.size(), finders)); } } diff --git a/java/src/org/openqa/selenium/support/Color.java b/java/src/org/openqa/selenium/support/Color.java index 60c4da53ee439..0c772ab7cd9b8 100644 --- a/java/src/org/openqa/selenium/support/Color.java +++ b/java/src/org/openqa/selenium/support/Color.java @@ -116,7 +116,7 @@ public int hashCode() { result = 31 * result + green; result = 31 * result + blue; temp = alpha != +0.0d ? Double.doubleToLongBits(alpha) : 0L; - result = 31 * result + (int) (temp ^ (temp >>> 32)); + result = 31 * result + Long.hashCode(temp); return result; } diff --git a/java/test/org/openqa/selenium/bidi/input/DefaultMouseTest.java b/java/test/org/openqa/selenium/bidi/input/DefaultMouseTest.java index f21609d0dc771..f9ac975f2995b 100644 --- a/java/test/org/openqa/selenium/bidi/input/DefaultMouseTest.java +++ b/java/test/org/openqa/selenium/bidi/input/DefaultMouseTest.java @@ -481,7 +481,7 @@ public void testCanMoveOverAndOutOfAnElement() { inputModule.perform( windowHandle, getBuilder(driver) - .moveToElement(redbox, redSize.getWidth() / 1 + 1, redSize.getHeight() / 1 + 1) + .moveToElement(redbox, redSize.getWidth() + 1, redSize.getHeight() + 1) .getSequences()); wait.until(attributeToBe(redbox, "background-color", Colors.GREEN.getColorValue().asRgba())); diff --git a/java/test/org/openqa/selenium/bidi/input/DragAndDropTest.java b/java/test/org/openqa/selenium/bidi/input/DragAndDropTest.java index f6568f29c98eb..425aecf3133b0 100644 --- a/java/test/org/openqa/selenium/bidi/input/DragAndDropTest.java +++ b/java/test/org/openqa/selenium/bidi/input/DragAndDropTest.java @@ -57,7 +57,7 @@ private static void sleep(int ms) { try { Thread.sleep(ms); } catch (InterruptedException e) { - throw new RuntimeException("Interrupted: " + e.toString()); + throw new RuntimeException("Interrupted: " + e); } } diff --git a/java/test/org/openqa/selenium/interactions/DefaultMouseTest.java b/java/test/org/openqa/selenium/interactions/DefaultMouseTest.java index 1649713b4579a..00b00471a6833 100644 --- a/java/test/org/openqa/selenium/interactions/DefaultMouseTest.java +++ b/java/test/org/openqa/selenium/interactions/DefaultMouseTest.java @@ -404,7 +404,7 @@ public void testCanMoveOverAndOutOfAnElement() { .isEqualTo(RED.getColorValue()); getBuilder(driver) - .moveToElement(redbox, redSize.getWidth() / 1 + 1, redSize.getHeight() / 1 + 1) + .moveToElement(redbox, redSize.getWidth() + 1, redSize.getHeight() + 1) .perform(); wait.until(attributeToBe(redbox, "background-color", Colors.GREEN.getColorValue().asRgba())); diff --git a/java/test/org/openqa/selenium/interactions/PenPointerTest.java b/java/test/org/openqa/selenium/interactions/PenPointerTest.java index ad26947242920..1dcb6affdcaf1 100644 --- a/java/test/org/openqa/selenium/interactions/PenPointerTest.java +++ b/java/test/org/openqa/selenium/interactions/PenPointerTest.java @@ -367,7 +367,7 @@ public void testCanMoveOverAndOutOfAnElement() { .isEqualTo(RED.getColorValue()); setDefaultPen(driver) - .moveToElement(redbox, redSize.getWidth() / 1 + 1, redSize.getHeight() / 1 + 1) + .moveToElement(redbox, redSize.getWidth() + 1, redSize.getHeight() + 1) .perform(); wait.until(attributeToBe(redbox, "background-color", Colors.GREEN.getColorValue().asRgba())); @@ -407,8 +407,8 @@ public void setPointerEventProperties() { Rectangle rect = pointerArea.getRect(); - int centerX = (int) Math.floor(rect.width / 2 + rect.getX()); - int centerY = (int) Math.floor(rect.height / 2 + rect.getY()); + int centerX = rect.width / 2 + rect.getX(); + int centerY = rect.height / 2 + rect.getY(); Assertions.assertThat(moveTo.get("button")).isEqualTo("-1"); Assertions.assertThat(moveTo.get("pageX")).isEqualTo("" + centerX); Assertions.assertThat(moveTo.get("pageY")).isEqualTo("" + centerY); From 5cd4bd2477e68ea35874913a1a7ef2a00e3bf382 Mon Sep 17 00:00:00 2001 From: Joe Bandenburg Date: Tue, 7 May 2024 01:24:59 -0400 Subject: [PATCH 013/723] [cdp][java] Allow filters to recover from failed requests in NetworkInterceptor (#13847) Co-authored-by: Puja Jagani --- .../devtools/RequestFailedException.java | 29 +++++++++++++++++++ .../selenium/devtools/idealized/Network.java | 18 ++++++++++-- .../devtools/NetworkInterceptorTest.java | 23 ++++++++++++++- 3 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 java/src/org/openqa/selenium/devtools/RequestFailedException.java diff --git a/java/src/org/openqa/selenium/devtools/RequestFailedException.java b/java/src/org/openqa/selenium/devtools/RequestFailedException.java new file mode 100644 index 0000000000000..6ffef0c946fc3 --- /dev/null +++ b/java/src/org/openqa/selenium/devtools/RequestFailedException.java @@ -0,0 +1,29 @@ +// 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.devtools; + +import org.openqa.selenium.WebDriverException; +import org.openqa.selenium.remote.http.Filter; +import org.openqa.selenium.remote.http.HttpHandler; + +/** + * This exception is thrown by the final {@link HttpHandler} in a {@link Filter} chain when the + * browser fails to send a HTTP request. It can be caught in a {@link Filter} to handle the error + * by, for example, returning a custom HTTP response. + */ +public class RequestFailedException extends WebDriverException {} diff --git a/java/src/org/openqa/selenium/devtools/idealized/Network.java b/java/src/org/openqa/selenium/devtools/idealized/Network.java index 2c09e877a7973..ec36b5d40d5d0 100644 --- a/java/src/org/openqa/selenium/devtools/idealized/Network.java +++ b/java/src/org/openqa/selenium/devtools/idealized/Network.java @@ -45,6 +45,7 @@ import org.openqa.selenium.devtools.DevToolsException; import org.openqa.selenium.devtools.Event; import org.openqa.selenium.devtools.NetworkInterceptor; +import org.openqa.selenium.devtools.RequestFailedException; import org.openqa.selenium.internal.Either; import org.openqa.selenium.internal.Require; import org.openqa.selenium.remote.http.Contents; @@ -202,8 +203,12 @@ public void prepareToInterceptTraffic() { String id = getRequestId(pausedRequest); if (hasErrorResponse(pausedRequest)) { - pendingResponses.remove(id); - devTools.send(continueWithoutModification(pausedRequest)); + CompletableFuture future = pendingResponses.remove(id); + if (future == null) { + devTools.send(continueWithoutModification(pausedRequest)); + } else { + future.completeExceptionally(new RequestFailedException()); + } return; } @@ -244,6 +249,11 @@ public void prepareToInterceptTraffic() { pendingResponses.remove(id); return STOP_PROCESSING; } catch (ExecutionException e) { + if (e.getCause() instanceof RequestFailedException) { + // Throwing here will give the user's filter a chance to intercept + // the failure and handle it. + throw (RequestFailedException) e.getCause(); + } if (fetchEnabled.get()) { LOG.log(WARNING, e, () -> "Unable to process request"); } @@ -261,6 +271,10 @@ public void prepareToInterceptTraffic() { } devTools.send(fulfillRequest(pausedRequest, forBrowser)); + } catch (RequestFailedException e) { + // If the exception reaches here, we know the user's filter has not handled it and the + // browser should continue its normal error handling. + devTools.send(continueWithoutModification(pausedRequest)); } catch (TimeoutException e) { if (fetchEnabled.get()) { throw e; diff --git a/java/test/org/openqa/selenium/devtools/NetworkInterceptorTest.java b/java/test/org/openqa/selenium/devtools/NetworkInterceptorTest.java index f916a1772c115..2999f1666c099 100644 --- a/java/test/org/openqa/selenium/devtools/NetworkInterceptorTest.java +++ b/java/test/org/openqa/selenium/devtools/NetworkInterceptorTest.java @@ -254,11 +254,32 @@ void shouldHandleRedirects() { @Test @NoDriverBeforeTest - void shouldProceedAsNormalIfRequestResultInAnKnownError() { + void shouldProceedAsNormalIfRequestResultInAnKnownErrorAndExceptionNotCaughtByFilter() { Filter filter = next -> next; try (NetworkInterceptor ignored = new NetworkInterceptor(driver, filter)) { assertThatExceptionOfType(WebDriverException.class) .isThrownBy(() -> driver.get("http://localhost:" + PortProber.findFreePort())); } } + + @Test + @NoDriverBeforeTest + void shouldPassResponseBackToBrowserIfRequestResultsInAnKnownErrorAndExceptionCaughtByFilter() { + Filter filter = + next -> + req -> { + try { + return next.execute(req); + } catch (RequestFailedException e) { + return new HttpResponse() + .setStatus(200) + .setContent(Contents.utf8String("Hello, World!")); + } + }; + try (NetworkInterceptor ignored = new NetworkInterceptor(driver, filter)) { + driver.get("http://localhost:" + PortProber.findFreePort()); + String body = driver.findElement(By.tagName("body")).getText(); + assertThat(body).contains("Hello, World!"); + } + } } From 0345a23bebf54aead25bb0f11c9c5c9d63112adc Mon Sep 17 00:00:00 2001 From: Selenium CI Bot Date: Tue, 7 May 2024 07:25:34 +0200 Subject: [PATCH 014/723] [dotnet][rb][java][js][py] Automated Browser Version Update (#13903) Update pinned browser versions Co-authored-by: Selenium CI Bot Co-authored-by: Diego Molina --- common/repositories.bzl | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/common/repositories.bzl b/common/repositories.bzl index bc71b842c4616..db8debcf8d304 100644 --- a/common/repositories.bzl +++ b/common/repositories.bzl @@ -50,8 +50,8 @@ js_library( http_archive( name = "linux_beta_firefox", - url = "https://ftp.mozilla.org/pub/firefox/releases/126.0b8/linux-x86_64/en-US/firefox-126.0b8.tar.bz2", - sha256 = "75198959b1eeedc81be229ad3066ee6d49ecde985ce5d5d11d61f0914e288517", + url = "https://ftp.mozilla.org/pub/firefox/releases/126.0b9/linux-x86_64/en-US/firefox-126.0b9.tar.bz2", + sha256 = "053e60089c6ab85507dca96ad8c9d32e3fc6d21ac5bdf7e616c673327804565f", build_file_content = """ load("@aspect_rules_js//js:defs.bzl", "js_library") package(default_visibility = ["//visibility:public"]) @@ -72,8 +72,8 @@ js_library( dmg_archive( name = "mac_beta_firefox", - url = "https://ftp.mozilla.org/pub/firefox/releases/126.0b8/mac/en-US/Firefox%20126.0b8.dmg", - sha256 = "ca247dbfa1b092f36c75ab785acb0c54e608545b76dc06fbac9a9034df0daf8a", + url = "https://ftp.mozilla.org/pub/firefox/releases/126.0b9/mac/en-US/Firefox%20126.0b9.dmg", + sha256 = "67806b532db26059fbe747ec3fc2f6306d9bb4b09e1b264c49461c4d613b5366", build_file_content = """ load("@aspect_rules_js//js:defs.bzl", "js_library") package(default_visibility = ["//visibility:public"]) @@ -123,10 +123,10 @@ js_library( pkg_archive( name = "mac_edge", - url = "https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/8325266a-e5ef-4b92-b110-6e387417723c/MicrosoftEdge-124.0.2478.67.pkg", - sha256 = "4c79de91852bda6a779761d06cfa00d48ae4f08dfe3903543f3674b973bd780b", + url = "https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/e6f7f9ba-499c-44cb-9c19-28daeaa82dc6/MicrosoftEdge-124.0.2478.80.pkg", + sha256 = "fc667b0401c05bbe0e4d337cc593641e2b653107fafd363b401cd32baa8a4f53", move = { - "MicrosoftEdge-124.0.2478.67.pkg/Payload/Microsoft Edge.app": "Edge.app", + "MicrosoftEdge-124.0.2478.80.pkg/Payload/Microsoft Edge.app": "Edge.app", }, build_file_content = """ load("@aspect_rules_js//js:defs.bzl", "js_library") @@ -143,8 +143,8 @@ js_library( deb_archive( name = "linux_edge", - url = "https://packages.microsoft.com/repos/edge/pool/main/m/microsoft-edge-stable/microsoft-edge-stable_124.0.2478.67-1_amd64.deb", - sha256 = "3d12f66a279b0a82b478625696f23e1ac935e0596d57e19a41da232ee0c58a65", + url = "https://packages.microsoft.com/repos/edge/pool/main/m/microsoft-edge-stable/microsoft-edge-stable_124.0.2478.80-1_amd64.deb", + sha256 = "a7eb75d95730c520eec998f755fcc427a9b4ac6a150bbb267b21e8383b6dc105", build_file_content = """ load("@aspect_rules_js//js:defs.bzl", "js_library") package(default_visibility = ["//visibility:public"]) @@ -165,8 +165,8 @@ js_library( http_archive( name = "linux_edgedriver", - url = "https://msedgedriver.azureedge.net/124.0.2478.67/edgedriver_linux64.zip", - sha256 = "25a169807beb4fc2485cf601f04c76cfffcc2c1e23a875941bc8aa41bee0587c", + url = "https://msedgedriver.azureedge.net/124.0.2478.80/edgedriver_linux64.zip", + sha256 = "4c9192c8e42ac1e1d779784ba95a0b28807cc75ae1be07be740f40bc20410670", build_file_content = """ load("@aspect_rules_js//js:defs.bzl", "js_library") package(default_visibility = ["//visibility:public"]) @@ -182,8 +182,8 @@ js_library( http_archive( name = "mac_edgedriver", - url = "https://msedgedriver.azureedge.net/124.0.2478.67/edgedriver_mac64.zip", - sha256 = "571d910bc662e2dfcf10e47cf40d11f76568b893abbde877f2beb487693ed983", + url = "https://msedgedriver.azureedge.net/124.0.2478.80/edgedriver_mac64.zip", + sha256 = "f8d8b0eaacb884196e5f368a64cad246a86e5a92941b0d37c5d7aa8ebb0fec1f", build_file_content = """ load("@aspect_rules_js//js:defs.bzl", "js_library") package(default_visibility = ["//visibility:public"]) From 2062410a5340f68d9e4e20398fda9e200fff306f Mon Sep 17 00:00:00 2001 From: Selenium CI Bot Date: Wed, 8 May 2024 10:33:16 +0200 Subject: [PATCH 015/723] [dotnet][rb][java][js][py] Automated Browser Version Update (#13916) Update pinned browser versions Co-authored-by: Selenium CI Bot --- common/repositories.bzl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/common/repositories.bzl b/common/repositories.bzl index db8debcf8d304..cb0fc09386f48 100644 --- a/common/repositories.bzl +++ b/common/repositories.bzl @@ -199,8 +199,8 @@ js_library( http_archive( name = "linux_chrome", - url = "https://storage.googleapis.com/chrome-for-testing-public/124.0.6367.91/linux64/chrome-linux64.zip", - sha256 = "035b3bce9748423b3d0c3f74fc6ff0f1a5b29a6454eff74565bab10af7397b75", + url = "https://storage.googleapis.com/chrome-for-testing-public/124.0.6367.155/linux64/chrome-linux64.zip", + sha256 = "0761489e320bb56a29f53c051abea0a26418afcef62af2fa9bf1d4768a78d005", build_file_content = """ load("@aspect_rules_js//js:defs.bzl", "js_library") package(default_visibility = ["//visibility:public"]) @@ -221,8 +221,8 @@ js_library( http_archive( name = "mac_chrome", - url = "https://storage.googleapis.com/chrome-for-testing-public/124.0.6367.91/mac-x64/chrome-mac-x64.zip", - sha256 = "729da107fadce00d7d1f60347a9e5276f6fdec5d0131a7f551d3297261ed1dd8", + url = "https://storage.googleapis.com/chrome-for-testing-public/124.0.6367.155/mac-x64/chrome-mac-x64.zip", + sha256 = "30456654c6699f2b8b6378a08d82caff439da1834213cb65e3536e669fc0e7ad", strip_prefix = "chrome-mac-x64", patch_cmds = [ "mv 'Google Chrome for Testing.app' Chrome.app", @@ -243,8 +243,8 @@ js_library( http_archive( name = "linux_chromedriver", - url = "https://storage.googleapis.com/chrome-for-testing-public/124.0.6367.91/linux64/chromedriver-linux64.zip", - sha256 = "c70691361eec965c8d6aaf3e68b0190d0dee0e0d3a72edca62a734d8b58f4b2c", + url = "https://storage.googleapis.com/chrome-for-testing-public/124.0.6367.155/linux64/chromedriver-linux64.zip", + sha256 = "7ae76046edce32e4c14de5fcceb9ba4a18268dcb0d87368160400fff89f54899", strip_prefix = "chromedriver-linux64", build_file_content = """ load("@aspect_rules_js//js:defs.bzl", "js_library") @@ -261,8 +261,8 @@ js_library( http_archive( name = "mac_chromedriver", - url = "https://storage.googleapis.com/chrome-for-testing-public/124.0.6367.91/mac-x64/chromedriver-mac-x64.zip", - sha256 = "44638284ae0986b15481563fe58aa01342852d197a6bb5f6965c3565f8623d76", + url = "https://storage.googleapis.com/chrome-for-testing-public/124.0.6367.155/mac-x64/chromedriver-mac-x64.zip", + sha256 = "e0c6700f68e08ceac14ed923c56d171fe9597cff308fb67a7a0ecbc05ce208f5", strip_prefix = "chromedriver-mac-x64", build_file_content = """ load("@aspect_rules_js//js:defs.bzl", "js_library") From 67ba0054e34cff220e68b457e88a0859114ff250 Mon Sep 17 00:00:00 2001 From: Puja Jagani Date: Wed, 8 May 2024 16:53:35 +0530 Subject: [PATCH 016/723] [js] Ensure parity in the locators used by methods (#13902) --- .../node/selenium-webdriver/lib/select.js | 44 ++++++------------- 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/javascript/node/selenium-webdriver/lib/select.js b/javascript/node/selenium-webdriver/lib/select.js index b68286f840692..d341552cabe36 100644 --- a/javascript/node/selenium-webdriver/lib/select.js +++ b/javascript/node/selenium-webdriver/lib/select.js @@ -36,7 +36,7 @@ 'use strict' -const { By, escapeCss } = require('./by') +const { By } = require('./by') const error = require('./error') /** @@ -146,6 +146,10 @@ class Select { * @param {WebElement} element Select WebElement. */ constructor(element) { + if (element === null) { + throw new Error(`Element must not be null. Please provide a valid ,