diff --git a/MODULE.bazel b/MODULE.bazel
index ccf7f61befdfa..724f137f6f0b1 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -181,7 +181,7 @@ maven.install(
"com.graphql-java:graphql-java:22.3",
"dev.failsafe:failsafe:3.3.2",
"io.grpc:grpc-context:1.69.0",
- "io.lettuce:lettuce-core:6.5.1.RELEASE",
+ "io.lettuce:lettuce-core:6.5.2.RELEASE",
"io.netty:netty-buffer",
"io.netty:netty-codec-http",
"io.netty:netty-codec-http2",
@@ -201,10 +201,10 @@ maven.install(
"io.opentelemetry.semconv:opentelemetry-semconv:1.28.0-alpha",
"it.ozimov:embedded-redis:0.7.3",
"net.bytebuddy:byte-buddy:1.15.11",
- "org.htmlunit:htmlunit-core-js:4.6.0",
+ "org.htmlunit:htmlunit-core-js:4.7.0",
"org.apache.commons:commons-exec:1.4.0",
"org.apache.logging.log4j:log4j-core:2.24.3",
- "org.assertj:assertj-core:3.27.1",
+ "org.assertj:assertj-core:3.27.2",
"org.bouncycastle:bcpkix-jdk18on:1.79",
"org.eclipse.mylyn.github:org.eclipse.egit.github.core:2.1.5",
"org.hsqldb:hsqldb:2.7.4",
diff --git a/common/src/web/fedcm/fedcm_async_js.html b/common/src/web/fedcm/fedcm_async_js.html
new file mode 100644
index 0000000000000..d1411be0a4cec
--- /dev/null
+++ b/common/src/web/fedcm/fedcm_async_js.html
@@ -0,0 +1,40 @@
+
+
+
+ FedCM Example
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dotnet/src/webdriver/Remote/HttpCommandExecutor.cs b/dotnet/src/webdriver/Remote/HttpCommandExecutor.cs
index 0686239405e38..85921d73954be 100644
--- a/dotnet/src/webdriver/Remote/HttpCommandExecutor.cs
+++ b/dotnet/src/webdriver/Remote/HttpCommandExecutor.cs
@@ -316,7 +316,7 @@ private async Task MakeHttpRequest(HttpRequestInfo requestInfo
private Response CreateResponse(HttpResponseInfo responseInfo)
{
- Response response = new Response();
+ Response response;
string body = responseInfo.Body;
if ((int)responseInfo.StatusCode < 200 || (int)responseInfo.StatusCode > 299)
{
@@ -326,8 +326,7 @@ private Response CreateResponse(HttpResponseInfo responseInfo)
}
else
{
- response.Status = WebDriverResult.UnknownError;
- response.Value = body;
+ response = new Response(sessionId: null, body, WebDriverResult.UnknownError);
}
}
else if (responseInfo.ContentType != null && responseInfo.ContentType.StartsWith(JsonMimeType, StringComparison.OrdinalIgnoreCase))
@@ -336,12 +335,12 @@ private Response CreateResponse(HttpResponseInfo responseInfo)
}
else
{
- response.Value = body;
+ response = new Response(sessionId: null, body, WebDriverResult.Success);
}
- if (response.Value is string)
+ if (response.Value is string valueString)
{
- response.Value = ((string)response.Value).Replace("\r\n", "\n").Replace("\n", Environment.NewLine);
+ response.Value = valueString.Replace("\r\n", "\n").Replace("\n", Environment.NewLine);
}
return response;
diff --git a/dotnet/src/webdriver/Response.cs b/dotnet/src/webdriver/Response.cs
index abe4bb2a9fcdd..9a0de908859a5 100644
--- a/dotnet/src/webdriver/Response.cs
+++ b/dotnet/src/webdriver/Response.cs
@@ -24,6 +24,8 @@
using System.Text.Json;
using System.Text.Json.Serialization;
+#nullable enable
+
namespace OpenQA.Selenium
{
///
@@ -48,12 +50,22 @@ public Response()
/// Initializes a new instance of the class
///
/// Session ID in use
- public Response(SessionId sessionId)
+ public Response(SessionId? sessionId)
{
- if (sessionId != null)
- {
- this.SessionId = sessionId.ToString();
- }
+ this.SessionId = sessionId?.ToString();
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ ///
+ /// The Session ID in use, if any.
+ /// The JSON payload of the response.
+ /// The WebDriver result status of the response.
+ public Response(string? sessionId, object? value, WebDriverResult status)
+ {
+ this.SessionId = sessionId;
+ this.Value = value;
+ this.Status = status;
}
///
@@ -61,75 +73,75 @@ public Response(SessionId sessionId)
///
/// The JSON string to deserialize into a .
/// A object described by the JSON string.
+ /// If is .
+ /// If is not a valid JSON object.
public static Response FromJson(string value)
{
- Dictionary rawResponse = JsonSerializer.Deserialize>(value, s_jsonSerializerOptions)
+ Dictionary rawResponse = JsonSerializer.Deserialize>(value, s_jsonSerializerOptions)
?? throw new WebDriverException("JSON success response returned \"null\" value");
- var response = new Response();
+ object? contents;
+ string? sessionId = null;
- if (rawResponse.ContainsKey("sessionId"))
+ if (rawResponse.TryGetValue("sessionId", out object? s) && s is not null)
{
- if (rawResponse["sessionId"] != null)
- {
- response.SessionId = rawResponse["sessionId"].ToString();
- }
+ sessionId = s.ToString();
}
- if (rawResponse.TryGetValue("value", out object valueObj))
+ if (rawResponse.TryGetValue("value", out object? valueObj))
{
- response.Value = valueObj;
+ contents = valueObj;
}
-
- // If the returned object does *not* have a "value" property
- // the response value should be the entirety of the response.
- // TODO: Remove this if statement altogether; there should
- // never be a spec-compliant response that does not contain a
- // value property.
- if (!rawResponse.ContainsKey("value") && response.Value == null)
+ else
{
+ // If the returned object does *not* have a "value" property
+ // the response value should be the entirety of the response.
+ // TODO: Remove this if statement altogether; there should
+ // never be a spec-compliant response that does not contain a
+ // value property.
+
// Special-case for the new session command, where the "capabilities"
// property of the response is the actual value we're interested in.
- if (rawResponse.ContainsKey("capabilities"))
+ if (rawResponse.TryGetValue("capabilities", out object? capabilities))
{
- response.Value = rawResponse["capabilities"];
+ contents = capabilities;
}
else
{
- response.Value = rawResponse;
+ contents = rawResponse;
}
}
- if (response.Value is Dictionary valueDictionary)
+ if (contents is Dictionary valueDictionary)
{
// Special case code for the new session command. If the response contains
// sessionId and capabilities properties, fix up the session ID and value members.
- if (valueDictionary.ContainsKey("sessionId"))
+ if (valueDictionary.TryGetValue("sessionId", out object? session))
{
- response.SessionId = valueDictionary["sessionId"].ToString();
- if (valueDictionary.TryGetValue("capabilities", out object capabilities))
+ sessionId = session.ToString();
+ if (valueDictionary.TryGetValue("capabilities", out object? capabilities))
{
- response.Value = capabilities;
+ contents = capabilities;
}
else
{
- response.Value = valueDictionary["value"];
+ contents = valueDictionary["value"];
}
}
}
- return response;
+ return new Response(sessionId, contents, WebDriverResult.Success);
}
///
/// Gets or sets the value from JSON.
///
- public object Value { get; set; }
+ public object? Value { get; set; }
///
/// Gets or sets the session ID.
///
- public string SessionId { get; set; }
+ public string? SessionId { get; set; }
///
/// Gets or sets the status value of the response.
@@ -142,26 +154,25 @@ public static Response FromJson(string value)
///
/// The JSON string to deserialize into a .
/// A object described by the JSON string.
+ /// If is .
+ /// If is not a valid JSON object.
+ /// If the JSON dictionary is not in the expected state, per spec.
public static Response FromErrorJson(string value)
{
- var deserializedResponse = JsonSerializer.Deserialize>(value, s_jsonSerializerOptions)
+ Dictionary deserializedResponse = JsonSerializer.Deserialize>(value, s_jsonSerializerOptions)
?? throw new WebDriverException("JSON error response returned \"null\" value");
- var response = new Response();
-
- if (!deserializedResponse.TryGetValue("value", out var valueObject))
+ if (!deserializedResponse.TryGetValue("value", out object? valueObject))
{
throw new WebDriverException($"The 'value' property was not found in the response:{Environment.NewLine}{value}");
}
- if (valueObject is not Dictionary valueDictionary)
+ if (valueObject is not Dictionary valueDictionary)
{
throw new WebDriverException($"The 'value' property is not a dictionary of {Environment.NewLine}{value}");
}
- response.Value = valueDictionary;
-
- if (!valueDictionary.TryGetValue("error", out var errorObject))
+ if (!valueDictionary.TryGetValue("error", out object? errorObject))
{
throw new WebDriverException($"The 'value > error' property was not found in the response:{Environment.NewLine}{value}");
}
@@ -171,11 +182,9 @@ public static Response FromErrorJson(string value)
throw new WebDriverException($"The 'value > error' property is not a string{Environment.NewLine}{value}");
}
- response.Value = deserializedResponse["value"];
-
- response.Status = WebDriverError.ResultFromError(errorString);
+ WebDriverResult status = WebDriverError.ResultFromError(errorString);
- return response;
+ return new Response(sessionId: null, valueDictionary, status);
}
///
diff --git a/java/maven_install.json b/java/maven_install.json
index b21bf018ab565..4b6e999df0928 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": -1069673593,
- "__RESOLVED_ARTIFACTS_HASH": -1004221368,
+ "__INPUT_ARTIFACTS_HASH": 1132645732,
+ "__RESOLVED_ARTIFACTS_HASH": 1947623231,
"artifacts": {
"com.beust:jcommander": {
"shasums": {
@@ -228,10 +228,10 @@
},
"io.lettuce:lettuce-core": {
"shasums": {
- "jar": "ff26c28351becdaf6d5abe25d97ea799a986b1746bfe5f70659d1e53745b6f1a",
- "sources": "383337d6e56a97563c31f2d06838c85f8295662a5f7f72408bef5d59329cf98a"
+ "jar": "59f6a591a631d844b355b831ee723bf6ce98d92f7a775de6b0690f0eb81480e7",
+ "sources": "e9d835ed5b0583fbf01deabdb2c4ab370ac73166a4011aac5f1e2ca397914912"
},
- "version": "6.5.1.RELEASE"
+ "version": "6.5.2.RELEASE"
},
"io.netty:netty-buffer": {
"shasums": {
@@ -550,10 +550,10 @@
},
"org.assertj:assertj-core": {
"shasums": {
- "jar": "ab4ab885146bc5dfbdd4cdfb06f1ae72ec6b5e8139f0ccdabcbe51374aebac0d",
- "sources": "0c9a7b4a85f3609bf700ad13f4173cde85cadcdd8feb829e059a000a5b9aa932"
+ "jar": "a8079b4cb67dca1dc5c7650bf27bd59277834c63280b661475986de3b602e3ae",
+ "sources": "fc96972d63cc234226a10b5a434acb085033f2bc68035df92abc3331595aa73d"
},
- "version": "3.27.1"
+ "version": "3.27.2"
},
"org.bouncycastle:bcpkix-jdk18on": {
"shasums": {
@@ -606,10 +606,10 @@
},
"org.htmlunit:htmlunit-core-js": {
"shasums": {
- "jar": "709c43eaab5b407468239b49ba990a7170ee582cbaa6a11c09a6118da22fdedc",
- "sources": "458acacd14d851ad0ad20310787b35d3224d0c31155bd6b17d41de2b352bb1b7"
+ "jar": "4f0c609fbfd2ca2ca9163cc63e9b947b13a57b5644400e2b1902c1335d160888",
+ "sources": "5834536abb3402f859cbb31f48d113e36c2dc6bc7dd7e01eca6478a61d00c70c"
},
- "version": "4.6.0"
+ "version": "4.7.0"
},
"org.jodd:jodd-util": {
"shasums": {
diff --git a/java/src/org/openqa/selenium/Platform.java b/java/src/org/openqa/selenium/Platform.java
index 66f7927eaeb9b..98d859b642689 100644
--- a/java/src/org/openqa/selenium/Platform.java
+++ b/java/src/org/openqa/selenium/Platform.java
@@ -32,7 +32,7 @@
public enum Platform {
/** Never returned, but can be used to request a browser running on any version of Windows. */
- WINDOWS("") {
+ WINDOWS("windows") {
@Override
public Platform family() {
return null;
@@ -302,6 +302,18 @@ public String toString() {
}
},
+ SEQUOIA("sequoia", "os x 15.0", "macos 15.0") {
+ @Override
+ public Platform family() {
+ return MAC;
+ }
+
+ @Override
+ public String toString() {
+ return "macOS 15.0";
+ }
+ },
+
/** Many platforms have UNIX traits, amongst them LINUX, Solaris and BSD. */
UNIX("solaris", "bsd") {
@Override
diff --git a/java/test/org/openqa/selenium/PlatformTest.java b/java/test/org/openqa/selenium/PlatformTest.java
index a87bc6bf0d9eb..8ff72882e0270 100644
--- a/java/test/org/openqa/selenium/PlatformTest.java
+++ b/java/test/org/openqa/selenium/PlatformTest.java
@@ -24,8 +24,10 @@
import static org.openqa.selenium.Platform.IOS;
import static org.openqa.selenium.Platform.LINUX;
import static org.openqa.selenium.Platform.MAC;
+import static org.openqa.selenium.Platform.SEQUOIA;
import static org.openqa.selenium.Platform.UNIX;
import static org.openqa.selenium.Platform.VISTA;
+import static org.openqa.selenium.Platform.WIN11;
import static org.openqa.selenium.Platform.WIN8;
import static org.openqa.selenium.Platform.WIN8_1;
import static org.openqa.selenium.Platform.WINDOWS;
@@ -57,6 +59,11 @@ void testWin81IsWindows() {
assertThat(WIN8_1.is(WINDOWS)).isTrue();
}
+ @Test
+ void testWindows11IsWindows() {
+ assertThat(WIN11.is(WINDOWS)).isTrue();
+ }
+
@Test
void testLinuxIsUnix() {
assertThat(LINUX.is(UNIX)).isTrue();
@@ -165,16 +172,41 @@ void testWindowsIsWindows() {
assertThat(WINDOWS).isEqualTo(Platform.fromString("windows"));
}
+ @Test
+ void testWindowsIsNotEmpty() {
+ assertThat(WINDOWS).isNotEqualTo(Platform.fromString(""));
+ }
+
@Test
void canParseMacOsXCorrectly() {
assertThat(Platform.fromString("Mac OS X")).isEqualTo(MAC);
}
+ @Test
+ void testAnyIsFromStringEmpty() {
+ assertThat(ANY).isEqualTo(Platform.fromString(""));
+ }
+
+ @Test
+ void testAnyIsFromStringAny() {
+ assertThat(ANY).isEqualTo(Platform.fromString("any"));
+ }
+
+ @Test
+ void testAnyIsNotFromStringWindows() {
+ assertThat(ANY).isNotEqualTo(Platform.fromString("windows"));
+ }
+
@Test
void catalinaIsMac() {
assertThat(CATALINA.is(MAC)).isTrue();
}
+ @Test
+ void sequoiaIsMac() {
+ assertThat(SEQUOIA.is(MAC)).isTrue();
+ }
+
@Test
void canParseCatalinaFromOSName() {
assertThat(Platform.fromString("macOS 10.15")).isEqualTo(CATALINA);
diff --git a/javascript/grid-ui/package.json b/javascript/grid-ui/package.json
index 2e7195ce1ab32..042029c165e3d 100644
--- a/javascript/grid-ui/package.json
+++ b/javascript/grid-ui/package.json
@@ -12,8 +12,8 @@
"@novnc/novnc": "1.5.0",
"@types/jest": "29.5.14",
"@types/node": "20.12.12",
- "@types/react": "18.2.72",
- "@types/react-dom": "18.2.22",
+ "@types/react": "18.3.18",
+ "@types/react-dom": "18.3.5",
"@types/react-modal": "3.16.3",
"@types/react-router-dom": "5.3.3",
"graphql": "16.10.0",
diff --git a/javascript/node/selenium-webdriver/BUILD.bazel b/javascript/node/selenium-webdriver/BUILD.bazel
index bc6e68042597d..75c855c641ec8 100644
--- a/javascript/node/selenium-webdriver/BUILD.bazel
+++ b/javascript/node/selenium-webdriver/BUILD.bazel
@@ -33,6 +33,7 @@ js_library(
"io/*.js",
"lib/*.js",
"lib/atoms/bidi-mutation-listener.js",
+ "lib/fedcm/*.js",
"net/*.js",
"remote/*.js",
"testing/*.js",
diff --git a/javascript/node/selenium-webdriver/lib/command.js b/javascript/node/selenium-webdriver/lib/command.js
index 5f7f481f77bf6..5d74b955bd4e6 100644
--- a/javascript/node/selenium-webdriver/lib/command.js
+++ b/javascript/node/selenium-webdriver/lib/command.js
@@ -185,6 +185,17 @@ const Name = {
GET_DOWNLOADABLE_FILES: 'getDownloadableFiles',
DOWNLOAD_FILE: 'downloadFile',
DELETE_DOWNLOADABLE_FILES: 'deleteDownloadableFiles',
+
+ // Federated Credential Management API
+ // https://www.w3.org/TR/fedcm/#automation
+ CANCEL_DIALOG: 'cancelDialog',
+ SELECT_ACCOUNT: 'selectAccount',
+ GET_ACCOUNTS: 'getAccounts',
+ GET_FEDCM_TITLE: 'getFedCmTitle',
+ GET_FEDCM_DIALOG_TYPE: 'getFedCmDialogType',
+ SET_DELAY_ENABLED: 'setDelayEnabled',
+ RESET_COOLDOWN: 'resetCooldown',
+ CLICK_DIALOG_BUTTON: 'clickdialogbutton',
}
/**
diff --git a/javascript/node/selenium-webdriver/lib/fedcm/account.js b/javascript/node/selenium-webdriver/lib/fedcm/account.js
new file mode 100644
index 0000000000000..451f192a69f54
--- /dev/null
+++ b/javascript/node/selenium-webdriver/lib/fedcm/account.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.
+
+class Account {
+ constructor(
+ accountId,
+ email,
+ name,
+ givenName,
+ pictureUrl,
+ idpConfigUrl,
+ loginState,
+ termsOfServiceUrl,
+ privacyPolicyUrl,
+ ) {
+ this._accountId = accountId
+ this._email = email
+ this._name = name
+ this._givenName = givenName
+ this._pictureUrl = pictureUrl
+ this._idpConfigUrl = idpConfigUrl
+ this._loginState = loginState
+ this._termsOfServiceUrl = termsOfServiceUrl
+ this._privacyPolicyUrl = privacyPolicyUrl
+ }
+
+ get accountId() {
+ return this._accountId
+ }
+
+ get email() {
+ return this._email
+ }
+
+ get name() {
+ return this._name
+ }
+
+ get givenName() {
+ return this._givenName
+ }
+
+ get pictureUrl() {
+ return this._pictureUrl
+ }
+
+ get idpConfigUrl() {
+ return this._idpConfigUrl
+ }
+
+ get loginState() {
+ return this._loginState
+ }
+
+ get termsOfServiceUrl() {
+ return this._termsOfServiceUrl
+ }
+
+ get privacyPolicyUrl() {
+ return this._privacyPolicyUrl
+ }
+}
+
+module.exports = Account
diff --git a/javascript/node/selenium-webdriver/lib/fedcm/dialog.js b/javascript/node/selenium-webdriver/lib/fedcm/dialog.js
new file mode 100644
index 0000000000000..cec84a78e5d6d
--- /dev/null
+++ b/javascript/node/selenium-webdriver/lib/fedcm/dialog.js
@@ -0,0 +1,76 @@
+// 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 command = require('../command')
+const Account = require('./account')
+
+class Dialog {
+ constructor(driver) {
+ this._driver = driver
+ }
+
+ async title() {
+ const result = await this._driver.execute(new command.Command(command.Name.GET_FEDCM_TITLE))
+
+ return result.title
+ }
+
+ subtitle() {
+ return this._driver.execute(new command.Command(command.Name.GET_FEDCM_TITLE))
+ }
+
+ type() {
+ return this._driver.execute(new command.Command(command.Name.GET_FEDCM_DIALOG_TYPE))
+ }
+
+ async accounts() {
+ const result = await this._driver.execute(new command.Command(command.Name.GET_ACCOUNTS))
+
+ const accountArray = []
+
+ result.forEach((account) => {
+ const acc = new Account(
+ account.accountId,
+ account.email,
+ account.name,
+ account.givenName,
+ account.pictureUrl,
+ account.idpConfigUrl,
+ account.loginState,
+ account.termsOfServiceUrl,
+ account.privacyPolicyUrl,
+ )
+ accountArray.push(acc)
+ })
+
+ return accountArray
+ }
+
+ selectAccount(index) {
+ return this._driver.execute(new command.Command(command.Name.SELECT_ACCOUNT).setParameter('accountIndex', index))
+ }
+
+ accept() {
+ return this._driver.execute(new command.Command(command.Name.CLICK_DIALOG_BUTTON))
+ }
+
+ dismiss() {
+ return this._driver.execute(new command.Command(command.Name.CANCEL_DIALOG))
+ }
+}
+
+module.exports = Dialog
diff --git a/javascript/node/selenium-webdriver/lib/http.js b/javascript/node/selenium-webdriver/lib/http.js
index eea7a4fe58d9f..2dd38c43b7169 100644
--- a/javascript/node/selenium-webdriver/lib/http.js
+++ b/javascript/node/selenium-webdriver/lib/http.js
@@ -320,6 +320,16 @@ const W3C_COMMAND_MAP = new Map([
[cmd.Name.GET_DOWNLOADABLE_FILES, get('/session/:sessionId/se/files')],
[cmd.Name.DOWNLOAD_FILE, post(`/session/:sessionId/se/files`)],
[cmd.Name.DELETE_DOWNLOADABLE_FILES, del(`/session/:sessionId/se/files`)],
+
+ // Federated Credential Management Command
+ [cmd.Name.CANCEL_DIALOG, post(`/session/:sessionId/fedcm/canceldialog`)],
+ [cmd.Name.SELECT_ACCOUNT, post(`/session/:sessionId/fedcm/selectaccount`)],
+ [cmd.Name.GET_FEDCM_TITLE, get(`/session/:sessionId/fedcm/gettitle`)],
+ [cmd.Name.GET_FEDCM_DIALOG_TYPE, get('/session/:sessionId/fedcm/getdialogtype')],
+ [cmd.Name.SET_DELAY_ENABLED, post(`/session/:sessionId/fedcm/setdelayenabled`)],
+ [cmd.Name.RESET_COOLDOWN, post(`/session/:sessionId/fedcm/resetcooldown`)],
+ [cmd.Name.CLICK_DIALOG_BUTTON, post(`/session/:sessionId/fedcm/clickdialogbutton`)],
+ [cmd.Name.GET_ACCOUNTS, get(`/session/:sessionId/fedcm/accountlist`)],
])
/**
diff --git a/javascript/node/selenium-webdriver/lib/test/fileserver.js b/javascript/node/selenium-webdriver/lib/test/fileserver.js
index 337c1b9205137..d215971f754a2 100644
--- a/javascript/node/selenium-webdriver/lib/test/fileserver.js
+++ b/javascript/node/selenium-webdriver/lib/test/fileserver.js
@@ -118,7 +118,7 @@ const Pages = (function () {
addPage('emptyText', 'bidi/emptyText.txt')
addPage('redirectedHttpEquiv', 'bidi/redirected_http_equiv.html')
addPage('releaseAction', 'bidi/release_action.html')
-
+ addPage('fedcm', 'fedcm/fedcm_async_js.html')
return pages
})()
diff --git a/javascript/node/selenium-webdriver/lib/webdriver.js b/javascript/node/selenium-webdriver/lib/webdriver.js
index 2c6a9aa48e259..d910f54d09bf5 100644
--- a/javascript/node/selenium-webdriver/lib/webdriver.js
+++ b/javascript/node/selenium-webdriver/lib/webdriver.js
@@ -45,6 +45,7 @@ const { PinnedScript } = require('./pinnedScript')
const JSZip = require('jszip')
const Script = require('./script')
const Network = require('./network')
+const Dialog = require('./fedcm/dialog')
// Capability names that are defined in the W3C spec.
const W3C_CAPABILITY_NAMES = new Set([
@@ -1106,6 +1107,18 @@ class WebDriver {
return this.execute(new command.Command(command.Name.SCREENSHOT))
}
+ setDelayEnabled(enabled) {
+ return this.execute(new command.Command(command.Name.SET_DELAY_ENABLED).setParameter('enabled', enabled))
+ }
+
+ resetCooldown() {
+ return this.execute(new command.Command(command.Name.RESET_COOLDOWN))
+ }
+
+ getFederalCredentialManagementDialog() {
+ return new Dialog(this)
+ }
+
/** @override */
manage() {
return new Options(this)
diff --git a/javascript/node/selenium-webdriver/test/fedcm/fedcm_test.js b/javascript/node/selenium-webdriver/test/fedcm/fedcm_test.js
new file mode 100644
index 0000000000000..4ae3ac70b5706
--- /dev/null
+++ b/javascript/node/selenium-webdriver/test/fedcm/fedcm_test.js
@@ -0,0 +1,183 @@
+// 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 { By } = require('selenium-webdriver/index')
+
+suite(
+ function (env) {
+ let driver
+
+ beforeEach(async function () {
+ driver = await env.builder().build()
+ })
+
+ afterEach(async function () {
+ await driver.quit()
+ })
+
+ describe('Federated Credential Management Test', function () {
+ it('credential mangement dialog should appear', async function () {
+ await driver.get(Pages.fedcm)
+
+ let triggerButton = await driver.findElement(By.id('triggerButton'))
+ await triggerButton.click()
+
+ let dialog
+
+ await driver.wait(
+ async () => {
+ try {
+ dialog = await driver.getFederalCredentialManagementDialog()
+ return (await dialog.type()) === 'AccountChooser'
+ } catch (error) {
+ return false
+ }
+ },
+ 10000,
+ 'Expected dialog type to be "AccountChooser"',
+ 2000,
+ )
+
+ assert.equal(await dialog.type(), 'AccountChooser')
+ let title = await dialog.title()
+ assert.equal(title.includes('Sign in to'), true)
+ })
+
+ it('can dismiss dialog', async function () {
+ await driver.get(Pages.fedcm)
+
+ let triggerButton = await driver.findElement(By.id('triggerButton'))
+ await triggerButton.click()
+
+ let dialog = await driver.getFederalCredentialManagementDialog()
+
+ await driver.wait(
+ async () => {
+ try {
+ return (await dialog.type()) === 'AccountChooser'
+ } catch (error) {
+ return false
+ }
+ },
+ 10000,
+ 'Expected dialog type to be "AccountChooser"',
+ 2000,
+ )
+
+ assert.equal(await dialog.type(), 'AccountChooser')
+ let title = await dialog.title()
+ assert.equal(title.includes('Sign in to'), true)
+
+ await dialog.dismiss()
+
+ try {
+ await dialog.type()
+ assert.fail('Above command should throw error')
+ } catch (error) {
+ assert.equal(error.message.includes('no such alert'), true)
+ }
+ })
+
+ it('can select account', async function () {
+ await driver.get(Pages.fedcm)
+
+ let triggerButton = await driver.findElement(By.id('triggerButton'))
+ await triggerButton.click()
+
+ let dialog = await driver.getFederalCredentialManagementDialog()
+
+ await driver.wait(
+ async () => {
+ try {
+ return (await dialog.type()) === 'AccountChooser'
+ } catch (error) {
+ return false
+ }
+ },
+ 10000,
+ 'Expected dialog type to be "AccountChooser"',
+ 2000,
+ )
+
+ assert.equal(await dialog.type(), 'AccountChooser')
+ let title = await dialog.title()
+ assert.equal(title.includes('Sign in to'), true)
+
+ await dialog.selectAccount(1)
+ })
+
+ it('can get account list', async function () {
+ await driver.get(Pages.fedcm)
+
+ let triggerButton = await driver.findElement(By.id('triggerButton'))
+ await triggerButton.click()
+
+ let dialog = await driver.getFederalCredentialManagementDialog()
+
+ await driver.wait(
+ async () => {
+ try {
+ return (await dialog.type()) === 'AccountChooser'
+ } catch (error) {
+ return false
+ }
+ },
+ 10000,
+ 'Expected dialog type to be "AccountChooser"',
+ 2000,
+ )
+
+ assert.equal(await dialog.type(), 'AccountChooser')
+ let title = await dialog.title()
+ assert.equal(title.includes('Sign in to'), true)
+
+ const accounts = await dialog.accounts()
+
+ assert.equal(accounts.length, 2)
+
+ const account1 = accounts[0]
+ const account2 = accounts[1]
+
+ assert.strictEqual(account1.name, 'John Doe')
+ assert.strictEqual(account1.email, 'john_doe@idp.example')
+ assert.strictEqual(account1.accountId, '1234')
+ assert.strictEqual(account1.givenName, 'John')
+ assert(account1.idpConfigUrl.includes('/fedcm/config.json'), true)
+ assert.strictEqual(account1.pictureUrl, 'https://idp.example/profile/123')
+ assert.strictEqual(account1.loginState, 'SignUp')
+ assert.strictEqual(account1.termsOfServiceUrl, 'https://rp.example/terms_of_service.html')
+ assert.strictEqual(account1.privacyPolicyUrl, 'https://rp.example/privacy_policy.html')
+
+ assert.strictEqual(account2.name, 'Aisha Ahmad')
+ assert.strictEqual(account2.email, 'aisha@idp.example')
+ assert.strictEqual(account2.accountId, '5678')
+ assert.strictEqual(account2.givenName, 'Aisha')
+ assert(account2.idpConfigUrl.includes('/fedcm/config.json'), true)
+ assert.strictEqual(account2.pictureUrl, 'https://idp.example/profile/567')
+ assert.strictEqual(account2.loginState, 'SignUp')
+ assert.strictEqual(account2.termsOfServiceUrl, 'https://rp.example/terms_of_service.html')
+ assert.strictEqual(account2.privacyPolicyUrl, 'https://rp.example/privacy_policy.html')
+ })
+ })
+ },
+ { browsers: [Browser.CHROME, Browser.EDGE] },
+)
diff --git a/package.json b/package.json
index 57278a663f412..dc0b5f15736a9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "selenium",
- "packageManager": "pnpm@9.6.0",
+ "packageManager": "pnpm@9.15.2",
"workspaces": [
"javascript/grid-ui",
"javascript/node/selenium-webdriver"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index bc3d00e8d2a1e..724898d079723 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -12,19 +12,19 @@ importers:
dependencies:
'@apollo/client':
specifier: 3.12.4
- version: 3.12.4(@types/react@18.2.72)(graphql@16.10.0)(react-dom@18.3.1)(react@18.3.1)
+ version: 3.12.4(@types/react@18.3.18)(graphql@16.10.0)(react-dom@18.3.1)(react@18.3.1)
'@emotion/react':
specifier: 11.14.0
- version: 11.14.0(@types/react@18.2.72)(react@18.3.1)
+ version: 11.14.0(@types/react@18.3.18)(react@18.3.1)
'@emotion/styled':
specifier: 11.14.0
- version: 11.14.0(@emotion/react@11.14.0)(@types/react@18.2.72)(react@18.3.1)
+ version: 11.14.0(@emotion/react@11.14.0)(@types/react@18.3.18)(react@18.3.1)
'@mui/icons-material':
specifier: 5.15.18
- version: 5.15.18(@mui/material@5.15.18)(@types/react@18.2.72)(react@18.3.1)
+ version: 5.15.18(@mui/material@5.15.18)(@types/react@18.3.18)(react@18.3.1)
'@mui/material':
specifier: 5.15.18
- version: 5.15.18(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@types/react@18.2.72)(react-dom@18.3.1)(react@18.3.1)
+ version: 5.15.18(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)
'@novnc/novnc':
specifier: 1.5.0
version: 1.5.0
@@ -35,11 +35,11 @@ importers:
specifier: 20.12.12
version: 20.12.12
'@types/react':
- specifier: 18.2.72
- version: 18.2.72
+ specifier: 18.3.18
+ version: 18.3.18
'@types/react-dom':
- specifier: 18.2.22
- version: 18.2.22
+ specifier: 18.3.5
+ version: 18.3.5(@types/react@18.3.18)
'@types/react-modal':
specifier: 3.16.3
version: 3.16.3
@@ -82,7 +82,7 @@ importers:
version: 6.6.3
'@testing-library/react':
specifier: 14.3.1
- version: 14.3.1(react-dom@18.3.1)(react@18.3.1)
+ version: 14.3.1(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)
'@testing-library/user-event':
specifier: 14.5.2
version: 14.5.2(@testing-library/dom@10.4.0)
@@ -182,7 +182,7 @@ packages:
'@jridgewell/gen-mapping': 0.3.8
'@jridgewell/trace-mapping': 0.3.25
- /@apollo/client@3.12.4(@types/react@18.2.72)(graphql@16.10.0)(react-dom@18.3.1)(react@18.3.1):
+ /@apollo/client@3.12.4(@types/react@18.3.18)(graphql@16.10.0)(react-dom@18.3.1)(react@18.3.1):
resolution: {integrity: sha512-S/eC9jxEW9Jg1BjD6AZonE1fHxYuvC3gFHop8FRQkUdeK63MmBD5r0DOrN2WlJbwha1MSD6A97OwXwjaujEQpA==}
peerDependencies:
graphql: ^15.0.0 || ^16.0.0
@@ -211,7 +211,7 @@ packages:
prop-types: 15.8.1
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
- rehackt: 0.1.0(@types/react@18.2.72)(react@18.3.1)
+ rehackt: 0.1.0(@types/react@18.3.18)(react@18.3.1)
response-iterator: 0.2.6
symbol-observable: 4.0.0
ts-invariant: 0.10.3
@@ -492,7 +492,7 @@ packages:
resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==}
dev: false
- /@emotion/react@11.14.0(@types/react@18.2.72)(react@18.3.1):
+ /@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1):
resolution: {integrity: sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==}
peerDependencies:
'@types/react': '*'
@@ -508,7 +508,7 @@ packages:
'@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@18.3.1)
'@emotion/utils': 1.4.2
'@emotion/weak-memoize': 0.4.0
- '@types/react': 18.2.72
+ '@types/react': 18.3.18
hoist-non-react-statics: 3.3.2
react: 18.3.1
transitivePeerDependencies:
@@ -529,7 +529,7 @@ packages:
resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==}
dev: false
- /@emotion/styled@11.14.0(@emotion/react@11.14.0)(@types/react@18.2.72)(react@18.3.1):
+ /@emotion/styled@11.14.0(@emotion/react@11.14.0)(@types/react@18.3.18)(react@18.3.1):
resolution: {integrity: sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==}
peerDependencies:
'@emotion/react': ^11.0.0-rc.0
@@ -542,11 +542,11 @@ packages:
'@babel/runtime': 7.26.0
'@emotion/babel-plugin': 11.13.5
'@emotion/is-prop-valid': 1.3.1
- '@emotion/react': 11.14.0(@types/react@18.2.72)(react@18.3.1)
+ '@emotion/react': 11.14.0(@types/react@18.3.18)(react@18.3.1)
'@emotion/serialize': 1.3.3
'@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@18.3.1)
'@emotion/utils': 1.4.2
- '@types/react': 18.2.72
+ '@types/react': 18.3.18
react: 18.3.1
transitivePeerDependencies:
- supports-color
@@ -1054,7 +1054,7 @@ packages:
lodash: 4.17.21
dev: true
- /@mui/base@5.0.0-beta.40(@types/react@18.2.72)(react-dom@18.3.1)(react@18.3.1):
+ /@mui/base@5.0.0-beta.40(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1):
resolution: {integrity: sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==}
engines: {node: '>=12.0.0'}
peerDependencies:
@@ -1067,10 +1067,10 @@ packages:
dependencies:
'@babel/runtime': 7.26.0
'@floating-ui/react-dom': 2.1.2(react-dom@18.3.1)(react@18.3.1)
- '@mui/types': 7.2.20(@types/react@18.2.72)
- '@mui/utils': 5.16.13(@types/react@18.2.72)(react@18.3.1)
+ '@mui/types': 7.2.21(@types/react@18.3.18)
+ '@mui/utils': 5.16.13(@types/react@18.3.18)(react@18.3.1)
'@popperjs/core': 2.11.8
- '@types/react': 18.2.72
+ '@types/react': 18.3.18
clsx: 2.1.1
prop-types: 15.8.1
react: 18.3.1
@@ -1081,7 +1081,7 @@ packages:
resolution: {integrity: sha512-xe5RwI0Q2O709Bd2Y7l1W1NIwNmln0y+xaGk5VgX3vDJbkQEqzdfTFZ73e0CkEZgJwyiWgk5HY0l8R4nysOxjw==}
dev: false
- /@mui/icons-material@5.15.18(@mui/material@5.15.18)(@types/react@18.2.72)(react@18.3.1):
+ /@mui/icons-material@5.15.18(@mui/material@5.15.18)(@types/react@18.3.18)(react@18.3.1):
resolution: {integrity: sha512-jGhyw02TSLM0NgW+MDQRLLRUD/K4eN9rlK2pTBTL1OtzyZmQ8nB060zK1wA0b7cVrIiG+zyrRmNAvGWXwm2N9Q==}
engines: {node: '>=12.0.0'}
peerDependencies:
@@ -1093,12 +1093,12 @@ packages:
optional: true
dependencies:
'@babel/runtime': 7.26.0
- '@mui/material': 5.15.18(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@types/react@18.2.72)(react-dom@18.3.1)(react@18.3.1)
- '@types/react': 18.2.72
+ '@mui/material': 5.15.18(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)
+ '@types/react': 18.3.18
react: 18.3.1
dev: false
- /@mui/material@5.15.18(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@types/react@18.2.72)(react-dom@18.3.1)(react@18.3.1):
+ /@mui/material@5.15.18(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1):
resolution: {integrity: sha512-n+/dsiqux74fFfcRUJjok+ieNQ7+BEk6/OwX9cLcLvriZrZb+/7Y8+Fd2HlUUbn5N0CDurgAHm0VH1DqyJ9HAw==}
engines: {node: '>=12.0.0'}
peerDependencies:
@@ -1116,15 +1116,15 @@ packages:
optional: true
dependencies:
'@babel/runtime': 7.26.0
- '@emotion/react': 11.14.0(@types/react@18.2.72)(react@18.3.1)
- '@emotion/styled': 11.14.0(@emotion/react@11.14.0)(@types/react@18.2.72)(react@18.3.1)
- '@mui/base': 5.0.0-beta.40(@types/react@18.2.72)(react-dom@18.3.1)(react@18.3.1)
+ '@emotion/react': 11.14.0(@types/react@18.3.18)(react@18.3.1)
+ '@emotion/styled': 11.14.0(@emotion/react@11.14.0)(@types/react@18.3.18)(react@18.3.1)
+ '@mui/base': 5.0.0-beta.40(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)
'@mui/core-downloads-tracker': 5.16.13
- '@mui/system': 5.16.13(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@types/react@18.2.72)(react@18.3.1)
- '@mui/types': 7.2.20(@types/react@18.2.72)
- '@mui/utils': 5.16.13(@types/react@18.2.72)(react@18.3.1)
- '@types/react': 18.2.72
- '@types/react-transition-group': 4.4.12(@types/react@18.2.72)
+ '@mui/system': 5.16.13(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@types/react@18.3.18)(react@18.3.1)
+ '@mui/types': 7.2.21(@types/react@18.3.18)
+ '@mui/utils': 5.16.13(@types/react@18.3.18)(react@18.3.1)
+ '@types/react': 18.3.18
+ '@types/react-transition-group': 4.4.12(@types/react@18.3.18)
clsx: 2.1.1
csstype: 3.1.3
prop-types: 15.8.1
@@ -1134,7 +1134,7 @@ packages:
react-transition-group: 4.4.5(react-dom@18.3.1)(react@18.3.1)
dev: false
- /@mui/private-theming@5.16.13(@types/react@18.2.72)(react@18.3.1):
+ /@mui/private-theming@5.16.13(@types/react@18.3.18)(react@18.3.1):
resolution: {integrity: sha512-+s0FklvDvO7j0yBZn19DIIT3rLfub2fWvXGtMX49rG/xHfDFcP7fbWbZKHZMMP/2/IoTRDrZCbY1iP0xZlmuJA==}
engines: {node: '>=12.0.0'}
peerDependencies:
@@ -1145,8 +1145,8 @@ packages:
optional: true
dependencies:
'@babel/runtime': 7.26.0
- '@mui/utils': 5.16.13(@types/react@18.2.72)(react@18.3.1)
- '@types/react': 18.2.72
+ '@mui/utils': 5.16.13(@types/react@18.3.18)(react@18.3.1)
+ '@types/react': 18.3.18
prop-types: 15.8.1
react: 18.3.1
dev: false
@@ -1166,14 +1166,14 @@ packages:
dependencies:
'@babel/runtime': 7.26.0
'@emotion/cache': 11.14.0
- '@emotion/react': 11.14.0(@types/react@18.2.72)(react@18.3.1)
- '@emotion/styled': 11.14.0(@emotion/react@11.14.0)(@types/react@18.2.72)(react@18.3.1)
+ '@emotion/react': 11.14.0(@types/react@18.3.18)(react@18.3.1)
+ '@emotion/styled': 11.14.0(@emotion/react@11.14.0)(@types/react@18.3.18)(react@18.3.1)
csstype: 3.1.3
prop-types: 15.8.1
react: 18.3.1
dev: false
- /@mui/system@5.16.13(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@types/react@18.2.72)(react@18.3.1):
+ /@mui/system@5.16.13(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@types/react@18.3.18)(react@18.3.1):
resolution: {integrity: sha512-JnO3VH3yNoAmgyr44/2jiS1tcNwshwAqAaG5fTEEjHQbkuZT/mvPYj2GC1cON0zEQ5V03xrCNl/D+gU9AXibpw==}
engines: {node: '>=12.0.0'}
peerDependencies:
@@ -1190,31 +1190,31 @@ packages:
optional: true
dependencies:
'@babel/runtime': 7.26.0
- '@emotion/react': 11.14.0(@types/react@18.2.72)(react@18.3.1)
- '@emotion/styled': 11.14.0(@emotion/react@11.14.0)(@types/react@18.2.72)(react@18.3.1)
- '@mui/private-theming': 5.16.13(@types/react@18.2.72)(react@18.3.1)
+ '@emotion/react': 11.14.0(@types/react@18.3.18)(react@18.3.1)
+ '@emotion/styled': 11.14.0(@emotion/react@11.14.0)(@types/react@18.3.18)(react@18.3.1)
+ '@mui/private-theming': 5.16.13(@types/react@18.3.18)(react@18.3.1)
'@mui/styled-engine': 5.16.13(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(react@18.3.1)
- '@mui/types': 7.2.20(@types/react@18.2.72)
- '@mui/utils': 5.16.13(@types/react@18.2.72)(react@18.3.1)
- '@types/react': 18.2.72
+ '@mui/types': 7.2.21(@types/react@18.3.18)
+ '@mui/utils': 5.16.13(@types/react@18.3.18)(react@18.3.1)
+ '@types/react': 18.3.18
clsx: 2.1.1
csstype: 3.1.3
prop-types: 15.8.1
react: 18.3.1
dev: false
- /@mui/types@7.2.20(@types/react@18.2.72):
- resolution: {integrity: sha512-straFHD7L8v05l/N5vcWk+y7eL9JF0C2mtph/y4BPm3gn2Eh61dDwDB65pa8DLss3WJfDXYC7Kx5yjP0EmXpgw==}
+ /@mui/types@7.2.21(@types/react@18.3.18):
+ resolution: {integrity: sha512-6HstngiUxNqLU+/DPqlUJDIPbzUBxIVHb1MmXP0eTWDIROiCR2viugXpEif0PPe2mLqqakPzzRClWAnK+8UJww==}
peerDependencies:
'@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
peerDependenciesMeta:
'@types/react':
optional: true
dependencies:
- '@types/react': 18.2.72
+ '@types/react': 18.3.18
dev: false
- /@mui/utils@5.16.13(@types/react@18.2.72)(react@18.3.1):
+ /@mui/utils@5.16.13(@types/react@18.3.18)(react@18.3.1):
resolution: {integrity: sha512-35kLiShnDPByk57Mz4PP66fQUodCFiOD92HfpW6dK9lc7kjhZsKHRKeYPgWuwEHeXwYsCSFtBCW4RZh/8WT+TQ==}
engines: {node: '>=12.0.0'}
peerDependencies:
@@ -1225,9 +1225,9 @@ packages:
optional: true
dependencies:
'@babel/runtime': 7.26.0
- '@mui/types': 7.2.20(@types/react@18.2.72)
+ '@mui/types': 7.2.21(@types/react@18.3.18)
'@types/prop-types': 15.7.14
- '@types/react': 18.2.72
+ '@types/react': 18.3.18
clsx: 2.1.1
prop-types: 15.8.1
react: 18.3.1
@@ -1353,7 +1353,7 @@ packages:
redent: 3.0.0
dev: true
- /@testing-library/react@14.3.1(react-dom@18.3.1)(react@18.3.1):
+ /@testing-library/react@14.3.1(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1):
resolution: {integrity: sha512-H99XjUhWQw0lTgyMN05W3xQG1Nh4lq574D8keFf1dDoNTJgp66VbJozRaczoF+wsiaPJNt/TcnfpLGufGxSrZQ==}
engines: {node: '>=14'}
peerDependencies:
@@ -1362,9 +1362,11 @@ packages:
dependencies:
'@babel/runtime': 7.26.0
'@testing-library/dom': 9.3.4
- '@types/react-dom': 18.2.22
+ '@types/react-dom': 18.3.5(@types/react@18.3.18)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
+ transitivePeerDependencies:
+ - '@types/react'
dev: true
/@testing-library/user-event@14.5.2(@testing-library/dom@10.4.0):
@@ -1447,22 +1449,24 @@ packages:
/@types/prop-types@15.7.14:
resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==}
- /@types/react-dom@18.2.22:
- resolution: {integrity: sha512-fHkBXPeNtfvri6gdsMYyW+dW7RXFo6Ad09nLFK0VQWR7yGLai/Cyvyj696gbwYvBnhGtevUG9cET0pmUbMtoPQ==}
+ /@types/react-dom@18.3.5(@types/react@18.3.18):
+ resolution: {integrity: sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==}
+ peerDependencies:
+ '@types/react': ^18.0.0
dependencies:
- '@types/react': 18.2.72
+ '@types/react': 18.3.18
/@types/react-modal@3.16.3:
resolution: {integrity: sha512-xXuGavyEGaFQDgBv4UVm8/ZsG+qxeQ7f77yNrW3n+1J6XAstUy5rYHeIHPh1KzsGc6IkCIdu6lQ2xWzu1jBTLg==}
dependencies:
- '@types/react': 18.2.72
+ '@types/react': 18.3.18
dev: false
/@types/react-router-dom@5.3.3:
resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==}
dependencies:
'@types/history': 4.7.11
- '@types/react': 18.2.72
+ '@types/react': 18.3.18
'@types/react-router': 5.1.20
dev: false
@@ -1470,19 +1474,19 @@ packages:
resolution: {integrity: sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==}
dependencies:
'@types/history': 4.7.11
- '@types/react': 18.2.72
+ '@types/react': 18.3.18
dev: false
- /@types/react-transition-group@4.4.12(@types/react@18.2.72):
+ /@types/react-transition-group@4.4.12(@types/react@18.3.18):
resolution: {integrity: sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==}
peerDependencies:
'@types/react': '*'
dependencies:
- '@types/react': 18.2.72
+ '@types/react': 18.3.18
dev: false
- /@types/react@18.2.72:
- resolution: {integrity: sha512-/e7GWxGzXQF7OJAua7UAYqYi/4VpXEfbGtmYQcAQwP3SjjjAXfybTf/JK5S+SaetB/ChXl8Y2g1hCsj7jDXxcg==}
+ /@types/react@18.3.18:
+ resolution: {integrity: sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==}
dependencies:
'@types/prop-types': 15.7.14
csstype: 3.1.3
@@ -5110,7 +5114,7 @@ packages:
engines: {node: '>=8'}
dev: true
- /rehackt@0.1.0(@types/react@18.2.72)(react@18.3.1):
+ /rehackt@0.1.0(@types/react@18.3.18)(react@18.3.1):
resolution: {integrity: sha512-7kRDOuLHB87D/JESKxQoRwv4DzbIdwkAGQ7p6QKGdVlY1IZheUnVhlk/4UZlNUVxdAXpyxikE3URsG067ybVzw==}
peerDependencies:
'@types/react': '*'
@@ -5121,7 +5125,7 @@ packages:
react:
optional: true
dependencies:
- '@types/react': 18.2.72
+ '@types/react': 18.3.18
react: 18.3.1
dev: false
diff --git a/py/requirements.txt b/py/requirements.txt
index 3dfbe58c683ab..aef1b0f79400f 100644
--- a/py/requirements.txt
+++ b/py/requirements.txt
@@ -7,7 +7,7 @@ secretstorage==3.3.3
debugpy==1.8.11
filetype==1.2.0
h11==0.14.0
-idna==3.7
+idna==3.10
importlib-metadata==6.8.0
inflection==0.5.1
iniconfig==2.0.0
diff --git a/py/requirements_lock.txt b/py/requirements_lock.txt
index a081808cccea8..6831a495cc0f3 100644
--- a/py/requirements_lock.txt
+++ b/py/requirements_lock.txt
@@ -257,9 +257,9 @@ h11==0.14.0 \
# via
# -r py/requirements.txt
# wsproto
-idna==3.7 \
- --hash=sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc \
- --hash=sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0
+idna==3.10 \
+ --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \
+ --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
# via
# -r py/requirements.txt
# requests
diff --git a/renovate.json b/renovate.json
index f5aba04d1c54e..e03df565fa82a 100644
--- a/renovate.json
+++ b/renovate.json
@@ -39,6 +39,7 @@
},
{
"matchManagers": [ "npm" ],
+ "rangeStrategy": "bump",
"commitMessagePrefix": "[js]",
"labels": [ "dependencies", "c-nodejs" ]
},
@@ -69,6 +70,7 @@
},
{
"matchManagers": [ "cargo" ],
+ "rangeStrategy": "bump",
"commitMessagePrefix": "[rust]",
"labels": [ "dependencies", "c-rust" ]
},