From f4a86a484be6e86038dd5973b6958ee18a88e292 Mon Sep 17 00:00:00 2001 From: Augustin Gottlieb Pequeno <33221555+aguspe@users.noreply.github.com> Date: Tue, 30 Jul 2024 14:54:59 +0200 Subject: [PATCH 01/34] [rb] BUGFIX: Add stamp to nightly build (#14320) * Add stamp to nightly build * Update version.rb * Revert rakefile changes --- rb/lib/selenium/webdriver/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rb/lib/selenium/webdriver/version.rb b/rb/lib/selenium/webdriver/version.rb index 0d5f30b465640..44e68c127c214 100644 --- a/rb/lib/selenium/webdriver/version.rb +++ b/rb/lib/selenium/webdriver/version.rb @@ -19,6 +19,6 @@ module Selenium module WebDriver - VERSION = '4.23.0' + VERSION = '4.24.0.nightly' end # WebDriver end # Selenium From 97d56d04e1b4ab4f8e527f8849b777c1e91d13f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Sautter?= Date: Tue, 30 Jul 2024 18:15:01 +0200 Subject: [PATCH 02/34] [java] close the HttClient in case starting the session fails --- .../node/config/DriverServiceSessionFactory.java | 13 +++++++++---- .../grid/node/docker/DockerSessionFactory.java | 9 +++++++-- .../grid/node/relay/RelaySessionFactory.java | 1 + 3 files changed, 17 insertions(+), 6 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 211672f870bed..dbf5a16638da2 100644 --- a/java/src/org/openqa/selenium/grid/node/config/DriverServiceSessionFactory.java +++ b/java/src/org/openqa/selenium/grid/node/config/DriverServiceSessionFactory.java @@ -146,6 +146,7 @@ public Either apply(CreateSessionRequest sess capabilities = removeCapability(capabilities, "browserVersion"); } + HttpClient client = null; try { service.start(); @@ -154,7 +155,7 @@ public Either apply(CreateSessionRequest sess ClientConfig clientConfig = ClientConfig.defaultConfig().readTimeout(sessionTimeout).baseUrl(serviceURL); - HttpClient client = clientFactory.createClient(clientConfig); + client = clientFactory.createClient(clientConfig); Command command = new Command(null, DriverCommand.NEW_SESSION(capabilities)); @@ -188,6 +189,7 @@ public Either apply(CreateSessionRequest sess caps = readVncEndpoint(capabilities, caps); span.addEvent("Driver service created session", attributeMap); + final HttpClient fClient = client; return Either.right( new DefaultActiveSession( tracer, @@ -201,8 +203,9 @@ public Either apply(CreateSessionRequest sess Instant.now()) { @Override public void stop() { - service.stop(); - client.close(); + try (fClient) { + service.stop(); + } } }); } catch (Exception e) { @@ -217,7 +220,9 @@ public void stop() { attributeMap.put(AttributeKey.EXCEPTION_MESSAGE.getKey(), errorMessage); span.addEvent(AttributeKey.EXCEPTION_EVENT.getKey(), attributeMap); - service.stop(); + try (final HttpClient fClient = client) { + service.stop(); + } return Either.left(new SessionNotCreatedException(errorMessage)); } } catch (Exception e) { 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 9a681c1fdd434..48f567f576268 100644 --- a/java/src/org/openqa/selenium/grid/node/docker/DockerSessionFactory.java +++ b/java/src/org/openqa/selenium/grid/node/docker/DockerSessionFactory.java @@ -197,6 +197,7 @@ public Either apply(CreateSessionRequest sess String.format( "Unable to connect to docker server (container id: %s)", container.getId()); LOG.warning(message); + client.close(); return Either.left(new RetrySessionRequestException(message)); } LOG.info(String.format("Server is ready (container id: %s)", container.getId())); @@ -222,6 +223,7 @@ public Either apply(CreateSessionRequest sess container.stop(Duration.ofMinutes(1)); String message = "Unable to create session: " + e.getMessage(); LOG.log(Level.WARNING, message, e); + client.close(); return Either.left(new SessionNotCreatedException(message)); } @@ -348,9 +350,10 @@ private Container startVideoContainer( Container videoContainer = docker.create(containerConfig); videoContainer.start(); String videoContainerIp = runningInDocker ? videoContainer.inspect().getIp() : "localhost"; + URI videoContainerUrl = URI.create(String.format("http://%s:%s", videoContainerIp, videoPort)); + HttpClient videoClient = + clientFactory.createClient(ClientConfig.defaultConfig().baseUri(videoContainerUrl)); try { - URL videoContainerUrl = new URL(String.format("http://%s:%s", videoContainerIp, videoPort)); - HttpClient videoClient = clientFactory.createClient(videoContainerUrl); LOG.fine(String.format("Waiting for video recording... (id: %s)", videoContainer.getId())); waitForServerToStart(videoClient, Duration.ofMinutes(1)); } catch (Exception e) { @@ -360,6 +363,8 @@ private Container startVideoContainer( "Unable to verify video recording started (container id: %s), %s", videoContainer.getId(), e.getMessage()); LOG.warning(message); + videoClient.close(); + return null; } LOG.info(String.format("Video container started (id: %s)", videoContainer.getId())); return videoContainer; 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 86860ab0919e1..fc0c9849ece97 100644 --- a/java/src/org/openqa/selenium/grid/node/relay/RelaySessionFactory.java +++ b/java/src/org/openqa/selenium/grid/node/relay/RelaySessionFactory.java @@ -215,6 +215,7 @@ public Either apply(CreateSessionRequest sess "Error while creating session with the service %s. %s", serviceUrl, e.getMessage()); attributeMap.put(EXCEPTION_MESSAGE.getKey(), errorMessage); span.addEvent(EXCEPTION_EVENT.getKey(), attributeMap); + client.close(); return Either.left(new SessionNotCreatedException(errorMessage)); } } catch (Exception e) { From 7833dc0cff1d30268a81abbb3b9f3f8b06a6dd5f Mon Sep 17 00:00:00 2001 From: Diego Molina Date: Wed, 31 Jul 2024 14:52:51 +0200 Subject: [PATCH 03/34] [rb] Updating the Gemfile.lock as well --- rb/Gemfile.lock | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/rb/Gemfile.lock b/rb/Gemfile.lock index d99af4f3dd4bb..dadfd59708695 100644 --- a/rb/Gemfile.lock +++ b/rb/Gemfile.lock @@ -3,7 +3,7 @@ PATH specs: selenium-devtools (0.127.0) selenium-webdriver (~> 4.2) - selenium-webdriver (4.23.0) + selenium-webdriver (4.24.0.nightly) base64 (~> 0.2) logger (~> 1.4) rexml (~> 3.2, >= 3.2.5) @@ -41,6 +41,8 @@ GEM diff-lcs (1.5.1) drb (2.2.1) ffi (1.17.0) + ffi (1.17.0-java) + ffi (1.17.0-x86_64-darwin) fileutils (1.7.2) git (1.19.1) addressable (~> 2.8) @@ -49,9 +51,11 @@ GEM i18n (1.14.5) concurrent-ruby (~> 1.0) io-console (0.7.2) + io-console (0.7.2-java) irb (1.14.0) rdoc (>= 4.0.0) reline (>= 0.4.2) + jar-dependencies (0.4.1) json (2.7.2) json (2.7.2-java) language_server-protocol (3.17.0.3) @@ -67,9 +71,11 @@ GEM racc psych (5.1.2) stringio - public_suffix (6.0.0) - racc (1.8.0) - racc (1.8.0-java) + psych (5.1.2-java) + jar-dependencies (>= 0.1.7) + public_suffix (6.0.1) + racc (1.8.1) + racc (1.8.1-java) rack (2.2.9) rainbow (3.1.1) rake (13.2.1) @@ -189,4 +195,4 @@ DEPENDENCIES yard (~> 0.9.11, >= 0.9.36) BUNDLED WITH - 2.2.33 + 2.5.14 From 9d01f114587e25862395d97944c2fa38268bb110 Mon Sep 17 00:00:00 2001 From: Diego Molina Date: Wed, 31 Jul 2024 17:49:26 +0200 Subject: [PATCH 04/34] [build] Using MSEdgeDriver 127.0.2651.72 for the build --- common/repositories.bzl | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/common/repositories.bzl b/common/repositories.bzl index bb4fd2c9fe389..d8a33c6d2800d 100644 --- a/common/repositories.bzl +++ b/common/repositories.bzl @@ -142,8 +142,8 @@ js_library( http_archive( name = "linux_edgedriver", - url = "https://msedgedriver.azureedge.net/127.0.2651.74/edgedriver_linux64.zip", - sha256 = "e6cb5d1a177cf4975efbf4b0868cc5de002d0e534611706c965008f78c28f5ae", + url = "https://msedgedriver.azureedge.net/127.0.2651.72/edgedriver_linux64.zip", + sha256 = "d549371e14bd6f3522d58ba88328cc411af86146b48f923fb9a9072569032103", build_file_content = """ load("@aspect_rules_js//js:defs.bzl", "js_library") package(default_visibility = ["//visibility:public"]) @@ -159,8 +159,8 @@ js_library( http_archive( name = "mac_edgedriver", - url = "https://msedgedriver.azureedge.net/127.0.2651.74/edgedriver_mac64.zip", - sha256 = "2ec351cb1d4d3838b1c0917a513d14282560cd90b7b376d665cf981546274525", + url = "https://msedgedriver.azureedge.net/127.0.2651.72/edgedriver_mac64.zip", + sha256 = "bf409629b5a0e741048bb825dfe41a2327e2a90640e06c755c4df65596a569f0", build_file_content = """ load("@aspect_rules_js//js:defs.bzl", "js_library") package(default_visibility = ["//visibility:public"]) @@ -176,8 +176,8 @@ js_library( http_archive( name = "linux_chrome", - url = "https://storage.googleapis.com/chrome-for-testing-public/127.0.6533.72/linux64/chrome-linux64.zip", - sha256 = "9ea898023336c4e5e0719fbe3cfc52caeaa93b1db51c8638178490b7a82e8146", + url = "https://storage.googleapis.com/chrome-for-testing-public/127.0.6533.88/linux64/chrome-linux64.zip", + sha256 = "20e2000334f8cefa115ad3e2c55d6ad0e3e254be33a5fd0b9178c3d1a9c78ba9", build_file_content = """ load("@aspect_rules_js//js:defs.bzl", "js_library") package(default_visibility = ["//visibility:public"]) @@ -198,8 +198,8 @@ js_library( http_archive( name = "mac_chrome", - url = "https://storage.googleapis.com/chrome-for-testing-public/127.0.6533.72/mac-x64/chrome-mac-x64.zip", - sha256 = "40d4c456d221e762859e82c1b5844fbfe86aedb2818d75f6094967382fbe72e7", + url = "https://storage.googleapis.com/chrome-for-testing-public/127.0.6533.88/mac-x64/chrome-mac-x64.zip", + sha256 = "91a010d846597e068f63b0d6ebb56f6a242ced697bc2b8375e22a24fc668582a", strip_prefix = "chrome-mac-x64", patch_cmds = [ "mv 'Google Chrome for Testing.app' Chrome.app", @@ -220,8 +220,8 @@ js_library( http_archive( name = "linux_chromedriver", - url = "https://storage.googleapis.com/chrome-for-testing-public/127.0.6533.72/linux64/chromedriver-linux64.zip", - sha256 = "a7971098c76d7bb4df4cfa2183eae922ccb2624d4e29235bd01c1a316987b82a", + url = "https://storage.googleapis.com/chrome-for-testing-public/127.0.6533.88/linux64/chromedriver-linux64.zip", + sha256 = "d603382aacda709d775f9366067da15ba2ff6bbccddb5ad264193a6b42230a8c", strip_prefix = "chromedriver-linux64", build_file_content = """ load("@aspect_rules_js//js:defs.bzl", "js_library") @@ -238,8 +238,8 @@ js_library( http_archive( name = "mac_chromedriver", - url = "https://storage.googleapis.com/chrome-for-testing-public/127.0.6533.72/mac-x64/chromedriver-mac-x64.zip", - sha256 = "73f94c90e7685bfb57e7ba2997fc1e24687f8b251e4d31795de8ecec8a40f908", + url = "https://storage.googleapis.com/chrome-for-testing-public/127.0.6533.88/mac-x64/chromedriver-mac-x64.zip", + sha256 = "056f37a603c988ac5d4352b8fbc28c0c606abd1f89de2fbc01998a7e76129969", strip_prefix = "chromedriver-mac-x64", build_file_content = """ load("@aspect_rules_js//js:defs.bzl", "js_library") From ef6a5e4fd045d02e346ef32bb43b54dc9a025ad9 Mon Sep 17 00:00:00 2001 From: Diego Molina Date: Wed, 31 Jul 2024 18:41:24 +0200 Subject: [PATCH 05/34] [build] Adding linux_edge repo back even if MS did not publish one --- MODULE.bazel | 9 ++++++--- common/repositories.bzl | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 509056c344299..8bcae4d2ae052 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -41,7 +41,11 @@ linter.register(name = "rust-rustfmt") node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node") node.toolchain(node_version = "20.9.0") -pnpm = use_extension("@aspect_rules_js//npm:extensions.bzl", "pnpm", dev_dependency = True) +pnpm = use_extension( + "@aspect_rules_js//npm:extensions.bzl", + "pnpm", + dev_dependency = True, +) use_repo(pnpm, "pnpm") npm = use_extension("@aspect_rules_js//npm:extensions.bzl", "npm") @@ -347,8 +351,7 @@ use_repo( "linux_beta_firefox", "linux_chrome", "linux_chromedriver", - # Commenting out `linux_edge` since this is not created, but it really should be. - #"linux_edge", + "linux_edge", "linux_edgedriver", "linux_firefox", "linux_geckodriver", diff --git a/common/repositories.bzl b/common/repositories.bzl index d8a33c6d2800d..191ee8ca28657 100644 --- a/common/repositories.bzl +++ b/common/repositories.bzl @@ -1,6 +1,7 @@ # This file has been generated using `bazel run scripts:pinned_browsers` load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +load("//common/private:deb_archive.bzl", "deb_archive") load("//common/private:dmg_archive.bzl", "dmg_archive") load("//common/private:drivers.bzl", "local_drivers") load("//common/private:pkg_archive.bzl", "pkg_archive") @@ -140,6 +141,28 @@ js_library( """, ) + deb_archive( + name = "linux_edge", + url = "https://packages.microsoft.com/repos/edge/pool/main/m/microsoft-edge-stable/microsoft-edge-stable_127.0.2651.74-1_amd64.deb", + sha256 = "533f5228cf9ffa30b135ca9d84a8b0f53a82bf63", + build_file_content = """ +load("@aspect_rules_js//js:defs.bzl", "js_library") +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "files", + srcs = glob(["**/*"]), +) + +exports_files(["opt/microsoft/msedge/microsoft-edge"]) + +js_library( + name = "edge-js", + data = [":files"], +) +""", + ) + http_archive( name = "linux_edgedriver", url = "https://msedgedriver.azureedge.net/127.0.2651.72/edgedriver_linux64.zip", From c063faee5df1bdc31879b645f6968686e1002de9 Mon Sep 17 00:00:00 2001 From: Diego Molina Date: Wed, 31 Jul 2024 19:04:33 +0200 Subject: [PATCH 06/34] [build] Adding the correct hash for linux_edge --- common/repositories.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/repositories.bzl b/common/repositories.bzl index 191ee8ca28657..4331d1a017c2d 100644 --- a/common/repositories.bzl +++ b/common/repositories.bzl @@ -144,7 +144,7 @@ js_library( deb_archive( name = "linux_edge", url = "https://packages.microsoft.com/repos/edge/pool/main/m/microsoft-edge-stable/microsoft-edge-stable_127.0.2651.74-1_amd64.deb", - sha256 = "533f5228cf9ffa30b135ca9d84a8b0f53a82bf63", + sha256 = "5d7363177d366c0247a304c9dc9caa09158d7768a632736c8cf36b0278340328", build_file_content = """ load("@aspect_rules_js//js:defs.bzl", "js_library") package(default_visibility = ["//visibility:public"]) From f16c2b90a2dcc4ffcd8a7498c274ccaa15282222 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Wed, 31 Jul 2024 20:25:39 +0300 Subject: [PATCH 07/34] [dotnet] Fix running of support tests in CI bazel (#14314) * Fix running of support tests in CI bazel * And here --------- Co-authored-by: Diego Molina --- dotnet/test/support/Events/BUILD.bazel | 8 ++++---- dotnet/test/support/Extensions/BUILD.bazel | 4 ++-- dotnet/test/support/UI/BUILD.bazel | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/dotnet/test/support/Events/BUILD.bazel b/dotnet/test/support/Events/BUILD.bazel index 497f55ad62b7f..250be2b042394 100644 --- a/dotnet/test/support/Events/BUILD.bazel +++ b/dotnet/test/support/Events/BUILD.bazel @@ -8,10 +8,10 @@ dotnet_nunit_test_suite( name = "SmallTests", size = "small", srcs = SMALL_TESTS, - target_frameworks = ["net7.0"], + target_frameworks = ["net8.0"], deps = [ "//dotnet/src/support", - "//dotnet/src/webdriver", + "//dotnet/src/webdriver:webdriver-net8.0", "//dotnet/test/common:fixtures", framework("nuget", "NUnit"), framework("nuget", "Moq"), @@ -36,10 +36,10 @@ dotnet_nunit_test_suite( data = [ "//dotnet/test/common:test-data", ], - target_frameworks = ["net7.0"], + target_frameworks = ["net8.0"], deps = [ "//dotnet/src/support", - "//dotnet/src/webdriver", + "//dotnet/src/webdriver:webdriver-net8.0", "//dotnet/test/common:fixtures", framework("nuget", "NUnit"), ], diff --git a/dotnet/test/support/Extensions/BUILD.bazel b/dotnet/test/support/Extensions/BUILD.bazel index 6d3db657b1dfe..b2468e129118d 100644 --- a/dotnet/test/support/Extensions/BUILD.bazel +++ b/dotnet/test/support/Extensions/BUILD.bazel @@ -4,10 +4,10 @@ dotnet_nunit_test_suite( name = "SmallTests", size = "small", srcs = glob(["*.cs"]), - target_frameworks = ["net7.0"], + target_frameworks = ["net8.0"], deps = [ "//dotnet/src/support", - "//dotnet/src/webdriver", + "//dotnet/src/webdriver:webdriver-net8.0", "//dotnet/test/common:fixtures", framework("nuget", "Moq"), framework("nuget", "NUnit"), diff --git a/dotnet/test/support/UI/BUILD.bazel b/dotnet/test/support/UI/BUILD.bazel index b8305c24c6fac..ef626213b0ebf 100644 --- a/dotnet/test/support/UI/BUILD.bazel +++ b/dotnet/test/support/UI/BUILD.bazel @@ -13,10 +13,10 @@ dotnet_nunit_test_suite( name = "SmallTests", size = "small", srcs = SMALL_TESTS, - target_frameworks = ["net7.0"], + target_frameworks = ["net8.0"], deps = [ "//dotnet/src/support", - "//dotnet/src/webdriver", + "//dotnet/src/webdriver:webdriver-net8.0", "//dotnet/test/common:fixtures", framework("nuget", "NUnit"), framework("nuget", "Moq"), @@ -41,10 +41,10 @@ dotnet_nunit_test_suite( data = [ "//dotnet/test/common:test-data", ], - target_frameworks = ["net7.0"], + target_frameworks = ["net8.0"], deps = [ "//dotnet/src/support", - "//dotnet/src/webdriver", + "//dotnet/src/webdriver:webdriver-net8.0", "//dotnet/test/common:fixtures", framework("nuget", "NUnit"), ], From 9e78deef5fc28ea7d234aa20d51f9b79292caadc Mon Sep 17 00:00:00 2001 From: Diego Molina Date: Wed, 31 Jul 2024 21:20:15 +0200 Subject: [PATCH 08/34] [nightly] Bumping to nightly versions --- dotnet/selenium-dotnet-version.bzl | 2 +- java/version.bzl | 2 +- javascript/node/selenium-webdriver/BUILD.bazel | 2 +- javascript/node/selenium-webdriver/package.json | 2 +- package-lock.json | 2 +- py/BUILD.bazel | 2 +- py/docs/source/conf.py | 2 +- py/selenium/webdriver/__init__.py | 2 +- py/setup.py | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dotnet/selenium-dotnet-version.bzl b/dotnet/selenium-dotnet-version.bzl index f699712bd705b..40ecf911659a8 100644 --- a/dotnet/selenium-dotnet-version.bzl +++ b/dotnet/selenium-dotnet-version.bzl @@ -1,6 +1,6 @@ # BUILD FILE SYNTAX: STARLARK -SE_VERSION = "4.23.0" +SE_VERSION = "4.24.0-nightly202407312116" ASSEMBLY_VERSION = "4.0.0.0" SUPPORTED_NET_STANDARD_VERSIONS = ["netstandard2.0"] diff --git a/java/version.bzl b/java/version.bzl index 4cf7912512a3b..9f65a9fd3c6e2 100644 --- a/java/version.bzl +++ b/java/version.bzl @@ -1,2 +1,2 @@ -SE_VERSION = "4.23.0" +SE_VERSION = "4.24.0-SNAPSHOT" TOOLS_JAVA_VERSION = "17" diff --git a/javascript/node/selenium-webdriver/BUILD.bazel b/javascript/node/selenium-webdriver/BUILD.bazel index 66844cdac465b..3559f4ec6b25f 100644 --- a/javascript/node/selenium-webdriver/BUILD.bazel +++ b/javascript/node/selenium-webdriver/BUILD.bazel @@ -11,7 +11,7 @@ load("//javascript/private:browsers.bzl", "BROWSERS") npm_link_all_packages(name = "node_modules") -VERSION = "4.23.0" +VERSION = "4.24.0-nightly202407312115" BROWSER_VERSIONS = [ "v85", diff --git a/javascript/node/selenium-webdriver/package.json b/javascript/node/selenium-webdriver/package.json index e422383fddba1..b452da3ecc7ae 100644 --- a/javascript/node/selenium-webdriver/package.json +++ b/javascript/node/selenium-webdriver/package.json @@ -1,6 +1,6 @@ { "name": "selenium-webdriver", - "version": "4.23.0", + "version": "4.24.0-nightly202407312115", "description": "The official WebDriver JavaScript bindings from the Selenium project", "license": "Apache-2.0", "keywords": [ diff --git a/package-lock.json b/package-lock.json index 36d433820e1b5..9753905a49343 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1707,7 +1707,7 @@ } }, "javascript/node/selenium-webdriver": { - "version": "4.23.0", + "version": "4.24.0-nightly202407312115", "license": "Apache-2.0", "dependencies": { "jszip": "^3.10.1", diff --git a/py/BUILD.bazel b/py/BUILD.bazel index 413050bc649c2..0cb2fbe21c10e 100644 --- a/py/BUILD.bazel +++ b/py/BUILD.bazel @@ -62,7 +62,7 @@ compile_pip_requirements( ], ) -SE_VERSION = "4.24.0.dev202407241614" +SE_VERSION = "4.24.0.dev202407312116" BROWSER_VERSIONS = [ "v85", diff --git a/py/docs/source/conf.py b/py/docs/source/conf.py index 09e676e44c93c..493229e91ad6e 100644 --- a/py/docs/source/conf.py +++ b/py/docs/source/conf.py @@ -58,7 +58,7 @@ # The short X.Y version. version = '4.24' # The full version, including alpha/beta/rc tags. -release = '4.24.0.dev202407241614' +release = '4.24.0.dev202407312116' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/py/selenium/webdriver/__init__.py b/py/selenium/webdriver/__init__.py index c1d5659aac33e..cab256e5ff17e 100644 --- a/py/selenium/webdriver/__init__.py +++ b/py/selenium/webdriver/__init__.py @@ -44,7 +44,7 @@ from .wpewebkit.service import Service as WPEWebKitService # noqa from .wpewebkit.webdriver import WebDriver as WPEWebKit # noqa -__version__ = "4.24.0.dev202407241614" +__version__ = "4.24.0.dev202407312116" # We need an explicit __all__ because the above won't otherwise be exported. __all__ = [ diff --git a/py/setup.py b/py/setup.py index 717dadb9952b2..b8e6a9866f271 100755 --- a/py/setup.py +++ b/py/setup.py @@ -28,7 +28,7 @@ setup_args = { 'cmdclass': {'install': install}, 'name': 'selenium', - 'version': "4.24.0.dev202407241614", + 'version': "4.24.0.dev202407312116", 'license': 'Apache 2.0', 'description': 'Official Python bindings for Selenium WebDriver.', 'long_description': open(join(abspath(dirname(__file__)), "README.rst")).read(), From 7c8727b1c0b6e4f75d0748f1cc462b4fc61a3521 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 1 Aug 2024 03:32:26 +0700 Subject: [PATCH 09/34] [js] expose selenium version for node.js (#14325) added version to index.js Co-authored-by: Diego Molina --- javascript/node/selenium-webdriver/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/javascript/node/selenium-webdriver/index.js b/javascript/node/selenium-webdriver/index.js index 61fb92739fa47..962b30c655bec 100644 --- a/javascript/node/selenium-webdriver/index.js +++ b/javascript/node/selenium-webdriver/index.js @@ -44,6 +44,7 @@ const BrowsingContext = require('./bidi/browsingContext') const BrowsingContextInspector = require('./bidi/browsingContextInspector') const ScriptManager = require('./bidi/scriptManager') const NetworkInspector = require('./bidi/networkInspector') +const version = require('./package.json').version const Browser = capabilities.Browser const Capabilities = capabilities.Capabilities @@ -794,3 +795,4 @@ exports.BrowsingContext = BrowsingContext exports.BrowsingContextInspector = BrowsingContextInspector exports.ScriptManager = ScriptManager exports.NetworkInspector = NetworkInspector +exports.version = version From c9f60efb31f5ad881b109b203e3269fc244638f2 Mon Sep 17 00:00:00 2001 From: Selenium CI Bot Date: Thu, 1 Aug 2024 00:19:30 +0000 Subject: [PATCH 10/34] Update mirror info (Thu Aug 1 00:19:30 UTC 2024) --- common/mirror/selenium | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/mirror/selenium b/common/mirror/selenium index 3dd89850fa3b9..fae1b09e7ab6c 100644 --- a/common/mirror/selenium +++ b/common/mirror/selenium @@ -3,13 +3,13 @@ "tag_name": "nightly", "assets": [ { - "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/nightly/selenium-java-4.23.0.zip" + "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/nightly/selenium-java-4.24.0-SNAPSHOT.zip" }, { - "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/nightly/selenium-server-4.23.0.jar" + "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/nightly/selenium-server-4.24.0-SNAPSHOT.jar" }, { - "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/nightly/selenium-server-4.23.0.zip" + "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/nightly/selenium-server-4.24.0-SNAPSHOT.zip" } ] }, From 0b2bb9a487fb6be3fa0ef179cfba39cf0ce2cdc7 Mon Sep 17 00:00:00 2001 From: Lauro Moura Date: Thu, 1 Aug 2024 06:42:19 -0300 Subject: [PATCH 11/34] py: Don't expose 0.0.0.0 as destination IP for tests (#14324) Webkit recently[1] started blocking 0.0.0.0 as destination addresses, and Chrome is also in the process of enabling such change[2]. This commit falls back to use the default localhost IP instead of 0.0.0.0 if we don't want to use the real IP. And if the server is actually using 0.0.0.0, fallback to localhost when generating the URL for the tests. [1] https://github.com/WebKit/WebKit/commit/e59cd4a4330877f4692ab31caaf5039185e845bf [2] https://chromestatus.com/feature/5106143060033536 Co-authored-by: Diego Molina --- py/conftest.py | 2 +- py/test/selenium/webdriver/common/webserver.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index b7edd49884bd2..f2189b6fa5dd8 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -320,7 +320,7 @@ def wait_for_server(url, timeout): @pytest.fixture(autouse=True, scope="session") def webserver(request): - host = get_lan_ip() if request.config.getoption("use_lan_ip") else "0.0.0.0" + host = get_lan_ip() if request.config.getoption("use_lan_ip") else None webserver = SimpleWebServer(host=host) webserver.start() diff --git a/py/test/selenium/webdriver/common/webserver.py b/py/test/selenium/webdriver/common/webserver.py index 2c68b5ec8285f..5a227c1722f6c 100644 --- a/py/test/selenium/webdriver/common/webserver.py +++ b/py/test/selenium/webdriver/common/webserver.py @@ -138,7 +138,7 @@ class SimpleWebServer: def __init__(self, host=DEFAULT_HOST_IP, port=DEFAULT_PORT): self.stop_serving = False - host = host + host = host if host else DEFAULT_HOST_IP port = port while True: try: @@ -171,7 +171,8 @@ def stop(self): def where_is(self, path, localhost=False) -> str: # True force serve the page from localhost - if localhost: + # 0.0.0.0 shouldn't be used as a destination address, so fallback to localhost + if localhost or self.host == "0.0.0.0": return f"http://{DEFAULT_HOST}:{self.port}/{path}" return f"http://{self.host}:{self.port}/{path}" From e28ba1fe1cdc723a02e2ce85cd61d9e624b0adb0 Mon Sep 17 00:00:00 2001 From: MustafaAgamy Date: Thu, 1 Aug 2024 15:59:17 +0300 Subject: [PATCH 12/34] [Java] Migrate the String.Format to String.Format(Locale.US) to handle different langauges for Edge, Chrome and Firefox (#13934) * *Changes Done: - Migrate the String.Format to Formatter.Format in : - ChromeDriverSerivce.java - EdgeDriverService.java - RemoteWebDriver.java *Issue Explaination: - Having System Date & Language in Arabic caused with driver setup. Using String.Format for ports and some other lines caused them to be localized in the system language and in arabic case it caused the numbers and some other character to be localized in arabic, e.g. the port. And that caused an issues when appending the port to the URL in order to setup the browser *Fix explaination: - Now it's utilizaing the Formatter.Format and forcing the localization to be in English.US in the Formatter Constructor * - Apply Suggested Code Enhancements from "codiumai-pr-agent-pro" to the classes changed: - ChromeDriverSerivce.java - EdgeDriverService.java - RemoteWebDriver.java *Changes Done: - Add try with resoruces to handle memory leaks where it's applicables - Changing String.ValueOf to ToString() * * Refactor The Formatting Logic for better optimzation in classes: - ChromeDriverService.java - EdgeDriverService.java - RemoteWebDriver.java - DriverService.java * Add Tests for both Edge and Chrome: - ChromeArabicDateTest.java at test/chrome - EdgeArabicDateTest.java at test/edge * - Added Logic for formatting the required configurations in GekoDriverService.java - Added Test Class for FirefoxArabicDateTest.java -Refactored the code of EdgeArabicDateTest.java And ChromeArabicDateTest.java to follow the same approach * Refactor the Formatter to String.format with Localization in - ChromeDriverService.java - EdgeDriverService.java - GeckoDriverService.java - RemoteWebDriver.java - DriverService.java * Fix spacing * Refactor FirefoxArabicDateTest : - Test added to LARGE_TESTS in BUILD.bazel - Refacotor the Test Logic * Fix spacing in FirefoxArabicDateTest.java * Tests Refactoring : - EdgeArabicDateTest.java - ChomeArabicDateTest.java - FirefoxArabicDateTest.java * [java] Fix formatting * Revert The Changes done to: - DriverService.java - RemoteWebDriver.java Change the logic to Locale.setDefault in : - ChomeDriverSerivce.java - EdgeDriverService.java - GeckDriverService.java * Fix Spaces * Fix Formatting * - Delete the Added Arabic Test Classes - Methods are added to the Functional Test Class for each driver accordingly * - Reverse changes made to class files * Fixing the Tests --------- Co-authored-by: Puja Jagani --- .../chrome/ChromeDriverFunctionalTest.java | 19 ++++++++++++++++++ .../edge/EdgeDriverFunctionalTest.java | 20 +++++++++++++++++++ .../selenium/firefox/FirefoxDriverTest.java | 19 ++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/java/test/org/openqa/selenium/chrome/ChromeDriverFunctionalTest.java b/java/test/org/openqa/selenium/chrome/ChromeDriverFunctionalTest.java index 3a34b6ed4f12d..110f71b618c99 100644 --- a/java/test/org/openqa/selenium/chrome/ChromeDriverFunctionalTest.java +++ b/java/test/org/openqa/selenium/chrome/ChromeDriverFunctionalTest.java @@ -27,6 +27,7 @@ import com.google.common.util.concurrent.Uninterruptibles; import java.time.Duration; import java.util.List; +import java.util.Locale; import java.util.Map; import org.assertj.core.api.Assumptions; import org.junit.jupiter.api.Test; @@ -40,6 +41,7 @@ import org.openqa.selenium.chromium.HasCdp; import org.openqa.selenium.chromium.HasNetworkConditions; import org.openqa.selenium.chromium.HasPermissions; +import org.openqa.selenium.net.PortProber; import org.openqa.selenium.remote.RemoteWebDriverBuilder; import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.testing.Ignore; @@ -200,4 +202,21 @@ void canExecuteCdpCommands() { assertThat(driver.getTitle()).isEqualTo("Hello WebDriver"); } + + @Test + @NoDriverBeforeTest + void shouldLaunchSuccessfullyWithArabicDate() { + Locale arabicLocale = new Locale("ar", "EG"); + Locale.setDefault(arabicLocale); + Locale.setDefault(Locale.US); + + int port = PortProber.findFreePort(); + ChromeDriverService.Builder builder = new ChromeDriverService.Builder(); + builder.usingPort(port); + ChromeDriverService service = builder.build(); + + driver = new ChromeDriver(service, (ChromeOptions) CHROME.getCapabilities()); + driver.get(pages.simpleTestPage); + assertThat(driver.getTitle()).isEqualTo("Hello WebDriver"); + } } diff --git a/java/test/org/openqa/selenium/edge/EdgeDriverFunctionalTest.java b/java/test/org/openqa/selenium/edge/EdgeDriverFunctionalTest.java index 7e070e7869c6b..7e7dce47248bb 100644 --- a/java/test/org/openqa/selenium/edge/EdgeDriverFunctionalTest.java +++ b/java/test/org/openqa/selenium/edge/EdgeDriverFunctionalTest.java @@ -26,6 +26,7 @@ import java.time.Duration; import java.util.List; +import java.util.Locale; import java.util.Map; import org.junit.jupiter.api.Test; import org.openqa.selenium.Capabilities; @@ -38,6 +39,7 @@ import org.openqa.selenium.chromium.HasCdp; import org.openqa.selenium.chromium.HasNetworkConditions; import org.openqa.selenium.chromium.HasPermissions; +import org.openqa.selenium.net.PortProber; import org.openqa.selenium.remote.RemoteWebDriverBuilder; import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.testing.Ignore; @@ -193,4 +195,22 @@ void canExecuteCdpCommands() { assertThat(driver.getTitle()).isEqualTo("Hello WebDriver"); } + + @Test + @NoDriverBeforeTest + void shouldLaunchSuccessfullyWithArabicDate() { + Locale arabicLocale = new Locale("ar", "EG"); + Locale.setDefault(arabicLocale); + Locale.setDefault(Locale.US); + + int port = PortProber.findFreePort(); + EdgeDriverService.Builder builder = new EdgeDriverService.Builder(); + builder.usingPort(port); + EdgeDriverService service = builder.build(); + + driver = new EdgeDriver(service, (EdgeOptions) EDGE.getCapabilities()); + + driver.get(pages.simpleTestPage); + assertThat(driver.getTitle()).isEqualTo("Hello WebDriver"); + } } diff --git a/java/test/org/openqa/selenium/firefox/FirefoxDriverTest.java b/java/test/org/openqa/selenium/firefox/FirefoxDriverTest.java index 0dceb93216e48..8714a26938cf4 100644 --- a/java/test/org/openqa/selenium/firefox/FirefoxDriverTest.java +++ b/java/test/org/openqa/selenium/firefox/FirefoxDriverTest.java @@ -37,6 +37,7 @@ import java.io.IOException; import java.lang.reflect.Field; import java.time.Duration; +import java.util.Locale; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; import org.mockito.ArgumentMatchers; @@ -50,6 +51,7 @@ import org.openqa.selenium.PageLoadStrategy; import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.WebElement; +import org.openqa.selenium.net.PortProber; import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.Command; import org.openqa.selenium.remote.CommandExecutor; @@ -268,5 +270,22 @@ void canSetContext() { assertThat(context.getContext()).isEqualTo(FirefoxCommandContext.CHROME); } + @Test + @NoDriverBeforeTest + void shouldLaunchSuccessfullyWithArabicDate() { + Locale arabicLocale = new Locale("ar", "EG"); + Locale.setDefault(arabicLocale); + Locale.setDefault(Locale.US); + + int port = PortProber.findFreePort(); + GeckoDriverService.Builder builder = new GeckoDriverService.Builder(); + builder.usingPort(port); + GeckoDriverService service = builder.build(); + + driver = new FirefoxDriver(service, (FirefoxOptions) FIREFOX.getCapabilities()); + driver.get(pages.simpleTestPage); + assertThat(driver.getTitle()).isEqualTo("Hello WebDriver"); + } + private static class CustomFirefoxProfile extends FirefoxProfile {} } From c8676eff107a7e5e617c6fc953baad45305cc680 Mon Sep 17 00:00:00 2001 From: Diego Molina Date: Thu, 1 Aug 2024 16:38:08 +0200 Subject: [PATCH 13/34] [java] Adding system property to disable tracing `webdriver.remote.enableTracing` --- .../org/openqa/selenium/remote/RemoteWebDriver.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/java/src/org/openqa/selenium/remote/RemoteWebDriver.java b/java/src/org/openqa/selenium/remote/RemoteWebDriver.java index db470c89757eb..ed3a445a26909 100644 --- a/java/src/org/openqa/selenium/remote/RemoteWebDriver.java +++ b/java/src/org/openqa/selenium/remote/RemoteWebDriver.java @@ -110,6 +110,10 @@ public class RemoteWebDriver TakesScreenshot { private static final Logger LOG = Logger.getLogger(RemoteWebDriver.class.getName()); + + /** Boolean system property that defines whether the tracing is enabled or not. */ + private static final String WEBDRIVER_REMOTE_ENABLE_TRACING = "webdriver.remote.enableTracing"; + private final ElementLocation elementLocation = new ElementLocation(); private Level level = Level.FINE; private ErrorHandler errorHandler = new ErrorHandler(); @@ -132,7 +136,10 @@ protected RemoteWebDriver() { } public RemoteWebDriver(Capabilities capabilities) { - this(getDefaultServerURL(), Require.nonNull("Capabilities", capabilities), true); + this( + getDefaultServerURL(), + Require.nonNull("Capabilities", capabilities), + Boolean.parseBoolean(System.getProperty(WEBDRIVER_REMOTE_ENABLE_TRACING, "true"))); } public RemoteWebDriver(Capabilities capabilities, boolean enableTracing) { @@ -141,7 +148,9 @@ public RemoteWebDriver(Capabilities capabilities, boolean enableTracing) { public RemoteWebDriver(URL remoteAddress, Capabilities capabilities) { this( - createExecutor(Require.nonNull("Server URL", remoteAddress), true), + createExecutor( + Require.nonNull("Server URL", remoteAddress), + Boolean.parseBoolean(System.getProperty(WEBDRIVER_REMOTE_ENABLE_TRACING, "true"))), Require.nonNull("Capabilities", capabilities)); } From 095602dfb6e6c1042d1cd6e5b26fe63bec12a4c8 Mon Sep 17 00:00:00 2001 From: Sri Harsha Date: Fri, 2 Aug 2024 12:50:37 +0530 Subject: [PATCH 14/34] [js]: Update npm deps --- .../node/selenium-webdriver/package.json | 22 +- package-lock.json | 389 ++++++++++-------- pnpm-lock.yaml | 301 ++++++++------ 3 files changed, 394 insertions(+), 318 deletions(-) diff --git a/javascript/node/selenium-webdriver/package.json b/javascript/node/selenium-webdriver/package.json index b452da3ecc7ae..74317909198da 100644 --- a/javascript/node/selenium-webdriver/package.json +++ b/javascript/node/selenium-webdriver/package.json @@ -26,27 +26,27 @@ "@bazel/runfiles": "^5.8.1", "jszip": "^3.10.1", "tmp": "^0.2.3", - "ws": "^8.17.1" + "ws": "^8.18.0" }, "devDependencies": { - "@eslint/js": "^9.5.0", + "@eslint/js": "^9.8.0", "clean-jsdoc-theme": "^4.3.0", - "eslint": "^9.5.0", + "eslint": "^9.8.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-mocha": "^10.4.3", - "eslint-plugin-n": "^17.9.0", + "eslint-plugin-mocha": "^10.5.0", + "eslint-plugin-n": "^17.10.1", "eslint-plugin-no-only-tests": "^3.1.0", - "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-prettier": "^5.2.1", "express": "^4.19.2", - "globals": "^15.6.0", - "has-flag": "^4.0.0", + "globals": "^15.9.0", + "has-flag": "^5.0.1", "jsdoc": "^4.0.3", - "mocha": "^10.5.1", + "mocha": "^10.7.0", "mocha-junit-reporter": "^2.2.1", "multer": "1.4.5-lts.1", - "prettier": "^3.3.2", + "prettier": "^3.3.3", "serve-index": "^1.9.1", - "sinon": "^17.0.1", + "sinon": "^18.0.0", "supports-color": "^9.4.0" }, "scripts": { diff --git a/package-lock.json b/package-lock.json index 9753905a49343..4fdd4b22b2250 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1710,38 +1710,40 @@ "version": "4.24.0-nightly202407312115", "license": "Apache-2.0", "dependencies": { + "@bazel/runfiles": "^5.8.1", "jszip": "^3.10.1", "tmp": "^0.2.3", - "ws": ">=8.16.0" + "ws": "^8.18.0" }, "devDependencies": { - "@bazel/runfiles": "^5.8.1", - "@eslint/js": "^9.1.1", + "@eslint/js": "^9.8.0", "clean-jsdoc-theme": "^4.3.0", - "eslint": "^9.1.0", + "eslint": "^9.8.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-mocha": "^10.4.3", - "eslint-plugin-n": "^17.2.1", + "eslint-plugin-mocha": "^10.5.0", + "eslint-plugin-n": "^17.10.1", "eslint-plugin-no-only-tests": "^3.1.0", - "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-prettier": "^5.2.1", "express": "^4.19.2", - "globals": "^15.0.0", + "globals": "^15.9.0", + "has-flag": "^5.0.1", "jsdoc": "^4.0.3", - "mocha": "^10.4.0", + "mocha": "^10.7.0", "mocha-junit-reporter": "^2.2.1", - "multer": "^1.4.5-lts.1", - "prettier": "^3.2.5", + "multer": "1.4.5-lts.1", + "prettier": "^3.3.3", "serve-index": "^1.9.1", - "sinon": "^17.0.1" + "sinon": "^18.0.0", + "supports-color": "^9.4.0" }, "engines": { "node": ">= 14.21.0" } }, "javascript/node/selenium-webdriver/node_modules/@eslint/eslintrc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.0.2.tgz", - "integrity": "sha512-wV19ZEGEMAC1eHgrS7UQPqsdEiCIbTKTasEfcXAigzoXICcqZSjBZEHlZwNVvKg6UBCjSlos84XiLqsRJnIcIg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -1773,29 +1775,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "javascript/node/selenium-webdriver/node_modules/@eslint/js": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.1.1.tgz", - "integrity": "sha512-5WoDz3Y19Bg2BnErkZTp0en+c/i9PvgFS7MBe1+m60HjFr0hrphlAGp4yzI7pxpt4xShln4ZyYp4neJm8hmOkQ==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "javascript/node/selenium-webdriver/node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, "javascript/node/selenium-webdriver/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -1827,6 +1806,27 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "javascript/node/selenium-webdriver/node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "javascript/node/selenium-webdriver/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "javascript/node/selenium-webdriver/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1846,28 +1846,28 @@ "dev": true }, "javascript/node/selenium-webdriver/node_modules/eslint": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.1.0.tgz", - "integrity": "sha512-1TCBecGFQtItia2o39P7Z4BK1X7ByNPxAiWJvwiyTGcOwYnTiiASgMpNA6a+beu8cFPhEDWvPf6mIlYUJv6sgA==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", + "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^3.0.2", - "@eslint/js": "9.1.1", - "@humanwhocodes/config-array": "^0.13.0", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.17.1", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.8.0", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.2.3", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.1", + "eslint-scope": "^8.0.2", "eslint-visitor-keys": "^4.0.0", - "espree": "^10.0.1", - "esquery": "^1.4.2", + "espree": "^10.1.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", @@ -1893,13 +1893,13 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" } }, "javascript/node/selenium-webdriver/node_modules/eslint-scope": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", - "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -1925,12 +1925,12 @@ } }, "javascript/node/selenium-webdriver/node_modules/espree": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz", - "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, "dependencies": { - "acorn": "^8.11.3", + "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.0.0" }, @@ -1967,9 +1967,9 @@ } }, "javascript/node/selenium-webdriver/node_modules/globals": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.0.0.tgz", - "integrity": "sha512-m/C/yR4mjO6pXDTm9/R/SpYTAIyaUB4EOzcaaMEl7mds7Mshct9GfejiJNQGjHHbdMPey13Kpu4TMbYi9ex1pw==", + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", "dev": true, "engines": { "node": ">=18" @@ -1979,24 +1979,27 @@ } }, "javascript/node/selenium-webdriver/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-5.0.1.tgz", + "integrity": "sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "javascript/node/selenium-webdriver/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -2506,8 +2509,7 @@ "node_modules/@bazel/runfiles": { "version": "5.8.1", "resolved": "https://registry.npmjs.org/@bazel/runfiles/-/runfiles-5.8.1.tgz", - "integrity": "sha512-NDdfpdQ6rZlylgv++iMn5FkObC/QlBQvipinGLSOguTYpRywmieOyJ29XHvUilspwTFSILWpoE9CqMGkHXug1g==", - "dev": true + "integrity": "sha512-NDdfpdQ6rZlylgv++iMn5FkObC/QlBQvipinGLSOguTYpRywmieOyJ29XHvUilspwTFSILWpoE9CqMGkHXug1g==" }, "node_modules/@emotion/babel-plugin": { "version": "11.11.0", @@ -3034,14 +3036,28 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", + "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", @@ -3080,6 +3096,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@eslint/js": { + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", + "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@floating-ui/core": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.2.tgz", @@ -3160,9 +3194,9 @@ "dev": true }, "node_modules/@humanwhocodes/retry": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.2.3.tgz", - "integrity": "sha512-X38nUbachlb01YMlvPFojKoiXq+LzZvuSce70KPMPdeM1Rj03k4dR7lDslhbqXn3Ang4EU3+EAmwEAsbrjHW3g==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", "dev": true, "engines": { "node": ">=18.18" @@ -4171,9 +4205,9 @@ } }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -4208,9 +4242,9 @@ } }, "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, "engines": { "node": ">=6" @@ -4843,9 +4877,9 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dependencies": { "ms": "2.1.2" }, @@ -4962,9 +4996,9 @@ } }, "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, "engines": { "node": ">=0.3.1" @@ -5057,9 +5091,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", - "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -5328,9 +5362,9 @@ } }, "node_modules/eslint-plugin-mocha": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-10.4.3.tgz", - "integrity": "sha512-emc4TVjq5Ht0/upR+psftuz6IBG5q279p+1dSRDeHf+NS9aaerBi3lXKo1SEzwC29hFIW21gO89CEWSvRsi8IQ==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-10.5.0.tgz", + "integrity": "sha512-F2ALmQVPT1GoP27O1JTZGrV9Pqg8k79OeIuvw63UxMtQKREZtmkK1NFgkZQ2TW7L2JSSFKHFPTtHu5z8R9QNRw==", "dev": true, "dependencies": { "eslint-utils": "^3.0.0", @@ -5387,25 +5421,25 @@ } }, "node_modules/eslint-plugin-n": { - "version": "17.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.2.1.tgz", - "integrity": "sha512-uW1+df2bo06kR7ix6nB614RUlvjRPrYxlaX832O6e1MCJp4V7YozEdvMgCYuvn4ltnjPu1FVYhQ2KRrmTNoJfg==", + "version": "17.10.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.10.1.tgz", + "integrity": "sha512-hm/q37W6efDptJXdwirsm6A257iY6ZNtpoSG0wEzFzjJ3AhL7OhEIhdSR2e4OdYfHO5EDeqlCfFrjf9q208IPw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "enhanced-resolve": "^5.15.0", + "enhanced-resolve": "^5.17.0", "eslint-plugin-es-x": "^7.5.0", "get-tsconfig": "^4.7.0", - "globals": "^14.0.0", + "globals": "^15.8.0", "ignore": "^5.2.4", - "minimatch": "^9.0.0", + "minimatch": "^9.0.5", "semver": "^7.5.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" + "url": "https://opencollective.com/eslint" }, "peerDependencies": { "eslint": ">=8.23.0" @@ -5421,9 +5455,9 @@ } }, "node_modules/eslint-plugin-n/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", "dev": true, "engines": { "node": ">=18" @@ -5445,9 +5479,9 @@ } }, "node_modules/eslint-plugin-n/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -5490,13 +5524,13 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", - "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" + "synckit": "^0.9.1" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -7762,31 +7796,31 @@ } }, "node_modules/mocha": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", - "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "8.1.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.0.tgz", + "integrity": "sha512-v8/rBWr2VO5YkspYINnvu81inSz2y3ODJrhO175/Exzor1RcEZZkizgE2A+w/CAXXoESS8Kys5E62dOHGHzULA==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" }, "bin": { "_mocha": "bin/_mocha", @@ -7831,9 +7865,9 @@ } }, "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -7914,9 +7948,9 @@ } }, "node_modules/nise": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz", - "integrity": "sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-6.0.0.tgz", + "integrity": "sha512-K8ePqo9BFvN31HXwEtTNGzgrPpmvgciDsFz8aztFjt4LqKO/JeFD8tBOeuDiCMXrIl/m1YvfH8auSpxfaD09wg==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0", @@ -7927,9 +7961,9 @@ } }, "node_modules/nise/node_modules/path-to-regexp": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", - "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", + "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", "dev": true }, "node_modules/no-case": { @@ -8264,9 +8298,9 @@ } }, "node_modules/prettier": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", - "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -8864,9 +8898,9 @@ "dev": true }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, "dependencies": { "randombytes": "^2.1.0" @@ -9073,32 +9107,23 @@ } }, "node_modules/sinon": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-17.0.1.tgz", - "integrity": "sha512-wmwE19Lie0MLT+ZYNpDymasPHUKTaZHUH/pKEubRXIzySv9Atnlw+BUMGCzWgV7b7wO+Hw6f1TEOr0IUnmU8/g==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-18.0.0.tgz", + "integrity": "sha512-+dXDXzD1sBO6HlmZDd7mXZCR/y5ECiEiGCBSGuFD/kZ0bDTofPYc6JaeGmPSF+1j1MejGUWkORbYOLDyvqCWpA==", "dev": true, "dependencies": { - "@sinonjs/commons": "^3.0.0", + "@sinonjs/commons": "^3.0.1", "@sinonjs/fake-timers": "^11.2.2", "@sinonjs/samsam": "^8.0.0", - "diff": "^5.1.0", - "nise": "^5.1.5", - "supports-color": "^7.2.0" + "diff": "^5.2.0", + "nise": "^6.0.0", + "supports-color": "^7" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/sinon" } }, - "node_modules/sinon/node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/sinon/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -9302,9 +9327,9 @@ } }, "node_modules/synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", + "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", "dev": true, "dependencies": { "@pkgr/core": "^0.1.0", @@ -9639,9 +9664,9 @@ } }, "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", "dev": true }, "node_modules/wrap-ansi": { @@ -9696,9 +9721,9 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "engines": { "node": ">=10.0.0" }, @@ -9776,9 +9801,9 @@ } }, "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "engines": { "node": ">=10" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9c08071ac2135..24ba616517dff 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -108,63 +108,63 @@ importers: specifier: ^0.2.3 version: 0.2.3 ws: - specifier: ^8.17.1 - version: 8.17.1 + specifier: ^8.18.0 + version: 8.18.0 devDependencies: '@eslint/js': - specifier: ^9.5.0 - version: 9.5.0 + specifier: ^9.8.0 + version: 9.8.0 clean-jsdoc-theme: specifier: ^4.3.0 version: 4.3.0(jsdoc@4.0.3) eslint: - specifier: ^9.5.0 - version: 9.5.0(supports-color@9.4.0) + specifier: ^9.8.0 + version: 9.8.0(supports-color@9.4.0) eslint-config-prettier: specifier: ^9.1.0 - version: 9.1.0(eslint@9.5.0) + version: 9.1.0(eslint@9.8.0) eslint-plugin-mocha: - specifier: ^10.4.3 - version: 10.4.3(eslint@9.5.0) + specifier: ^10.5.0 + version: 10.5.0(eslint@9.8.0) eslint-plugin-n: - specifier: ^17.9.0 - version: 17.9.0(eslint@9.5.0) + specifier: ^17.10.1 + version: 17.10.1(eslint@9.8.0) eslint-plugin-no-only-tests: specifier: ^3.1.0 version: 3.1.0 eslint-plugin-prettier: - specifier: ^5.1.3 - version: 5.1.3(eslint-config-prettier@9.1.0)(eslint@9.5.0)(prettier@3.3.2) + specifier: ^5.2.1 + version: 5.2.1(eslint-config-prettier@9.1.0)(eslint@9.8.0)(prettier@3.3.3) express: specifier: ^4.19.2 version: 4.19.2(supports-color@9.4.0) globals: - specifier: ^15.6.0 - version: 15.6.0 + specifier: ^15.9.0 + version: 15.9.0 has-flag: - specifier: ^4.0.0 - version: 4.0.0 + specifier: ^5.0.1 + version: 5.0.1 jsdoc: specifier: ^4.0.3 version: 4.0.3 mocha: - specifier: ^10.5.1 - version: 10.5.1 + specifier: ^10.7.0 + version: 10.7.0 mocha-junit-reporter: specifier: ^2.2.1 - version: 2.2.1(mocha@10.5.1)(supports-color@9.4.0) + version: 2.2.1(mocha@10.7.0)(supports-color@9.4.0) multer: specifier: 1.4.5-lts.1 version: 1.4.5-lts.1 prettier: - specifier: ^3.3.2 - version: 3.3.2 + specifier: ^3.3.3 + version: 3.3.3 serve-index: specifier: ^1.9.1 version: 1.9.1(supports-color@9.4.0) sinon: - specifier: ^17.0.1 - version: 17.0.1 + specifier: ^18.0.0 + version: 18.0.0 supports-color: specifier: ^9.4.0 version: 9.4.0 @@ -247,7 +247,7 @@ packages: '@babel/traverse': 7.24.7 '@babel/types': 7.24.7 convert-source-map: 2.0.0 - debug: 4.3.5(supports-color@9.4.0) + debug: 4.3.5 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -480,7 +480,7 @@ packages: '@babel/helper-split-export-declaration': 7.24.7 '@babel/parser': 7.24.7 '@babel/types': 7.24.7 - debug: 4.3.5(supports-color@9.4.0) + debug: 4.3.5 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -622,6 +622,8 @@ packages: /@esbuild/aix-ppc64@0.19.12: resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] requiresBuild: true dev: true optional: true @@ -629,6 +631,8 @@ packages: /@esbuild/android-arm64@0.19.12: resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} engines: {node: '>=12'} + cpu: [arm64] + os: [android] requiresBuild: true dev: true optional: true @@ -636,6 +640,8 @@ packages: /@esbuild/android-arm@0.19.12: resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} engines: {node: '>=12'} + cpu: [arm] + os: [android] requiresBuild: true dev: true optional: true @@ -643,6 +649,8 @@ packages: /@esbuild/android-x64@0.19.12: resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} engines: {node: '>=12'} + cpu: [x64] + os: [android] requiresBuild: true dev: true optional: true @@ -650,6 +658,8 @@ packages: /@esbuild/darwin-arm64@0.19.12: resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] requiresBuild: true dev: true optional: true @@ -657,6 +667,8 @@ packages: /@esbuild/darwin-x64@0.19.12: resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} engines: {node: '>=12'} + cpu: [x64] + os: [darwin] requiresBuild: true dev: true optional: true @@ -664,6 +676,8 @@ packages: /@esbuild/freebsd-arm64@0.19.12: resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] requiresBuild: true dev: true optional: true @@ -671,6 +685,8 @@ packages: /@esbuild/freebsd-x64@0.19.12: resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] requiresBuild: true dev: true optional: true @@ -678,6 +694,8 @@ packages: /@esbuild/linux-arm64@0.19.12: resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} engines: {node: '>=12'} + cpu: [arm64] + os: [linux] requiresBuild: true dev: true optional: true @@ -685,6 +703,8 @@ packages: /@esbuild/linux-arm@0.19.12: resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} engines: {node: '>=12'} + cpu: [arm] + os: [linux] requiresBuild: true dev: true optional: true @@ -692,6 +712,8 @@ packages: /@esbuild/linux-ia32@0.19.12: resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} engines: {node: '>=12'} + cpu: [ia32] + os: [linux] requiresBuild: true dev: true optional: true @@ -699,6 +721,8 @@ packages: /@esbuild/linux-loong64@0.19.12: resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} engines: {node: '>=12'} + cpu: [loong64] + os: [linux] requiresBuild: true dev: true optional: true @@ -706,6 +730,8 @@ packages: /@esbuild/linux-mips64el@0.19.12: resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] requiresBuild: true dev: true optional: true @@ -713,6 +739,8 @@ packages: /@esbuild/linux-ppc64@0.19.12: resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] requiresBuild: true dev: true optional: true @@ -720,6 +748,8 @@ packages: /@esbuild/linux-riscv64@0.19.12: resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] requiresBuild: true dev: true optional: true @@ -727,6 +757,8 @@ packages: /@esbuild/linux-s390x@0.19.12: resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} engines: {node: '>=12'} + cpu: [s390x] + os: [linux] requiresBuild: true dev: true optional: true @@ -734,6 +766,8 @@ packages: /@esbuild/linux-x64@0.19.12: resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} engines: {node: '>=12'} + cpu: [x64] + os: [linux] requiresBuild: true dev: true optional: true @@ -741,6 +775,8 @@ packages: /@esbuild/netbsd-x64@0.19.12: resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] requiresBuild: true dev: true optional: true @@ -748,6 +784,8 @@ packages: /@esbuild/openbsd-x64@0.19.12: resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] requiresBuild: true dev: true optional: true @@ -755,6 +793,8 @@ packages: /@esbuild/sunos-x64@0.19.12: resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} engines: {node: '>=12'} + cpu: [x64] + os: [sunos] requiresBuild: true dev: true optional: true @@ -762,6 +802,8 @@ packages: /@esbuild/win32-arm64@0.19.12: resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} engines: {node: '>=12'} + cpu: [arm64] + os: [win32] requiresBuild: true dev: true optional: true @@ -769,6 +811,8 @@ packages: /@esbuild/win32-ia32@0.19.12: resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} engines: {node: '>=12'} + cpu: [ia32] + os: [win32] requiresBuild: true dev: true optional: true @@ -776,6 +820,8 @@ packages: /@esbuild/win32-x64@0.19.12: resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} engines: {node: '>=12'} + cpu: [x64] + os: [win32] requiresBuild: true dev: true optional: true @@ -790,13 +836,13 @@ packages: eslint-visitor-keys: 3.4.3 dev: true - /@eslint-community/eslint-utils@4.4.0(eslint@9.5.0): + /@eslint-community/eslint-utils@4.4.0(eslint@9.8.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 9.5.0(supports-color@9.4.0) + eslint: 9.8.0(supports-color@9.4.0) eslint-visitor-keys: 3.4.3 dev: true @@ -805,8 +851,13 @@ packages: engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} dev: true - /@eslint/config-array@0.16.0(supports-color@9.4.0): - resolution: {integrity: sha512-/jmuSd74i4Czf1XXn7wGRWZCuyaUZ330NH1Bek0Pplatt4Sy1S5haN21SCLLdbeKslQ+S0wEJ+++v5YibSi+Lg==} + /@eslint-community/regexpp@4.11.0: + resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/config-array@0.17.1(supports-color@9.4.0): + resolution: {integrity: sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: '@eslint/object-schema': 2.1.4 @@ -821,7 +872,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 - debug: 4.3.5(supports-color@9.4.0) + debug: 4.3.5 espree: 9.6.1 globals: 13.24.0 ignore: 5.3.1 @@ -855,8 +906,8 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@eslint/js@9.5.0: - resolution: {integrity: sha512-A7+AOT2ICkodvtsWnxZP4Xxk3NbZ3VMHd8oihydLRGrJgqqdEz1qSeEgXYyT/Cu8h1TWWsQRejIx48mtjZ5y1w==} + /@eslint/js@9.8.0: + resolution: {integrity: sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dev: true @@ -907,7 +958,7 @@ packages: deprecated: Use @eslint/config-array instead dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.5(supports-color@9.4.0) + debug: 4.3.5 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -1454,7 +1505,7 @@ packages: '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/type-utils': 5.62.0(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.4.5) - debug: 4.3.5(supports-color@9.4.0) + debug: 4.3.5 eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.1 @@ -1479,7 +1530,7 @@ packages: '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5) - debug: 4.3.5(supports-color@9.4.0) + debug: 4.3.5 eslint: 8.57.0 typescript: 5.4.5 transitivePeerDependencies: @@ -1506,7 +1557,7 @@ packages: dependencies: '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5) '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.4.5) - debug: 4.3.5(supports-color@9.4.0) + debug: 4.3.5 eslint: 8.57.0 tsutils: 3.21.0(typescript@5.4.5) typescript: 5.4.5 @@ -1530,7 +1581,7 @@ packages: dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.5(supports-color@9.4.0) + debug: 4.3.5 globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.2 @@ -1638,8 +1689,8 @@ packages: uri-js: 4.4.1 dev: true - /ansi-colors@4.1.1: - resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} + /ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} dev: true @@ -2217,8 +2268,19 @@ packages: ms: 2.1.3 dev: true - /debug@4.3.4(supports-color@8.1.1): - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + /debug@4.3.5: + resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + + /debug@4.3.5(supports-color@8.1.1): + resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -2241,6 +2303,7 @@ packages: dependencies: ms: 2.1.2 supports-color: 9.4.0 + dev: true /decamelize@4.0.0: resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} @@ -2317,11 +2380,6 @@ packages: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - /diff@5.0.0: - resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} - engines: {node: '>=0.3.1'} - dev: true - /diff@5.2.0: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} @@ -2594,23 +2652,23 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - /eslint-compat-utils@0.5.1(eslint@9.5.0): + /eslint-compat-utils@0.5.1(eslint@9.8.0): resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} engines: {node: '>=12'} peerDependencies: eslint: '>=6.0.0' dependencies: - eslint: 9.5.0(supports-color@9.4.0) + eslint: 9.8.0(supports-color@9.4.0) semver: 7.6.2 dev: true - /eslint-config-prettier@9.1.0(eslint@9.5.0): + /eslint-config-prettier@9.1.0(eslint@9.8.0): resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 9.5.0(supports-color@9.4.0) + eslint: 9.8.0(supports-color@9.4.0) dev: true /eslint-config-standard-jsx@11.0.0(eslint-plugin-react@7.34.3)(eslint@8.57.0): @@ -2699,16 +2757,16 @@ packages: - supports-color dev: true - /eslint-plugin-es-x@7.7.0(eslint@9.5.0): + /eslint-plugin-es-x@7.7.0(eslint@9.8.0): resolution: {integrity: sha512-aP3qj8BwiEDPttxQkZdI221DLKq9sI/qHolE2YSQL1/9+xk7dTV+tB1Fz8/IaCA+lnLA1bDEnvaS2LKs0k2Uig==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: eslint: '>=8' dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.8.0) '@eslint-community/regexpp': 4.10.1 - eslint: 9.5.0(supports-color@9.4.0) - eslint-compat-utils: 0.5.1(eslint@9.5.0) + eslint: 9.8.0(supports-color@9.4.0) + eslint-compat-utils: 0.5.1(eslint@9.8.0) dev: true /eslint-plugin-es@4.1.0(eslint@8.57.0): @@ -2757,14 +2815,14 @@ packages: - supports-color dev: true - /eslint-plugin-mocha@10.4.3(eslint@9.5.0): - resolution: {integrity: sha512-emc4TVjq5Ht0/upR+psftuz6IBG5q279p+1dSRDeHf+NS9aaerBi3lXKo1SEzwC29hFIW21gO89CEWSvRsi8IQ==} + /eslint-plugin-mocha@10.5.0(eslint@9.8.0): + resolution: {integrity: sha512-F2ALmQVPT1GoP27O1JTZGrV9Pqg8k79OeIuvw63UxMtQKREZtmkK1NFgkZQ2TW7L2JSSFKHFPTtHu5z8R9QNRw==} engines: {node: '>=14.0.0'} peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 9.5.0(supports-color@9.4.0) - eslint-utils: 3.0.0(eslint@9.5.0) + eslint: 9.8.0(supports-color@9.4.0) + eslint-utils: 3.0.0(eslint@9.8.0) globals: 13.24.0 rambda: 7.5.0 dev: true @@ -2786,18 +2844,18 @@ packages: semver: 7.6.2 dev: true - /eslint-plugin-n@17.9.0(eslint@9.5.0): - resolution: {integrity: sha512-CPSaXDXdrT4nsrOrO4mT4VB6FMUkoySRkHWuuJJHVqsIEjIeZgMY1H7AzSwPbDScikBmLN82KeM1u7ixV7PzGg==} + /eslint-plugin-n@17.10.1(eslint@9.8.0): + resolution: {integrity: sha512-hm/q37W6efDptJXdwirsm6A257iY6ZNtpoSG0wEzFzjJ3AhL7OhEIhdSR2e4OdYfHO5EDeqlCfFrjf9q208IPw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: '>=8.23.0' dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.8.0) enhanced-resolve: 5.17.0 - eslint: 9.5.0(supports-color@9.4.0) - eslint-plugin-es-x: 7.7.0(eslint@9.5.0) + eslint: 9.8.0(supports-color@9.4.0) + eslint-plugin-es-x: 7.7.0(eslint@9.8.0) get-tsconfig: 4.7.5 - globals: 15.6.0 + globals: 15.9.0 ignore: 5.3.1 minimatch: 9.0.5 semver: 7.6.2 @@ -2808,8 +2866,8 @@ packages: engines: {node: '>=5.0.0'} dev: true - /eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0)(eslint@9.5.0)(prettier@3.3.2): - resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} + /eslint-plugin-prettier@5.2.1(eslint-config-prettier@9.1.0)(eslint@9.8.0)(prettier@3.3.3): + resolution: {integrity: sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -2822,11 +2880,11 @@ packages: eslint-config-prettier: optional: true dependencies: - eslint: 9.5.0(supports-color@9.4.0) - eslint-config-prettier: 9.1.0(eslint@9.5.0) - prettier: 3.3.2 + eslint: 9.8.0(supports-color@9.4.0) + eslint-config-prettier: 9.1.0(eslint@9.8.0) + prettier: 3.3.3 prettier-linter-helpers: 1.0.0 - synckit: 0.8.8 + synckit: 0.9.1 dev: true /eslint-plugin-promise@6.2.0(eslint@8.57.0): @@ -2881,8 +2939,8 @@ packages: estraverse: 5.3.0 dev: true - /eslint-scope@8.0.1: - resolution: {integrity: sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==} + /eslint-scope@8.0.2: + resolution: {integrity: sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: esrecurse: 4.3.0 @@ -2906,13 +2964,13 @@ packages: eslint-visitor-keys: 2.1.0 dev: true - /eslint-utils@3.0.0(eslint@9.5.0): + /eslint-utils@3.0.0(eslint@9.8.0): resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} peerDependencies: eslint: '>=5' dependencies: - eslint: 9.5.0(supports-color@9.4.0) + eslint: 9.8.0(supports-color@9.4.0) eslint-visitor-keys: 2.1.0 dev: true @@ -2952,7 +3010,7 @@ packages: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.5(supports-color@9.4.0) + debug: 4.3.5 doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -2983,16 +3041,16 @@ packages: - supports-color dev: true - /eslint@9.5.0(supports-color@9.4.0): - resolution: {integrity: sha512-+NAOZFrW/jFTS3dASCGBxX1pkFD0/fsO+hfAkJ4TyYKwgsXZbqzrw+seCYFCcPCYXvnD67tAnglU7GQTz6kcVw==} + /eslint@9.8.0(supports-color@9.4.0): + resolution: {integrity: sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0) - '@eslint-community/regexpp': 4.10.1 - '@eslint/config-array': 0.16.0(supports-color@9.4.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.8.0) + '@eslint-community/regexpp': 4.11.0 + '@eslint/config-array': 0.17.1(supports-color@9.4.0) '@eslint/eslintrc': 3.1.0(supports-color@9.4.0) - '@eslint/js': 9.5.0 + '@eslint/js': 9.8.0 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.3.0 '@nodelib/fs.walk': 1.2.8 @@ -3001,7 +3059,7 @@ packages: cross-spawn: 7.0.3 debug: 4.3.5(supports-color@9.4.0) escape-string-regexp: 4.0.0 - eslint-scope: 8.0.1 + eslint-scope: 8.0.2 eslint-visitor-keys: 4.0.0 espree: 10.1.0 esquery: 1.5.0 @@ -3383,7 +3441,7 @@ packages: fs.realpath: 1.0.0 inflight: 1.0.6 inherits: 2.0.4 - minimatch: 5.0.1 + minimatch: 5.1.6 once: 1.4.0 dev: true @@ -3403,8 +3461,8 @@ packages: engines: {node: '>=18'} dev: true - /globals@15.6.0: - resolution: {integrity: sha512-UzcJi88Hw//CurUIRa9Jxb0vgOCcuD/MNjwmXp633cyaRKkCWACkoqHCtfZv43b1kqXGg/fpOa8bwgacCeXsVg==} + /globals@15.9.0: + resolution: {integrity: sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==} engines: {node: '>=18'} dev: true @@ -3488,6 +3546,11 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + /has-flag@5.0.1: + resolution: {integrity: sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA==} + engines: {node: '>=12'} + dev: true + /has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} dependencies: @@ -4238,19 +4301,11 @@ packages: dependencies: brace-expansion: 1.1.11 - /minimatch@5.0.1: - resolution: {integrity: sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==} - engines: {node: '>=10'} - dependencies: - brace-expansion: 2.0.1 - dev: true - /minimatch@5.1.6: resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} engines: {node: '>=10'} dependencies: brace-expansion: 2.0.1 - dev: false /minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} @@ -4280,7 +4335,7 @@ packages: hasBin: true dev: true - /mocha-junit-reporter@2.2.1(mocha@10.5.1)(supports-color@9.4.0): + /mocha-junit-reporter@2.2.1(mocha@10.7.0)(supports-color@9.4.0): resolution: {integrity: sha512-iDn2tlKHn8Vh8o4nCzcUVW4q7iXp7cC4EB78N0cDHIobLymyHNwe0XG8HEHHjc3hJlXm0Vy6zcrxaIhnI2fWmw==} peerDependencies: mocha: '>=2.2.5' @@ -4288,37 +4343,37 @@ packages: debug: 4.3.5(supports-color@9.4.0) md5: 2.3.0 mkdirp: 3.0.1 - mocha: 10.5.1 + mocha: 10.7.0 strip-ansi: 6.0.1 xml: 1.0.1 transitivePeerDependencies: - supports-color dev: true - /mocha@10.5.1: - resolution: {integrity: sha512-eq5tEnaz2kM9ade8cuGJBMh5fBb9Ih/TB+ddlmPR+wLQmwLhUwa0ovqDlg7OTfKquW0BI7NUcNWX7DH8sC+3gw==} + /mocha@10.7.0: + resolution: {integrity: sha512-v8/rBWr2VO5YkspYINnvu81inSz2y3ODJrhO175/Exzor1RcEZZkizgE2A+w/CAXXoESS8Kys5E62dOHGHzULA==} engines: {node: '>= 14.0.0'} hasBin: true dependencies: - ansi-colors: 4.1.1 + ansi-colors: 4.1.3 browser-stdout: 1.3.1 chokidar: 3.6.0 - debug: 4.3.4(supports-color@8.1.1) - diff: 5.0.0 + debug: 4.3.5(supports-color@8.1.1) + diff: 5.2.0 escape-string-regexp: 4.0.0 find-up: 5.0.0 glob: 8.1.0 he: 1.2.0 js-yaml: 4.1.0 log-symbols: 4.1.0 - minimatch: 5.0.1 + minimatch: 5.1.6 ms: 2.1.3 - serialize-javascript: 6.0.0 + serialize-javascript: 6.0.2 strip-json-comments: 3.1.1 supports-color: 8.1.1 - workerpool: 6.2.1 + workerpool: 6.5.1 yargs: 16.2.0 - yargs-parser: 20.2.4 + yargs-parser: 20.2.9 yargs-unparser: 2.0.0 dev: true @@ -4359,8 +4414,8 @@ packages: engines: {node: '>= 0.6'} dev: true - /nise@5.1.9: - resolution: {integrity: sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==} + /nise@6.0.0: + resolution: {integrity: sha512-K8ePqo9BFvN31HXwEtTNGzgrPpmvgciDsFz8aztFjt4LqKO/JeFD8tBOeuDiCMXrIl/m1YvfH8auSpxfaD09wg==} dependencies: '@sinonjs/commons': 3.0.1 '@sinonjs/fake-timers': 11.2.2 @@ -4690,8 +4745,8 @@ packages: fast-diff: 1.3.0 dev: true - /prettier@3.3.2: - resolution: {integrity: sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==} + /prettier@3.3.3: + resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} engines: {node: '>=14'} hasBin: true dev: true @@ -5075,8 +5130,8 @@ packages: - supports-color dev: true - /serialize-javascript@6.0.0: - resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} + /serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} dependencies: randombytes: 2.1.0 dev: true @@ -5171,14 +5226,14 @@ packages: object-inspect: 1.13.2 dev: true - /sinon@17.0.1: - resolution: {integrity: sha512-wmwE19Lie0MLT+ZYNpDymasPHUKTaZHUH/pKEubRXIzySv9Atnlw+BUMGCzWgV7b7wO+Hw6f1TEOr0IUnmU8/g==} + /sinon@18.0.0: + resolution: {integrity: sha512-+dXDXzD1sBO6HlmZDd7mXZCR/y5ECiEiGCBSGuFD/kZ0bDTofPYc6JaeGmPSF+1j1MejGUWkORbYOLDyvqCWpA==} dependencies: '@sinonjs/commons': 3.0.1 '@sinonjs/fake-timers': 11.2.2 '@sinonjs/samsam': 8.0.0 diff: 5.2.0 - nise: 5.1.9 + nise: 6.0.0 supports-color: 7.2.0 dev: true @@ -5372,6 +5427,7 @@ packages: /supports-color@9.4.0: resolution: {integrity: sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==} engines: {node: '>=12'} + dev: true /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} @@ -5382,8 +5438,8 @@ packages: engines: {node: '>=0.10'} dev: false - /synckit@0.8.8: - resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} + /synckit@0.9.1: + resolution: {integrity: sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==} engines: {node: ^14.18.0 || >=16.0.0} dependencies: '@pkgr/core': 0.1.1 @@ -5708,8 +5764,8 @@ packages: engines: {node: '>=0.10.0'} dev: true - /workerpool@6.2.1: - resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} + /workerpool@6.5.1: + resolution: {integrity: sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==} dev: true /wrap-ansi@7.0.0: @@ -5723,8 +5779,8 @@ packages: /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - /ws@8.17.1: - resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + /ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -5766,11 +5822,6 @@ packages: engines: {node: '>= 6'} dev: false - /yargs-parser@20.2.4: - resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} - engines: {node: '>=10'} - dev: true - /yargs-parser@20.2.9: resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} engines: {node: '>=10'} From 9c686a563cd9c6e3fe835139e8f43b94744b706b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Sautter?= Date: Fri, 2 Aug 2024 18:00:23 +0200 Subject: [PATCH 15/34] [java] wait for the close response #14280 --- .../remote/http/jdk/JdkHttpClient.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/java/src/org/openqa/selenium/remote/http/jdk/JdkHttpClient.java b/java/src/org/openqa/selenium/remote/http/jdk/JdkHttpClient.java index e936c725eb8f9..1f324de56fd52 100644 --- a/java/src/org/openqa/selenium/remote/http/jdk/JdkHttpClient.java +++ b/java/src/org/openqa/selenium/remote/http/jdk/JdkHttpClient.java @@ -164,6 +164,7 @@ public WebSocket openSocket(HttpRequest request, WebSocket.Listener listener) { throw new ConnectionFailedException("JdkWebSocket initial request execution error", e); } + CompletableFuture closed = new CompletableFuture<>(); CompletableFuture webSocketCompletableFuture = client .newWebSocketBuilder() @@ -222,6 +223,7 @@ public CompletionStage onBinary( public CompletionStage onClose( java.net.http.WebSocket webSocket, int statusCode, String reason) { LOG.fine("Closing websocket"); + closed.complete(statusCode); listener.onClose(statusCode, reason); return null; } @@ -277,7 +279,24 @@ public WebSocket send(Message message) { Level.FINE, "Sending close message, statusCode {0}, reason: {1}", new Object[] {statusCode, closeMessage.reason()}); - makeCall = () -> underlyingSocket.sendClose(statusCode, closeMessage.reason()); + makeCall = + () -> { + CompletableFuture future = + underlyingSocket.sendClose(statusCode, closeMessage.reason()); + try { + closed.get(4, TimeUnit.SECONDS); + } catch (ExecutionException e) { + LOG.log( + Level.WARNING, + "failed to wait for the websocket to close", + e.getCause()); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (java.util.concurrent.TimeoutException e) { + LOG.finer("wait for the websocket to close timed out"); + } + return future; + }; } else { LOG.fine("Output is closed, not sending close message"); return this; From 1167e3d5cfe5ef9e49fcf66e820af209b9e39e2f Mon Sep 17 00:00:00 2001 From: Puja Jagani Date: Tue, 6 Aug 2024 06:56:17 +0530 Subject: [PATCH 16/34] [bidi][js] Add authentication handlers (#14345) * [bidi][js] Add authentication handlers * Fix imports --- .../node/selenium-webdriver/bidi/network.js | 59 ++++++++++++-- .../node/selenium-webdriver/lib/network.js | 78 ++++++++++++++++++ .../node/selenium-webdriver/lib/webdriver.js | 12 +++ .../test/bidi/network_commands_test.js | 6 +- .../test/lib/webdriver_network_test.js | 80 +++++++++++++++++++ 5 files changed, 226 insertions(+), 9 deletions(-) create mode 100644 javascript/node/selenium-webdriver/lib/network.js create mode 100644 javascript/node/selenium-webdriver/test/lib/webdriver_network_test.js diff --git a/javascript/node/selenium-webdriver/bidi/network.js b/javascript/node/selenium-webdriver/bidi/network.js index b0ad6aeb80727..af80fcf145580 100644 --- a/javascript/node/selenium-webdriver/bidi/network.js +++ b/javascript/node/selenium-webdriver/bidi/network.js @@ -21,11 +21,22 @@ const { ContinueResponseParameters } = require('./continueResponseParameters') const { ContinueRequestParameters } = require('./continueRequestParameters') const { ProvideResponseParameters } = require('./provideResponseParameters') +const NetworkEvent = { + BEFORE_REQUEST_SENT: 'network.beforeRequestSent', + RESPONSE_STARTED: 'network.responseStarted', + RESPONSE_COMPLETED: 'network.responseCompleted', + AUTH_REQUIRED: 'network.authRequired', + FETCH_ERROR: 'network.fetchError', +} + /** * Represents all commands and events of Network module. * Described in https://w3c.github.io/webdriver-bidi/#module-network. */ class Network { + #callbackId = 0 + #listener + /** * Represents a Network object. * @constructor @@ -35,6 +46,43 @@ class Network { constructor(driver, browsingContextIds) { this._driver = driver this._browsingContextIds = browsingContextIds + this.#listener = new Map() + this.#listener.set(NetworkEvent.AUTH_REQUIRED, new Map()) + this.#listener.set(NetworkEvent.BEFORE_REQUEST_SENT, new Map()) + this.#listener.set(NetworkEvent.FETCH_ERROR, new Map()) + this.#listener.set(NetworkEvent.RESPONSE_STARTED, new Map()) + this.#listener.set(NetworkEvent.RESPONSE_COMPLETED, new Map()) + } + + addCallback(eventType, callback) { + const id = ++this.#callbackId + + const eventCallbackMap = this.#listener.get(eventType) + eventCallbackMap.set(id, callback) + return id + } + + removeCallback(id) { + let hasId = false + for (const [, callbacks] of this.#listener) { + if (callbacks.has(id)) { + callbacks.delete(id) + hasId = true + } + } + + if (!hasId) { + throw Error(`Callback with id ${id} not found`) + } + } + + invokeCallbacks(eventType, data) { + const callbacks = this.#listener.get(eventType) + if (callbacks) { + for (const [, callback] of callbacks) { + callback(data) + } + } } async init() { @@ -75,10 +123,10 @@ class Network { * Subscribes to the 'network.authRequired' event and handles it with the provided callback. * * @param {Function} callback - The callback function to handle the event. - * @returns {Promise} - A promise that resolves when the subscription is successful. + * @returns {Promise} - A promise that resolves when the subscription is successful. */ async authRequired(callback) { - await this.subscribeAndHandleEvent('network.authRequired', callback) + return await this.subscribeAndHandleEvent('network.authRequired', callback) } /** @@ -97,10 +145,8 @@ class Network { } else { await this.bidi.subscribe(eventType) } - await this._on(callback) - } + let id = this.addCallback(eventType, callback) - async _on(callback) { this.ws = await this.bidi.socket this.ws.on('message', (event) => { const { params } = JSON.parse(Buffer.from(event.toString())) @@ -134,9 +180,10 @@ class Network { params.errorText, ) } - callback(response) + this.invokeCallbacks(eventType, response) } }) + return id } /** diff --git a/javascript/node/selenium-webdriver/lib/network.js b/javascript/node/selenium-webdriver/lib/network.js new file mode 100644 index 0000000000000..c047fd2a7ec4e --- /dev/null +++ b/javascript/node/selenium-webdriver/lib/network.js @@ -0,0 +1,78 @@ +// 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. + +const network = require('../bidi/network') +const { InterceptPhase } = require('../bidi/interceptPhase') +const { AddInterceptParameters } = require('../bidi/addInterceptParameters') + +class Network { + #driver + #network + #callBackInterceptIdMap = new Map() + + constructor(driver) { + this.#driver = driver + } + + // This should be done in the constructor. + // But since it needs to call async methods we cannot do that in the constructor. + // We can have a separate async method that initialises the Script instance. + // However, that pattern does not allow chaining the methods as we would like the user to use it. + // Since it involves awaiting to get the instance and then another await to call the method. + // Using this allows the user to do this "await driver.network.addAuthenticationHandler(callback)" + async #init() { + if (this.#network !== undefined) { + return + } + this.#network = await network(this.#driver) + } + + async addAuthenticationHandler(username, password) { + await this.#init() + + const interceptId = await this.#network.addIntercept(new AddInterceptParameters(InterceptPhase.AUTH_REQUIRED)) + + const id = await this.#network.authRequired(async (event) => { + await this.#network.continueWithAuth(event.request.request, username, password) + }) + + this.#callBackInterceptIdMap.set(id, interceptId) + return id + } + + async removeAuthenticationHandler(id) { + await this.#init() + + const interceptId = this.#callBackInterceptIdMap.get(id) + + await this.#network.removeIntercept(interceptId) + await this.#network.removeCallback(id) + + this.#callBackInterceptIdMap.delete(id) + } + + async clearAuthenticationHandlers() { + for (const [key, value] of this.#callBackInterceptIdMap.entries()) { + await this.#network.removeIntercept(value) + await this.#network.removeCallback(key) + } + + this.#callBackInterceptIdMap.clear() + } +} + +module.exports = Network diff --git a/javascript/node/selenium-webdriver/lib/webdriver.js b/javascript/node/selenium-webdriver/lib/webdriver.js index add28497d0211..ac4e2e1a6a432 100644 --- a/javascript/node/selenium-webdriver/lib/webdriver.js +++ b/javascript/node/selenium-webdriver/lib/webdriver.js @@ -44,6 +44,7 @@ const BIDI = require('../bidi') const { PinnedScript } = require('./pinnedScript') const JSZip = require('jszip') const Script = require('./script') +const Network = require('./network') // Capability names that are defined in the W3C spec. const W3C_CAPABILITY_NAMES = new Set([ @@ -656,6 +657,7 @@ function filterNonW3CCaps(capabilities) { */ class WebDriver { #script = undefined + #network = undefined /** * @param {!(./session.Session|IThenable)} session Either * a known session or a promise that will be resolved to a session. @@ -1116,6 +1118,16 @@ class WebDriver { return this.#script } + network() { + // The Network maintains state of the callbacks. + // Returning a new instance of the same driver will not work while removing callbacks. + if (this.#network === undefined) { + this.#network = new Network(this) + } + + return this.#network + } + validatePrintPageParams(keys, object) { let page = {} let margin = {} diff --git a/javascript/node/selenium-webdriver/test/bidi/network_commands_test.js b/javascript/node/selenium-webdriver/test/bidi/network_commands_test.js index 3c7a686991ebd..7c282aa913e37 100644 --- a/javascript/node/selenium-webdriver/test/bidi/network_commands_test.js +++ b/javascript/node/selenium-webdriver/test/bidi/network_commands_test.js @@ -130,7 +130,7 @@ suite( await driver.get(Pages.logEntryAdded) - assert.strictEqual(counter, 1) + assert.strictEqual(counter >= 1, true) }) it('can continue response', async function () { @@ -145,7 +145,7 @@ suite( await driver.get(Pages.logEntryAdded) - assert.strictEqual(counter, 1) + assert.strictEqual(counter >= 1, true) }) it('can provide response', async function () { @@ -160,7 +160,7 @@ suite( await driver.get(Pages.logEntryAdded) - assert.strictEqual(counter, 1) + assert.strictEqual(counter >= 1, true) }) }) }, diff --git a/javascript/node/selenium-webdriver/test/lib/webdriver_network_test.js b/javascript/node/selenium-webdriver/test/lib/webdriver_network_test.js new file mode 100644 index 0000000000000..538fefa87916d --- /dev/null +++ b/javascript/node/selenium-webdriver/test/lib/webdriver_network_test.js @@ -0,0 +1,80 @@ +// 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. + +'use strict' + +const assert = require('node:assert') +const { Browser } = require('selenium-webdriver') +const { Pages, suite } = require('../../lib/test') +const until = require('selenium-webdriver/lib/until') +const { By } = require('selenium-webdriver') + +suite( + function (env) { + let driver + + beforeEach(async function () { + driver = await env.builder().build() + }) + + afterEach(async function () { + await driver.quit() + }) + + describe('script()', function () { + it('can add authentication handler', async function () { + await driver.network().addAuthenticationHandler('genie', 'bottle') + await driver.get(Pages.basicAuth) + + await driver.wait(until.elementLocated(By.css('pre'))) + let source = await driver.getPageSource() + assert.equal(source.includes('Access granted'), true) + }) + + it('can remove authentication handler', async function () { + const id = await driver.network().addAuthenticationHandler('genie', 'bottle') + + await driver.network().removeAuthenticationHandler(id) + + try { + await driver.get(Pages.basicAuth) + await driver.wait(until.elementLocated(By.css('pre'))) + assert.fail('Page should not be loaded') + } catch (e) { + assert.strictEqual(e.name, 'UnexpectedAlertOpenError') + } + }) + + it('can clear authentication handlers', async function () { + await driver.network().addAuthenticationHandler('genie', 'bottle') + + await driver.network().addAuthenticationHandler('bottle', 'genie') + + await driver.network().clearAuthenticationHandlers() + + try { + await driver.get(Pages.basicAuth) + await driver.wait(until.elementLocated(By.css('pre'))) + assert.fail('Page should not be loaded') + } catch (e) { + assert.strictEqual(e.name, 'UnexpectedAlertOpenError') + } + }) + }) + }, + { browsers: [Browser.FIREFOX] }, +) From 7a18a86ef83a868abb1dfc372c55e5ad6f5002a4 Mon Sep 17 00:00:00 2001 From: Puja Jagani Date: Tue, 6 Aug 2024 10:36:54 +0530 Subject: [PATCH 17/34] [bidi][js] Add high-level script command (#14293) * [bidi][js] Add high-level script command * Fix formatting * Fix tests * Fix linting --------- Co-authored-by: Sri Harsha <12621691+harsha509@users.noreply.github.com> --- .../selenium-webdriver/bidi/protocolValue.js | 86 ++++- .../node/selenium-webdriver/lib/script.js | 16 + .../test/bidi/local_value_test.js | 6 +- .../test/bidi/locate_nodes_test.js | 5 +- .../test/lib/webdriver_script_execute_test.js | 311 ++++++++++++++++++ 5 files changed, 417 insertions(+), 7 deletions(-) create mode 100644 javascript/node/selenium-webdriver/test/lib/webdriver_script_execute_test.js diff --git a/javascript/node/selenium-webdriver/bidi/protocolValue.js b/javascript/node/selenium-webdriver/bidi/protocolValue.js index 059621b792e9e..4bfb27aa221ab 100644 --- a/javascript/node/selenium-webdriver/bidi/protocolValue.js +++ b/javascript/node/selenium-webdriver/bidi/protocolValue.js @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -const { PrimitiveType, NonPrimitiveType, RemoteType } = require('./protocolType') +const { PrimitiveType, NonPrimitiveType, RemoteType, SpecialNumberType } = require('./protocolType') const TYPE_CONSTANT = 'type' const VALUE_CONSTANT = 'value' @@ -189,6 +189,88 @@ class LocalValue { return new ReferenceValue(handle, sharedId) } + static getArgument(argument) { + let localValue = null + + if ( + argument === SpecialNumberType.NAN || + argument === SpecialNumberType.MINUS_ZERO || + argument === SpecialNumberType.INFINITY || + argument === SpecialNumberType.MINUS_INFINITY + ) { + localValue = LocalValue.createSpecialNumberValue(argument) + return localValue + } + + const type = typeof argument + + switch (type) { + case PrimitiveType.STRING: + localValue = LocalValue.createStringValue(argument) + break + case PrimitiveType.NUMBER: + localValue = LocalValue.createNumberValue(argument) + break + case PrimitiveType.BOOLEAN: + localValue = LocalValue.createBooleanValue(argument) + break + case PrimitiveType.BIGINT: + localValue = LocalValue.createBigIntValue(argument.toString()) + break + case PrimitiveType.UNDEFINED: + localValue = LocalValue.createUndefinedValue() + break + case NonPrimitiveType.OBJECT: + if (argument === null) { + localValue = LocalValue.createNullValue() + break + } + if (argument instanceof Date) { + localValue = LocalValue.createDateValue(argument) + } else if (argument instanceof Map) { + const map = [] + + argument.forEach((value, key) => { + let objectKey + if (typeof key === 'string') { + objectKey = key + } else { + objectKey = LocalValue.getArgument(key) + } + const objectValue = LocalValue.getArgument(value) + map.push([objectKey, objectValue]) + }) + localValue = new LocalValue(NonPrimitiveType.MAP, map) + } else if (argument instanceof Set) { + const set = [] + argument.forEach((value) => { + set.push(LocalValue.getArgument(value)) + }) + localValue = LocalValue.createSetValue(set) + } else if (argument instanceof Array) { + const arr = [] + argument.forEach((value) => { + arr.push(LocalValue.getArgument(value)) + }) + localValue = LocalValue.createArrayValue(arr) + } else if (argument instanceof RegExp) { + localValue = LocalValue.createRegularExpressionValue({ + pattern: argument.source, + flags: argument.flags, + }) + } else { + let value = [] + Object.entries(argument).forEach((entry) => { + value.push([LocalValue.getArgument(entry[0]), LocalValue.getArgument(entry[1])]) + }) + localValue = new LocalValue(NonPrimitiveType.OBJECT, value) + } + break + } + + return localValue + } + asMap() { let toReturn = {} toReturn[TYPE_CONSTANT] = this.type @@ -246,7 +328,7 @@ class RemoteValue { } deserializeValue(value, type) { - if ([NonPrimitiveType.MAP, NonPrimitiveType.OBJECT].includes(type)) { + if (type === NonPrimitiveType.OBJECT) { return Object.fromEntries(value) } else if (type === NonPrimitiveType.REGULAR_EXPRESSION) { return new RegExpValue(value.pattern, value.flags) diff --git a/javascript/node/selenium-webdriver/lib/script.js b/javascript/node/selenium-webdriver/lib/script.js index 2a64dd03e7d56..04b8fac06787a 100644 --- a/javascript/node/selenium-webdriver/lib/script.js +++ b/javascript/node/selenium-webdriver/lib/script.js @@ -121,6 +121,22 @@ class Script { await this.#initScript() await this.#script.removePreloadScript(id) } + + async execute(script, ...args) { + await this.#initScript() + + const browsingContextId = await this.#driver.getWindowHandle() + + const argumentList = [] + + args.forEach((arg) => { + argumentList.push(LocalValue.getArgument(arg)) + }) + + const response = await this.#script.callFunctionInBrowsingContext(browsingContextId, script, true, argumentList) + + return response.result + } } module.exports = Script diff --git a/javascript/node/selenium-webdriver/test/bidi/local_value_test.js b/javascript/node/selenium-webdriver/test/bidi/local_value_test.js index d7bc7c4eeef5c..94c4f48bdc82e 100644 --- a/javascript/node/selenium-webdriver/test/bidi/local_value_test.js +++ b/javascript/node/selenium-webdriver/test/bidi/local_value_test.js @@ -350,9 +350,9 @@ suite( let resultValue = result.result.value - assert.equal(Object.keys(resultValue).length, 1) - assert.equal(resultValue['foobar'].type, 'string') - assert.equal(resultValue['foobar'].value, 'foobar') + assert.equal(resultValue[0][0], 'foobar') + assert.equal(resultValue[0][1].type, 'string') + assert.equal(resultValue[0][1].value, 'foobar') }) it('can call function with object argument', async function () { diff --git a/javascript/node/selenium-webdriver/test/bidi/locate_nodes_test.js b/javascript/node/selenium-webdriver/test/bidi/locate_nodes_test.js index a2736b5f40fab..109f2e07ad00e 100644 --- a/javascript/node/selenium-webdriver/test/bidi/locate_nodes_test.js +++ b/javascript/node/selenium-webdriver/test/bidi/locate_nodes_test.js @@ -201,9 +201,10 @@ suite( assert.equal(response.resultType, EvaluateResultType.SUCCESS) assert.equal(response.result.type, 'map') - const sharedId = response.result.value.sharedId + const value = response.result.value[0] - assert.strictEqual(sharedId.value, nodeId) + assert.strictEqual(value[1].type, 'string') + assert.strictEqual(value[1].value, nodeId) }) it('can find element', async function () { diff --git a/javascript/node/selenium-webdriver/test/lib/webdriver_script_execute_test.js b/javascript/node/selenium-webdriver/test/lib/webdriver_script_execute_test.js new file mode 100644 index 0000000000000..79253b2db8d7c --- /dev/null +++ b/javascript/node/selenium-webdriver/test/lib/webdriver_script_execute_test.js @@ -0,0 +1,311 @@ +// 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. + +'use strict' + +const assert = require('node:assert') +const { Browser } = require('selenium-webdriver/') +const { suite } = require('../../lib/test') + +const ScriptManager = require('selenium-webdriver/bidi/scriptManager') +const { LocalValue, RegExpValue } = require('selenium-webdriver/bidi/protocolValue') +const { SpecialNumberType } = require('selenium-webdriver/bidi/protocolType') + +suite( + function (env) { + let driver + + beforeEach(async function () { + driver = await env.builder().build() + }) + + afterEach(async function () { + await driver.quit() + }) + + describe('Execute script', function () { + it('can execute script with undefined argument', async function () { + const result = await driver + .script() + .execute( + '(arg) => {{\n' + + ' if(arg!==undefined)\n' + + ' throw Error("Argument should be undefined, but was "+arg);\n' + + ' return arg;\n' + + ' }}', + undefined, + ) + + assert.equal(result.type, 'undefined') + }) + + it('can execute script with null argument', async function () { + const result = await driver + .script() + .execute( + '(arg) => {{\n' + + ' if(arg!==null)\n' + + ' throw Error("Argument should be null, but was "+arg);\n' + + ' return arg;\n' + + ' }}', + null, + ) + + assert.equal(result.type, 'null') + }) + it('can execute script with minus zero argument', async function () { + const result = await driver + .script() + .execute( + '(arg) => {{\n' + + ' if(arg!==-0)\n' + + ' throw Error("Argument should be -0, but was " + arg);\n' + + ' return arg;\n' + + ' }}', + SpecialNumberType.MINUS_ZERO, + ) + + assert.equal(result.type, 'number') + assert.equal(result.value, '-0') + }) + + it('can execute script with infinity argument', async function () { + const result = await driver + .script() + .execute( + '(arg) => {{\n' + + ' if(arg!==Infinity)\n' + + ' throw Error("Argument should be Infinity, but was "+arg);\n' + + ' return arg;\n' + + ' }}', + SpecialNumberType.INFINITY, + ) + + assert.equal(result.type, 'number') + assert.equal(result.value, 'Infinity') + }) + + it('can execute script with minus infinity argument', async function () { + const result = await driver + .script() + .execute( + '(arg) => {{\n' + + ' if(arg!==-Infinity)\n' + + ' throw Error("Argument should be -Infinity, but was "+arg);\n' + + ' return arg;\n' + + ' }}', + SpecialNumberType.MINUS_INFINITY, + ) + + assert.equal(result.type, 'number') + assert.equal(result.value, '-Infinity') + }) + + it('can execute script with number argument', async function () { + const result = await driver + .script() + .execute( + '(arg) => {{\n' + + ' if(arg!==1.4)\n' + + ' throw Error("Argument should be 1.4, but was "+arg);\n' + + ' return arg;\n' + + ' }}', + 1.4, + ) + + assert.equal(result.type, 'number') + assert.equal(result.value, 1.4) + }) + + it('can execute script with boolean argument', async function () { + const result = await driver + .script() + .execute( + '(arg) => {{\n' + + ' if(arg!==true)\n' + + ' throw Error("Argument should be true, but was "+arg);\n' + + ' return arg;\n' + + ' }}', + true, + ) + + assert.equal(result.type, 'boolean') + assert.equal(result.value, true) + }) + + it('can execute script with big int argument', async function () { + const result = await driver + .script() + .execute( + '(arg) => {{\n' + + ' if(arg!==42n)\n' + + ' throw Error("Argument should be 42n, but was "+arg);\n' + + ' return arg;\n' + + ' }}', + 42n, + ) + + assert.equal(result.type, 'bigint') + assert.equal(result.value, '42') + }) + + it('can execute script with array argument', async function () { + let arrayValue = ['foobar'] + + const result = await driver + .script() + .execute( + '(arg) => {{\n' + + ' if(! (arg instanceof Array))\n' + + ' throw Error("Argument type should be Array, but was "+\n' + + ' Object.prototype.toString.call(arg));\n' + + ' return arg;\n' + + ' }}', + arrayValue, + ) + + assert.equal(result.type, 'array') + + let resultValue = result.value + assert.equal(resultValue.length, 1) + assert.equal(resultValue[0].type, 'string') + assert.equal(resultValue[0].value, 'foobar') + }) + + it('can execute script with set argument', async function () { + let setValues = new Set() + setValues.add('foobar') + setValues.add('test') + + const result = await driver + .script() + .execute( + '(arg) => {{\n' + + ' if(! (arg instanceof Set))\n' + + ' throw Error("Argument type should be Set, but was "+\n' + + ' Object.prototype.toString.call(arg));\n' + + ' return arg;\n' + + ' }}', + setValues, + ) + + assert.equal(result.type, 'set') + + let resultValue = result.value + assert.equal(resultValue.length, 2) + assert.equal(resultValue[0].type, 'string') + assert.equal(resultValue[0].value, 'foobar') + assert.equal(resultValue[1].type, 'string') + assert.equal(resultValue[1].value, 'test') + }) + + it('can execute script with date argument', async function () { + const result = await driver + .script() + .execute( + '(arg) => {{\n' + + ' if(! (arg instanceof Date))\n' + + ' throw Error("Argument type should be Date, but was "+\n' + + ' Object.prototype.toString.call(arg));\n' + + ' return arg;\n' + + ' }}', + new Date('2022-05-31T13:47:29.000Z'), + ) + + assert.equal(result.type, 'date') + assert.equal(result.value, '2022-05-31T13:47:29.000Z') + }) + + it('can execute script with map argument', async function () { + let mapValue = new Map() + mapValue.set(1, 2) + mapValue.set('foo', 'bar') + mapValue.set(true, false) + mapValue.set('baz', [1, 2, 3]) + + const result = await driver + .script() + .execute( + '(arg) => {{\n' + + ' if(! (arg instanceof Map))\n' + + ' throw Error("Argument type should be Map, but was "+\n' + + ' Object.prototype.toString.call(arg));\n' + + ' return arg;\n' + + ' }}', + mapValue, + ) + assert.equal(result.type, 'map') + assert.notEqual(result.value, null) + + let resultValue = result.value + + assert.equal(resultValue.length, 4) + + assert.equal( + JSON.stringify(resultValue), + '[[{"type":"number","value":1},{"type":"number","value":2}],["foo",{"type":"string","value":"bar"}],[{"type":"boolean","value":true},{"type":"boolean","value":false}],["baz",{"type":"array","value":[{"type":"number","value":1},{"type":"number","value":2},{"type":"number","value":3}]}]]', + ) + }) + + it('can execute script with object argument', async function () { + const result = await driver + .script() + .execute( + '(arg) => {{\n' + + ' if(! (arg instanceof Object))\n' + + ' throw Error("Argument type should be Object, but was "+\n' + + ' Object.prototype.toString.call(arg));\n' + + ' return arg;\n' + + ' }}', + { foobar: 'foobar' }, + ) + + assert.equal(result.type, 'object') + + let resultValue = result.value + assert.equal(resultValue['foobar'].type, 'string') + assert.equal(resultValue['foobar'].value, 'foobar') + }) + + it('can execute script with regex argument', async function () { + const id = await driver.getWindowHandle() + const manager = await ScriptManager(id, driver) + let argumentValues = [] + let value = LocalValue.createRegularExpressionValue(new RegExpValue('foo', 'g')) + argumentValues.push(value) + + const result = await driver + .script() + .execute( + '(arg) => {{\n' + + ' if(! (arg instanceof RegExp))\n' + + ' throw Error("Argument type should be RegExp, but was "+\n' + + ' Object.prototype.toString.call(arg));\n' + + ' return arg;\n' + + ' }}', + new RegExp('foo', 'g'), + ) + + let resultValue = result.value + + assert.equal(resultValue.pattern, 'foo') + assert.equal(resultValue.flags, 'g') + }) + }) + }, + { browsers: [Browser.FIREFOX, Browser.CHROME, Browser.EDGE] }, +) From 97eb16c755405103a0b55b1a00ee8a2c3b884aa5 Mon Sep 17 00:00:00 2001 From: Puja Jagani Date: Tue, 6 Aug 2024 11:29:21 +0530 Subject: [PATCH 18/34] [bidi][java] Add authentication handlers (#14334) Related to #13993 --- .../openqa/selenium/bidi/module/Network.java | 6 +- .../org/openqa/selenium/remote/BUILD.bazel | 1 + .../org/openqa/selenium/remote/Network.java | 31 ++++++ .../openqa/selenium/remote/RemoteNetwork.java | 79 +++++++++++++++ .../selenium/remote/RemoteWebDriver.java | 9 ++ .../org/openqa/selenium/WebNetworkTest.java | 99 +++++++++++++++++++ 6 files changed, 222 insertions(+), 3 deletions(-) create mode 100644 java/src/org/openqa/selenium/remote/Network.java create mode 100644 java/src/org/openqa/selenium/remote/RemoteNetwork.java create mode 100644 java/test/org/openqa/selenium/WebNetworkTest.java diff --git a/java/src/org/openqa/selenium/bidi/module/Network.java b/java/src/org/openqa/selenium/bidi/module/Network.java index 5050e368b5519..1237fceeb5023 100644 --- a/java/src/org/openqa/selenium/bidi/module/Network.java +++ b/java/src/org/openqa/selenium/bidi/module/Network.java @@ -169,11 +169,11 @@ public void onResponseCompleted(Consumer consumer) { } } - public void onAuthRequired(Consumer consumer) { + public long onAuthRequired(Consumer consumer) { if (browsingContextIds.isEmpty()) { - this.bidi.addListener(authRequired, consumer); + return this.bidi.addListener(authRequired, consumer); } else { - this.bidi.addListener(browsingContextIds, authRequired, consumer); + return this.bidi.addListener(browsingContextIds, authRequired, consumer); } } diff --git a/java/src/org/openqa/selenium/remote/BUILD.bazel b/java/src/org/openqa/selenium/remote/BUILD.bazel index 07cf0a0ffea52..ff6969e73fcc4 100644 --- a/java/src/org/openqa/selenium/remote/BUILD.bazel +++ b/java/src/org/openqa/selenium/remote/BUILD.bazel @@ -60,6 +60,7 @@ java_library( "//java/src/org/openqa/selenium/bidi", "//java/src/org/openqa/selenium/bidi/log", "//java/src/org/openqa/selenium/bidi/module", + "//java/src/org/openqa/selenium/bidi/network", "//java/src/org/openqa/selenium/bidi/script", "//java/src/org/openqa/selenium/concurrent", "//java/src/org/openqa/selenium/devtools", diff --git a/java/src/org/openqa/selenium/remote/Network.java b/java/src/org/openqa/selenium/remote/Network.java new file mode 100644 index 0000000000000..7c2a4b6893eba --- /dev/null +++ b/java/src/org/openqa/selenium/remote/Network.java @@ -0,0 +1,31 @@ +// 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.remote; + +import org.openqa.selenium.Beta; +import org.openqa.selenium.UsernameAndPassword; + +@Beta +public interface Network { + + long addAuthenticationHandler(UsernameAndPassword usernameAndPassword); + + void removeAuthenticationHandler(long id); + + void clearAuthenticationHandlers(); +} diff --git a/java/src/org/openqa/selenium/remote/RemoteNetwork.java b/java/src/org/openqa/selenium/remote/RemoteNetwork.java new file mode 100644 index 0000000000000..539be1bbfa5d9 --- /dev/null +++ b/java/src/org/openqa/selenium/remote/RemoteNetwork.java @@ -0,0 +1,79 @@ +// 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.remote; + +import java.util.HashMap; +import java.util.Map; +import org.openqa.selenium.Beta; +import org.openqa.selenium.UsernameAndPassword; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.bidi.BiDi; +import org.openqa.selenium.bidi.HasBiDi; +import org.openqa.selenium.bidi.network.AddInterceptParameters; +import org.openqa.selenium.bidi.network.InterceptPhase; + +@Beta +class RemoteNetwork implements Network { + + private final BiDi biDi; + private final org.openqa.selenium.bidi.module.Network network; + + private final Map authCallbackIdMap = new HashMap<>(); + + public RemoteNetwork(WebDriver driver) { + this.biDi = ((HasBiDi) driver).getBiDi(); + this.network = new org.openqa.selenium.bidi.module.Network(driver); + } + + @Override + public long addAuthenticationHandler(UsernameAndPassword usernameAndPassword) { + String intercept = + network.addIntercept(new AddInterceptParameters(InterceptPhase.AUTH_REQUIRED)); + + long id = + network.onAuthRequired( + responseDetails -> + network.continueWithAuth( + responseDetails.getRequest().getRequestId(), usernameAndPassword)); + + authCallbackIdMap.put(id, intercept); + return id; + } + + @Override + public void removeAuthenticationHandler(long id) { + String intercept = authCallbackIdMap.get(id); + + if (intercept != null) { + network.removeIntercept(intercept); + this.biDi.removeListener(id); + authCallbackIdMap.remove(id); + } + } + + @Override + public void clearAuthenticationHandlers() { + authCallbackIdMap.forEach( + (callback, intercept) -> { + network.removeIntercept(intercept); + this.biDi.removeListener(callback); + }); + + authCallbackIdMap.clear(); + } +} diff --git a/java/src/org/openqa/selenium/remote/RemoteWebDriver.java b/java/src/org/openqa/selenium/remote/RemoteWebDriver.java index ed3a445a26909..4afa13ea9be83 100644 --- a/java/src/org/openqa/selenium/remote/RemoteWebDriver.java +++ b/java/src/org/openqa/selenium/remote/RemoteWebDriver.java @@ -130,6 +130,8 @@ public class RemoteWebDriver private Script remoteScript; + private Network remoteNetwork; + // For cglib protected RemoteWebDriver() { this.capabilities = init(new ImmutableCapabilities()); @@ -504,6 +506,13 @@ public Script script() { return this.remoteScript; } + public Network network() { + if (this.remoteNetwork == null) { + this.remoteNetwork = new RemoteNetwork(this); + } + return this.remoteNetwork; + } + protected JsonToWebElementConverter getElementConverter() { return converter; } diff --git a/java/test/org/openqa/selenium/WebNetworkTest.java b/java/test/org/openqa/selenium/WebNetworkTest.java new file mode 100644 index 0000000000000..0684544f3c48e --- /dev/null +++ b/java/test/org/openqa/selenium/WebNetworkTest.java @@ -0,0 +1,99 @@ +// 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; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.environment.webserver.AppServer; +import org.openqa.selenium.environment.webserver.NettyAppServer; +import org.openqa.selenium.remote.RemoteWebDriver; +import org.openqa.selenium.testing.JupiterTestBase; +import org.openqa.selenium.testing.NotYetImplemented; +import org.openqa.selenium.testing.drivers.Browser; + +class WebNetworkTest extends JupiterTestBase { + + private String page; + private AppServer server; + + @BeforeEach + public void setUp() { + server = new NettyAppServer(); + server.start(); + } + + @AfterEach + public void cleanUp() { + driver.quit(); + } + + @Test + @NotYetImplemented(Browser.CHROME) + @NotYetImplemented(Browser.EDGE) + void canAddAuthenticationHandler() { + ((RemoteWebDriver) driver) + .network() + .addAuthenticationHandler(new UsernameAndPassword("test", "test")); + + page = server.whereIs("basicAuth"); + driver.get(page); + + assertThat(driver.findElement(By.tagName("h1")).getText()).isEqualTo("authorized"); + } + + @Test + @NotYetImplemented(Browser.CHROME) + @NotYetImplemented(Browser.EDGE) + void canRemoveAuthenticationHandler() { + long id = + ((RemoteWebDriver) driver) + .network() + .addAuthenticationHandler(new UsernameAndPassword("test", "test")); + + ((RemoteWebDriver) driver).network().removeAuthenticationHandler(id); + page = server.whereIs("basicAuth"); + driver.get(page); + + assertThatExceptionOfType(UnhandledAlertException.class) + .isThrownBy(() -> driver.findElement(By.tagName("h1"))); + } + + @Test + @NotYetImplemented(Browser.CHROME) + @NotYetImplemented(Browser.EDGE) + void canClearAuthenticationHandlers() { + ((RemoteWebDriver) driver) + .network() + .addAuthenticationHandler(new UsernameAndPassword("test", "test")); + + ((RemoteWebDriver) driver) + .network() + .addAuthenticationHandler(new UsernameAndPassword("test1", "test1")); + + ((RemoteWebDriver) driver).network().clearAuthenticationHandlers(); + page = server.whereIs("basicAuth"); + driver.get(page); + + assertThatExceptionOfType(UnhandledAlertException.class) + .isThrownBy(() -> driver.findElement(By.tagName("h1"))); + } +} From b4e78bac0c69276398ed534369d71c643a49d240 Mon Sep 17 00:00:00 2001 From: Boni Garcia Date: Tue, 6 Aug 2024 14:37:04 +0200 Subject: [PATCH 19/34] Include geckodriver 0.35.0 (released on 2024-08-06) in mapping file --- common/geckodriver/geckodriver-support.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/common/geckodriver/geckodriver-support.json b/common/geckodriver/geckodriver-support.json index a88a09550fd5d..60a35a6212597 100644 --- a/common/geckodriver/geckodriver-support.json +++ b/common/geckodriver/geckodriver-support.json @@ -1,5 +1,9 @@ { "geckodriver-releases": [ + { + "geckodriver-version": "0.35.0", + "min-firefox-version": 115 + }, { "geckodriver-version": "0.34.0", "min-firefox-version": 115 From 33c69b5398a3bffb3094af6d20e9697b96c72260 Mon Sep 17 00:00:00 2001 From: joerg1985 <16140691+joerg1985@users.noreply.github.com> Date: Thu, 8 Aug 2024 11:16:43 +0200 Subject: [PATCH 20/34] [grid] ensure the local_sessionmap.remove event is raised (#14337) Co-authored-by: Diego Molina --- .../sessionmap/local/LocalSessionMap.java | 72 ++++++++----------- 1 file changed, 28 insertions(+), 44 deletions(-) diff --git a/java/src/org/openqa/selenium/grid/sessionmap/local/LocalSessionMap.java b/java/src/org/openqa/selenium/grid/sessionmap/local/LocalSessionMap.java index 2dae2e5779e4f..6e2ff03859170 100644 --- a/java/src/org/openqa/selenium/grid/sessionmap/local/LocalSessionMap.java +++ b/java/src/org/openqa/selenium/grid/sessionmap/local/LocalSessionMap.java @@ -20,12 +20,12 @@ import static org.openqa.selenium.remote.RemoteTags.SESSION_ID; import static org.openqa.selenium.remote.RemoteTags.SESSION_ID_EVENT; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.ConcurrentMap; import java.util.logging.Logger; +import java.util.stream.Collectors; import org.openqa.selenium.NoSuchSessionException; import org.openqa.selenium.events.EventBus; import org.openqa.selenium.grid.config.Config; @@ -48,28 +48,14 @@ public class LocalSessionMap extends SessionMap { private static final Logger LOG = Logger.getLogger(LocalSessionMap.class.getName()); private final EventBus bus; - private final Map knownSessions = new ConcurrentHashMap<>(); - private final ReadWriteLock lock = new ReentrantReadWriteLock(/* be fair */ true); + private final ConcurrentMap knownSessions = new ConcurrentHashMap<>(); public LocalSessionMap(Tracer tracer, EventBus bus) { super(tracer); this.bus = Require.nonNull("Event bus", bus); - bus.addListener( - SessionClosedEvent.listener( - id -> { - try (Span span = tracer.getCurrentContext().createSpan("local_sessionmap.remove")) { - AttributeMap attributeMap = tracer.createAttributeMap(); - attributeMap.put(AttributeKey.LOGGER_CLASS.getKey(), getClass().getName()); - SESSION_ID.accept(span, id); - SESSION_ID_EVENT.accept(attributeMap, id); - knownSessions.remove(id); - String sessionDeletedMessage = "Deleted session from local Session Map"; - span.addEvent(sessionDeletedMessage, attributeMap); - LOG.info(String.format("%s, Id: %s", sessionDeletedMessage, id)); - } - })); + bus.addListener(SessionClosedEvent.listener(this::remove)); bus.addListener( NodeRemovedEvent.listener( @@ -77,14 +63,19 @@ public LocalSessionMap(Tracer tracer, EventBus bus) { nodeStatus.getSlots().stream() .filter(slot -> slot.getSession() != null) .map(slot -> slot.getSession().getId()) - .forEach(knownSessions::remove))); + .forEach(this::remove))); bus.addListener( NodeRestartedEvent.listener( - nodeStatus -> - knownSessions - .values() - .removeIf(value -> value.getUri().equals(nodeStatus.getExternalUri())))); + nodeStatus -> { + List toRemove = + knownSessions.entrySet().stream() + .filter((e) -> e.getValue().getUri().equals(nodeStatus.getExternalUri())) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + toRemove.forEach(this::remove); + })); } public static SessionMap create(Config config) { @@ -103,8 +94,6 @@ public boolean isReady() { public boolean add(Session session) { Require.nonNull("Session", session); - Lock writeLock = lock.writeLock(); - writeLock.lock(); try (Span span = tracer.getCurrentContext().createSpan("local_sessionmap.add")) { AttributeMap attributeMap = tracer.createAttributeMap(); attributeMap.put(AttributeKey.LOGGER_CLASS.getKey(), getClass().getName()); @@ -115,8 +104,6 @@ public boolean add(Session session) { span.addEvent("Added session into local session map", attributeMap); return true; - } finally { - writeLock.unlock(); } } @@ -124,30 +111,27 @@ public boolean add(Session session) { public Session get(SessionId id) { Require.nonNull("Session ID", id); - Lock readLock = lock.readLock(); - readLock.lock(); - try { - Session session = knownSessions.get(id); - if (session == null) { - throw new NoSuchSessionException("Unable to find session with ID: " + id); - } - - return session; - } finally { - readLock.unlock(); + Session session = knownSessions.get(id); + if (session == null) { + throw new NoSuchSessionException("Unable to find session with ID: " + id); } + + return session; } @Override public void remove(SessionId id) { Require.nonNull("Session ID", id); - Lock writeLock = lock.writeLock(); - writeLock.lock(); - try { + try (Span span = tracer.getCurrentContext().createSpan("local_sessionmap.remove")) { + AttributeMap attributeMap = tracer.createAttributeMap(); + attributeMap.put(AttributeKey.LOGGER_CLASS.getKey(), getClass().getName()); + SESSION_ID.accept(span, id); + SESSION_ID_EVENT.accept(attributeMap, id); knownSessions.remove(id); - } finally { - writeLock.unlock(); + String sessionDeletedMessage = "Deleted session from local Session Map"; + span.addEvent(sessionDeletedMessage, attributeMap); + LOG.info(String.format("%s, Id: %s", sessionDeletedMessage, id)); } } } From 208c04ccfe529a2e621d70901d8eb7d08a967fd2 Mon Sep 17 00:00:00 2001 From: Puja Jagani Date: Fri, 9 Aug 2024 13:19:54 +0530 Subject: [PATCH 21/34] [bidi][java] Add filter auth handler (#14349) --- .../org/openqa/selenium/remote/Network.java | 4 + .../openqa/selenium/remote/RemoteNetwork.java | 84 ++++++++++++----- .../org/openqa/selenium/WebNetworkTest.java | 89 +++++++++++++++++-- 3 files changed, 147 insertions(+), 30 deletions(-) diff --git a/java/src/org/openqa/selenium/remote/Network.java b/java/src/org/openqa/selenium/remote/Network.java index 7c2a4b6893eba..b64060b980237 100644 --- a/java/src/org/openqa/selenium/remote/Network.java +++ b/java/src/org/openqa/selenium/remote/Network.java @@ -17,6 +17,8 @@ package org.openqa.selenium.remote; +import java.net.URI; +import java.util.function.Predicate; import org.openqa.selenium.Beta; import org.openqa.selenium.UsernameAndPassword; @@ -25,6 +27,8 @@ public interface Network { long addAuthenticationHandler(UsernameAndPassword usernameAndPassword); + long addAuthenticationHandler(Predicate filter, UsernameAndPassword usernameAndPassword); + void removeAuthenticationHandler(long id); void clearAuthenticationHandlers(); diff --git a/java/src/org/openqa/selenium/remote/RemoteNetwork.java b/java/src/org/openqa/selenium/remote/RemoteNetwork.java index 539be1bbfa5d9..4a1f921921d66 100644 --- a/java/src/org/openqa/selenium/remote/RemoteNetwork.java +++ b/java/src/org/openqa/selenium/remote/RemoteNetwork.java @@ -17,8 +17,12 @@ package org.openqa.selenium.remote; -import java.util.HashMap; +import java.net.URI; import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Predicate; import org.openqa.selenium.Beta; import org.openqa.selenium.UsernameAndPassword; import org.openqa.selenium.WebDriver; @@ -33,47 +37,81 @@ class RemoteNetwork implements Network { private final BiDi biDi; private final org.openqa.selenium.bidi.module.Network network; - private final Map authCallbackIdMap = new HashMap<>(); + private final Map authHandlers = new ConcurrentHashMap<>(); + + private final AtomicLong callBackId = new AtomicLong(1); public RemoteNetwork(WebDriver driver) { this.biDi = ((HasBiDi) driver).getBiDi(); this.network = new org.openqa.selenium.bidi.module.Network(driver); + + interceptAuthTraffic(); + } + + private void interceptAuthTraffic() { + this.network.addIntercept(new AddInterceptParameters(InterceptPhase.AUTH_REQUIRED)); + + network.onAuthRequired( + responseDetails -> { + String requestId = responseDetails.getRequest().getRequestId(); + + URI uri = URI.create(responseDetails.getRequest().getUrl()); + Optional authCredentials = getAuthCredentials(uri); + if (authCredentials.isPresent()) { + network.continueWithAuth(requestId, authCredentials.get()); + return; + } + + network.continueWithAuthNoCredentials(requestId); + }); + } + + private Optional getAuthCredentials(URI uri) { + return authHandlers.values().stream() + .filter(authDetails -> authDetails.getFilter().test(uri)) + .map(AuthDetails::getUsernameAndPassword) + .findFirst(); } @Override public long addAuthenticationHandler(UsernameAndPassword usernameAndPassword) { - String intercept = - network.addIntercept(new AddInterceptParameters(InterceptPhase.AUTH_REQUIRED)); + return addAuthenticationHandler(url -> true, usernameAndPassword); + } - long id = - network.onAuthRequired( - responseDetails -> - network.continueWithAuth( - responseDetails.getRequest().getRequestId(), usernameAndPassword)); + @Override + public long addAuthenticationHandler( + Predicate filter, UsernameAndPassword usernameAndPassword) { + long id = this.callBackId.incrementAndGet(); - authCallbackIdMap.put(id, intercept); + authHandlers.put(id, new AuthDetails(filter, usernameAndPassword)); return id; } @Override public void removeAuthenticationHandler(long id) { - String intercept = authCallbackIdMap.get(id); - - if (intercept != null) { - network.removeIntercept(intercept); - this.biDi.removeListener(id); - authCallbackIdMap.remove(id); - } + authHandlers.remove(id); } @Override public void clearAuthenticationHandlers() { - authCallbackIdMap.forEach( - (callback, intercept) -> { - network.removeIntercept(intercept); - this.biDi.removeListener(callback); - }); + authHandlers.clear(); + } + + private class AuthDetails { + private final Predicate filter; + private final UsernameAndPassword usernameAndPassword; - authCallbackIdMap.clear(); + public AuthDetails(Predicate filter, UsernameAndPassword usernameAndPassword) { + this.filter = filter; + this.usernameAndPassword = usernameAndPassword; + } + + public Predicate getFilter() { + return filter; + } + + public UsernameAndPassword getUsernameAndPassword() { + return usernameAndPassword; + } } } diff --git a/java/test/org/openqa/selenium/WebNetworkTest.java b/java/test/org/openqa/selenium/WebNetworkTest.java index 0684544f3c48e..8036b5edce59b 100644 --- a/java/test/org/openqa/selenium/WebNetworkTest.java +++ b/java/test/org/openqa/selenium/WebNetworkTest.java @@ -20,14 +20,16 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import java.net.URI; +import java.util.function.Predicate; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.environment.webserver.AppServer; import org.openqa.selenium.environment.webserver.NettyAppServer; import org.openqa.selenium.remote.RemoteWebDriver; +import org.openqa.selenium.testing.Ignore; import org.openqa.selenium.testing.JupiterTestBase; -import org.openqa.selenium.testing.NotYetImplemented; import org.openqa.selenium.testing.drivers.Browser; class WebNetworkTest extends JupiterTestBase { @@ -47,8 +49,8 @@ public void cleanUp() { } @Test - @NotYetImplemented(Browser.CHROME) - @NotYetImplemented(Browser.EDGE) + @Ignore(Browser.CHROME) + @Ignore(Browser.EDGE) void canAddAuthenticationHandler() { ((RemoteWebDriver) driver) .network() @@ -61,8 +63,64 @@ void canAddAuthenticationHandler() { } @Test - @NotYetImplemented(Browser.CHROME) - @NotYetImplemented(Browser.EDGE) + @Ignore(Browser.CHROME) + @Ignore(Browser.EDGE) + void canAddAuthenticationHandlerWithFilter() { + Predicate filter = uri -> uri.getPath().contains("basicAuth"); + + ((RemoteWebDriver) driver) + .network() + .addAuthenticationHandler(filter, new UsernameAndPassword("test", "test")); + + page = server.whereIs("basicAuth"); + driver.get(page); + + assertThat(driver.findElement(By.tagName("h1")).getText()).isEqualTo("authorized"); + } + + @Test + @Ignore(Browser.CHROME) + @Ignore(Browser.EDGE) + void canAddMultipleAuthenticationHandlersWithFilter() { + ((RemoteWebDriver) driver) + .network() + .addAuthenticationHandler( + uri -> uri.getPath().contains("basicAuth"), new UsernameAndPassword("test", "test")); + + ((RemoteWebDriver) driver) + .network() + .addAuthenticationHandler( + uri -> uri.getPath().contains("test"), new UsernameAndPassword("test1", "test1")); + + page = server.whereIs("basicAuth"); + driver.get(page); + + assertThat(driver.findElement(By.tagName("h1")).getText()).isEqualTo("authorized"); + } + + @Test + @Ignore(Browser.CHROME) + @Ignore(Browser.EDGE) + void canAddMultipleAuthenticationHandlersWithTheSameFilter() { + ((RemoteWebDriver) driver) + .network() + .addAuthenticationHandler( + uri -> uri.getPath().contains("basicAuth"), new UsernameAndPassword("test", "test")); + + ((RemoteWebDriver) driver) + .network() + .addAuthenticationHandler( + uri -> uri.getPath().contains("basicAuth"), new UsernameAndPassword("test", "test")); + + page = server.whereIs("basicAuth"); + driver.get(page); + + assertThat(driver.findElement(By.tagName("h1")).getText()).isEqualTo("authorized"); + } + + @Test + @Ignore(Browser.CHROME) + @Ignore(Browser.EDGE) void canRemoveAuthenticationHandler() { long id = ((RemoteWebDriver) driver) @@ -78,9 +136,26 @@ void canRemoveAuthenticationHandler() { } @Test - @NotYetImplemented(Browser.CHROME) - @NotYetImplemented(Browser.EDGE) + @Ignore(Browser.CHROME) + @Ignore(Browser.EDGE) + void canRemoveAuthenticationHandlerThatDoesNotExist() { + ((RemoteWebDriver) driver).network().removeAuthenticationHandler(5); + page = server.whereIs("basicAuth"); + driver.get(page); + + assertThatExceptionOfType(UnhandledAlertException.class) + .isThrownBy(() -> driver.findElement(By.tagName("h1"))); + } + + @Test + @Ignore(Browser.CHROME) + @Ignore(Browser.EDGE) void canClearAuthenticationHandlers() { + ((RemoteWebDriver) driver) + .network() + .addAuthenticationHandler( + uri -> uri.getPath().contains("basicAuth"), new UsernameAndPassword("test", "test")); + ((RemoteWebDriver) driver) .network() .addAuthenticationHandler(new UsernameAndPassword("test", "test")); From 656257d8e93f76ef618fab108607280b0f9d8436 Mon Sep 17 00:00:00 2001 From: Diego Molina Date: Fri, 9 Aug 2024 14:31:37 +0200 Subject: [PATCH 22/34] [java] Release 4.23.1 --- java/CHANGELOG | 14 ++++++++++++++ java/version.bzl | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/java/CHANGELOG b/java/CHANGELOG index 3676b97c47153..2180a73068525 100644 --- a/java/CHANGELOG +++ b/java/CHANGELOG @@ -1,3 +1,17 @@ +v4.23.1 +====== +* [bidi] Add dom mutation handler support (#14304) +* [grid] Exclude status DRAINING when distributor getting available nodes (#14282) +* [bidi] Add script pinning methods (#14305) +* Allow setting JDKHttpClient connectionTimeout, readTimeout, version via system property (#14306) +* remove package org.openqa.selenium.grid.session.remote (#14295) +* close the HttClient in case starting the session fails +* Adding system property to disable tracing `webdriver.remote.enableTracing` +* wait for the close response #14280 +* [bidi] Add authentication handlers (#14334) +* [grid] ensure the local_sessionmap.remove event is raised (#14337) +* [bidi] Add filter auth handler (#14349) + v4.23.0 ====== * Use Files.notExists to check files #14088 diff --git a/java/version.bzl b/java/version.bzl index 9f65a9fd3c6e2..50c94e6d24855 100644 --- a/java/version.bzl +++ b/java/version.bzl @@ -1,2 +1,2 @@ -SE_VERSION = "4.24.0-SNAPSHOT" +SE_VERSION = "4.23.1" TOOLS_JAVA_VERSION = "17" From 00efe99487b96eb313947a36fe78919ca86a5b9e Mon Sep 17 00:00:00 2001 From: Diego Molina Date: Fri, 9 Aug 2024 14:40:55 +0200 Subject: [PATCH 23/34] [java] Setting nightly version --- java/version.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/version.bzl b/java/version.bzl index 50c94e6d24855..9f65a9fd3c6e2 100644 --- a/java/version.bzl +++ b/java/version.bzl @@ -1,2 +1,2 @@ -SE_VERSION = "4.23.1" +SE_VERSION = "4.24.0-SNAPSHOT" TOOLS_JAVA_VERSION = "17" From 7fc61ef2b6db09c89f64c674156b6884fd4c328e Mon Sep 17 00:00:00 2001 From: Pavel Sobolev Date: Fri, 9 Aug 2024 17:02:42 +0300 Subject: [PATCH 24/34] [py] Allow overriding `GLOBAL_DEFAULT_TIMEOUT` (#14354) Allow overriding `GLOBAL_DEFAULT_TIMEOUT`. Co-authored-by: Diego Molina --- py/selenium/webdriver/remote/remote_connection.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/py/selenium/webdriver/remote/remote_connection.py b/py/selenium/webdriver/remote/remote_connection.py index eab43d4693a6c..f09937945b90f 100644 --- a/py/selenium/webdriver/remote/remote_connection.py +++ b/py/selenium/webdriver/remote/remote_connection.py @@ -136,7 +136,11 @@ class RemoteConnection: """ browser_name = None - _timeout = socket._GLOBAL_DEFAULT_TIMEOUT + _timeout = ( + float(os.getenv("GLOBAL_DEFAULT_TIMEOUT")) + if "GLOBAL_DEFAULT_TIMEOUT" in os.environ + else socket._GLOBAL_DEFAULT_TIMEOUT + ) _ca_certs = os.getenv("REQUESTS_CA_BUNDLE") if "REQUESTS_CA_BUNDLE" in os.environ else certifi.where() @classmethod From 00a3f4c2d20d74cf0148c273786bfc712923ca6c Mon Sep 17 00:00:00 2001 From: Navin Chandra <98466550+navin772@users.noreply.github.com> Date: Fri, 9 Aug 2024 19:58:53 +0530 Subject: [PATCH 25/34] [py] fix mypy errors for `timeouts.py` and `print_page_options.py` (#14362) Fixed some typo errors as well Signed-off-by: Navin Chandra Co-authored-by: Sri Harsha <12621691+harsha509@users.noreply.github.com> Co-authored-by: Diego Molina --- .../webdriver/common/print_page_options.py | 35 ++++++++++--------- py/selenium/webdriver/common/timeouts.py | 6 ++-- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/py/selenium/webdriver/common/print_page_options.py b/py/selenium/webdriver/common/print_page_options.py index 8673f58610f04..1ffde95c88e67 100644 --- a/py/selenium/webdriver/common/print_page_options.py +++ b/py/selenium/webdriver/common/print_page_options.py @@ -19,6 +19,7 @@ from typing import TYPE_CHECKING from typing import List from typing import Optional +from typing import Type if TYPE_CHECKING: from typing import Literal @@ -125,10 +126,9 @@ def __set__(self, obj, value) -> None: class _ValidateTypeDescriptor: """Base Class Descriptor which validates type of any subclass attribute.""" - expected_type = None - - def __init__(self, name, expected_type): + def __init__(self, name, expected_type: Type): self.name = name + self.expected_type = expected_type def __get__(self, obj, cls): return obj._print_options.get(self.name, None) @@ -142,19 +142,22 @@ def __set__(self, obj, value) -> None: class _ValidateBackGround(_ValidateTypeDescriptor): """Expected type of background attribute.""" - expected_type = bool + def __init__(self, name): + super().__init__(name, bool) class _ValidateShrinkToFit(_ValidateTypeDescriptor): - """Expected type of shirnk to fit attribute.""" + """Expected type of shrink to fit attribute.""" - expected_type = bool + def __init__(self, name): + super().__init__(name, bool) class _ValidatePageRanges(_ValidateTypeDescriptor): - """Excepted type of page ranges attribute.""" + """Expected type of page ranges attribute.""" - expected_type = list + def __init__(self, name): + super().__init__(name, list) class PrintOptions: @@ -190,7 +193,7 @@ class PrintOptions: - Set - `self.page_width` = `value` - Patameters + Parameters ---------- `value`: `float` @@ -210,7 +213,7 @@ class PrintOptions: - Get - `self.margin_top` - Set - - `slef.margin_top` = `value` + - `self.margin_top` = `value` Parameters ---------- @@ -253,7 +256,7 @@ class PrintOptions: ----- - Get - `self.margin_left` - -Set + - Set - `self.margin_left` = `value` Parameters @@ -334,13 +337,13 @@ class PrintOptions: - `None` """ - background = _ValidateBackGround("background", bool) + background = _ValidateBackGround("background") """Gets and Sets background: Usage ----- - Get - - `self.backgorund` + - `self.background` - Set - `self.background` = `value` @@ -356,7 +359,7 @@ class PrintOptions: - `None` """ - shrink_to_fit = _ValidateShrinkToFit("shrinkToFit", bool) + shrink_to_fit = _ValidateShrinkToFit("shrinkToFit") """Gets and Sets shrink_to_fit: Usage @@ -378,7 +381,7 @@ class PrintOptions: - `None` """ - page_ranges = _ValidatePageRanges("pageRanges", list) + page_ranges = _ValidatePageRanges("pageRanges") """Gets and Sets page_ranges: Usage @@ -415,4 +418,4 @@ def _validate_num_property(self, property_name: str, value: float) -> None: raise ValueError(f"{property_name} should be an integer or a float") if value < 0: - raise ValueError(f"{property_name} cannot be less then 0") + raise ValueError(f"{property_name} cannot be less than 0") diff --git a/py/selenium/webdriver/common/timeouts.py b/py/selenium/webdriver/common/timeouts.py index 10423ad3cb19c..adaa9507bef08 100644 --- a/py/selenium/webdriver/common/timeouts.py +++ b/py/selenium/webdriver/common/timeouts.py @@ -68,9 +68,9 @@ def __init__(self, implicit_wait: float = 0, page_load: float = 0, script: float before throwing an error. """ - self.implicit_wait = implicit_wait - self.page_load = page_load - self.script = script + self._implicit_wait = self._convert(implicit_wait) + self._page_load = self._convert(page_load) + self._script = self._convert(script) # Creating descriptor objects implicit_wait = _TimeoutsDescriptor("_implicit_wait") From 13be88d5543a17167230825ee8a79e27ba11b063 Mon Sep 17 00:00:00 2001 From: Puja Jagani Date: Fri, 9 Aug 2024 20:15:33 +0530 Subject: [PATCH 26/34] [java] Add "se" prefixed capabilities to session response (#14323) * [java] Add "se:containerName" to session response * Ensure all prefixed caps in request are added in response --------- Co-authored-by: Diego Molina --- .../config/DriverServiceSessionFactory.java | 18 ++++++++++++ .../grid/node/local/LocalNodeTest.java | 29 +++++++++++++++++++ 2 files changed, 47 insertions(+) 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 dbf5a16638da2..a70817d6654a2 100644 --- a/java/src/org/openqa/selenium/grid/node/config/DriverServiceSessionFactory.java +++ b/java/src/org/openqa/selenium/grid/node/config/DriverServiceSessionFactory.java @@ -187,6 +187,7 @@ public Either apply(CreateSessionRequest sess caps = readDevToolsEndpointAndVersion(caps); caps = readVncEndpoint(capabilities, caps); + caps = readPrefixedCaps(capabilities, caps); span.addEvent("Driver service created session", attributeMap); final HttpClient fClient = client; @@ -300,6 +301,23 @@ private Capabilities readVncEndpoint(Capabilities requestedCaps, Capabilities re return returnedCaps; } + private Capabilities readPrefixedCaps(Capabilities requestedCaps, Capabilities returnedCaps) { + + PersistentCapabilities returnPrefixedCaps = new PersistentCapabilities(returnedCaps); + + Map requestedCapsMap = requestedCaps.asMap(); + Map returnedCapsMap = returnedCaps.asMap(); + + requestedCapsMap.forEach( + (k, v) -> { + if (k.startsWith("se:") && !returnedCapsMap.containsKey(k)) { + returnPrefixedCaps.setCapability(k, v); + } + }); + + return returnPrefixedCaps; + } + // We remove a capability before sending the caps to the driver because some drivers will // reject session requests when they cannot parse the specific capabilities (like platform or // browser version). diff --git a/java/test/org/openqa/selenium/grid/node/local/LocalNodeTest.java b/java/test/org/openqa/selenium/grid/node/local/LocalNodeTest.java index e27e95d25c2ff..ccd2b44f3dae8 100644 --- a/java/test/org/openqa/selenium/grid/node/local/LocalNodeTest.java +++ b/java/test/org/openqa/selenium/grid/node/local/LocalNodeTest.java @@ -350,6 +350,35 @@ void seVncCdpUrlCapabilityWhenGridUrlWithTrailingSlash() throws URISyntaxExcepti assertThat(seCdp.toString().contains("wss://my.domain.com/session")).isTrue(); } + @Test + void responseCapsShowContainerName() throws URISyntaxException { + Tracer tracer = DefaultTestTracer.createTracer(); + EventBus bus = new GuavaEventBus(); + + String gridUrl = "http://localhost:7890/subPath"; + URI uri = new URI(gridUrl); + Capabilities stereotype = new ImmutableCapabilities("se:containerName", "container-1"); + + LocalNode.Builder builder = + LocalNode.builder(tracer, bus, uri, uri, registrationSecret) + .add( + stereotype, + new TestSessionFactory( + (id, caps) -> new Session(id, uri, stereotype, caps, Instant.now()))); + LocalNode localNode = builder.build(); + + Either response = + localNode.newSession( + new CreateSessionRequest(ImmutableSet.of(W3C), stereotype, ImmutableMap.of())); + assertThat(response.isRight()).isTrue(); + + CreateSessionResponse sessionResponse = response.right(); + Capabilities capabilities = sessionResponse.getSession().getCapabilities(); + Object seContainerName = capabilities.getCapability("se:containerName"); + assertThat(seContainerName).isNotNull(); + assertThat(seContainerName).isEqualTo("container-1"); + } + @Test void cdpIsDisabledAndResponseCapsShowThat() throws URISyntaxException { Tracer tracer = DefaultTestTracer.createTracer(); From 204fefd8aa5ece4dfae2ec0e6fae03946aa05038 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 9 Aug 2024 22:42:42 +0530 Subject: [PATCH 27/34] chore(deps): update dependency aspect_bazel_lib to v2.7.9 (#14332) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Sri Harsha <12621691+harsha509@users.noreply.github.com> --- MODULE.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MODULE.bazel b/MODULE.bazel index 8bcae4d2ae052..7c121fef1f9b5 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,7 +1,7 @@ module(name = "selenium") bazel_dep(name = "apple_rules_lint", version = "0.3.2") -bazel_dep(name = "aspect_bazel_lib", version = "2.7.7") +bazel_dep(name = "aspect_bazel_lib", version = "2.7.9") bazel_dep(name = "aspect_rules_esbuild", version = "0.20.1") bazel_dep(name = "aspect_rules_js", version = "1.42.3") bazel_dep(name = "aspect_rules_ts", version = "2.4.2") From 21e3a9250321dfa9dffabbe88d422564c8069d30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Sautter?= Date: Fri, 9 Aug 2024 20:44:09 +0200 Subject: [PATCH 28/34] [bidi][java] return the id of the listener added --- java/src/org/openqa/selenium/bidi/BiDi.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/src/org/openqa/selenium/bidi/BiDi.java b/java/src/org/openqa/selenium/bidi/BiDi.java index 912355a75a61c..bb4c4ad1d5254 100644 --- a/java/src/org/openqa/selenium/bidi/BiDi.java +++ b/java/src/org/openqa/selenium/bidi/BiDi.java @@ -62,7 +62,7 @@ public long addListener(Event event, Consumer handler) { return connection.addListener(event, handler); } - public void addListener(String browsingContextId, Event event, Consumer handler) { + public long addListener(String browsingContextId, Event event, Consumer handler) { Require.nonNull("Event to listen for", event); Require.nonNull("Browsing context id", browsingContextId); Require.nonNull("Handler to call", handler); @@ -76,7 +76,7 @@ public void addListener(String browsingContextId, Event event, Consumer long addListener(Set browsingContextIds, Event event, Consumer handler) { From a5de3775db76dde54b9c6a94fbe3f2b816eacb80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Sautter?= Date: Fri, 9 Aug 2024 20:46:53 +0200 Subject: [PATCH 29/34] [grid] shutdown the websocket on unexpected failures --- .../netty/server/WebSocketUpgradeHandler.java | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/java/src/org/openqa/selenium/netty/server/WebSocketUpgradeHandler.java b/java/src/org/openqa/selenium/netty/server/WebSocketUpgradeHandler.java index ad14fff29298a..226be194c5950 100644 --- a/java/src/org/openqa/selenium/netty/server/WebSocketUpgradeHandler.java +++ b/java/src/org/openqa/selenium/netty/server/WebSocketUpgradeHandler.java @@ -44,10 +44,15 @@ import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker; import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory; import io.netty.util.AttributeKey; +import java.util.Arrays; +import java.util.Objects; import java.util.Optional; import java.util.function.BiFunction; import java.util.function.Consumer; +import java.util.logging.Level; +import java.util.logging.Logger; import org.openqa.selenium.internal.Require; +import org.openqa.selenium.remote.http.CloseMessage; import org.openqa.selenium.remote.http.Message; // Plenty of code in this class is taken from Netty's own @@ -56,6 +61,7 @@ class WebSocketUpgradeHandler extends ChannelInboundHandlerAdapter { + private static final Logger LOG = Logger.getLogger(WebSocketUpgradeHandler.class.getName()); private final AttributeKey> key; private final BiFunction, Optional>> factory; private WebSocketServerHandshaker handshaker; @@ -180,6 +186,27 @@ private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame fram @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - ctx.close(); + try { + Consumer consumer = ctx.channel().attr(key).get(); + + if (consumer != null) { + byte[] reason = Objects.toString(cause).getBytes(UTF_8); + + // the spec defines it as max 123 bytes encoded in UTF_8 + if (reason.length > 123) { + reason = Arrays.copyOf(reason, 123); + Arrays.fill(reason, 120, 123, (byte) '.'); + } + + try { + consumer.accept(new CloseMessage(1011, new String(reason, UTF_8))); + } catch (Exception ex) { + LOG.log(Level.FINE, "failed to send the close message", ex); + } + } + } finally { + LOG.log(Level.FINE, "exception caught, close the context", cause); + ctx.close(); + } } } From 888ce3b182ebf69cc5c942f7907d86f227c34b1e Mon Sep 17 00:00:00 2001 From: mk868 Date: Fri, 9 Aug 2024 22:39:41 +0200 Subject: [PATCH 30/34] [java] Add JSpecify annotations to WebElement and SearchContext (#14319) [java] Add JSpecify annotations to WebElement and SearchContext (#14291) --- MODULE.bazel | 1 + java/maven_install.json | 16 ++++++++++++++-- java/src/org/openqa/selenium/BUILD.bazel | 4 ++-- java/src/org/openqa/selenium/SearchContext.java | 2 ++ java/src/org/openqa/selenium/WebElement.java | 13 ++++++++----- 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 7c121fef1f9b5..0ee03b3fc581c 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -210,6 +210,7 @@ maven.install( "org.bouncycastle:bcpkix-jdk18on:1.78.1", "org.eclipse.mylyn.github:org.eclipse.egit.github.core:2.1.5", "org.hsqldb:hsqldb:2.7.3", + "org.jspecify:jspecify:1.0.0", "org.junit.jupiter:junit-jupiter-api:5.10.3", "org.junit.jupiter:junit-jupiter-engine:5.10.3", "org.junit.jupiter:junit-jupiter-params:5.10.3", diff --git a/java/maven_install.json b/java/maven_install.json index 20c9884b32628..f5722636b1062 100644 --- a/java/maven_install.json +++ b/java/maven_install.json @@ -1,7 +1,7 @@ { "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL", - "__INPUT_ARTIFACTS_HASH": 966816920, - "__RESOLVED_ARTIFACTS_HASH": -1502533934, + "__INPUT_ARTIFACTS_HASH": -1798640815, + "__RESOLVED_ARTIFACTS_HASH": 890286156, "conflict_resolution": { "com.google.code.gson:gson:2.8.9": "com.google.code.gson:gson:2.11.0", "com.google.errorprone:error_prone_annotations:2.3.2": "com.google.errorprone:error_prone_annotations:2.27.0", @@ -654,6 +654,13 @@ }, "version": "6.2.2" }, + "org.jspecify:jspecify": { + "shasums": { + "jar": "1fad6e6be7557781e4d33729d49ae1cdc8fdda6fe477bb0cc68ce351eafdfbab", + "sources": "adf0898191d55937fb3192ba971826f4f294292c4a960740f3c27310e7b70296" + }, + "version": "1.0.0" + }, "org.junit.jupiter:junit-jupiter-api": { "shasums": { "jar": "6efe6e01ca1ff79b7bf4c6f1eed0b29292e166c27eaf7b00ac981a14d4de61aa", @@ -2620,6 +2627,9 @@ "jodd.typeconverter.impl", "jodd.util" ], + "org.jspecify:jspecify": [ + "org.jspecify.annotations" + ], "org.junit.jupiter:junit-jupiter-api": [ "org.junit.jupiter.api", "org.junit.jupiter.api.condition", @@ -3134,6 +3144,8 @@ "org.htmlunit:htmlunit-core-js:jar:sources", "org.jodd:jodd-util", "org.jodd:jodd-util:jar:sources", + "org.jspecify:jspecify", + "org.jspecify:jspecify:jar:sources", "org.junit.jupiter:junit-jupiter-api", "org.junit.jupiter:junit-jupiter-api:jar:sources", "org.junit.jupiter:junit-jupiter-engine", diff --git a/java/src/org/openqa/selenium/BUILD.bazel b/java/src/org/openqa/selenium/BUILD.bazel index 8a26ac79a8f4a..94d243ec83524 100644 --- a/java/src/org/openqa/selenium/BUILD.bazel +++ b/java/src/org/openqa/selenium/BUILD.bazel @@ -1,4 +1,4 @@ -load("//java:defs.bzl", "java_dist_zip", "java_export", "java_import", "javadoc") +load("//java:defs.bzl", "artifact", "java_dist_zip", "java_export", "java_import", "javadoc") load("//java:version.bzl", "SE_VERSION") load("//java/src/org/openqa/selenium/devtools:versions.bzl", "CDP_DEPS") @@ -32,8 +32,8 @@ java_export( pom_template = ":template-pom", visibility = ["//visibility:public"], deps = [ - # Nothing from third party ":manifest", + artifact("org.jspecify:jspecify"), ], ) diff --git a/java/src/org/openqa/selenium/SearchContext.java b/java/src/org/openqa/selenium/SearchContext.java index 1eb614b3aac4c..9da7967fe5b26 100644 --- a/java/src/org/openqa/selenium/SearchContext.java +++ b/java/src/org/openqa/selenium/SearchContext.java @@ -18,7 +18,9 @@ package org.openqa.selenium; import java.util.List; +import org.jspecify.annotations.NullMarked; +@NullMarked public interface SearchContext { /** * Find all elements within the current context using the given mechanism. diff --git a/java/src/org/openqa/selenium/WebElement.java b/java/src/org/openqa/selenium/WebElement.java index 5dc7b8c8d9113..8f9029ec2fd97 100644 --- a/java/src/org/openqa/selenium/WebElement.java +++ b/java/src/org/openqa/selenium/WebElement.java @@ -18,6 +18,8 @@ package org.openqa.selenium; import java.util.List; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; /** * Represents an HTML element. Generally, all interesting operations to do with interacting with a @@ -28,6 +30,7 @@ * fails, then an {@link org.openqa.selenium.StaleElementReferenceException} is thrown, and all * future calls to this instance will fail. */ +@NullMarked public interface WebElement extends SearchContext, TakesScreenshot { /** * Click this element. If this causes a new page to load, you should discard all references to @@ -98,7 +101,7 @@ public interface WebElement extends SearchContext, TakesScreenshot { * @param name The name of the property. * @return The property's current value or null if the value is not set. */ - default String getDomProperty(String name) { + default @Nullable String getDomProperty(String name) { throw new UnsupportedOperationException("getDomProperty"); } @@ -122,7 +125,7 @@ default String getDomProperty(String name) { * @param name The name of the attribute. * @return The attribute's value or null if the value is not set. */ - default String getDomAttribute(String name) { + default @Nullable String getDomAttribute(String name) { throw new UnsupportedOperationException("getDomAttribute"); } @@ -163,7 +166,7 @@ default String getDomAttribute(String name) { * @param name The name of the attribute. * @return The attribute/property's current value or null if the value is not set. */ - String getAttribute(String name); + @Nullable String getAttribute(String name); /** * Gets result of computing the WAI-ARIA role of element. @@ -173,7 +176,7 @@ default String getDomAttribute(String name) { * * @return the WAI-ARIA role of the element. */ - default String getAriaRole() { + default @Nullable String getAriaRole() { throw new UnsupportedOperationException("getAriaRole"); } @@ -186,7 +189,7 @@ default String getAriaRole() { * * @return the accessible name of the element. */ - default String getAccessibleName() { + default @Nullable String getAccessibleName() { throw new UnsupportedOperationException("getAccessibleName"); } From d1189490046a9aaaa9d297f890a9a68b306c0ac6 Mon Sep 17 00:00:00 2001 From: Selenium CI Bot Date: Sat, 10 Aug 2024 00:17:19 +0000 Subject: [PATCH 31/34] Update mirror info (Sat Aug 10 00:17:19 UTC 2024) --- common/mirror/selenium | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/common/mirror/selenium b/common/mirror/selenium index fae1b09e7ab6c..2cf5b54c309b9 100644 --- a/common/mirror/selenium +++ b/common/mirror/selenium @@ -25,11 +25,20 @@ { "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.23.0/selenium-java-4.23.0.zip" }, + { + "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.23.0/selenium-java-4.23.1.zip" + }, { "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.23.0/selenium-server-4.23.0.jar" }, { "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.23.0/selenium-server-4.23.0.zip" + }, + { + "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.23.0/selenium-server-4.23.1.jar" + }, + { + "browser_download_url": "https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.23.0/selenium-server-4.23.1.zip" } ] }, From aa4a41e44a8ef4c75e7b71eb4e50da2546411d8a Mon Sep 17 00:00:00 2001 From: Sri Harsha <12621691+harsha509@users.noreply.github.com> Date: Sat, 10 Aug 2024 15:55:20 +0530 Subject: [PATCH 32/34] [JS]: Handle optional dependency for @bazel/runfiles (#14352) * [JS]: Handle optional dependency for @bazel/runfiles * fix lint issue * [js]: remove console msg and safe exit if runfiles never found * [js]: fix rbe build(use global node process) * [JS]:Fix error handling for missing runfiles --------- Co-authored-by: Puja Jagani --- javascript/node/selenium-webdriver/testing/index.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/javascript/node/selenium-webdriver/testing/index.js b/javascript/node/selenium-webdriver/testing/index.js index 116009e26ea22..c96f18d453592 100644 --- a/javascript/node/selenium-webdriver/testing/index.js +++ b/javascript/node/selenium-webdriver/testing/index.js @@ -35,7 +35,6 @@ const fs = require('node:fs') const path = require('node:path') const { isatty } = require('node:tty') -const { runfiles } = require('@bazel/runfiles') const chrome = require('../chrome') const edge = require('../edge') const firefox = require('../firefox') @@ -46,6 +45,14 @@ const { Browser } = require('../lib/capabilities') const { Builder } = require('../index') const { getBinaryPaths } = require('../common/driverFinder') +let runfiles +try { + // Attempt to require @bazel/runfiles + runfiles = require('@bazel/runfiles').runfiles +} catch { + // Fall through +} + /** * Describes a browser targeted by a {@linkplain suite test suite}. * @record @@ -544,6 +551,10 @@ function locate(fileLike) { return fileLike } + if (!runfiles) { + throw new Error('Unable to find ' + fileLike) + } + try { return runfiles.resolve(fileLike) } catch { From 3bad4c77d183aaf0fa60ce8e7dac7838e41c5cd5 Mon Sep 17 00:00:00 2001 From: Simon Stewart Date: Sat, 10 Aug 2024 14:20:36 +0100 Subject: [PATCH 33/34] [bazel] With the move to aspect_rules_js we do not need to pre-warm the npm cache (#14370) --- scripts/github-actions/ci-build.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/github-actions/ci-build.sh b/scripts/github-actions/ci-build.sh index 8f9a2e574415d..c8eb0f86c2b22 100755 --- a/scripts/github-actions/ci-build.sh +++ b/scripts/github-actions/ci-build.sh @@ -4,12 +4,6 @@ set -eufo pipefail # We want to see what's going on set -x -# The NPM repository rule wants to write to the HOME directory -# but that's configured for the remote build machines, so run -# that repository rule first so that the subsequent remote -# build runs successfully. We don't care what the output is. -bazel query @npm//:all >/dev/null - # Now run the tests. The engflow build uses pinned browsers # so this should be fine # shellcheck disable=SC2046 From 596070d9ae308203be74b5df4519cbcc0a1e38b1 Mon Sep 17 00:00:00 2001 From: Simon Stewart Date: Mon, 12 Aug 2024 10:15:10 +0100 Subject: [PATCH 34/34] [bazel + ci]: Stop being selective about which parts of the tree to test (#14373) We no longer need to do this now that the entire project is built with Bazel. --- .skipped-tests | 2 ++ rust/BUILD.bazel | 22 ++-------------------- rust/tests/BUILD.bazel | 26 ++++++++++++++++++++++++++ scripts/github-actions/ci-build.sh | 8 +------- 4 files changed, 31 insertions(+), 27 deletions(-) create mode 100644 rust/tests/BUILD.bazel diff --git a/.skipped-tests b/.skipped-tests index 16f00c9b99235..82b2d1c796077 100644 --- a/.skipped-tests +++ b/.skipped-tests @@ -19,6 +19,7 @@ -//javascript/atoms:test-chrome -//javascript/atoms:test-edge -//javascript/atoms:test-firefox-beta +-//javascript/chrome-driver/... -//javascript/node/selenium-webdriver:test-bidi-network-test.js-chrome -//javascript/node/selenium-webdriver:test-builder-test.js-chrome -//javascript/node/selenium-webdriver:test-builder-test.js-firefox @@ -54,3 +55,4 @@ -//rb/spec/integration/selenium/webdriver:element-chrome -//rb/spec/integration/selenium/webdriver:element-chrome-bidi -//rb/spec/integration/selenium/webdriver:element-chrome-remote +-//rust/tests/... diff --git a/rust/BUILD.bazel b/rust/BUILD.bazel index 12b51c6e582a2..e8efae2dc457e 100644 --- a/rust/BUILD.bazel +++ b/rust/BUILD.bazel @@ -1,5 +1,5 @@ load("@crates//:defs.bzl", "all_crate_deps") -load("//rust:defs.bzl", "rust_binary", "rust_library", "rust_test", "rust_test_suite", "rustfmt_config") +load("//rust:defs.bzl", "rust_binary", "rust_library", "rust_test", "rustfmt_config") rustfmt_config( name = "enable-rustfmt", @@ -92,6 +92,7 @@ rust_library( exclude = ["main.rs"], ), edition = "2021", + visibility = ["//rust:__subpackages__"], deps = all_crate_deps(normal = True), ) @@ -117,22 +118,3 @@ rust_test( edition = "2021", tags = ["no-sandbox"], ) - -rust_test_suite( - name = "integration", - size = "small", - srcs = glob(["tests/**/*_tests.rs"]), - data = [ - "tests/common.rs", - ":selenium-manager", - ], - edition = "2021", - tags = [ - "no-sandbox", - "requires-network", - ], - deps = [":selenium_manager"] + all_crate_deps( - normal = True, - normal_dev = True, - ), -) diff --git a/rust/tests/BUILD.bazel b/rust/tests/BUILD.bazel new file mode 100644 index 0000000000000..a037d96041f43 --- /dev/null +++ b/rust/tests/BUILD.bazel @@ -0,0 +1,26 @@ +load("@crates//:defs.bzl", "all_crate_deps") +load("//rust:defs.bzl", "rust_test_suite", "rustfmt_config") + +rustfmt_config( + name = "enable-rustfmt", +) + +rust_test_suite( + name = "integration", + size = "small", + srcs = glob(["**/*_tests.rs"]), + data = [ + "common.rs", + "//rust:selenium-manager", + ], + edition = "2021", + tags = [ + "no-sandbox", + "requires-network", + ], + deps = ["//rust:selenium_manager"] + all_crate_deps( + package_name = "rust", + normal = True, + normal_dev = True, + ), +) diff --git a/scripts/github-actions/ci-build.sh b/scripts/github-actions/ci-build.sh index c8eb0f86c2b22..e64cbcf62cde8 100755 --- a/scripts/github-actions/ci-build.sh +++ b/scripts/github-actions/ci-build.sh @@ -10,13 +10,7 @@ set -x bazel test --config=remote-ci --build_tests_only \ --test_tag_filters=-exclusive-if-local,-skip-remote \ --keep_going --flaky_test_attempts=2 \ - //dotnet/... \ - //java/... \ - //javascript/atoms/... \ - //javascript/node/selenium-webdriver/... \ - //javascript/webdriver/... \ - //py/... \ - //rb/spec/... -- $(cat .skipped-tests | tr '\n' ' ') + //... -- $(cat .skipped-tests | tr '\n' ' ') # Build the packages we want to ship to users bazel build --config=remote-ci \