diff --git a/MODULE.bazel b/MODULE.bazel index c1817b08269e8..3ab1515e9c3fb 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -173,7 +173,7 @@ maven.install( "com.github.spotbugs:spotbugs:4.8.6", "com.github.stephenc.jcip:jcip-annotations:1.0-1", "com.google.code.gson:gson:2.11.0", - "com.google.guava:guava:33.3.0-jre", + "com.google.guava:guava:33.3.1-jre", "com.google.auto:auto-common:1.2.2", "com.google.auto.service:auto-service:1.1.1", "com.google.auto.service:auto-service-annotations:1.1.1", diff --git a/dotnet/src/webdriver/BiDi/BiDi.cs b/dotnet/src/webdriver/BiDi/BiDi.cs index db53571e8ad8c..34a9452dec144 100644 --- a/dotnet/src/webdriver/BiDi/BiDi.cs +++ b/dotnet/src/webdriver/BiDi/BiDi.cs @@ -1,9 +1,10 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; using OpenQA.Selenium.BiDi.Communication; using OpenQA.Selenium.BiDi.Communication.Transport; +#nullable enable + namespace OpenQA.Selenium.BiDi; public class BiDi : IAsyncDisposable @@ -38,11 +39,11 @@ internal BiDi(string url) } internal Modules.Session.SessionModule SessionModule => _sessionModule.Value; - internal Modules.BrowsingContext.BrowsingContextModule BrowsingContextModule => _browsingContextModule.Value; + internal Modules.BrowsingContext.BrowsingContextModule BrowsingContext => _browsingContextModule.Value; public Modules.Browser.BrowserModule Browser => _browserModule.Value; public Modules.Network.NetworkModule Network => _networkModule.Value; internal Modules.Input.InputModule InputModule => _inputModule.Value; - internal Modules.Script.ScriptModule ScriptModule => _scriptModule.Value; + public Modules.Script.ScriptModule Script => _scriptModule.Value; public Modules.Log.LogModule Log => _logModule.Value; public Modules.Storage.StorageModule Storage => _storageModule.Value; @@ -60,16 +61,6 @@ public static async Task ConnectAsync(string url) return bidi; } - public Task CreateContextAsync(Modules.BrowsingContext.ContextType type, Modules.BrowsingContext.CreateOptions? options = null) - { - return BrowsingContextModule.CreateAsync(type, options); - } - - public Task> GetTreeAsync(Modules.BrowsingContext.GetTreeOptions? options = null) - { - return BrowsingContextModule.GetTreeAsync(options); - } - public Task EndAsync(Modules.Session.EndOptions? options = null) { return SessionModule.EndAsync(options); @@ -81,44 +72,4 @@ public async ValueTask DisposeAsync() _transport?.Dispose(); } - - public Task OnContextCreatedAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) - { - return BrowsingContextModule.OnContextCreatedAsync(handler, options); - } - - public Task OnContextCreatedAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) - { - return BrowsingContextModule.OnContextCreatedAsync(handler, options); - } - - public Task OnContextDestroyedAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) - { - return BrowsingContextModule.OnContextDestroyedAsync(handler, options); - } - - public Task OnContextDestroyedAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) - { - return BrowsingContextModule.OnContextDestroyedAsync(handler, options); - } - - public Task OnUserPromptOpenedAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) - { - return BrowsingContextModule.OnUserPromptOpenedAsync(handler, options); - } - - public Task OnUserPromptOpenedAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) - { - return BrowsingContextModule.OnUserPromptOpenedAsync(handler, options); - } - - public Task OnUserPromptClosedAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) - { - return BrowsingContextModule.OnUserPromptClosedAsync(handler, options); - } - - public Task OnUserPromptClosedAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) - { - return BrowsingContextModule.OnUserPromptClosedAsync(handler, options); - } } diff --git a/dotnet/src/webdriver/BiDi/BiDiException.cs b/dotnet/src/webdriver/BiDi/BiDiException.cs index 7f2ddd5b59cbc..6959645111b01 100644 --- a/dotnet/src/webdriver/BiDi/BiDiException.cs +++ b/dotnet/src/webdriver/BiDi/BiDiException.cs @@ -1,5 +1,7 @@ using System; +#nullable enable + namespace OpenQA.Selenium.BiDi; public class BiDiException : Exception diff --git a/dotnet/src/webdriver/BiDi/Communication/Broker.cs b/dotnet/src/webdriver/BiDi/Communication/Broker.cs index 82549d1d5c5b1..5f8a0983846c9 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Broker.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Broker.cs @@ -10,6 +10,8 @@ using System.Threading; using System.Threading.Tasks; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication; public class Broker : IAsyncDisposable @@ -34,7 +36,7 @@ public class Broker : IAsyncDisposable private readonly JsonSerializerOptions _jsonSerializerOptions; - public Broker(BiDi bidi, ITransport transport) + internal Broker(BiDi bidi, ITransport transport) { _bidi = bidi; _transport = transport; @@ -51,7 +53,7 @@ public Broker(BiDi bidi, ITransport transport) new NavigationConverter(), new InterceptConverter(_bidi), new RequestConverter(_bidi), - new ChannelConverter(_bidi), + new ChannelConverter(), new HandleConverter(_bidi), new InternalIdConverter(_bidi), new PreloadScriptConverter(_bidi), @@ -59,6 +61,7 @@ public Broker(BiDi bidi, ITransport transport) new RealmTypeConverter(), new DateTimeOffsetConverter(), new PrintPageRangeConverter(), + new InputOriginConverter(), new JsonStringEnumConverter(JsonNamingPolicy.CamelCase), // https://github.com/dotnet/runtime/issues/72604 @@ -68,6 +71,13 @@ public Broker(BiDi bidi, ITransport transport) new Json.Converters.Polymorphic.RealmInfoConverter(), new Json.Converters.Polymorphic.LogEntryConverter(), // + + // Enumerable + new Json.Converters.Enumerable.GetCookiesResultConverter(), + new Json.Converters.Enumerable.LocateNodesResultConverter(), + new Json.Converters.Enumerable.InputSourceActionsConverter(), + new Json.Converters.Enumerable.GetUserContextsResultConverter(), + new Json.Converters.Enumerable.GetRealmsResultConverter(), } }; } diff --git a/dotnet/src/webdriver/BiDi/Communication/Command.cs b/dotnet/src/webdriver/BiDi/Communication/Command.cs index bfa7113512068..729b319cc03ec 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Command.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Command.cs @@ -1,5 +1,7 @@ using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication; [JsonPolymorphic(TypeDiscriminatorPropertyName = "method")] diff --git a/dotnet/src/webdriver/BiDi/Communication/CommandOptions.cs b/dotnet/src/webdriver/BiDi/Communication/CommandOptions.cs index 93cc63fc2ebfc..ffb6616ae9cef 100644 --- a/dotnet/src/webdriver/BiDi/Communication/CommandOptions.cs +++ b/dotnet/src/webdriver/BiDi/Communication/CommandOptions.cs @@ -1,5 +1,7 @@ using System; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication; public record CommandOptions diff --git a/dotnet/src/webdriver/BiDi/Communication/EventHandler.cs b/dotnet/src/webdriver/BiDi/Communication/EventHandler.cs index 4aab8620e3f2b..ce5444eb0d9fd 100644 --- a/dotnet/src/webdriver/BiDi/Communication/EventHandler.cs +++ b/dotnet/src/webdriver/BiDi/Communication/EventHandler.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Threading.Tasks; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication; public abstract class EventHandler(string eventName, Type eventArgsType, IEnumerable? contexts = null) diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/BrowserUserContextConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/BrowserUserContextConverter.cs index 7997f7c0f1541..3d478cf5d9f69 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/BrowserUserContextConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/BrowserUserContextConverter.cs @@ -3,6 +3,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters; internal class BrowserUserContextConverter : JsonConverter diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/BrowsingContextConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/BrowsingContextConverter.cs index 2718700f3ffac..8c1a928ef19ad 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/BrowsingContextConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/BrowsingContextConverter.cs @@ -3,6 +3,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters; internal class BrowsingContextConverter : JsonConverter diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/ChannelConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/ChannelConverter.cs index c2a7da0accffd..ac35a22fcc2c4 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/ChannelConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/ChannelConverter.cs @@ -3,22 +3,17 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters; internal class ChannelConverter : JsonConverter { - private readonly BiDi _bidi; - - public ChannelConverter(BiDi bidi) - { - _bidi = bidi; - } - public override Channel? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var id = reader.GetString(); - return new Channel(_bidi, id!); + return new Channel(id!); } public override void Write(Utf8JsonWriter writer, Channel value, JsonSerializerOptions options) diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/DateTimeOffsetConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/DateTimeOffsetConverter.cs index 9d87f0f17342e..ff9b6258d3a69 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/DateTimeOffsetConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/DateTimeOffsetConverter.cs @@ -2,6 +2,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters; internal class DateTimeOffsetConverter : JsonConverter diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Enumerable/GetCookiesResultConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Enumerable/GetCookiesResultConverter.cs new file mode 100644 index 0000000000000..bd92fa36eb119 --- /dev/null +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Enumerable/GetCookiesResultConverter.cs @@ -0,0 +1,26 @@ +using OpenQA.Selenium.BiDi.Modules.Storage; +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; + +#nullable enable + +namespace OpenQA.Selenium.BiDi.Communication.Json.Converters.Enumerable; + +internal class GetCookiesResultConverter : JsonConverter +{ + public override GetCookiesResult Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var doc = JsonDocument.ParseValue(ref reader); + var cookies = doc.RootElement.GetProperty("cookies").Deserialize>(options); + var partitionKey = doc.RootElement.GetProperty("partitionKey").Deserialize(options); + + return new GetCookiesResult(cookies!, partitionKey!); + } + + public override void Write(Utf8JsonWriter writer, GetCookiesResult value, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } +} diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Enumerable/GetRealmsResultConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Enumerable/GetRealmsResultConverter.cs new file mode 100644 index 0000000000000..34c5a979c02c6 --- /dev/null +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Enumerable/GetRealmsResultConverter.cs @@ -0,0 +1,25 @@ +using OpenQA.Selenium.BiDi.Modules.Script; +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; + +#nullable enable + +namespace OpenQA.Selenium.BiDi.Communication.Json.Converters.Enumerable; + +internal class GetRealmsResultConverter : JsonConverter +{ + public override GetRealmsResult Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var doc = JsonDocument.ParseValue(ref reader); + var realms = doc.RootElement.GetProperty("realms").Deserialize>(options); + + return new GetRealmsResult(realms!); + } + + public override void Write(Utf8JsonWriter writer, GetRealmsResult value, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } +} diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Enumerable/GetUserContextsResultConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Enumerable/GetUserContextsResultConverter.cs new file mode 100644 index 0000000000000..123c415c9bcd1 --- /dev/null +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Enumerable/GetUserContextsResultConverter.cs @@ -0,0 +1,25 @@ +using OpenQA.Selenium.BiDi.Modules.Browser; +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; + +#nullable enable + +namespace OpenQA.Selenium.BiDi.Communication.Json.Converters.Enumerable; + +internal class GetUserContextsResultConverter : JsonConverter +{ + public override GetUserContextsResult Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var doc = JsonDocument.ParseValue(ref reader); + var userContexts = doc.RootElement.GetProperty("userContexts").Deserialize>(options); + + return new GetUserContextsResult(userContexts!); + } + + public override void Write(Utf8JsonWriter writer, GetUserContextsResult value, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } +} diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Enumerable/InputSourceActionsConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Enumerable/InputSourceActionsConverter.cs new file mode 100644 index 0000000000000..4e4c72c91fbe9 --- /dev/null +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Enumerable/InputSourceActionsConverter.cs @@ -0,0 +1,61 @@ +using OpenQA.Selenium.BiDi.Modules.Input; +using System; +using System.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; + +#nullable enable + +namespace OpenQA.Selenium.BiDi.Communication.Json.Converters.Enumerable; + +internal class InputSourceActionsConverter : JsonConverter +{ + public override SourceActions Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + + public override void Write(Utf8JsonWriter writer, SourceActions value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + + writer.WriteString("id", value.Id); + + switch (value) + { + case KeyActions keys: + writer.WriteString("type", "key"); + writer.WritePropertyName("actions"); + JsonSerializer.Serialize(writer, keys.Actions.Select(a => a as IKeySourceAction), options); + + break; + case PointerActions pointers: + writer.WriteString("type", "pointer"); + if (pointers.Options is not null) + { + writer.WritePropertyName("parameters"); + JsonSerializer.Serialize(writer, pointers.Options, options); + } + + writer.WritePropertyName("actions"); + JsonSerializer.Serialize(writer, pointers.Actions.Select(a => a as IPointerSourceAction), options); + + break; + case WheelActions wheels: + writer.WriteString("type", "wheel"); + writer.WritePropertyName("actions"); + JsonSerializer.Serialize(writer, wheels.Actions.Select(a => a as IWheelSourceAction), options); + + break; + case NoneActions none: + writer.WriteString("type", "none"); + writer.WritePropertyName("actions"); + JsonSerializer.Serialize(writer, none.Actions.Select(a => a as INoneSourceAction), options); + + break; + } + + writer.WriteEndObject(); + } +} + diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Enumerable/LocateNodesResultConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Enumerable/LocateNodesResultConverter.cs new file mode 100644 index 0000000000000..307433c7be023 --- /dev/null +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Enumerable/LocateNodesResultConverter.cs @@ -0,0 +1,26 @@ +using OpenQA.Selenium.BiDi.Modules.BrowsingContext; +using OpenQA.Selenium.BiDi.Modules.Script; +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; + +#nullable enable + +namespace OpenQA.Selenium.BiDi.Communication.Json.Converters.Enumerable; + +internal class LocateNodesResultConverter : JsonConverter +{ + public override LocateNodesResult Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var doc = JsonDocument.ParseValue(ref reader); + var nodes = doc.RootElement.GetProperty("nodes").Deserialize>(options); + + return new LocateNodesResult(nodes!); + } + + public override void Write(Utf8JsonWriter writer, LocateNodesResult value, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } +} diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/HandleConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/HandleConverter.cs index 71e0ed6e5ae51..2117bb72fa519 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/HandleConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/HandleConverter.cs @@ -3,6 +3,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters; internal class HandleConverter : JsonConverter diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/InputOriginConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/InputOriginConverter.cs new file mode 100644 index 0000000000000..c544362ccccd8 --- /dev/null +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/InputOriginConverter.cs @@ -0,0 +1,36 @@ +using OpenQA.Selenium.BiDi.Modules.Input; +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +#nullable enable + +namespace OpenQA.Selenium.BiDi.Communication.Json.Converters; + +internal class InputOriginConverter : JsonConverter +{ + public override Origin Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + + public override void Write(Utf8JsonWriter writer, Origin value, JsonSerializerOptions options) + { + if (value is Origin.Viewport) + { + writer.WriteStringValue("viewport"); + } + else if (value is Origin.Pointer) + { + writer.WriteStringValue("pointer"); + } + else if (value is Origin.Element element) + { + writer.WriteStartObject(); + writer.WriteString("type", "element"); + writer.WritePropertyName("element"); + JsonSerializer.Serialize(writer, element.SharedReference, options); + writer.WriteEndObject(); + } + } +} diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/InterceptConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/InterceptConverter.cs index 3a207a89116c2..3fd062b22fae3 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/InterceptConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/InterceptConverter.cs @@ -3,6 +3,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters; internal class InterceptConverter : JsonConverter diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/InternalIdConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/InternalIdConverter.cs index 9271a1877be71..7edcaa7543464 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/InternalIdConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/InternalIdConverter.cs @@ -3,6 +3,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters; internal class InternalIdConverter : JsonConverter diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/NavigationConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/NavigationConverter.cs index 040e7fb723919..e61d300f18f56 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/NavigationConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/NavigationConverter.cs @@ -3,6 +3,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters; internal class NavigationConverter : JsonConverter diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/EvaluateResultConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/EvaluateResultConverter.cs index c349d82f90f04..ac0fd1a7bbfcc 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/EvaluateResultConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/EvaluateResultConverter.cs @@ -3,6 +3,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters.Polymorphic; // https://github.com/dotnet/runtime/issues/72604 @@ -14,8 +16,8 @@ internal class EvaluateResultConverter : JsonConverter return jsonDocument.RootElement.GetProperty("type").ToString() switch { - "success" => jsonDocument.Deserialize(options), - "exception" => jsonDocument.Deserialize(options), + "success" => jsonDocument.Deserialize(options), + "exception" => jsonDocument.Deserialize(options), _ => null, }; } diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/LogEntryConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/LogEntryConverter.cs index ada10ab054a50..e5ccbac46f326 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/LogEntryConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/LogEntryConverter.cs @@ -3,24 +3,26 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters.Polymorphic; // https://github.com/dotnet/runtime/issues/72604 -internal class LogEntryConverter : JsonConverter +internal class LogEntryConverter : JsonConverter { - public override BaseLogEntry? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override Modules.Log.Entry? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var jsonDocument = JsonDocument.ParseValue(ref reader); return jsonDocument.RootElement.GetProperty("type").ToString() switch { - "console" => jsonDocument.Deserialize(options), - "javascript" => jsonDocument.Deserialize(options), + "console" => jsonDocument.Deserialize(options), + "javascript" => jsonDocument.Deserialize(options), _ => null, }; } - public override void Write(Utf8JsonWriter writer, BaseLogEntry value, JsonSerializerOptions options) + public override void Write(Utf8JsonWriter writer, Modules.Log.Entry value, JsonSerializerOptions options) { throw new NotImplementedException(); } diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/MessageConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/MessageConverter.cs index 6164dcc04690d..b9d86ae634902 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/MessageConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/MessageConverter.cs @@ -2,6 +2,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters.Polymorphic; // https://github.com/dotnet/runtime/issues/72604 diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/RealmInfoConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/RealmInfoConverter.cs index b3d061783dfae..9824377ca47ac 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/RealmInfoConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/RealmInfoConverter.cs @@ -3,6 +3,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters.Polymorphic; // https://github.com/dotnet/runtime/issues/72604 @@ -14,14 +16,14 @@ internal class RealmInfoConverter : JsonConverter return jsonDocument.RootElement.GetProperty("type").ToString() switch { - "window" => jsonDocument.Deserialize(options), - "dedicated-worker" => jsonDocument.Deserialize(options), - "shared-worker" => jsonDocument.Deserialize(options), - "service-worker" => jsonDocument.Deserialize(options), - "worker" => jsonDocument.Deserialize(options), - "paint-worklet" => jsonDocument.Deserialize(options), - "audio-worklet" => jsonDocument.Deserialize(options), - "worklet" => jsonDocument.Deserialize(options), + "window" => jsonDocument.Deserialize(options), + "dedicated-worker" => jsonDocument.Deserialize(options), + "shared-worker" => jsonDocument.Deserialize(options), + "service-worker" => jsonDocument.Deserialize(options), + "worker" => jsonDocument.Deserialize(options), + "paint-worklet" => jsonDocument.Deserialize(options), + "audio-worklet" => jsonDocument.Deserialize(options), + "worklet" => jsonDocument.Deserialize(options), _ => null, }; } diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/RemoteValueConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/RemoteValueConverter.cs index 1d3b08211b348..3f19d2a18c56c 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/RemoteValueConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/RemoteValueConverter.cs @@ -3,6 +3,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters.Polymorphic; // https://github.com/dotnet/runtime/issues/72604 @@ -12,31 +14,38 @@ internal class RemoteValueConverter : JsonConverter { var jsonDocument = JsonDocument.ParseValue(ref reader); + if (jsonDocument.RootElement.ValueKind == JsonValueKind.String) + { + return new RemoteValue.String(jsonDocument.RootElement.GetString()!); + } + return jsonDocument.RootElement.GetProperty("type").ToString() switch { - "number" => jsonDocument.Deserialize(options), - "string" => jsonDocument.Deserialize(options), - "null" => jsonDocument.Deserialize(options), - "undefined" => jsonDocument.Deserialize(options), - "symbol" => jsonDocument.Deserialize(options), - "object" => jsonDocument.Deserialize(options), - "function" => jsonDocument.Deserialize(options), - "regexp" => jsonDocument.Deserialize(options), - "date" => jsonDocument.Deserialize(options), - "map" => jsonDocument.Deserialize(options), - "set" => jsonDocument.Deserialize(options), - "weakmap" => jsonDocument.Deserialize(options), - "weakset" => jsonDocument.Deserialize(options), - "generator" => jsonDocument.Deserialize(options), - "error" => jsonDocument.Deserialize(options), - "proxy" => jsonDocument.Deserialize(options), - "promise" => jsonDocument.Deserialize(options), - "typedarray" => jsonDocument.Deserialize(options), - "arraybuffer" => jsonDocument.Deserialize(options), - "nodelist" => jsonDocument.Deserialize(options), - "htmlcollection" => jsonDocument.Deserialize(options), - "node" => jsonDocument.Deserialize(options), - "window" => jsonDocument.Deserialize(options), + "number" => jsonDocument.Deserialize(options), + "boolean" => jsonDocument.Deserialize(options), + "string" => jsonDocument.Deserialize(options), + "null" => jsonDocument.Deserialize(options), + "undefined" => jsonDocument.Deserialize(options), + "symbol" => jsonDocument.Deserialize(options), + "array" => jsonDocument.Deserialize(options), + "object" => jsonDocument.Deserialize(options), + "function" => jsonDocument.Deserialize(options), + "regexp" => jsonDocument.Deserialize(options), + "date" => jsonDocument.Deserialize(options), + "map" => jsonDocument.Deserialize(options), + "set" => jsonDocument.Deserialize(options), + "weakmap" => jsonDocument.Deserialize(options), + "weakset" => jsonDocument.Deserialize(options), + "generator" => jsonDocument.Deserialize(options), + "error" => jsonDocument.Deserialize(options), + "proxy" => jsonDocument.Deserialize(options), + "promise" => jsonDocument.Deserialize(options), + "typedarray" => jsonDocument.Deserialize(options), + "arraybuffer" => jsonDocument.Deserialize(options), + "nodelist" => jsonDocument.Deserialize(options), + "htmlcollection" => jsonDocument.Deserialize(options), + "node" => jsonDocument.Deserialize(options), + "window" => jsonDocument.Deserialize(options), _ => null, }; } diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/PreloadScriptConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/PreloadScriptConverter.cs index 53dba4b424388..4b68ce22c52ff 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/PreloadScriptConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/PreloadScriptConverter.cs @@ -3,6 +3,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters; internal class PreloadScriptConverter : JsonConverter diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/PrintPageRangeConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/PrintPageRangeConverter.cs index afd375d078a59..76ffd9b34ad4e 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/PrintPageRangeConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/PrintPageRangeConverter.cs @@ -3,6 +3,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters; internal class PrintPageRangeConverter : JsonConverter diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/RealmConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/RealmConverter.cs index ab2baedc6fd28..60cde6d1152db 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/RealmConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/RealmConverter.cs @@ -3,6 +3,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters; internal class RealmConverter : JsonConverter diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/RealmTypeConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/RealmTypeConverter.cs index f92966b1a3f1f..048250fd526d5 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/RealmTypeConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/RealmTypeConverter.cs @@ -3,6 +3,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters; internal class RealmTypeConverter : JsonConverter @@ -27,6 +29,19 @@ public override RealmType Read(ref Utf8JsonReader reader, Type typeToConvert, Js public override void Write(Utf8JsonWriter writer, RealmType value, JsonSerializerOptions options) { - throw new NotImplementedException(); + var str = value switch + { + RealmType.Window => "window", + RealmType.DedicatedWorker => "dedicated-worker", + RealmType.SharedWorker => "shared-worker", + RealmType.ServiceWorker => "service-worker", + RealmType.Worker => "worker", + RealmType.PaintWorker => "paint-worker", + RealmType.AudioWorker => "audio-worker", + RealmType.Worklet => "worklet", + _ => throw new JsonException($"Unrecognized '{value}' value of {typeof(RealmType)}."), + }; + + writer.WriteStringValue(str); } } diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/RequestConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/RequestConverter.cs index 7a15a569faa06..0524246d6b3b3 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/RequestConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/RequestConverter.cs @@ -3,6 +3,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Json.Converters; internal class RequestConverter : JsonConverter diff --git a/dotnet/src/webdriver/BiDi/Communication/Message.cs b/dotnet/src/webdriver/BiDi/Communication/Message.cs index 75925ed4d7592..c00a2777a33f4 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Message.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Message.cs @@ -1,5 +1,7 @@ using System.Text.Json; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication; // https://github.com/dotnet/runtime/issues/72604 diff --git a/dotnet/src/webdriver/BiDi/Communication/Transport/ITransport.cs b/dotnet/src/webdriver/BiDi/Communication/Transport/ITransport.cs index 404d62734f9d2..3ed6d2e32a4cf 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Transport/ITransport.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Transport/ITransport.cs @@ -3,9 +3,11 @@ using System.Threading; using System; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Transport; -public interface ITransport : IDisposable +interface ITransport : IDisposable { Task ConnectAsync(CancellationToken cancellationToken); diff --git a/dotnet/src/webdriver/BiDi/Communication/Transport/WebSocketTransport.cs b/dotnet/src/webdriver/BiDi/Communication/Transport/WebSocketTransport.cs index 52cd5c0ffa7f2..76384f51b1261 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Transport/WebSocketTransport.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Transport/WebSocketTransport.cs @@ -7,9 +7,11 @@ using System.Text; using OpenQA.Selenium.Internal.Logging; +#nullable enable + namespace OpenQA.Selenium.BiDi.Communication.Transport; -public class WebSocketTransport(Uri _uri) : ITransport, IDisposable +class WebSocketTransport(Uri _uri) : ITransport, IDisposable { private readonly static ILogger _logger = Log.GetLogger(); @@ -59,7 +61,7 @@ public async Task SendAsJsonAsync(Command command, JsonSerializerOptions jsonSer { if (_logger.IsEnabled(LogEventLevel.Trace)) { - _logger.Trace($"BiDi SND >> {buffer.Length} > {Encoding.UTF8.GetString(buffer)}"); + _logger.Trace($"BiDi SND >> {Encoding.UTF8.GetString(buffer)}"); } await _webSocket.SendAsync(new ArraySegment(buffer), WebSocketMessageType.Text, true, cancellationToken).ConfigureAwait(false); diff --git a/dotnet/src/webdriver/BiDi/EventArgs.cs b/dotnet/src/webdriver/BiDi/EventArgs.cs index 01d5cd3280acf..30361ca95e6cb 100644 --- a/dotnet/src/webdriver/BiDi/EventArgs.cs +++ b/dotnet/src/webdriver/BiDi/EventArgs.cs @@ -1,6 +1,8 @@ using OpenQA.Selenium.BiDi.Modules.BrowsingContext; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi; public abstract record EventArgs(BiDi BiDi) diff --git a/dotnet/src/webdriver/BiDi/Modules/Browser/BrowserModule.cs b/dotnet/src/webdriver/BiDi/Modules/Browser/BrowserModule.cs index e42982b773d8c..ba7fb0496dd6d 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Browser/BrowserModule.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Browser/BrowserModule.cs @@ -2,6 +2,8 @@ using System.Threading.Tasks; using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Browser; public sealed class BrowserModule(Broker broker) : Module(broker) @@ -16,11 +18,9 @@ public async Task CreateUserContextAsync(CreateUserContextOptio return await Broker.ExecuteCommandAsync(new CreateUserContextCommand(), options).ConfigureAwait(false); } - public async Task> GetUserContextsAsync(GetUserContextsOptions? options = null) + public async Task GetUserContextsAsync(GetUserContextsOptions? options = null) { - var result = await Broker.ExecuteCommandAsync(new GetUserContextsCommand(), options).ConfigureAwait(false); - - return result.UserContexts; + return await Broker.ExecuteCommandAsync(new GetUserContextsCommand(), options).ConfigureAwait(false); } public async Task RemoveUserContextAsync(UserContext userContext, RemoveUserContextOptions? options = null) diff --git a/dotnet/src/webdriver/BiDi/Modules/Browser/CloseCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Browser/CloseCommand.cs index 345a3c5a22935..59f9db7374929 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Browser/CloseCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Browser/CloseCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Browser; internal class CloseCommand() : Command(CommandParameters.Empty); diff --git a/dotnet/src/webdriver/BiDi/Modules/Browser/CreateUserContextCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Browser/CreateUserContextCommand.cs index 9b84d1ee11532..ce44e5ae2f367 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Browser/CreateUserContextCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Browser/CreateUserContextCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Browser; internal class CreateUserContextCommand() : Command(CommandParameters.Empty); diff --git a/dotnet/src/webdriver/BiDi/Modules/Browser/GetUserContextsCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Browser/GetUserContextsCommand.cs index 5a1a0a211cf1c..161a1bf286f1e 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Browser/GetUserContextsCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Browser/GetUserContextsCommand.cs @@ -1,10 +1,29 @@ using OpenQA.Selenium.BiDi.Communication; +using System.Collections; using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Browser; internal class GetUserContextsCommand() : Command(CommandParameters.Empty); public record GetUserContextsOptions : CommandOptions; -public record GetUserContextsResult(IReadOnlyList UserContexts); +public record GetUserContextsResult : IReadOnlyList +{ + private readonly IReadOnlyList _userContexts; + + internal GetUserContextsResult(IReadOnlyList userContexts) + { + _userContexts = userContexts; + } + + public UserContextInfo this[int index] => _userContexts[index]; + + public int Count => _userContexts.Count; + + public IEnumerator GetEnumerator() => _userContexts.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => (_userContexts as IEnumerable).GetEnumerator(); +} diff --git a/dotnet/src/webdriver/BiDi/Modules/Browser/RemoveUserContextCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Browser/RemoveUserContextCommand.cs index b937ad48ffc80..7877eb0f710ff 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Browser/RemoveUserContextCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Browser/RemoveUserContextCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Browser; internal class RemoveUserContextCommand(RemoveUserContextCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/Browser/UserContext.cs b/dotnet/src/webdriver/BiDi/Modules/Browser/UserContext.cs index 5e8bcd712062a..a2e689d494aaa 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Browser/UserContext.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Browser/UserContext.cs @@ -1,6 +1,8 @@ using System; using System.Threading.Tasks; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Browser; public class UserContext : IAsyncDisposable @@ -13,7 +15,7 @@ internal UserContext(BiDi bidi, string id) Id = id; } - public string Id { get; } + internal string Id { get; } public Task RemoveAsync() { @@ -24,4 +26,16 @@ public async ValueTask DisposeAsync() { await RemoveAsync().ConfigureAwait(false); } + + public override bool Equals(object? obj) + { + if (obj is UserContext userContextObj) return userContextObj.Id == Id; + + return false; + } + + public override int GetHashCode() + { + return Id.GetHashCode(); + } } diff --git a/dotnet/src/webdriver/BiDi/Modules/Browser/UserContextInfo.cs b/dotnet/src/webdriver/BiDi/Modules/Browser/UserContextInfo.cs index 7f4949b49a2fa..99b7e59a486b2 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Browser/UserContextInfo.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Browser/UserContextInfo.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Browser; public record UserContextInfo(UserContext UserContext); diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/ActivateCommand.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/ActivateCommand.cs index f05354060e89a..4934e51b815bd 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/ActivateCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/ActivateCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; internal class ActivateCommand(ActivateCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContext.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContext.cs index 80c7b7d49fb70..e83f671ae227e 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContext.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContext.cs @@ -2,6 +2,8 @@ using System.Threading.Tasks; using System; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; public class BrowsingContext @@ -13,7 +15,7 @@ internal BrowsingContext(BiDi bidi, string id) _logModule = new Lazy(() => new BrowsingContextLogModule(this, BiDi.Log)); _networkModule = new Lazy(() => new BrowsingContextNetworkModule(this, BiDi.Network)); - _scriptModule = new Lazy(() => new BrowsingContextScriptModule(this, BiDi.ScriptModule)); + _scriptModule = new Lazy(() => new BrowsingContextScriptModule(this, BiDi.Script)); _storageModule = new Lazy(() => new BrowsingContextStorageModule(this, BiDi.Storage)); _inputModule = new Lazy(() => new BrowsingContextInputModule(this, BiDi.InputModule)); } @@ -40,37 +42,37 @@ internal BrowsingContext(BiDi bidi, string id) public Task NavigateAsync(string url, NavigateOptions? options = null) { - return BiDi.BrowsingContextModule.NavigateAsync(this, url, options); + return BiDi.BrowsingContext.NavigateAsync(this, url, options); } public Task ReloadAsync(ReloadOptions? options = null) { - return BiDi.BrowsingContextModule.ReloadAsync(this, options); + return BiDi.BrowsingContext.ReloadAsync(this, options); } public Task ActivateAsync(ActivateOptions? options = null) { - return BiDi.BrowsingContextModule.ActivateAsync(this, options); + return BiDi.BrowsingContext.ActivateAsync(this, options); } - public Task> LocateNodesAsync(Locator locator, LocateNodesOptions? options = null) + public Task LocateNodesAsync(Locator locator, LocateNodesOptions? options = null) { - return BiDi.BrowsingContextModule.LocateNodesAsync(this, locator, options); + return BiDi.BrowsingContext.LocateNodesAsync(this, locator, options); } public Task CaptureScreenshotAsync(CaptureScreenshotOptions? options = null) { - return BiDi.BrowsingContextModule.CaptureScreenshotAsync(this, options); + return BiDi.BrowsingContext.CaptureScreenshotAsync(this, options); } public Task CloseAsync(CloseOptions? options = null) { - return BiDi.BrowsingContextModule.CloseAsync(this, options); + return BiDi.BrowsingContext.CloseAsync(this, options); } public Task TraverseHistoryAsync(int delta, TraverseHistoryOptions? options = null) { - return BiDi.BrowsingContextModule.TraverseHistoryAsync(this, delta, options); + return BiDi.BrowsingContext.TraverseHistoryAsync(this, delta, options); } public Task NavigateBackAsync(TraverseHistoryOptions? options = null) @@ -85,17 +87,17 @@ public Task NavigateForwardAsync(TraverseHistoryOptions? options = null) public Task SetViewportAsync(SetViewportOptions? options = null) { - return BiDi.BrowsingContextModule.SetViewportAsync(this, options); + return BiDi.BrowsingContext.SetViewportAsync(this, options); } public Task PrintAsync(PrintOptions? options = null) { - return BiDi.BrowsingContextModule.PrintAsync(this, options); + return BiDi.BrowsingContext.PrintAsync(this, options); } public Task HandleUserPromptAsync(HandleUserPromptOptions? options = null) { - return BiDi.BrowsingContextModule.HandleUserPromptAsync(this, options); + return BiDi.BrowsingContext.HandleUserPromptAsync(this, options); } public Task> GetTreeAsync(BrowsingContextGetTreeOptions? options = null) @@ -105,77 +107,77 @@ public Task> GetTreeAsync(BrowsingContextGetT Root = this }; - return BiDi.BrowsingContextModule.GetTreeAsync(getTreeOptions); + return BiDi.BrowsingContext.GetTreeAsync(getTreeOptions); } public Task OnNavigationStartedAsync(Func handler, SubscriptionOptions? options = null) { - return BiDi.BrowsingContextModule.OnNavigationStartedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); + return BiDi.BrowsingContext.OnNavigationStartedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); } public Task OnNavigationStartedAsync(Action handler, SubscriptionOptions? options = null) { - return BiDi.BrowsingContextModule.OnNavigationStartedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); + return BiDi.BrowsingContext.OnNavigationStartedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); } public Task OnFragmentNavigatedAsync(Func handler, SubscriptionOptions? options = null) { - return BiDi.BrowsingContextModule.OnFragmentNavigatedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); + return BiDi.BrowsingContext.OnFragmentNavigatedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); } public Task OnFragmentNavigatedAsync(Action handler, SubscriptionOptions? options = null) { - return BiDi.BrowsingContextModule.OnFragmentNavigatedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); + return BiDi.BrowsingContext.OnFragmentNavigatedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); } public Task OnDomContentLoadedAsync(Func handler, SubscriptionOptions? options = null) { - return BiDi.BrowsingContextModule.OnDomContentLoadedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); + return BiDi.BrowsingContext.OnDomContentLoadedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); } public Task OnLoadAsync(Action handler, SubscriptionOptions? options = null) { - return BiDi.BrowsingContextModule.OnLoadAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); + return BiDi.BrowsingContext.OnLoadAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); } public Task OnLoadAsync(Func handler, SubscriptionOptions? options = null) { - return BiDi.BrowsingContextModule.OnLoadAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); + return BiDi.BrowsingContext.OnLoadAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); } public Task OnDownloadWillBeginAsync(Action handler, SubscriptionOptions? options = null) { - return BiDi.BrowsingContextModule.OnDownloadWillBeginAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); + return BiDi.BrowsingContext.OnDownloadWillBeginAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); } public Task OnDownloadWillBeginAsync(Func handler, SubscriptionOptions? options = null) { - return BiDi.BrowsingContextModule.OnDownloadWillBeginAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); + return BiDi.BrowsingContext.OnDownloadWillBeginAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); } public Task OnNavigationAbortedAsync(Action handler, SubscriptionOptions? options = null) { - return BiDi.BrowsingContextModule.OnNavigationAbortedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); + return BiDi.BrowsingContext.OnNavigationAbortedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); } public Task OnNavigationAbortedAsync(Func handler, SubscriptionOptions? options = null) { - return BiDi.BrowsingContextModule.OnNavigationAbortedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); + return BiDi.BrowsingContext.OnNavigationAbortedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); } public Task OnNavigationFailedAsync(Action handler, SubscriptionOptions? options = null) { - return BiDi.BrowsingContextModule.OnNavigationFailedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); + return BiDi.BrowsingContext.OnNavigationFailedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); } public Task OnNavigationFailedAsync(Func handler, SubscriptionOptions? options = null) { - return BiDi.BrowsingContextModule.OnNavigationFailedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); + return BiDi.BrowsingContext.OnNavigationFailedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); } public Task OnDomContentLoadedAsync(Action handler, SubscriptionOptions? options = null) { - return BiDi.BrowsingContextModule.OnDomContentLoadedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); + return BiDi.BrowsingContext.OnDomContentLoadedAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [this] }); } public override bool Equals(object? obj) diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextInfo.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextInfo.cs index 52f2edeb972e0..f2303915feb90 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextInfo.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextInfo.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; // TODO: Split it to separate class with just info and event args diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextInputModule.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextInputModule.cs index ceae616cb2378..919758b14ba79 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextInputModule.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextInputModule.cs @@ -2,16 +2,19 @@ using OpenQA.Selenium.BiDi.Modules.Input; using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; public class BrowsingContextInputModule(BrowsingContext context, InputModule inputModule) { public Task PerformActionsAsync(IEnumerable actions, PerformActionsOptions? options = null) { - options ??= new(); - - options.Actions = actions; + return inputModule.PerformActionsAsync(context, actions, options); + } - return inputModule.PerformActionsAsync(context, options); + public Task ReleaseActionsAsync(ReleaseActionsOptions? options = null) + { + return inputModule.ReleaseActionsAsync(context, options); } } diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextLogModule.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextLogModule.cs index 03187efd7265c..a085bb07de630 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextLogModule.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextLogModule.cs @@ -2,11 +2,13 @@ using System.Threading.Tasks; using System; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; public class BrowsingContextLogModule(BrowsingContext context, LogModule logModule) { - public Task OnEntryAddedAsync(Func handler, SubscriptionOptions options = null) + public Task OnEntryAddedAsync(Func handler, SubscriptionOptions? options = null) { return logModule.OnEntryAddedAsync(async args => { @@ -17,7 +19,7 @@ public Task OnEntryAddedAsync(Func handler, Su }, options); } - public Task OnEntryAddedAsync(Action handler, SubscriptionOptions options = null) + public Task OnEntryAddedAsync(Action handler, SubscriptionOptions? options = null) { return logModule.OnEntryAddedAsync(args => { diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextModule.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextModule.cs index fe7a1d3f36343..690df63f7ab2d 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextModule.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextModule.cs @@ -3,6 +3,8 @@ using System.Threading.Tasks; using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; public class BrowsingContextModule(Broker broker) : Module(broker) @@ -42,7 +44,7 @@ public async Task ActivateAsync(BrowsingContext context, ActivateOptions? option await Broker.ExecuteCommandAsync(new ActivateCommand(@params), options).ConfigureAwait(false); } - public async Task> LocateNodesAsync(BrowsingContext context, Locator locator, LocateNodesOptions? options = null) + public async Task LocateNodesAsync(BrowsingContext context, Locator locator, LocateNodesOptions? options = null) { var @params = new LocateNodesCommandParameters(context, locator); @@ -53,9 +55,7 @@ public async Task ActivateAsync(BrowsingContext context, ActivateOptions? option @params.StartNodes = options.StartNodes; } - var result = await Broker.ExecuteCommandAsync(new LocateNodesCommand(@params), options).ConfigureAwait(false); - - return result.Nodes; + return await Broker.ExecuteCommandAsync(new LocateNodesCommand(@params), options).ConfigureAwait(false); } public async Task CaptureScreenshotAsync(BrowsingContext context, CaptureScreenshotOptions? options = null) diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextNetworkModule.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextNetworkModule.cs index 4b4d805eb3041..e25f255f423c7 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextNetworkModule.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextNetworkModule.cs @@ -2,6 +2,8 @@ using System; using OpenQA.Selenium.BiDi.Modules.Network; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; public class BrowsingContextNetworkModule(BrowsingContext context, NetworkModule networkModule) @@ -34,7 +36,7 @@ public async Task InterceptResponseAsync(Func InterceptAuthenticationAsync(Func handler, BrowsingContextAddInterceptOptions? interceptOptions = null, SubscriptionOptions? options = null) + public async Task InterceptAuthAsync(Func handler, BrowsingContextAddInterceptOptions? interceptOptions = null, SubscriptionOptions? options = null) { AddInterceptOptions addInterceptOptions = new(interceptOptions) { @@ -88,7 +90,12 @@ public Task OnFetchErrorAsync(Action handler, return networkModule.OnFetchErrorAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [context] }); } - internal Task OnAuthRequiredAsync(Func handler, SubscriptionOptions? options = null) + public Task OnAuthRequiredAsync(Func handler, SubscriptionOptions? options = null) + { + return networkModule.OnAuthRequiredAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [context] }); + } + + public Task OnAuthRequiredAsync(Action handler, SubscriptionOptions? options = null) { return networkModule.OnAuthRequiredAsync(handler, new BrowsingContextsSubscriptionOptions(options) { Contexts = [context] }); } diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextScriptModule.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextScriptModule.cs index d2756ecc503cc..f6f8b77e43c55 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextScriptModule.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextScriptModule.cs @@ -2,6 +2,8 @@ using OpenQA.Selenium.BiDi.Modules.Script; using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; public class BrowsingContextScriptModule(BrowsingContext context, ScriptModule scriptModule) @@ -25,9 +27,9 @@ public async Task> GetRealmsAsync(GetRealmsOptions? opt return await scriptModule.GetRealmsAsync(options).ConfigureAwait(false); } - public Task EvaluateAsync(string expression, bool awaitPromise, EvaluateOptions? options = null, ContextTargetOptions? targetOptions = null) + public Task EvaluateAsync(string expression, bool awaitPromise, EvaluateOptions? options = null, ContextTargetOptions? targetOptions = null) { - var contextTarget = new ContextTarget(context); + var contextTarget = new Target.Context(context); if (targetOptions is not null) { @@ -37,16 +39,16 @@ public Task EvaluateAsync(string expression, bool awaitPromise, Eva return scriptModule.EvaluateAsync(expression, awaitPromise, contextTarget, options); } - public async Task EvaluateAsync(string expression, bool awaitPromise, EvaluateOptions? options = null) + public async Task EvaluateAsync(string expression, bool awaitPromise, EvaluateOptions? options = null, ContextTargetOptions? targetOptions = null) { - var remoteValue = await EvaluateAsync(expression, awaitPromise, options).ConfigureAwait(false); + var result = await EvaluateAsync(expression, awaitPromise, options, targetOptions).ConfigureAwait(false); - return remoteValue.ConvertTo(); + return result.Result.ConvertTo(); } - public Task CallFunctionAsync(string functionDeclaration, bool awaitPromise, CallFunctionOptions? options = null, ContextTargetOptions? targetOptions = null) + public Task CallFunctionAsync(string functionDeclaration, bool awaitPromise, CallFunctionOptions? options = null, ContextTargetOptions? targetOptions = null) { - var contextTarget = new ContextTarget(context); + var contextTarget = new Target.Context(context); if (targetOptions is not null) { @@ -55,4 +57,11 @@ public Task CallFunctionAsync(string functionDeclaration, bool awai return scriptModule.CallFunctionAsync(functionDeclaration, awaitPromise, contextTarget, options); } + + public async Task CallFunctionAsync(string functionDeclaration, bool awaitPromise, CallFunctionOptions? options = null, ContextTargetOptions? targetOptions = null) + { + var result = await CallFunctionAsync(functionDeclaration, awaitPromise, options, targetOptions).ConfigureAwait(false); + + return result.Result.ConvertTo(); + } } diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextStorageModule.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextStorageModule.cs index 810f1ab0b32db..d89343d1ab0f9 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextStorageModule.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/BrowsingContextStorageModule.cs @@ -1,6 +1,8 @@ using System.Threading.Tasks; using OpenQA.Selenium.BiDi.Modules.Storage; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; public class BrowsingContextStorageModule(BrowsingContext context, StorageModule storageModule) @@ -9,7 +11,7 @@ public Task GetCookiesAsync(GetCookiesOptions? options = null) { options ??= new(); - options.Partition = new BrowsingContextPartitionDescriptor(context); + options.Partition = new PartitionDescriptor.Context(context); return storageModule.GetCookiesAsync(options); } @@ -18,7 +20,7 @@ public async Task DeleteCookiesAsync(DeleteCookiesOptions? options { options ??= new(); - options.Partition = new BrowsingContextPartitionDescriptor(context); + options.Partition = new PartitionDescriptor.Context(context); var res = await storageModule.DeleteCookiesAsync(options).ConfigureAwait(false); @@ -29,7 +31,7 @@ public async Task SetCookieAsync(PartialCookie cookie, SetCookieOp { options ??= new(); - options.Partition = new BrowsingContextPartitionDescriptor(context); + options.Partition = new PartitionDescriptor.Context(context); var res = await storageModule.SetCookieAsync(cookie, options).ConfigureAwait(false); diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/CaptureScreenshotCommand.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/CaptureScreenshotCommand.cs index 69ea01b0e70d8..df5f203c1d3fc 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/CaptureScreenshotCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/CaptureScreenshotCommand.cs @@ -1,6 +1,8 @@ using OpenQA.Selenium.BiDi.Communication; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; internal class CaptureScreenshotCommand(CaptureScreenshotCommandParameters @params) : Command(@params); @@ -35,13 +37,14 @@ public record struct ImageFormat(string Type) } [JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] -[JsonDerivedType(typeof(BoxClipRectangle), "box")] -[JsonDerivedType(typeof(ElementClipRectangle), "element")] -public abstract record ClipRectangle; - -public record BoxClipRectangle(double X, double Y, double Width, double Height) : ClipRectangle; +[JsonDerivedType(typeof(Box), "box")] +[JsonDerivedType(typeof(Element), "element")] +public abstract record ClipRectangle +{ + public record Box(double X, double Y, double Width, double Height) : ClipRectangle; -public record ElementClipRectangle(Script.SharedReference Element) : ClipRectangle; + public record Element([property: JsonPropertyName("element")] Script.SharedReference SharedReference) : ClipRectangle; +} public record CaptureScreenshotResult(string Data) { diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/CloseCommand.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/CloseCommand.cs index ac531a28699ac..e3f3279a97955 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/CloseCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/CloseCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; internal class CloseCommand(CloseCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/CreateCommand.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/CreateCommand.cs index 86a81bcada46a..a70f89726c364 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/CreateCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/CreateCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; internal class CreateCommand(CreateCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/GetTreeCommand.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/GetTreeCommand.cs index fe6a38c1fe0bc..eb03c29856266 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/GetTreeCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/GetTreeCommand.cs @@ -1,6 +1,8 @@ using OpenQA.Selenium.BiDi.Communication; using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; internal class GetTreeCommand(GetTreeCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/HandleUserPromptCommand.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/HandleUserPromptCommand.cs index 2dd2888d19a87..a566ef6edf963 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/HandleUserPromptCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/HandleUserPromptCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; class HandleUserPromptCommand(HandleUserPromptCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/LocateNodesCommand.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/LocateNodesCommand.cs index 2dce843e557a3..d32188ae7cce3 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/LocateNodesCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/LocateNodesCommand.cs @@ -1,6 +1,9 @@ using OpenQA.Selenium.BiDi.Communication; +using System.Collections; using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; internal class LocateNodesCommand(LocateNodesCommandParameters @params) : Command(@params); @@ -23,4 +26,20 @@ public record LocateNodesOptions : CommandOptions public IEnumerable? StartNodes { get; set; } } -public record LocateNodesResult(IReadOnlyList Nodes); +public record LocateNodesResult : IReadOnlyList +{ + private readonly IReadOnlyList _nodes; + + internal LocateNodesResult(IReadOnlyList nodes) + { + _nodes = nodes; + } + + public Script.RemoteValue.Node this[int index] => _nodes[index]; + + public int Count => _nodes.Count; + + public IEnumerator GetEnumerator() => _nodes.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => (_nodes as IEnumerable).GetEnumerator(); +} diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/Locator.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/Locator.cs index d931019afd446..d22215f5f6d92 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/Locator.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/Locator.cs @@ -1,43 +1,37 @@ using System.Text.Json.Serialization; -using static OpenQA.Selenium.BiDi.Modules.BrowsingContext.AccessibilityLocator; + +#nullable enable namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; [JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] -[JsonDerivedType(typeof(AccessibilityLocator), "accessibility")] -[JsonDerivedType(typeof(CssLocator), "css")] -[JsonDerivedType(typeof(InnerTextLocator), "innerText")] -[JsonDerivedType(typeof(XPathLocator), "xpath")] +[JsonDerivedType(typeof(Accessibility), "accessibility")] +[JsonDerivedType(typeof(Css), "css")] +[JsonDerivedType(typeof(InnerText), "innerText")] +[JsonDerivedType(typeof(XPath), "xpath")] public abstract record Locator { - public static CssLocator Css(string value) - => new(value); - - public static InnerTextLocator InnerText(string value, bool? ignoreCase = null, MatchType? matchType = null, long? maxDepth = null) - => new(value) { IgnoreCase = ignoreCase, MatchType = matchType, MaxDepth = maxDepth }; - - public static XPathLocator XPath(string value) - => new(value); -} - -public record AccessibilityLocator(AccessibilityValue Value) : Locator -{ - public record AccessibilityValue + public record Accessibility(Accessibility.AccessibilityValue Value) : Locator { - public string? Name { get; set; } - public string? Role { get; set; } + public record AccessibilityValue + { + public string? Name { get; set; } + public string? Role { get; set; } + } } -} -public record CssLocator(string Value) : Locator; + public record Css(string Value) : Locator; -public record InnerTextLocator(string Value) : Locator -{ - public bool? IgnoreCase { get; set; } + public record InnerText(string Value) : Locator + { + public bool? IgnoreCase { get; set; } - public MatchType? MatchType { get; set; } + public MatchType? MatchType { get; set; } - public long? MaxDepth { get; set; } + public long? MaxDepth { get; set; } + } + + public record XPath(string Value) : Locator; } public enum MatchType @@ -45,5 +39,3 @@ public enum MatchType Full, Partial } - -public record XPathLocator(string Value) : Locator; diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/NavigateCommand.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/NavigateCommand.cs index 401c0ec2093d4..7481a6141e430 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/NavigateCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/NavigateCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; internal class NavigateCommand(NavigateCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/Navigation.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/Navigation.cs index 0b56229ade1de..3ce169d0f40c6 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/Navigation.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/Navigation.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; public record Navigation(string Id); diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/NavigationInfo.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/NavigationInfo.cs index fe7a83399bf11..e934e3030d305 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/NavigationInfo.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/NavigationInfo.cs @@ -1,5 +1,7 @@ using System; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; public record NavigationInfo(BiDi BiDi, BrowsingContext Context, Navigation Navigation, DateTimeOffset Timestamp, string Url) diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/PrintCommand.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/PrintCommand.cs index 66c270c12dd97..70fa6bcdd1f2a 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/PrintCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/PrintCommand.cs @@ -2,6 +2,8 @@ using System; using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; internal class PrintCommand(PrintCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/ReloadCommand.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/ReloadCommand.cs index fea265ce15200..1dd805fd0a00b 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/ReloadCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/ReloadCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; internal class ReloadCommand(ReloadCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/SetViewportCommand.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/SetViewportCommand.cs index 0ed6e869e85a7..a43cb30157e15 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/SetViewportCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/SetViewportCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; internal class SetViewportCommand(SetViewportCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/TraverseHistoryCommand.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/TraverseHistoryCommand.cs index 65797e0164cd0..b8c78b2601adb 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/TraverseHistoryCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/TraverseHistoryCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; internal class TraverseHistoryCommand(TraverseHistoryCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/UserPromptClosedEventArgs.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/UserPromptClosedEventArgs.cs index fa59f7262fcc2..c7123e89f76be 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/UserPromptClosedEventArgs.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/UserPromptClosedEventArgs.cs @@ -1,5 +1,7 @@ using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; public record UserPromptClosedEventArgs(BiDi BiDi, BrowsingContext Context, bool Accepted) diff --git a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/UserPromptOpenedEventArgs.cs b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/UserPromptOpenedEventArgs.cs index 8e6658bd79523..03dd37be8cbeb 100644 --- a/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/UserPromptOpenedEventArgs.cs +++ b/dotnet/src/webdriver/BiDi/Modules/BrowsingContext/UserPromptOpenedEventArgs.cs @@ -1,5 +1,7 @@ using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext; public record UserPromptOpenedEventArgs(BiDi BiDi, BrowsingContext Context, UserPromptType Type, string Message) diff --git a/dotnet/src/webdriver/BiDi/Modules/Input/InputModule.cs b/dotnet/src/webdriver/BiDi/Modules/Input/InputModule.cs index a31b0371dfb4a..53f913132c758 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Input/InputModule.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Input/InputModule.cs @@ -1,18 +1,16 @@ using OpenQA.Selenium.BiDi.Communication; +using System.Collections.Generic; using System.Threading.Tasks; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Input; public sealed class InputModule(Broker broker) : Module(broker) { - public async Task PerformActionsAsync(BrowsingContext.BrowsingContext context, PerformActionsOptions? options = null) + public async Task PerformActionsAsync(BrowsingContext.BrowsingContext context, IEnumerable actions, PerformActionsOptions? options = null) { - var @params = new PerformActionsCommandParameters(context); - - if (options is not null) - { - @params.Actions = options.Actions; - } + var @params = new PerformActionsCommandParameters(context, actions); await Broker.ExecuteCommandAsync(new PerformActionsCommand(@params), options).ConfigureAwait(false); } @@ -21,6 +19,6 @@ public async Task ReleaseActionsAsync(BrowsingContext.BrowsingContext context, R { var @params = new ReleaseActionsCommandParameters(context); - await Broker.ExecuteCommandAsync(new ReleaseActionsCommand(@params), options); + await Broker.ExecuteCommandAsync(new ReleaseActionsCommand(@params), options).ConfigureAwait(false); } } diff --git a/dotnet/src/webdriver/BiDi/Modules/Input/Key.cs b/dotnet/src/webdriver/BiDi/Modules/Input/Key.cs new file mode 100644 index 0000000000000..a7d99ffca3ac9 --- /dev/null +++ b/dotnet/src/webdriver/BiDi/Modules/Input/Key.cs @@ -0,0 +1,8 @@ +//namespace OpenQA.Selenium.BiDi.Modules.Input; + +//partial record Key +//{ +// public const char Shift = '\uE008'; + +// public const char Pause = '\uE00B'; +//} diff --git a/dotnet/src/webdriver/BiDi/Modules/Input/Origin.cs b/dotnet/src/webdriver/BiDi/Modules/Input/Origin.cs new file mode 100644 index 0000000000000..5cc909cd6aabe --- /dev/null +++ b/dotnet/src/webdriver/BiDi/Modules/Input/Origin.cs @@ -0,0 +1,17 @@ +using System.Text.Json.Serialization; + +#nullable enable + +namespace OpenQA.Selenium.BiDi.Modules.Input; + +public abstract record Origin +{ + public record Viewport() : Origin; + + public record Pointer() : Origin; + + public record Element([property: JsonPropertyName("element")] Script.SharedReference SharedReference) : Origin + { + public string Type { get; } = "element"; + } +} diff --git a/dotnet/src/webdriver/BiDi/Modules/Input/PerformActionsCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Input/PerformActionsCommand.cs index 0a719c7513ce7..878b576417fba 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Input/PerformActionsCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Input/PerformActionsCommand.cs @@ -1,74 +1,12 @@ using OpenQA.Selenium.BiDi.Communication; -using System; using System.Collections.Generic; -using System.Text.Json.Serialization; + +#nullable enable namespace OpenQA.Selenium.BiDi.Modules.Input; internal class PerformActionsCommand(PerformActionsCommandParameters @params) : Command(@params); -internal record PerformActionsCommandParameters(BrowsingContext.BrowsingContext Context) : CommandParameters -{ - public IEnumerable? Actions { get; set; } -} - -public record PerformActionsOptions : CommandOptions -{ - public IEnumerable? Actions { get; set; } = []; -} - -[JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] -[JsonDerivedType(typeof(KeySourceActions), "key")] -public abstract record SourceActions -{ - public static KeySourceActions Press(string text) - { - var keySourceActions = new KeySourceActions(); - - foreach (var character in text) - { - keySourceActions.Actions.AddRange([ - new KeyDownAction(character.ToString()), - new KeyUpAction(character.ToString()) - ]); - } - - return keySourceActions; - } -} - -public record KeySourceActions : SourceActions -{ - public string Id { get; set; } = Guid.NewGuid().ToString(); - - public List Actions { get; set; } = []; - - public new KeySourceActions Press(string text) - { - Actions.AddRange(SourceActions.Press(text).Actions); - - return this; - } - - public KeySourceActions Pause(long? duration = null) - { - Actions.Add(new KeyPauseAction { Duration = duration }); - - return this; - } -} - -[JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] -[JsonDerivedType(typeof(KeyPauseAction), "pause")] -[JsonDerivedType(typeof(KeyDownAction), "keyDown")] -[JsonDerivedType(typeof(KeyUpAction), "keyUp")] -public abstract record KeySourceAction; - -public record KeyPauseAction : KeySourceAction -{ - public long? Duration { get; set; } -} - -public record KeyDownAction(string Value) : KeySourceAction; +internal record PerformActionsCommandParameters(BrowsingContext.BrowsingContext Context, IEnumerable Actions) : CommandParameters; -public record KeyUpAction(string Value) : KeySourceAction; +public record PerformActionsOptions : CommandOptions; diff --git a/dotnet/src/webdriver/BiDi/Modules/Input/ReleaseActionsCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Input/ReleaseActionsCommand.cs index 0ee6d6345d21b..2331e1bec6c49 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Input/ReleaseActionsCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Input/ReleaseActionsCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Input; internal class ReleaseActionsCommand(ReleaseActionsCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/Input/SequentialSourceActions.cs b/dotnet/src/webdriver/BiDi/Modules/Input/SequentialSourceActions.cs new file mode 100644 index 0000000000000..dfdbc3f69a331 --- /dev/null +++ b/dotnet/src/webdriver/BiDi/Modules/Input/SequentialSourceActions.cs @@ -0,0 +1,161 @@ +//using System.Collections; +//using System.Collections.Generic; +//using System.Linq; + +//namespace OpenQA.Selenium.BiDi.Modules.Input; + +//public interface ISequentialSourceActions : IEnumerable +//{ +// ISequentialSourceActions Pause(int duration); + +// ISequentialSourceActions Type(string text); +// ISequentialSourceActions KeyDown(char key); +// ISequentialSourceActions KeyUp(char key); + +// ISequentialSourceActions PointerDown(int button, PointerDownOptions? options = null); +// ISequentialSourceActions PointerUp(int button); +// ISequentialSourceActions PointerMove(int x, int y, PointerMoveOptions? options = null); +//} + +//public record SequentialSourceActions : ISequentialSourceActions +//{ +// private readonly KeyActions _keyActions = []; +// private readonly PointerActions _pointerActions = []; +// private readonly WheelActions _wheelActions = []; +// private readonly WheelActions _noneActions = []; + +// public ISequentialSourceActions Pause(int duration) +// { +// _noneActions.Add(new Pause { Duration = duration }); + +// return Normalized(); +// } + +// public ISequentialSourceActions Type(string text) +// { +// _keyActions.Type(text); + +// return Normalized(); +// } + +// public ISequentialSourceActions KeyDown(char key) +// { +// _keyActions.Add(new Key.Down(key)); + +// return Normalized(); +// } + +// public ISequentialSourceActions KeyUp(char key) +// { +// _keyActions.Add(new Key.Up(key)); + +// return Normalized(); +// } + +// public ISequentialSourceActions PointerDown(int button, PointerDownOptions? options = null) +// { +// _pointerActions.Add(new Pointer.Down(button) +// { +// Width = options?.Width, +// Height = options?.Height, +// Pressure = options?.Pressure, +// TangentialPressure = options?.TangentialPressure, +// Twist = options?.Twist, +// AltitudeAngle = options?.AltitudeAngle, +// AzimuthAngle = options?.AzimuthAngle +// }); + +// return Normalized(); +// } + +// public ISequentialSourceActions PointerUp(int button) +// { +// _pointerActions.Add(new Pointer.Up(button)); + +// return Normalized(); +// } + +// public ISequentialSourceActions PointerMove(int x, int y, PointerMoveOptions? options = null) +// { +// _pointerActions.Add(new Pointer.Move(x, y) +// { +// Duration = options?.Duration, +// Origin = options?.Origin, +// Width = options?.Width, +// Height = options?.Height, +// Pressure = options?.Pressure, +// TangentialPressure = options?.TangentialPressure, +// Twist = options?.Twist, +// AltitudeAngle = options?.AltitudeAngle, +// AzimuthAngle = options?.AzimuthAngle +// }); + +// return Normalized(); +// } + +// private SequentialSourceActions Normalized() +// { +// var max = new[] { _keyActions.Count(), _pointerActions.Count(), _wheelActions.Count(), _noneActions.Count() }.Max(); + +// for (int i = _keyActions.Count(); i < max; i++) +// { +// _keyActions.Add(new Pause()); +// } + +// for (int i = _pointerActions.Count(); i < max; i++) +// { +// _pointerActions.Add(new Pause()); +// } + +// for (int i = _wheelActions.Count(); i < max; i++) +// { +// _wheelActions.Add(new Pause()); +// } + +// for (int i = _noneActions.Count(); i < max; i++) +// { +// _noneActions.Add(new Pause()); +// } + +// return this; +// } + +// public IEnumerator GetEnumerator() +// { +// var sourceActions = new List +// { +// _keyActions, +// _pointerActions, +// _wheelActions, +// _noneActions +// }; +// return sourceActions.GetEnumerator(); +// } + +// IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +//} + +//public record PointerDownOptions : IPointerCommonProperties +//{ +// public int? Width { get; set; } +// public int? Height { get; set; } +// public double? Pressure { get; set; } +// public double? TangentialPressure { get; set; } +// public int? Twist { get; set; } +// public double? AltitudeAngle { get; set; } +// public double? AzimuthAngle { get; set; } +//} + +//public record PointerMoveOptions : IPointerCommonProperties +//{ +// public int? Duration { get; set; } +// public Origin? Origin { get; set; } + +// public int? Width { get; set; } +// public int? Height { get; set; } +// public double? Pressure { get; set; } +// public double? TangentialPressure { get; set; } +// public int? Twist { get; set; } +// public double? AltitudeAngle { get; set; } +// public double? AzimuthAngle { get; set; } +//} diff --git a/dotnet/src/webdriver/BiDi/Modules/Input/SourceActions.cs b/dotnet/src/webdriver/BiDi/Modules/Input/SourceActions.cs new file mode 100644 index 0000000000000..a9b7ed3f7001f --- /dev/null +++ b/dotnet/src/webdriver/BiDi/Modules/Input/SourceActions.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +#nullable enable + +namespace OpenQA.Selenium.BiDi.Modules.Input; + +public abstract record SourceActions +{ + public string Id { get; } = Guid.NewGuid().ToString(); +} + +public interface ISourceAction; + +public record SourceActions : SourceActions, IEnumerable where T : ISourceAction +{ + public IList Actions { get; set; } = []; + + public IEnumerator GetEnumerator() => Actions.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => Actions.GetEnumerator(); + + public void Add(ISourceAction action) => Actions.Add(action); +} + +[JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] +[JsonDerivedType(typeof(Pause), "pause")] +[JsonDerivedType(typeof(Key.Down), "keyDown")] +[JsonDerivedType(typeof(Key.Up), "keyUp")] +public interface IKeySourceAction : ISourceAction; + +public record KeyActions : SourceActions +{ + public KeyActions Type(string text) + { + foreach (var character in text) + { + Add(new Key.Down(character)); + Add(new Key.Up(character)); + } + + return this; + } +} + +[JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] +[JsonDerivedType(typeof(Pause), "pause")] +[JsonDerivedType(typeof(Pointer.Down), "pointerDown")] +[JsonDerivedType(typeof(Pointer.Up), "pointerUp")] +[JsonDerivedType(typeof(Pointer.Move), "pointerMove")] +public interface IPointerSourceAction : ISourceAction; + +public record PointerActions : SourceActions +{ + public PointerParameters? Options { get; set; } +} + +[JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] +[JsonDerivedType(typeof(Pause), "pause")] +[JsonDerivedType(typeof(Wheel.Scroll), "scroll")] +public interface IWheelSourceAction : ISourceAction; + +public record WheelActions : SourceActions; + +[JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] +[JsonDerivedType(typeof(Pause), "pause")] +public interface INoneSourceAction : ISourceAction; + +public record NoneActions : SourceActions; + +public abstract partial record Key : IKeySourceAction +{ + public record Down(char Value) : Key; + + public record Up(char Value) : Key; +} + +public abstract record Pointer : IPointerSourceAction +{ + public record Down(int Button) : Pointer, IPointerCommonProperties + { + public int? Width { get; set; } + public int? Height { get; set; } + public double? Pressure { get; set; } + public double? TangentialPressure { get; set; } + public int? Twist { get; set; } + public double? AltitudeAngle { get; set; } + public double? AzimuthAngle { get; set; } + } + + public record Up(int Button) : Pointer; + + public record Move(int X, int Y) : Pointer, IPointerCommonProperties + { + public int? Duration { get; set; } + + public Origin? Origin { get; set; } + + public int? Width { get; set; } + public int? Height { get; set; } + public double? Pressure { get; set; } + public double? TangentialPressure { get; set; } + public int? Twist { get; set; } + public double? AltitudeAngle { get; set; } + public double? AzimuthAngle { get; set; } + } +} + +public abstract record Wheel : IWheelSourceAction +{ + public record Scroll(int X, int Y, int DeltaX, int DeltaY) : Wheel + { + public int? Duration { get; set; } + + public Origin? Origin { get; set; } + } +} + +public abstract record None : INoneSourceAction; + +public record Pause : ISourceAction, IKeySourceAction, IPointerSourceAction, IWheelSourceAction, INoneSourceAction +{ + public long? Duration { get; set; } +} + +public record PointerParameters +{ + public PointerType? PointerType { get; set; } +} + +public enum PointerType +{ + Mouse, + Pen, + Touch +} + +public interface IPointerCommonProperties +{ + public int? Width { get; set; } + + public int? Height { get; set; } + + public double? Pressure { get; set; } + + public double? TangentialPressure { get; set; } + + public int? Twist { get; set; } + + public double? AltitudeAngle { get; set; } + + public double? AzimuthAngle { get; set; } +} diff --git a/dotnet/src/webdriver/BiDi/Modules/Log/Entry.cs b/dotnet/src/webdriver/BiDi/Modules/Log/Entry.cs new file mode 100644 index 0000000000000..dba3714e27403 --- /dev/null +++ b/dotnet/src/webdriver/BiDi/Modules/Log/Entry.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; + +#nullable enable + +namespace OpenQA.Selenium.BiDi.Modules.Log; + +// https://github.com/dotnet/runtime/issues/72604 +//[JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] +//[JsonDerivedType(typeof(Console), "console")] +//[JsonDerivedType(typeof(Javascript), "javascript")] +public abstract record Entry(BiDi BiDi, Level Level, Script.Source Source, string Text, DateTimeOffset Timestamp) + : EventArgs(BiDi) +{ + public Script.StackTrace? StackTrace { get; set; } + + public record Console(BiDi BiDi, Level Level, Script.Source Source, string Text, DateTimeOffset Timestamp, string Method, IReadOnlyList Args) + : Entry(BiDi, Level, Source, Text, Timestamp); + + public record Javascript(BiDi BiDi, Level Level, Script.Source Source, string Text, DateTimeOffset Timestamp) + : Entry(BiDi, Level, Source, Text, Timestamp); +} + +public enum Level +{ + Debug, + Info, + Warn, + Error +} diff --git a/dotnet/src/webdriver/BiDi/Modules/Log/LogEntry.cs b/dotnet/src/webdriver/BiDi/Modules/Log/LogEntry.cs deleted file mode 100644 index f210c126a8859..0000000000000 --- a/dotnet/src/webdriver/BiDi/Modules/Log/LogEntry.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace OpenQA.Selenium.BiDi.Modules.Log; - -// https://github.com/dotnet/runtime/issues/72604 -//[JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] -//[JsonDerivedType(typeof(ConsoleLogEntry), "console")] -//[JsonDerivedType(typeof(JavascriptLogEntry), "javascript")] -public abstract record BaseLogEntry(BiDi BiDi, Level Level, Script.Source Source, string Text, DateTimeOffset Timestamp) - : EventArgs(BiDi); - -public record ConsoleLogEntry(BiDi BiDi, Level Level, Script.Source Source, string Text, DateTimeOffset Timestamp, string Method, IReadOnlyList Args) - : BaseLogEntry(BiDi, Level, Source, Text, Timestamp); - -public record JavascriptLogEntry(BiDi BiDi, Level Level, Script.Source Source, string Text, DateTimeOffset Timestamp) - : BaseLogEntry(BiDi, Level, Source, Text, Timestamp); - -public enum Level -{ - Debug, - Info, - Warn, - Error -} diff --git a/dotnet/src/webdriver/BiDi/Modules/Log/LogModule.cs b/dotnet/src/webdriver/BiDi/Modules/Log/LogModule.cs index 7bf84d530126a..aeb09a08754bd 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Log/LogModule.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Log/LogModule.cs @@ -2,16 +2,18 @@ using System; using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Log; public sealed class LogModule(Broker broker) : Module(broker) { - public async Task OnEntryAddedAsync(Func handler, SubscriptionOptions? options = null) + public async Task OnEntryAddedAsync(Func handler, SubscriptionOptions? options = null) { return await Broker.SubscribeAsync("log.entryAdded", handler, options).ConfigureAwait(false); } - public async Task OnEntryAddedAsync(Action handler, SubscriptionOptions? options = null) + public async Task OnEntryAddedAsync(Action handler, SubscriptionOptions? options = null) { return await Broker.SubscribeAsync("log.entryAdded", handler, options).ConfigureAwait(false); } diff --git a/dotnet/src/webdriver/BiDi/Modules/Module.cs b/dotnet/src/webdriver/BiDi/Modules/Module.cs index a6ac7d1719c43..a7c2491349750 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Module.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Module.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules; public abstract class Module(Broker broker) diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/AddInterceptCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Network/AddInterceptCommand.cs index 4856193d512d9..219f3640ca466 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/AddInterceptCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/AddInterceptCommand.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; internal class AddInterceptCommand(AddInterceptCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/AuthChallenge.cs b/dotnet/src/webdriver/BiDi/Modules/Network/AuthChallenge.cs index b304cbacf3f1e..f85da002f189e 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/AuthChallenge.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/AuthChallenge.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public record AuthChallenge(string Scheme, string Realm); diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/AuthCredentials.cs b/dotnet/src/webdriver/BiDi/Modules/Network/AuthCredentials.cs index 384360e660f44..8f78b5465f969 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/AuthCredentials.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/AuthCredentials.cs @@ -1,12 +1,14 @@ using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; [JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] -[JsonDerivedType(typeof(BasicAuthCredentials), "password")] +[JsonDerivedType(typeof(Basic), "password")] public abstract record AuthCredentials { - public static BasicAuthCredentials Basic(string username, string password) => new(username, password); + public record Basic(string Username, string Password) : AuthCredentials; } -public record BasicAuthCredentials(string Username, string Password) : AuthCredentials; + diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/AuthRequiredEventArgs.cs b/dotnet/src/webdriver/BiDi/Modules/Network/AuthRequiredEventArgs.cs index 6e3e8626e8b5f..dca341b07b4da 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/AuthRequiredEventArgs.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/AuthRequiredEventArgs.cs @@ -1,5 +1,7 @@ using System; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public record AuthRequiredEventArgs(BiDi BiDi, BrowsingContext.BrowsingContext Context, bool IsBlocked, BrowsingContext.Navigation Navigation, long RedirectCount, RequestData Request, DateTimeOffset Timestamp, ResponseData Response) : diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/BaseParametersEventArgs.cs b/dotnet/src/webdriver/BiDi/Modules/Network/BaseParametersEventArgs.cs index d632e433e137d..e8e721d033ca5 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/BaseParametersEventArgs.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/BaseParametersEventArgs.cs @@ -2,6 +2,8 @@ using System.Text.Json.Serialization; using System; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public abstract record BaseParametersEventArgs(BiDi BiDi, BrowsingContext.BrowsingContext Context, bool IsBlocked, BrowsingContext.Navigation Navigation, long RedirectCount, RequestData Request, DateTimeOffset Timestamp) diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/BeforeRequestSentEventArgs.cs b/dotnet/src/webdriver/BiDi/Modules/Network/BeforeRequestSentEventArgs.cs index 0ca4994bd7bae..53f4b85aa3669 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/BeforeRequestSentEventArgs.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/BeforeRequestSentEventArgs.cs @@ -1,6 +1,8 @@ using OpenQA.Selenium.BiDi.Modules.BrowsingContext; using System; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public record BeforeRequestSentEventArgs(BiDi BiDi, BrowsingContext.BrowsingContext Context, bool IsBlocked, Navigation Navigation, long RedirectCount, RequestData Request, DateTimeOffset Timestamp, Initiator Initiator) diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/BytesValue.cs b/dotnet/src/webdriver/BiDi/Modules/Network/BytesValue.cs index 02b982422d4c7..6c5d88a930d66 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/BytesValue.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/BytesValue.cs @@ -1,15 +1,17 @@ using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; [JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] -[JsonDerivedType(typeof(StringValue), "string")] -[JsonDerivedType(typeof(Base64Value), "base64")] +[JsonDerivedType(typeof(String), "string")] +[JsonDerivedType(typeof(Base64), "base64")] public abstract record BytesValue { - public static implicit operator BytesValue(string value) => new StringValue(value); -} + public static implicit operator BytesValue(string value) => new String(value); -public record StringValue(string Value) : BytesValue; + public record String(string Value) : BytesValue; -public record Base64Value(string Value) : BytesValue; + public record Base64(string Value) : BytesValue; +} diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/ContinueRequestCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Network/ContinueRequestCommand.cs index bdf572ece2c08..447dfa41baa70 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/ContinueRequestCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/ContinueRequestCommand.cs @@ -1,6 +1,8 @@ using OpenQA.Selenium.BiDi.Communication; using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; internal class ContinueRequestCommand(ContinueRequestCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/ContinueResponseCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Network/ContinueResponseCommand.cs index 6762035e94e38..ba2e4e60a1bed 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/ContinueResponseCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/ContinueResponseCommand.cs @@ -1,6 +1,8 @@ using OpenQA.Selenium.BiDi.Communication; using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; internal class ContinueResponseCommand(ContinueResponseCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/ContinueWithAuthCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Network/ContinueWithAuthCommand.cs index 4c6553181da92..c486066015ec4 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/ContinueWithAuthCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/ContinueWithAuthCommand.cs @@ -1,21 +1,24 @@ using OpenQA.Selenium.BiDi.Communication; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; internal class ContinueWithAuthCommand(ContinueWithAuthParameters @params) : Command(@params); [JsonPolymorphic(TypeDiscriminatorPropertyName = "action")] -[JsonDerivedType(typeof(ContinueWithAuthCredentials), "provideCredentials")] -[JsonDerivedType(typeof(ContinueWithDefaultAuth), "default")] -[JsonDerivedType(typeof(ContinueWithCancelledAuth), "cancel")] -internal abstract record ContinueWithAuthParameters(Request Request) : CommandParameters; - -internal record ContinueWithAuthCredentials(Request Request, AuthCredentials Credentials) : ContinueWithAuthParameters(Request); +[JsonDerivedType(typeof(Credentials), "provideCredentials")] +[JsonDerivedType(typeof(Default), "default")] +[JsonDerivedType(typeof(Cancel), "cancel")] +internal abstract record ContinueWithAuthParameters(Request Request) : CommandParameters +{ + internal record Credentials(Request Request, [property: JsonPropertyName("credentials")] AuthCredentials AuthCredentials) : ContinueWithAuthParameters(Request); -internal record ContinueWithDefaultAuth(Request Request) : ContinueWithAuthParameters(Request); + internal record Default(Request Request) : ContinueWithAuthParameters(Request); -internal record ContinueWithCancelledAuth(Request Request) : ContinueWithAuthParameters(Request); + internal record Cancel(Request Request) : ContinueWithAuthParameters(Request); +} public record ContinueWithAuthOptions : CommandOptions; diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/Cookie.cs b/dotnet/src/webdriver/BiDi/Modules/Network/Cookie.cs index 0c615762e7044..f3a4bedc8f926 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/Cookie.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/Cookie.cs @@ -1,6 +1,8 @@ using System; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public record Cookie(string Name, BytesValue Value, string Domain, string Path, long Size, bool HttpOnly, bool Secure, SameSite SameSite) diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/CookieHeader.cs b/dotnet/src/webdriver/BiDi/Modules/Network/CookieHeader.cs index dac9bd7b8260a..e588a87d0acb8 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/CookieHeader.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/CookieHeader.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public record CookieHeader(string Name, BytesValue Value); diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/FailRequestCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Network/FailRequestCommand.cs index fe25e4904e34f..f3b01ee692743 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/FailRequestCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/FailRequestCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; internal class FailRequestCommand(FailRequestCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/FetchErrorEventArgs.cs b/dotnet/src/webdriver/BiDi/Modules/Network/FetchErrorEventArgs.cs index ce77fbed5216c..6c911e0009fa7 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/FetchErrorEventArgs.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/FetchErrorEventArgs.cs @@ -1,6 +1,8 @@ using OpenQA.Selenium.BiDi.Modules.BrowsingContext; using System; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public record FetchErrorEventArgs(BiDi BiDi, BrowsingContext.BrowsingContext Context, bool IsBlocked, Navigation Navigation, long RedirectCount, RequestData Request, DateTimeOffset Timestamp, string ErrorText) diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/FetchTimingInfo.cs b/dotnet/src/webdriver/BiDi/Modules/Network/FetchTimingInfo.cs index d1b8caf24e5ca..d5980cc2ca141 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/FetchTimingInfo.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/FetchTimingInfo.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public record FetchTimingInfo(double TimeOrigin, diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/Header.cs b/dotnet/src/webdriver/BiDi/Modules/Network/Header.cs index d32397f88dbd3..0804a1919dec0 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/Header.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/Header.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public record Header(string Name, BytesValue Value); diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/Initiator.cs b/dotnet/src/webdriver/BiDi/Modules/Network/Initiator.cs index 128b69f5097cf..a1449e77928a2 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/Initiator.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/Initiator.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public record Initiator(InitiatorType Type) diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/Intercept.cs b/dotnet/src/webdriver/BiDi/Modules/Network/Intercept.cs index 26d71006cc03f..4fd55a7d14b0f 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/Intercept.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/Intercept.cs @@ -3,39 +3,41 @@ using System.Linq; using System.Threading.Tasks; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public class Intercept : IAsyncDisposable { private readonly BiDi _bidi; - protected readonly IList _onBeforeRequestSentSubscriptions = []; - protected readonly IList _onResponseStartedSubscriptions = []; - protected readonly IList _onAuthRequiredSubscriptions = []; - internal Intercept(BiDi bidi, string id) { _bidi = bidi; Id = id; } - public string Id { get; } + internal string Id { get; } + + protected IList OnBeforeRequestSentSubscriptions { get; } = []; + protected IList OnResponseStartedSubscriptions { get; } = []; + protected IList OnAuthRequiredSubscriptions { get; } = []; public async Task RemoveAsync() { await _bidi.Network.RemoveInterceptAsync(this).ConfigureAwait(false); - foreach (var subscription in _onBeforeRequestSentSubscriptions) + foreach (var subscription in OnBeforeRequestSentSubscriptions) { await subscription.UnsubscribeAsync().ConfigureAwait(false); } - foreach (var subscription in _onResponseStartedSubscriptions) + foreach (var subscription in OnResponseStartedSubscriptions) { await subscription.UnsubscribeAsync().ConfigureAwait(false); } - foreach (var subscription in _onAuthRequiredSubscriptions) + foreach (var subscription in OnAuthRequiredSubscriptions) { await subscription.UnsubscribeAsync().ConfigureAwait(false); } @@ -45,21 +47,21 @@ public async Task OnBeforeRequestSentAsync(Func await Filter(args, handler), options).ConfigureAwait(false); - _onBeforeRequestSentSubscriptions.Add(subscription); + OnBeforeRequestSentSubscriptions.Add(subscription); } public async Task OnResponseStartedAsync(Func handler, SubscriptionOptions? options = null) { var subscription = await _bidi.Network.OnResponseStartedAsync(async args => await Filter(args, handler), options).ConfigureAwait(false); - _onResponseStartedSubscriptions.Add(subscription); + OnResponseStartedSubscriptions.Add(subscription); } public async Task OnAuthRequiredAsync(Func handler, SubscriptionOptions? options = null) { var subscription = await _bidi.Network.OnAuthRequiredAsync(async args => await Filter(args, handler), options).ConfigureAwait(false); - _onAuthRequiredSubscriptions.Add(subscription); + OnAuthRequiredSubscriptions.Add(subscription); } private async Task Filter(BeforeRequestSentEventArgs args, Func handler) diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/NetworkModule.cs b/dotnet/src/webdriver/BiDi/Modules/Network/NetworkModule.cs index 65264dbf51a67..7d4eac19a673f 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/NetworkModule.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/NetworkModule.cs @@ -3,6 +3,8 @@ using System.Threading.Tasks; using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public sealed class NetworkModule(Broker broker) : Module(broker) @@ -47,7 +49,7 @@ public async Task InterceptResponseAsync(Func InterceptAuthenticationAsync(Func handler, AddInterceptOptions? interceptOptions = null, SubscriptionOptions? options = null) + public async Task InterceptAuthAsync(Func handler, AddInterceptOptions? interceptOptions = null, SubscriptionOptions? options = null) { var intercept = await AddInterceptAsync([InterceptPhase.AuthRequired], interceptOptions).ConfigureAwait(false); @@ -113,17 +115,17 @@ internal async Task ProvideResponseAsync(Request request, ProvideResponseOptions internal async Task ContinueWithAuthAsync(Request request, AuthCredentials credentials, ContinueWithAuthOptions? options = null) { - await Broker.ExecuteCommandAsync(new ContinueWithAuthCommand(new ContinueWithAuthCredentials(request, credentials)), options).ConfigureAwait(false); + await Broker.ExecuteCommandAsync(new ContinueWithAuthCommand(new ContinueWithAuthParameters.Credentials(request, credentials)), options).ConfigureAwait(false); } internal async Task ContinueWithAuthAsync(Request request, ContinueWithDefaultAuthOptions? options = null) { - await Broker.ExecuteCommandAsync(new ContinueWithAuthCommand(new ContinueWithDefaultAuth(request)), options).ConfigureAwait(false); + await Broker.ExecuteCommandAsync(new ContinueWithAuthCommand(new ContinueWithAuthParameters.Default(request)), options).ConfigureAwait(false); } internal async Task ContinueWithAuthAsync(Request request, ContinueWithCancelledAuthOptions? options = null) { - await Broker.ExecuteCommandAsync(new ContinueWithAuthCommand(new ContinueWithCancelledAuth(request)), options).ConfigureAwait(false); + await Broker.ExecuteCommandAsync(new ContinueWithAuthCommand(new ContinueWithAuthParameters.Cancel(request)), options).ConfigureAwait(false); } public async Task OnBeforeRequestSentAsync(Func handler, SubscriptionOptions? options = null) @@ -166,7 +168,12 @@ public async Task OnFetchErrorAsync(Action ha return await Broker.SubscribeAsync("network.fetchError", handler, options).ConfigureAwait(false); } - internal async Task OnAuthRequiredAsync(Func handler, SubscriptionOptions? options = null) + public async Task OnAuthRequiredAsync(Func handler, SubscriptionOptions? options = null) + { + return await Broker.SubscribeAsync("network.authRequired", handler, options).ConfigureAwait(false); + } + + public async Task OnAuthRequiredAsync(Action handler, SubscriptionOptions? options = null) { return await Broker.SubscribeAsync("network.authRequired", handler, options).ConfigureAwait(false); } diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/ProvideResponseCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Network/ProvideResponseCommand.cs index 317ac4474b4fa..6dae6fc24556f 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/ProvideResponseCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/ProvideResponseCommand.cs @@ -1,6 +1,8 @@ using OpenQA.Selenium.BiDi.Communication; using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; internal class ProvideResponseCommand(ProvideResponseCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/RemoveInterceptCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Network/RemoveInterceptCommand.cs index de64aa1200fb7..c592b74e13a1a 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/RemoveInterceptCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/RemoveInterceptCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; internal class RemoveInterceptCommand(RemoveInterceptCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/Request.cs b/dotnet/src/webdriver/BiDi/Modules/Network/Request.cs index 1b68df0768897..f7b93fbebff19 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/Request.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/Request.cs @@ -1,5 +1,7 @@ using System.Threading.Tasks; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public class Request diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/RequestData.cs b/dotnet/src/webdriver/BiDi/Modules/Network/RequestData.cs index 442db03520234..01cc77f040e79 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/RequestData.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/RequestData.cs @@ -1,5 +1,7 @@ using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public record RequestData(Request Request, string Url, string Method, IReadOnlyList
Headers, IReadOnlyList Cookies, long HeadersSize, long? BodySize, FetchTimingInfo Timings); diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/ResponseCompletedEventArgs.cs b/dotnet/src/webdriver/BiDi/Modules/Network/ResponseCompletedEventArgs.cs index 81fec792efdfd..75c9aa21332bd 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/ResponseCompletedEventArgs.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/ResponseCompletedEventArgs.cs @@ -1,6 +1,8 @@ using OpenQA.Selenium.BiDi.Modules.BrowsingContext; using System; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public record ResponseCompletedEventArgs(BiDi BiDi, BrowsingContext.BrowsingContext Context, bool IsBlocked, Navigation Navigation, long RedirectCount, RequestData Request, DateTimeOffset Timestamp, ResponseData Response) diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/ResponseContent.cs b/dotnet/src/webdriver/BiDi/Modules/Network/ResponseContent.cs index 9647356e7b052..5511c4b24129f 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/ResponseContent.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/ResponseContent.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public record ResponseContent(long Size); diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/ResponseData.cs b/dotnet/src/webdriver/BiDi/Modules/Network/ResponseData.cs index 5ac779301b9ab..3d21c2c202fe8 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/ResponseData.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/ResponseData.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public record ResponseData(string Url, @@ -9,7 +11,7 @@ public record ResponseData(string Url, string StatusText, bool FromCache, IReadOnlyList
Headers, - string MymeType, + string MimeType, long BytesReceived, long? HeadersSize, long? BodySize, diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/ResponseStartedEventArgs.cs b/dotnet/src/webdriver/BiDi/Modules/Network/ResponseStartedEventArgs.cs index 0c80739bf4c72..aa3aff6fd5cf9 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/ResponseStartedEventArgs.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/ResponseStartedEventArgs.cs @@ -1,6 +1,8 @@ using OpenQA.Selenium.BiDi.Modules.BrowsingContext; using System; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public record ResponseStartedEventArgs(BiDi BiDi, BrowsingContext.BrowsingContext Context, bool IsBlocked, Navigation Navigation, long RedirectCount, RequestData Request, DateTimeOffset Timestamp, ResponseData Response) diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/SetCookieHeader.cs b/dotnet/src/webdriver/BiDi/Modules/Network/SetCookieHeader.cs index d11d8ee8a21e5..a73c9171419f0 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/SetCookieHeader.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/SetCookieHeader.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; public record SetCookieHeader(string Name, BytesValue Value) diff --git a/dotnet/src/webdriver/BiDi/Modules/Network/UrlPattern.cs b/dotnet/src/webdriver/BiDi/Modules/Network/UrlPattern.cs index 50226a115f327..30a034fbee4d0 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Network/UrlPattern.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Network/UrlPattern.cs @@ -1,31 +1,31 @@ using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Network; [JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] -[JsonDerivedType(typeof(UrlPatternPattern), "pattern")] -[JsonDerivedType(typeof(UrlPatternString), "string")] +[JsonDerivedType(typeof(Pattern), "pattern")] +[JsonDerivedType(typeof(String), "string")] public abstract record UrlPattern { - public static UrlPatternPattern Patter(string? protocol = null, string? hostname = null, string? port = null, string? pathname = null, string? search = null) - => new() { Protocol = protocol, Hostname = hostname, Port = port, Pathname = pathname, Search = search }; + public static implicit operator UrlPattern(string value) => new String(value); - public static UrlPatternString String(string pattern) => new UrlPatternString(pattern); + public record Pattern : UrlPattern + { + public string? Protocol { get; set; } - public static implicit operator UrlPattern(string value) => new UrlPatternString(value); -} + public string? Hostname { get; set; } -public record UrlPatternPattern : UrlPattern -{ - public string? Protocol { get; set; } + public string? Port { get; set; } - public string? Hostname { get; set; } + public string? Pathname { get; set; } - public string? Port { get; set; } + public string? Search { get; set; } + } - public string? Pathname { get; set; } - - public string? Search { get; set; } + public record String(string Pattern) : UrlPattern + { + public new string Pattern { get; } = Pattern; + } } - -public record UrlPatternString(string Pattern) : UrlPattern; diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/AddPreloadScriptCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Script/AddPreloadScriptCommand.cs index 516e65b10f45c..512d79a86900e 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/AddPreloadScriptCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/AddPreloadScriptCommand.cs @@ -1,13 +1,15 @@ using OpenQA.Selenium.BiDi.Communication; using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; internal class AddPreloadScriptCommand(AddPreloadScriptCommandParameters @params) : Command(@params); internal record AddPreloadScriptCommandParameters(string FunctionDeclaration) : CommandParameters { - public IEnumerable? Arguments { get; set; } + public IEnumerable? Arguments { get; set; } public IEnumerable? Contexts { get; set; } @@ -24,7 +26,7 @@ internal AddPreloadScriptOptions(BrowsingContextAddPreloadScriptOptions? options Sandbox = options?.Sandbox; } - public IEnumerable? Arguments { get; set; } + public IEnumerable? Arguments { get; set; } public IEnumerable? Contexts { get; set; } @@ -33,7 +35,7 @@ internal AddPreloadScriptOptions(BrowsingContextAddPreloadScriptOptions? options public record BrowsingContextAddPreloadScriptOptions { - public IEnumerable? Arguments { get; set; } + public IEnumerable? Arguments { get; set; } public string? Sandbox { get; set; } } diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/CallFunctionCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Script/CallFunctionCommand.cs index 08c9800911044..9ff03a72896f4 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/CallFunctionCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/CallFunctionCommand.cs @@ -1,6 +1,8 @@ using OpenQA.Selenium.BiDi.Communication; using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; internal class CallFunctionCommand(CallFunctionCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/Channel.cs b/dotnet/src/webdriver/BiDi/Modules/Script/Channel.cs index a828d9a4caff3..6518aee1d5388 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/Channel.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/Channel.cs @@ -1,14 +1,5 @@ -namespace OpenQA.Selenium.BiDi.Modules.Script; - -public class Channel -{ - readonly BiDi _bidi; +#nullable enable - internal Channel(BiDi bidi, string id) - { - _bidi = bidi; - Id = id; - } +namespace OpenQA.Selenium.BiDi.Modules.Script; - internal string Id { get; } -} +public record Channel(string Id); diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/ChannelValue.cs b/dotnet/src/webdriver/BiDi/Modules/Script/ChannelValue.cs deleted file mode 100644 index 4b92a7dc15b96..0000000000000 --- a/dotnet/src/webdriver/BiDi/Modules/Script/ChannelValue.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace OpenQA.Selenium.BiDi.Modules.Script; - -public record ChannelValue : LocalValue -{ - public string Type => "channel"; -} - -public record ChannelProperties(Channel Channel) -{ - public SerializationOptions? SerializationOptions { get; set; } - - public ResultOwnership? Ownership { get; set; } -} diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/DisownCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Script/DisownCommand.cs index dfe04fc14e0be..b09ab31da07b3 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/DisownCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/DisownCommand.cs @@ -1,6 +1,8 @@ using OpenQA.Selenium.BiDi.Communication; using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; internal class DisownCommand(DisownCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/EvaluateCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Script/EvaluateCommand.cs index 307a9156e8b4b..8ccba001543af 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/EvaluateCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/EvaluateCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; internal class EvaluateCommand(EvaluateCommandParameters @params) : Command(@params); @@ -24,12 +26,16 @@ public record EvaluateOptions : CommandOptions // https://github.com/dotnet/runtime/issues/72604 //[JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] -//[JsonDerivedType(typeof(EvaluateResultSuccess), "success")] -//[JsonDerivedType(typeof(EvaluateResultException), "exception")] -public abstract record EvaluateResult; - -public record EvaluateResultSuccess(RemoteValue Result) : EvaluateResult; +//[JsonDerivedType(typeof(Success), "success")] +//[JsonDerivedType(typeof(Exception), "exception")] +public abstract record EvaluateResult +{ + public record Success(RemoteValue Result, Realm Realm) : EvaluateResult + { + public static implicit operator RemoteValue(Success success) => success.Result; + } -public record EvaluateResultException(ExceptionDetails ExceptionDetails) : EvaluateResult; + public record Exception(ExceptionDetails ExceptionDetails, Realm Realm) : EvaluateResult; +} public record ExceptionDetails(long ColumnNumber, long LineNumber, StackTrace StackTrace, string Text); diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/GetRealmsCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Script/GetRealmsCommand.cs index 98d4a03ba785f..e5730a9d21a06 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/GetRealmsCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/GetRealmsCommand.cs @@ -1,6 +1,9 @@ using OpenQA.Selenium.BiDi.Communication; +using System.Collections; using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; internal class GetRealmsCommand(GetRealmsCommandParameters @params) : Command(@params); @@ -19,4 +22,20 @@ public record GetRealmsOptions : CommandOptions public RealmType? Type { get; set; } } -internal record GetRealmsResult(IReadOnlyList Realms); +public record GetRealmsResult : IReadOnlyList +{ + private readonly IReadOnlyList _realms; + + internal GetRealmsResult(IReadOnlyList realms) + { + _realms = realms; + } + + public RealmInfo this[int index] => _realms[index]; + + public int Count => _realms.Count; + + public IEnumerator GetEnumerator() => _realms.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => (_realms as IEnumerable).GetEnumerator(); +} diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/Handle.cs b/dotnet/src/webdriver/BiDi/Modules/Script/Handle.cs index 2e2649af926cf..8323bea292827 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/Handle.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/Handle.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; public class Handle diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/InternalId.cs b/dotnet/src/webdriver/BiDi/Modules/Script/InternalId.cs index 89e08f58f9121..1a34d8bd61bb5 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/InternalId.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/InternalId.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; public class InternalId diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/LocalValue.cs b/dotnet/src/webdriver/BiDi/Modules/Script/LocalValue.cs index 3451352ab962d..2b162c438dd3d 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/LocalValue.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/LocalValue.cs @@ -1,31 +1,36 @@ using System.Collections.Generic; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; [JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] -[JsonDerivedType(typeof(NumberLocalValue), "number")] -[JsonDerivedType(typeof(StringLocalValue), "string")] -[JsonDerivedType(typeof(NullLocalValue), "null")] -[JsonDerivedType(typeof(UndefinedLocalValue), "undefined")] -[JsonDerivedType(typeof(ArrayLocalValue), "array")] -[JsonDerivedType(typeof(DateLocalValue), "date")] -[JsonDerivedType(typeof(MapLocalValue), "map")] -[JsonDerivedType(typeof(ObjectLocalValue), "object")] -[JsonDerivedType(typeof(RegExpLocalValue), "regexp")] -[JsonDerivedType(typeof(SetLocalValue), "set")] +[JsonDerivedType(typeof(Number), "number")] +[JsonDerivedType(typeof(String), "string")] +[JsonDerivedType(typeof(Null), "null")] +[JsonDerivedType(typeof(Undefined), "undefined")] +[JsonDerivedType(typeof(Channel), "channel")] +[JsonDerivedType(typeof(Array), "array")] +[JsonDerivedType(typeof(Date), "date")] +[JsonDerivedType(typeof(Map), "map")] +[JsonDerivedType(typeof(Object), "object")] +[JsonDerivedType(typeof(RegExp), "regexp")] +[JsonDerivedType(typeof(Set), "set")] public abstract record LocalValue { - public static implicit operator LocalValue(int value) { return new NumberLocalValue(value); } - public static implicit operator LocalValue(string value) { return new StringLocalValue(value); } + public static implicit operator LocalValue(int value) { return new Number(value); } + public static implicit operator LocalValue(string value) { return new String(value); } // TODO: Extend converting from types public static LocalValue ConvertFrom(object? value) { switch (value) { + case LocalValue: + return (LocalValue)value; case null: - return new NullLocalValue(); + return new Null(); case int: return (int)value; case string: @@ -43,41 +48,55 @@ public static LocalValue ConvertFrom(object? value) values.Add([property.Name, ConvertFrom(property.GetValue(value))]); } - return new ObjectLocalValue(values); + return new Object(values); } } } -} -public abstract record PrimitiveProtocolLocalValue : LocalValue -{ + public abstract record PrimitiveProtocolLocalValue : LocalValue + { -} + } -public record NumberLocalValue(long Value) : PrimitiveProtocolLocalValue -{ - public static explicit operator NumberLocalValue(int n) => new NumberLocalValue(n); -} + public record Number(long Value) : PrimitiveProtocolLocalValue + { + public static explicit operator Number(int n) => new Number(n); + } -public record StringLocalValue(string Value) : PrimitiveProtocolLocalValue; + public record String(string Value) : PrimitiveProtocolLocalValue; -public record NullLocalValue : PrimitiveProtocolLocalValue; + public record Null : PrimitiveProtocolLocalValue; -public record UndefinedLocalValue : PrimitiveProtocolLocalValue; + public record Undefined : PrimitiveProtocolLocalValue; -public record ArrayLocalValue(IEnumerable Value) : LocalValue; + public record Channel(Channel.ChannelProperties Value) : LocalValue + { + [JsonInclude] + internal string type = "channel"; -public record DateLocalValue(string Value) : LocalValue; + public record ChannelProperties(Script.Channel Channel) + { + public SerializationOptions? SerializationOptions { get; set; } -public record MapLocalValue(IDictionary Value) : LocalValue; // seems to implement IDictionary + public ResultOwnership? Ownership { get; set; } + } + } -public record ObjectLocalValue(IEnumerable> Value) : LocalValue; + public record Array(IEnumerable Value) : LocalValue; -public record RegExpLocalValue(RegExpValue Value) : LocalValue; + public record Date(string Value) : LocalValue; -public record RegExpValue(string Pattern) -{ - public string? Flags { get; set; } -} + public record Map(IDictionary Value) : LocalValue; // seems to implement IDictionary + + public record Object(IEnumerable> Value) : LocalValue; -public record SetLocalValue(IEnumerable Value) : LocalValue; + public record RegExp(RegExp.RegExpValue Value) : LocalValue + { + public record RegExpValue(string Pattern) + { + public string? Flags { get; set; } + } + } + + public record Set(IEnumerable Value) : LocalValue; +} diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/MessageEventArgs.cs b/dotnet/src/webdriver/BiDi/Modules/Script/MessageEventArgs.cs new file mode 100644 index 0000000000000..e6062a76262c1 --- /dev/null +++ b/dotnet/src/webdriver/BiDi/Modules/Script/MessageEventArgs.cs @@ -0,0 +1,5 @@ +#nullable enable + +namespace OpenQA.Selenium.BiDi.Modules.Script; + +public record MessageEventArgs(BiDi BiDi, Channel Channel, RemoteValue Data, Source Source) : EventArgs(BiDi); diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/NodeProperties.cs b/dotnet/src/webdriver/BiDi/Modules/Script/NodeProperties.cs index 87bf2680efa6f..5cc214fcd225c 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/NodeProperties.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/NodeProperties.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; public record NodeProperties(long NodeType, long ChildNodeCount) @@ -9,7 +11,7 @@ public record NodeProperties(long NodeType, long ChildNodeCount) public IReadOnlyDictionary? Attributes { get; internal set; } [JsonInclude] - public IReadOnlyList? Children { get; internal set; } + public IReadOnlyList? Children { get; internal set; } [JsonInclude] public string? LocalName { get; internal set; } @@ -24,5 +26,5 @@ public record NodeProperties(long NodeType, long ChildNodeCount) public string? NodeValue { get; internal set; } [JsonInclude] - public NodeRemoteValue? ShadowRoot { get; internal set; } + public RemoteValue.Node? ShadowRoot { get; internal set; } } diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/PreloadScript.cs b/dotnet/src/webdriver/BiDi/Modules/Script/PreloadScript.cs index a59b9c099f05d..1b9027f21cf39 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/PreloadScript.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/PreloadScript.cs @@ -1,6 +1,8 @@ using System; using System.Threading.Tasks; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; public class PreloadScript : IAsyncDisposable @@ -17,7 +19,7 @@ public PreloadScript(BiDi bidi, string id) public Task RemoveAsync() { - return _bidi.ScriptModule.RemovePreloadScriptAsync(this); + return _bidi.Script.RemovePreloadScriptAsync(this); } public async ValueTask DisposeAsync() diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/Realm.cs b/dotnet/src/webdriver/BiDi/Modules/Script/Realm.cs index 0b8bf28fdf994..a690df5eabd91 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/Realm.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/Realm.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; public class Realm diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/RealmDestroyedEventArgs.cs b/dotnet/src/webdriver/BiDi/Modules/Script/RealmDestroyedEventArgs.cs new file mode 100644 index 0000000000000..b5d30f09c5fd3 --- /dev/null +++ b/dotnet/src/webdriver/BiDi/Modules/Script/RealmDestroyedEventArgs.cs @@ -0,0 +1,5 @@ +#nullable enable + +namespace OpenQA.Selenium.BiDi.Modules.Script; + +public record RealmDestroyedEventArgs(BiDi BiDi, Realm Realm) : EventArgs(BiDi); diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/RealmInfo.cs b/dotnet/src/webdriver/BiDi/Modules/Script/RealmInfo.cs index 4d88aa5e7b25c..4715be57392a7 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/RealmInfo.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/RealmInfo.cs @@ -1,36 +1,37 @@ using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; // https://github.com/dotnet/runtime/issues/72604 //[JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] -//[JsonDerivedType(typeof(WindowRealmInfo), "window")] -//[JsonDerivedType(typeof(DedicatedWorkerRealmInfo), "dedicated-worker")] -//[JsonDerivedType(typeof(SharedWorkerRealmInfo), "shared-worker")] -//[JsonDerivedType(typeof(ServiceWorkerRealmInfo), "service-worker")] -//[JsonDerivedType(typeof(WorkerRealmInfo), "worker")] -//[JsonDerivedType(typeof(PaintWorkletRealmInfo), "paint-worklet")] -//[JsonDerivedType(typeof(AudioWorkletRealmInfo), "audio-worklet")] -//[JsonDerivedType(typeof(WorkletRealmInfo), "worklet")] -public abstract record RealmInfo(BiDi BiDi) : EventArgs(BiDi); - -public abstract record BaseRealmInfo(BiDi BiDi, Realm Realm, string Origin) : RealmInfo(BiDi); - -public record WindowRealmInfo(BiDi BiDi, Realm Realm, string Origin, BrowsingContext.BrowsingContext Context) : BaseRealmInfo(BiDi, Realm, Origin) +//[JsonDerivedType(typeof(Window), "window")] +//[JsonDerivedType(typeof(DedicatedWorker), "dedicated-worker")] +//[JsonDerivedType(typeof(SharedWorker), "shared-worker")] +//[JsonDerivedType(typeof(ServiceWorker), "service-worker")] +//[JsonDerivedType(typeof(Worker), "worker")] +//[JsonDerivedType(typeof(PaintWorklet), "paint-worklet")] +//[JsonDerivedType(typeof(AudioWorklet), "audio-worklet")] +//[JsonDerivedType(typeof(Worklet), "worklet")] +public abstract record RealmInfo(BiDi BiDi, Realm Realm, string Origin) : EventArgs(BiDi) { - public string? Sandbox { get; set; } -} + public record Window(BiDi BiDi, Realm Realm, string Origin, BrowsingContext.BrowsingContext Context) : RealmInfo(BiDi, Realm, Origin) + { + public string? Sandbox { get; set; } + } -public record DedicatedWorkerRealmInfo(BiDi BiDi, Realm Realm, string Origin, IReadOnlyList Owners) : BaseRealmInfo(BiDi, Realm, Origin); + public record DedicatedWorker(BiDi BiDi, Realm Realm, string Origin, IReadOnlyList Owners) : RealmInfo(BiDi, Realm, Origin); -public record SharedWorkerRealmInfo(BiDi BiDi, Realm Realm, string Origin) : BaseRealmInfo(BiDi, Realm, Origin); + public record SharedWorker(BiDi BiDi, Realm Realm, string Origin) : RealmInfo(BiDi, Realm, Origin); -public record ServiceWorkerRealmInfo(BiDi BiDi, Realm Realm, string Origin) : BaseRealmInfo(BiDi, Realm, Origin); + public record ServiceWorker(BiDi BiDi, Realm Realm, string Origin) : RealmInfo(BiDi, Realm, Origin); -public record WorkerRealmInfo(BiDi BiDi, Realm Realm, string Origin) : BaseRealmInfo(BiDi, Realm, Origin); + public record Worker(BiDi BiDi, Realm Realm, string Origin) : RealmInfo(BiDi, Realm, Origin); -public record PaintWorkletRealmInfo(BiDi BiDi, Realm Realm, string Origin) : BaseRealmInfo(BiDi, Realm, Origin); + public record PaintWorklet(BiDi BiDi, Realm Realm, string Origin) : RealmInfo(BiDi, Realm, Origin); -public record AudioWorkletRealmInfo(BiDi BiDi, Realm Realm, string Origin) : BaseRealmInfo(BiDi, Realm, Origin); + public record AudioWorklet(BiDi BiDi, Realm Realm, string Origin) : RealmInfo(BiDi, Realm, Origin); -public record WorkletRealmInfo(BiDi BiDi, Realm Realm, string Origin) : BaseRealmInfo(BiDi, Realm, Origin); + public record Worklet(BiDi BiDi, Realm Realm, string Origin) : RealmInfo(BiDi, Realm, Origin); +} diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/RealmType.cs b/dotnet/src/webdriver/BiDi/Modules/Script/RealmType.cs index 0db521054c4d9..08444b2666830 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/RealmType.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/RealmType.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; public enum RealmType diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/RemoteReference.cs b/dotnet/src/webdriver/BiDi/Modules/Script/RemoteReference.cs index f936501b0cb14..ac64940070e7e 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/RemoteReference.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/RemoteReference.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; public abstract record RemoteReference : LocalValue; diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/RemoteValue.cs b/dotnet/src/webdriver/BiDi/Modules/Script/RemoteValue.cs index 0ce3be3404fa5..074ab2570b43e 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/RemoteValue.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/RemoteValue.cs @@ -1,44 +1,49 @@ using System; using System.Collections.Generic; +using System.Text.Json; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; // https://github.com/dotnet/runtime/issues/72604 //[JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] -//[JsonDerivedType(typeof(NumberRemoteValue), "number")] -//[JsonDerivedType(typeof(StringRemoteValue), "string")] -//[JsonDerivedType(typeof(NullRemoteValue), "null")] -//[JsonDerivedType(typeof(UndefinedRemoteValue), "undefined")] -//[JsonDerivedType(typeof(SymbolRemoteValue), "symbol")] -//[JsonDerivedType(typeof(ObjectRemoteValue), "object")] -//[JsonDerivedType(typeof(FunctionRemoteValue), "function")] -//[JsonDerivedType(typeof(RegExpRemoteValue), "regexp")] -//[JsonDerivedType(typeof(DateRemoteValue), "date")] -//[JsonDerivedType(typeof(MapRemoteValue), "map")] -//[JsonDerivedType(typeof(SetRemoteValue), "set")] -//[JsonDerivedType(typeof(WeakMapRemoteValue), "weakmap")] -//[JsonDerivedType(typeof(WeakSetRemoteValue), "weakset")] -//[JsonDerivedType(typeof(GeneratorRemoteValue), "generator")] -//[JsonDerivedType(typeof(ErrorRemoteValue), "error")] -//[JsonDerivedType(typeof(ProxyRemoteValue), "proxy")] -//[JsonDerivedType(typeof(PromiseRemoteValue), "promise")] -//[JsonDerivedType(typeof(TypedArrayRemoteValue), "typedarray")] -//[JsonDerivedType(typeof(ArrayBufferRemoteValue), "arraybuffer")] -//[JsonDerivedType(typeof(NodeListRemoteValue), "nodelist")] -//[JsonDerivedType(typeof(HtmlCollectionRemoteValue), "htmlcollection")] -//[JsonDerivedType(typeof(NodeRemoteValue), "node")] -//[JsonDerivedType(typeof(WindowProxyRemoteValue), "window")] +//[JsonDerivedType(typeof(Number), "number")] +//[JsonDerivedType(typeof(Boolean), "boolean")] +//[JsonDerivedType(typeof(String), "string")] +//[JsonDerivedType(typeof(Null), "null")] +//[JsonDerivedType(typeof(Undefined), "undefined")] +//[JsonDerivedType(typeof(Symbol), "symbol")] +//[JsonDerivedType(typeof(Array), "array")] +//[JsonDerivedType(typeof(Object), "object")] +//[JsonDerivedType(typeof(Function), "function")] +//[JsonDerivedType(typeof(RegExp), "regexp")] +//[JsonDerivedType(typeof(Date), "date")] +//[JsonDerivedType(typeof(Map), "map")] +//[JsonDerivedType(typeof(Set), "set")] +//[JsonDerivedType(typeof(WeakMap), "weakmap")] +//[JsonDerivedType(typeof(WeakSet), "weakset")] +//[JsonDerivedType(typeof(Generator), "generator")] +//[JsonDerivedType(typeof(Error), "error")] +//[JsonDerivedType(typeof(Proxy), "proxy")] +//[JsonDerivedType(typeof(Promise), "promise")] +//[JsonDerivedType(typeof(TypedArray), "typedarray")] +//[JsonDerivedType(typeof(ArrayBuffer), "arraybuffer")] +//[JsonDerivedType(typeof(NodeList), "nodelist")] +//[JsonDerivedType(typeof(HtmlCollection), "htmlcollection")] +//[JsonDerivedType(typeof(Node), "node")] +//[JsonDerivedType(typeof(WindowProxy), "window")] public abstract record RemoteValue { - public static implicit operator int(RemoteValue remoteValue) => (int)((NumberRemoteValue)remoteValue).Value; - public static implicit operator long(RemoteValue remoteValue) => ((NumberRemoteValue)remoteValue).Value; + public static implicit operator int(RemoteValue remoteValue) => (int)((Number)remoteValue).Value; + public static implicit operator long(RemoteValue remoteValue) => ((Number)remoteValue).Value; public static implicit operator string(RemoteValue remoteValue) { return remoteValue switch { - StringRemoteValue stringValue => stringValue.Value, - NullRemoteValue => null!, + String stringValue => stringValue.Value, + Null => null!, _ => throw new BiDiException($"Cannot convert {remoteValue} to string") }; } @@ -48,13 +53,17 @@ public static implicit operator string(RemoteValue remoteValue) { var type = typeof(TResult); + if (type == typeof(bool)) + { + return (TResult)(Convert.ToBoolean(((Boolean)this).Value) as object); + } if (type == typeof(int)) { - return (TResult)(Convert.ToInt32(((NumberRemoteValue)this).Value) as object); + return (TResult)(Convert.ToInt32(((Number)this).Value) as object); } else if (type == typeof(string)) { - return (TResult)(((StringRemoteValue)this).Value as object); + return (TResult)(((String)this).Value as object); } else if (type is object) { @@ -64,177 +73,184 @@ public static implicit operator string(RemoteValue remoteValue) throw new BiDiException("Cannot convert ....."); } -} -public abstract record PrimitiveProtocolRemoteValue : RemoteValue; + public record Number(long Value) : PrimitiveProtocolRemoteValue; -public record NumberRemoteValue(long Value) : PrimitiveProtocolRemoteValue; + public record Boolean(bool Value) : PrimitiveProtocolRemoteValue; -public record StringRemoteValue(string Value) : PrimitiveProtocolRemoteValue; + public record String(string Value) : PrimitiveProtocolRemoteValue; -public record NullRemoteValue : PrimitiveProtocolRemoteValue; + public record Null : PrimitiveProtocolRemoteValue; -public record UndefinedRemoteValue : PrimitiveProtocolRemoteValue; + public record Undefined : PrimitiveProtocolRemoteValue; -public record SymbolRemoteValue : RemoteValue -{ - public Handle? Handle { get; set; } + public record Symbol : RemoteValue + { + public Handle? Handle { get; set; } - public InternalId? InternalId { get; set; } -} + public InternalId? InternalId { get; set; } + } -public record ArrayRemoteValue : RemoteValue -{ - public Handle? Handle { get; set; } + public record Array : RemoteValue + { + public Handle? Handle { get; set; } - public InternalId? InternalId { get; set; } + public InternalId? InternalId { get; set; } - public IReadOnlyList? Value { get; set; } -} + public IReadOnlyList? Value { get; set; } + } -public record ObjectRemoteValue : RemoteValue -{ - public Handle? Handle { get; set; } + public record Object : RemoteValue + { + public Handle? Handle { get; set; } - public InternalId? InternalId { get; set; } + public InternalId? InternalId { get; set; } - public IReadOnlyList>? Value { get; set; } -} + public IReadOnlyList>? Value { get; set; } + } -public record FunctionRemoteValue : RemoteValue -{ - public Handle? Handle { get; set; } + public record Function : RemoteValue + { + public Handle? Handle { get; set; } - public InternalId? InternalId { get; set; } -} + public InternalId? InternalId { get; set; } + } -public record RegExpRemoteValue(RegExpValue Value) : RemoteValue -{ - public Handle? Handle { get; set; } + public record RegExp(RegExp.RegExpValue Value) : RemoteValue + { + public Handle? Handle { get; set; } - public InternalId? InternalId { get; set; } -} + public InternalId? InternalId { get; set; } -public record DateRemoteValue(string Value) : RemoteValue -{ - public Handle? Handle { get; set; } + public record RegExpValue(string Pattern) + { + public string? Flags { get; set; } + } + } - public InternalId? InternalId { get; set; } -} + public record Date(string Value) : RemoteValue + { + public Handle? Handle { get; set; } -public record MapRemoteValue : RemoteValue -{ - public Handle? Handle { get; set; } + public InternalId? InternalId { get; set; } + } - public InternalId? InternalId { get; set; } + public record Map : RemoteValue + { + public Handle? Handle { get; set; } - public IDictionary? Value { get; set; } -} + public InternalId? InternalId { get; set; } -public record SetRemoteValue : RemoteValue -{ - public Handle? Handle { get; set; } + public IDictionary? Value { get; set; } + } - public InternalId? InternalId { get; set; } + public record Set : RemoteValue + { + public Handle? Handle { get; set; } - public IReadOnlyList? Value { get; set; } -} + public InternalId? InternalId { get; set; } -public record WeakMapRemoteValue : RemoteValue -{ - public Handle? Handle { get; set; } + public IReadOnlyList? Value { get; set; } + } - public InternalId? InternalId { get; set; } -} + public record WeakMap : RemoteValue + { + public Handle? Handle { get; set; } -public record WeakSetRemoteValue : RemoteValue -{ - public Handle? Handle { get; set; } + public InternalId? InternalId { get; set; } + } - public InternalId? InternalId { get; set; } -} + public record WeakSet : RemoteValue + { + public Handle? Handle { get; set; } -public record GeneratorRemoteValue : RemoteValue -{ - public Handle? Handle { get; set; } + public InternalId? InternalId { get; set; } + } - public InternalId? InternalId { get; set; } -} + public record Generator : RemoteValue + { + public Handle? Handle { get; set; } -public record ErrorRemoteValue : RemoteValue -{ - public Handle? Handle { get; set; } + public InternalId? InternalId { get; set; } + } - public InternalId? InternalId { get; set; } -} + public record Error : RemoteValue + { + public Handle? Handle { get; set; } -public record ProxyRemoteValue : RemoteValue -{ - public Handle? Handle { get; set; } + public InternalId? InternalId { get; set; } + } - public InternalId? InternalId { get; set; } -} + public record Proxy : RemoteValue + { + public Handle? Handle { get; set; } -public record PromiseRemoteValue : RemoteValue -{ - public Handle? Handle { get; set; } + public InternalId? InternalId { get; set; } + } - public InternalId? InternalId { get; set; } -} + public record Promise : RemoteValue + { + public Handle? Handle { get; set; } -public record TypedArrayRemoteValue : RemoteValue -{ - public Handle? Handle { get; set; } + public InternalId? InternalId { get; set; } + } - public InternalId? InternalId { get; set; } -} + public record TypedArray : RemoteValue + { + public Handle? Handle { get; set; } -public record ArrayBufferRemoteValue : RemoteValue -{ - public Handle? Handle { get; set; } + public InternalId? InternalId { get; set; } + } - public InternalId? InternalId { get; set; } -} + public record ArrayBuffer : RemoteValue + { + public Handle? Handle { get; set; } -public record NodeListRemoteValue : RemoteValue -{ - public Handle? Handle { get; set; } + public InternalId? InternalId { get; set; } + } - public InternalId? InternalId { get; set; } + public record NodeList : RemoteValue + { + public Handle? Handle { get; set; } - public IReadOnlyList? Value { get; set; } -} + public InternalId? InternalId { get; set; } -public record HtmlCollectionRemoteValue : RemoteValue -{ - public Handle? Handle { get; set; } + public IReadOnlyList? Value { get; set; } + } - public InternalId? InternalId { get; set; } + public record HtmlCollection : RemoteValue + { + public Handle? Handle { get; set; } - public IReadOnlyList? Value { get; set; } -} + public InternalId? InternalId { get; set; } -public record NodeRemoteValue : RemoteValue -{ - [JsonInclude] - public string? SharedId { get; internal set; } + public IReadOnlyList? Value { get; set; } + } - public Handle? Handle { get; set; } + public record Node : RemoteValue + { + [JsonInclude] + public string? SharedId { get; internal set; } - public InternalId? InternalId { get; set; } + public Handle? Handle { get; set; } - [JsonInclude] - public NodeProperties? Value { get; internal set; } -} + public InternalId? InternalId { get; set; } -public record WindowProxyRemoteValue(WindowProxyProperties Value) : RemoteValue -{ - public Handle? Handle { get; set; } + [JsonInclude] + public NodeProperties? Value { get; internal set; } + } - public InternalId? InternalId { get; set; } + public record WindowProxy(WindowProxy.Properties Value) : RemoteValue + { + public Handle? Handle { get; set; } + + public InternalId? InternalId { get; set; } + + public record Properties(BrowsingContext.BrowsingContext Context); + } } -public record WindowProxyProperties(BrowsingContext.BrowsingContext Context); +public abstract record PrimitiveProtocolRemoteValue : RemoteValue; public enum Mode { diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/RemovePreloadScriptCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Script/RemovePreloadScriptCommand.cs index a64d5dd42775c..850ab9ecc0f6c 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/RemovePreloadScriptCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/RemovePreloadScriptCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; internal class RemovePreloadScriptCommand(RemovePreloadScriptCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/ResultOwnership.cs b/dotnet/src/webdriver/BiDi/Modules/Script/ResultOwnership.cs index 68e77e72a1f01..c69595bc3293c 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/ResultOwnership.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/ResultOwnership.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; public enum ResultOwnership diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/ScriptEvaluateException.cs b/dotnet/src/webdriver/BiDi/Modules/Script/ScriptEvaluateException.cs index 2270835f32639..4daa2cc704b1c 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/ScriptEvaluateException.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/ScriptEvaluateException.cs @@ -1,10 +1,12 @@ using System; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; -public class ScriptEvaluateException(EvaluateResultException evaluateResultException) : Exception +public class ScriptEvaluateException(EvaluateResult.Exception evaluateResultException) : Exception { - private readonly EvaluateResultException _evaluateResultException = evaluateResultException; + private readonly EvaluateResult.Exception _evaluateResultException = evaluateResultException; public string Text => _evaluateResultException.ExceptionDetails.Text; diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/ScriptModule.cs b/dotnet/src/webdriver/BiDi/Modules/Script/ScriptModule.cs index b5e8f2ae61b22..fee6e4a10dcfc 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/ScriptModule.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/ScriptModule.cs @@ -1,13 +1,16 @@ using OpenQA.Selenium.BiDi.Communication; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; public sealed class ScriptModule(Broker broker) : Module(broker) { - public async Task EvaluateAsync(string expression, bool awaitPromise, Target target, EvaluateOptions? options = null) + public async Task EvaluateAsync(string expression, bool awaitPromise, Target target, EvaluateOptions? options = null) { var @params = new EvaluateCommandParameters(expression, target, awaitPromise); @@ -20,15 +23,22 @@ public async Task EvaluateAsync(string expression, bool awaitPromis var result = await Broker.ExecuteCommandAsync(new EvaluateCommand(@params), options).ConfigureAwait(false); - if (result is EvaluateResultException exp) + if (result is EvaluateResult.Exception exp) { throw new ScriptEvaluateException(exp); } - return ((EvaluateResultSuccess)result).Result; + return (EvaluateResult.Success)result; } - public async Task CallFunctionAsync(string functionDeclaration, bool awaitPromise, Target target, CallFunctionOptions? options = null) + public async Task EvaluateAsync(string expression, bool awaitPromise, Target target, EvaluateOptions? options = null) + { + var result = await EvaluateAsync(expression, awaitPromise, target, options).ConfigureAwait(false); + + return result.Result.ConvertTo(); + } + + public async Task CallFunctionAsync(string functionDeclaration, bool awaitPromise, Target target, CallFunctionOptions? options = null) { var @params = new CallFunctionCommandParameters(functionDeclaration, awaitPromise, target); @@ -43,15 +53,22 @@ public async Task CallFunctionAsync(string functionDeclaration, boo var result = await Broker.ExecuteCommandAsync(new CallFunctionCommand(@params), options).ConfigureAwait(false); - if (result is EvaluateResultException exp) + if (result is EvaluateResult.Exception exp) { throw new ScriptEvaluateException(exp); } - return ((EvaluateResultSuccess)result).Result; + return (EvaluateResult.Success)result; + } + + public async Task CallFunctionAsync(string functionDeclaration, bool awaitPromise, Target target, CallFunctionOptions? options = null) + { + var result = await CallFunctionAsync(functionDeclaration, awaitPromise, target, options).ConfigureAwait(false); + + return result.Result.ConvertTo(); } - public async Task> GetRealmsAsync(GetRealmsOptions? options = null) + public async Task GetRealmsAsync(GetRealmsOptions? options = null) { var @params = new GetRealmsCommandParameters(); @@ -61,9 +78,7 @@ public async Task> GetRealmsAsync(GetRealmsOptions? opt @params.Type = options.Type; } - var result = await Broker.ExecuteCommandAsync(new GetRealmsCommand(@params), options).ConfigureAwait(false); - - return result.Realms; + return await Broker.ExecuteCommandAsync(new GetRealmsCommand(@params), options).ConfigureAwait(false); } public async Task AddPreloadScriptAsync(string functionDeclaration, AddPreloadScriptOptions? options = null) @@ -88,4 +103,34 @@ public async Task RemovePreloadScriptAsync(PreloadScript script, RemovePreloadSc await Broker.ExecuteCommandAsync(new RemovePreloadScriptCommand(@params), options).ConfigureAwait(false); } + + public async Task OnMessageAsync(Func handler, SubscriptionOptions? options = null) + { + return await Broker.SubscribeAsync("script.message", handler, options).ConfigureAwait(false); + } + + public async Task OnMessageAsync(Action handler, SubscriptionOptions? options = null) + { + return await Broker.SubscribeAsync("script.message", handler, options).ConfigureAwait(false); + } + + public async Task OnRealmCreatedAsync(Func handler, SubscriptionOptions? options = null) + { + return await Broker.SubscribeAsync("script.realmCreated", handler, options).ConfigureAwait(false); + } + + public async Task OnRealmCreatedAsync(Action handler, SubscriptionOptions? options = null) + { + return await Broker.SubscribeAsync("script.realmCreated", handler, options).ConfigureAwait(false); + } + + public async Task OnRealmDestroyedAsync(Func handler, SubscriptionOptions? options = null) + { + return await Broker.SubscribeAsync("script.realmDestroyed", handler, options).ConfigureAwait(false); + } + + public async Task OnRealmDestroyedAsync(Action handler, SubscriptionOptions? options = null) + { + return await Broker.SubscribeAsync("script.realmDestroyed", handler, options).ConfigureAwait(false); + } } diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/SerializationOptions.cs b/dotnet/src/webdriver/BiDi/Modules/Script/SerializationOptions.cs index 57659570eaaf4..bbb275cc08c2f 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/SerializationOptions.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/SerializationOptions.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; public class SerializationOptions diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/Source.cs b/dotnet/src/webdriver/BiDi/Modules/Script/Source.cs index 309ac31a0ba75..27bdbcad6f695 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/Source.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/Source.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; public record Source(Realm Realm) diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/StackFrame.cs b/dotnet/src/webdriver/BiDi/Modules/Script/StackFrame.cs index 7e3694e9a5e68..208485e0bd636 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/StackFrame.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/StackFrame.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; public record StackFrame(long LineNumber, long ColumnNumber, string Url, string FunctionName); diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/StackTrace.cs b/dotnet/src/webdriver/BiDi/Modules/Script/StackTrace.cs index b9ec5c6bf1d0a..15bbfd829bb1e 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/StackTrace.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/StackTrace.cs @@ -1,5 +1,7 @@ using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Script; public record StackTrace(IReadOnlyCollection CallFrames); diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/Target.cs b/dotnet/src/webdriver/BiDi/Modules/Script/Target.cs index 7c20cb8b33b6f..a05849a62c8b9 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/Target.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/Target.cs @@ -1,16 +1,19 @@ using System.Text.Json.Serialization; -namespace OpenQA.Selenium.BiDi.Modules.Script; - -[JsonDerivedType(typeof(RealmTarget))] -[JsonDerivedType(typeof(ContextTarget))] -public abstract record Target; +#nullable enable -public record RealmTarget(Realm Realm) : Target; +namespace OpenQA.Selenium.BiDi.Modules.Script; -public record ContextTarget(BrowsingContext.BrowsingContext Context) : Target +[JsonDerivedType(typeof(Realm))] +[JsonDerivedType(typeof(Context))] +public abstract record Target { - public string? Sandbox { get; set; } + public record Realm([property: JsonPropertyName("realm")] Script.Realm Target) : Target; + + public record Context([property: JsonPropertyName("context")] BrowsingContext.BrowsingContext Target) : Target + { + public string? Sandbox { get; set; } + } } public class ContextTargetOptions diff --git a/dotnet/src/webdriver/BiDi/Modules/Session/CapabilitiesRequest.cs b/dotnet/src/webdriver/BiDi/Modules/Session/CapabilitiesRequest.cs index be4c7ac6d69db..542f9e1c3f076 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Session/CapabilitiesRequest.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Session/CapabilitiesRequest.cs @@ -1,5 +1,7 @@ using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Session; public class CapabilitiesRequest diff --git a/dotnet/src/webdriver/BiDi/Modules/Session/CapabilityRequest.cs b/dotnet/src/webdriver/BiDi/Modules/Session/CapabilityRequest.cs index 1cd33a08be0ad..b449e984bb540 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Session/CapabilityRequest.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Session/CapabilityRequest.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Session; public class CapabilityRequest diff --git a/dotnet/src/webdriver/BiDi/Modules/Session/EndCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Session/EndCommand.cs index 73180d2cd6bda..a41d0be7c2ded 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Session/EndCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Session/EndCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Session; internal class EndCommand() : Command(CommandParameters.Empty); diff --git a/dotnet/src/webdriver/BiDi/Modules/Session/NewCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Session/NewCommand.cs index 3c965e0f1d505..97759165116a2 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Session/NewCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Session/NewCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Session; internal class NewCommand(NewCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/Session/ProxyConfiguration.cs b/dotnet/src/webdriver/BiDi/Modules/Session/ProxyConfiguration.cs index 171dbb0ec8c2b..4243dbbaf69c1 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Session/ProxyConfiguration.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Session/ProxyConfiguration.cs @@ -1,32 +1,35 @@ using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Session; [JsonPolymorphic(TypeDiscriminatorPropertyName = "proxyType")] -[JsonDerivedType(typeof(AutodetectProxyConfiguration), "autodetect")] -[JsonDerivedType(typeof(DirectProxyConfiguration), "direct")] -[JsonDerivedType(typeof(ManualProxyConfiguration), "manual")] -[JsonDerivedType(typeof(PacProxyConfiguration), "pac")] -[JsonDerivedType(typeof(SystemProxyConfiguration), "system")] -public abstract record ProxyConfiguration; - -public record AutodetectProxyConfiguration : ProxyConfiguration; +[JsonDerivedType(typeof(Autodetect), "autodetect")] +[JsonDerivedType(typeof(Direct), "direct")] +[JsonDerivedType(typeof(Manual), "manual")] +[JsonDerivedType(typeof(Pac), "pac")] +[JsonDerivedType(typeof(System), "system")] +public abstract record ProxyConfiguration +{ + public record Autodetect : ProxyConfiguration; -public record DirectProxyConfiguration : ProxyConfiguration; + public record Direct : ProxyConfiguration; -public record ManualProxyConfiguration : ProxyConfiguration -{ - public string? FtpProxy { get; set; } + public record Manual : ProxyConfiguration + { + public string? FtpProxy { get; set; } - public string? HttpProxy { get; set; } + public string? HttpProxy { get; set; } - public string? SslProxy { get; set; } + public string? SslProxy { get; set; } - public string? SocksProxy { get; set; } + public string? SocksProxy { get; set; } - public long? SocksVersion { get; set; } -} + public long? SocksVersion { get; set; } + } -public record PacProxyConfiguration(string ProxyAutoconfigUrl) : ProxyConfiguration; + public record Pac(string ProxyAutoconfigUrl) : ProxyConfiguration; -public record SystemProxyConfiguration : ProxyConfiguration; + public record System : ProxyConfiguration; +} diff --git a/dotnet/src/webdriver/BiDi/Modules/Session/SessionModule.cs b/dotnet/src/webdriver/BiDi/Modules/Session/SessionModule.cs index 3a1ec251a2956..88503bf894cd8 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Session/SessionModule.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Session/SessionModule.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Threading.Tasks; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Session; internal sealed class SessionModule(Broker broker) : Module(broker) diff --git a/dotnet/src/webdriver/BiDi/Modules/Session/StatusCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Session/StatusCommand.cs index 2c25c17e60313..8ab6de213b138 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Session/StatusCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Session/StatusCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Session; internal class StatusCommand() : Command(CommandParameters.Empty); diff --git a/dotnet/src/webdriver/BiDi/Modules/Session/SubscribeCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Session/SubscribeCommand.cs index 1d33180d1e3b7..607e5c69944c6 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Session/SubscribeCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Session/SubscribeCommand.cs @@ -1,6 +1,8 @@ using OpenQA.Selenium.BiDi.Communication; using System.Collections.Generic; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Session; internal class SubscribeCommand(SubscribeCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/Session/UnsubscribeCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Session/UnsubscribeCommand.cs index e96f6b4cf828d..6ca1f7517b439 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Session/UnsubscribeCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Session/UnsubscribeCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Session; internal class UnsubscribeCommand(SubscribeCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/Storage/DeleteCookiesCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Storage/DeleteCookiesCommand.cs index bcc27fdf9f8b3..13dcf2f30d3ba 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Storage/DeleteCookiesCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Storage/DeleteCookiesCommand.cs @@ -1,5 +1,7 @@ using OpenQA.Selenium.BiDi.Communication; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Storage; internal class DeleteCookiesCommand(DeleteCookiesCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/Storage/GetCookiesCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Storage/GetCookiesCommand.cs index c7c7c2c01dda3..06cd0c09f6925 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Storage/GetCookiesCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Storage/GetCookiesCommand.cs @@ -1,8 +1,11 @@ using OpenQA.Selenium.BiDi.Communication; using System; +using System.Collections; using System.Collections.Generic; using System.Text.Json.Serialization; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Storage; internal class GetCookiesCommand(GetCookiesCommandParameters @params) : Command(@params); @@ -21,7 +24,26 @@ public record GetCookiesOptions : CommandOptions public PartitionDescriptor? Partition { get; set; } } -public record GetCookiesResult(IReadOnlyList Cookies, PartitionKey PartitionKey); +public record GetCookiesResult : IReadOnlyList +{ + private readonly IReadOnlyList _cookies; + + internal GetCookiesResult(IReadOnlyList cookies, PartitionKey partitionKey) + { + _cookies = cookies; + PartitionKey = partitionKey; + } + + public PartitionKey PartitionKey { get; init; } + + public Network.Cookie this[int index] => _cookies[index]; + + public int Count => _cookies.Count; + + public IEnumerator GetEnumerator() => _cookies.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => (_cookies as IEnumerable).GetEnumerator(); +} public class CookieFilter { @@ -45,15 +67,16 @@ public class CookieFilter } [JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] -[JsonDerivedType(typeof(BrowsingContextPartitionDescriptor), "context")] -[JsonDerivedType(typeof(StorageKeyPartitionDescriptor), "storageKey")] -public abstract record PartitionDescriptor; - -public record BrowsingContextPartitionDescriptor(BrowsingContext.BrowsingContext Context) : PartitionDescriptor; - -public record StorageKeyPartitionDescriptor : PartitionDescriptor +[JsonDerivedType(typeof(Context), "context")] +[JsonDerivedType(typeof(StorageKey), "storageKey")] +public abstract record PartitionDescriptor { - public string? UserContext { get; set; } + public record Context([property: JsonPropertyName("context")] BrowsingContext.BrowsingContext Descriptor) : PartitionDescriptor; + + public record StorageKey : PartitionDescriptor + { + public string? UserContext { get; set; } - public string? SourceOrigin { get; set; } + public string? SourceOrigin { get; set; } + } } diff --git a/dotnet/src/webdriver/BiDi/Modules/Storage/PartitionKey.cs b/dotnet/src/webdriver/BiDi/Modules/Storage/PartitionKey.cs index 2d9ac37a41a22..30200db4b5f60 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Storage/PartitionKey.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Storage/PartitionKey.cs @@ -1,8 +1,10 @@ +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Storage; public class PartitionKey { - public string? UserContext { get; set; } + public Browser.UserContext? UserContext { get; set; } public string? SourceOrigin { get; set; } } diff --git a/dotnet/src/webdriver/BiDi/Modules/Storage/SetCookieCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Storage/SetCookieCommand.cs index f0dcf22904eba..7e7cb79824cbc 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Storage/SetCookieCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Storage/SetCookieCommand.cs @@ -1,6 +1,8 @@ using OpenQA.Selenium.BiDi.Communication; using System; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Storage; internal class SetCookieCommand(SetCookieCommandParameters @params) : Command(@params); diff --git a/dotnet/src/webdriver/BiDi/Modules/Storage/StorageModule.cs b/dotnet/src/webdriver/BiDi/Modules/Storage/StorageModule.cs index 249d7d37634d1..71969d9914c2a 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Storage/StorageModule.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Storage/StorageModule.cs @@ -1,6 +1,8 @@ using OpenQA.Selenium.BiDi.Communication; using System.Threading.Tasks; +#nullable enable + namespace OpenQA.Selenium.BiDi.Modules.Storage; public class StorageModule(Broker broker) : Module(broker) diff --git a/dotnet/src/webdriver/BiDi/Subscription.cs b/dotnet/src/webdriver/BiDi/Subscription.cs index 21995fee00dcf..8870b07fb18bf 100644 --- a/dotnet/src/webdriver/BiDi/Subscription.cs +++ b/dotnet/src/webdriver/BiDi/Subscription.cs @@ -3,22 +3,24 @@ using System.Collections.Generic; using System.Threading.Tasks; +#nullable enable + namespace OpenQA.Selenium.BiDi; public class Subscription : IAsyncDisposable { - private readonly Broker Broker; + private readonly Broker _broker; private readonly Communication.EventHandler _eventHandler; internal Subscription(Broker broker, Communication.EventHandler eventHandler) { - Broker = broker; + _broker = broker; _eventHandler = eventHandler; } public async Task UnsubscribeAsync() { - await Broker.UnsubscribeAsync(_eventHandler).ConfigureAwait(false); + await _broker.UnsubscribeAsync(_eventHandler).ConfigureAwait(false); } public async ValueTask DisposeAsync() diff --git a/dotnet/src/webdriver/BiDi/WebDriver.Extensions.cs b/dotnet/src/webdriver/BiDi/WebDriver.Extensions.cs index c039dd4087740..a3e7df31cec50 100644 --- a/dotnet/src/webdriver/BiDi/WebDriver.Extensions.cs +++ b/dotnet/src/webdriver/BiDi/WebDriver.Extensions.cs @@ -1,6 +1,8 @@ using OpenQA.Selenium.BiDi.Modules.BrowsingContext; using System.Threading.Tasks; +#nullable enable + namespace OpenQA.Selenium.BiDi; public static class WebDriverExtensions diff --git a/dotnet/src/webdriver/Command.cs b/dotnet/src/webdriver/Command.cs index d12274ca90d7a..409c393860d6c 100644 --- a/dotnet/src/webdriver/Command.cs +++ b/dotnet/src/webdriver/Command.cs @@ -28,15 +28,16 @@ namespace OpenQA.Selenium /// public class Command { + private SessionId commandSessionId; + private string commandName; + private Dictionary commandParameters = new Dictionary(); + private readonly static JsonSerializerOptions s_jsonSerializerOptions = new() { + TypeInfoResolver = CommandJsonSerializerContext.Default, Converters = { new ResponseValueJsonConverter() } }; - private SessionId commandSessionId; - private string commandName; - private Dictionary commandParameters = new Dictionary(); - /// /// Initializes a new instance of the class using a command name and a JSON-encoded string for the parameters. /// @@ -101,7 +102,7 @@ public string ParametersAsJsonString string parametersString = string.Empty; if (this.commandParameters != null && this.commandParameters.Count > 0) { - parametersString = JsonSerializer.Serialize(this.commandParameters); + parametersString = JsonSerializer.Serialize(this.commandParameters, s_jsonSerializerOptions); } if (string.IsNullOrEmpty(parametersString)) @@ -133,4 +134,34 @@ private static Dictionary ConvertParametersFromJson(string value return parameters; } } + + // Built-in types + [JsonSerializable(typeof(bool))] + [JsonSerializable(typeof(byte))] + [JsonSerializable(typeof(sbyte))] + [JsonSerializable(typeof(char))] + [JsonSerializable(typeof(decimal))] + [JsonSerializable(typeof(double))] + [JsonSerializable(typeof(float))] + [JsonSerializable(typeof(int))] + [JsonSerializable(typeof(uint))] + [JsonSerializable(typeof(nint))] + [JsonSerializable(typeof(nuint))] + [JsonSerializable(typeof(long))] + [JsonSerializable(typeof(ulong))] + [JsonSerializable(typeof(short))] + [JsonSerializable(typeof(ushort))] + + [JsonSerializable(typeof(string))] + + // Selenium WebDriver types + [JsonSerializable(typeof(char[]))] + [JsonSerializable(typeof(byte[]))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(Cookie))] + [JsonSerializable(typeof(Proxy))] + internal partial class CommandJsonSerializerContext : JsonSerializerContext + { + + } } diff --git a/dotnet/src/webdriver/Internal/ResponseValueJsonConverter.cs b/dotnet/src/webdriver/Internal/ResponseValueJsonConverter.cs index 9967d790c55c9..6b888a788236b 100644 --- a/dotnet/src/webdriver/Internal/ResponseValueJsonConverter.cs +++ b/dotnet/src/webdriver/Internal/ResponseValueJsonConverter.cs @@ -30,75 +30,107 @@ internal class ResponseValueJsonConverter : JsonConverter { public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return this.ProcessToken(ref reader, options); + return ProcessReadToken(ref reader, options); } public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) { - JsonSerializer.Serialize(writer, value, options); + switch (value) + { + case null: + writer.WriteNullValue(); + break; + case Enum: + writer.WriteNumberValue(Convert.ToInt64(value)); + break; + case IEnumerable list: + writer.WriteStartArray(); + foreach (var item in list) + { + Write(writer, item, options); + } + writer.WriteEndArray(); + break; + case IDictionary dictionary: + writer.WriteStartObject(); + foreach (var pair in dictionary) + { + writer.WritePropertyName(pair.Key); + Write(writer, pair.Value, options); + } + writer.WriteEndObject(); + break; + case object obj: + JsonSerializer.Serialize(writer, obj, options.GetTypeInfo(obj.GetType())); + break; + } } - private object ProcessToken(ref Utf8JsonReader reader, JsonSerializerOptions options) + private static object ProcessReadToken(ref Utf8JsonReader reader, JsonSerializerOptions options) { // Recursively processes a token. This is required for elements that next other elements. - object processedObject = null; + object processedObject; - if (reader.TokenType == JsonTokenType.StartObject) + switch (reader.TokenType) { - Dictionary dictionaryValue = new Dictionary(); - while (reader.Read() && reader.TokenType != JsonTokenType.EndObject) - { - string elementKey = reader.GetString(); - reader.Read(); - dictionaryValue.Add(elementKey, this.ProcessToken(ref reader, options)); - } + case JsonTokenType.StartObject: + { + Dictionary dictionaryValue = []; + while (reader.Read() && reader.TokenType != JsonTokenType.EndObject) + { + string elementKey = reader.GetString(); + reader.Read(); + dictionaryValue.Add(elementKey, ProcessReadToken(ref reader, options)); + } - processedObject = dictionaryValue; - } - else if (reader.TokenType == JsonTokenType.StartArray) - { - List arrayValue = new List(); - while (reader.Read() && reader.TokenType != JsonTokenType.EndArray) - { - arrayValue.Add(this.ProcessToken(ref reader, options)); - } + processedObject = dictionaryValue; + break; + } - processedObject = arrayValue.ToArray(); - } - else if (reader.TokenType == JsonTokenType.Null) - { - processedObject = null; - } - else if (reader.TokenType == JsonTokenType.False) - { - processedObject = false; - } - else if (reader.TokenType == JsonTokenType.True) - { - processedObject = true; - } - else if (reader.TokenType == JsonTokenType.String) - { - processedObject = reader.GetString(); - } - else if (reader.TokenType == JsonTokenType.Number) - { - if (reader.TryGetInt64(out long longValue)) - { - processedObject = longValue; - } - else if (reader.TryGetDouble(out double doubleValue)) - { - processedObject = doubleValue; - } - else - { - throw new JsonException($"Unrecognized '{JsonElement.ParseValue(ref reader)}' token as a number value."); - } - } - else - { - throw new JsonException($"Unrecognized '{reader.TokenType}' token type while parsing command response."); + case JsonTokenType.StartArray: + { + List arrayValue = []; + while (reader.Read() && reader.TokenType != JsonTokenType.EndArray) + { + arrayValue.Add(ProcessReadToken(ref reader, options)); + } + + processedObject = arrayValue.ToArray(); + break; + } + + case JsonTokenType.Null: + processedObject = null; + break; + case JsonTokenType.False: + processedObject = false; + break; + case JsonTokenType.True: + processedObject = true; + break; + case JsonTokenType.String: + processedObject = reader.GetString(); + break; + case JsonTokenType.Number: + { + if (reader.TryGetInt64(out long longValue)) + { + processedObject = longValue; + } + else if (reader.TryGetDouble(out double doubleValue)) + { + processedObject = doubleValue; + } + else + { + throw new JsonException($"Unrecognized '{JsonElement.ParseValue(ref reader)}' token as a number value."); + } + + break; + } + + default: + throw new JsonException($"Unrecognized '{reader.TokenType}' token type while parsing command response."); } return processedObject; diff --git a/dotnet/src/webdriver/Response.cs b/dotnet/src/webdriver/Response.cs index 674a6488135b4..ebfd47e2cfa1b 100644 --- a/dotnet/src/webdriver/Response.cs +++ b/dotnet/src/webdriver/Response.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Globalization; using System.Text.Json; +using System.Text.Json.Serialization; namespace OpenQA.Selenium { @@ -31,7 +32,8 @@ public class Response { private readonly static JsonSerializerOptions s_jsonSerializerOptions = new() { - Converters = { new ResponseValueJsonConverter() } + TypeInfoResolver = ResponseJsonSerializerContext.Default, + Converters = { new ResponseValueJsonConverter() } // we still need it to make `Object` as `Dictionary` }; private object responseValue; @@ -208,4 +210,10 @@ public override string ToString() return string.Format(CultureInfo.InvariantCulture, "({0} {1}: {2})", this.SessionId, this.Status, this.Value); } } + + [JsonSerializable(typeof(Dictionary))] + internal partial class ResponseJsonSerializerContext : JsonSerializerContext + { + + } } diff --git a/dotnet/src/webdriver/SeleniumManager.cs b/dotnet/src/webdriver/SeleniumManager.cs index 4b28f7862d138..60c8cd5255389 100644 --- a/dotnet/src/webdriver/SeleniumManager.cs +++ b/dotnet/src/webdriver/SeleniumManager.cs @@ -195,28 +195,12 @@ private static ResultResponse RunCommand(string fileName, string arguments) if (jsonResponse.Logs is not null) { - foreach (var entry in jsonResponse.Logs) + // Treat SM's logs always as Trace to avoid SM writing at Info level + if (_logger.IsEnabled(LogEventLevel.Trace)) { - switch (entry.Level) + foreach (var entry in jsonResponse.Logs) { - case "WARN": - if (_logger.IsEnabled(LogEventLevel.Warn)) - { - _logger.Warn(entry.Message); - } - break; - case "DEBUG": - if (_logger.IsEnabled(LogEventLevel.Debug)) - { - _logger.Debug(entry.Message); - } - break; - case "INFO": - if (_logger.IsEnabled(LogEventLevel.Info)) - { - _logger.Info(entry.Message); - } - break; + _logger.Trace($"{entry.Level} {entry.Message}"); } } } diff --git a/dotnet/test/common/BiDi/BiDiFixture.cs b/dotnet/test/common/BiDi/BiDiFixture.cs new file mode 100644 index 0000000000000..b7bf01de81b52 --- /dev/null +++ b/dotnet/test/common/BiDi/BiDiFixture.cs @@ -0,0 +1,54 @@ +using NUnit.Framework; +using OpenQA.Selenium.Environment; +using System.Threading.Tasks; + +namespace OpenQA.Selenium.BiDi; + +[Parallelizable(ParallelScope.All)] +[FixtureLifeCycle(LifeCycle.InstancePerTestCase)] +public class BiDiTestFixture +{ + protected IWebDriver driver; + protected BiDi bidi; + protected Modules.BrowsingContext.BrowsingContext context; + + protected UrlBuilder UrlBuilder { get; } = EnvironmentManager.Instance.UrlBuilder; + + [SetUp] + public async Task BiDiSetUp() + { + var options = new BiDiEnabledDriverOptions() + { + UseWebSocketUrl = true, + UnhandledPromptBehavior = UnhandledPromptBehavior.Ignore, + }; + + driver = EnvironmentManager.Instance.CreateDriverInstance(options); + + context = await driver.AsBiDiContextAsync(); + bidi = context.BiDi; + } + + [TearDown] + public async Task BiDiTearDown() + { + if (bidi is not null) + { + await bidi.DisposeAsync(); + } + + driver?.Dispose(); + } + + public class BiDiEnabledDriverOptions : DriverOptions + { + public override void AddAdditionalOption(string capabilityName, object capabilityValue) + { + } + + public override ICapabilities ToCapabilities() + { + return null; + } + } +} diff --git a/dotnet/test/common/BiDi/Browser/BrowserTest.cs b/dotnet/test/common/BiDi/Browser/BrowserTest.cs new file mode 100644 index 0000000000000..74bbd956848a1 --- /dev/null +++ b/dotnet/test/common/BiDi/Browser/BrowserTest.cs @@ -0,0 +1,43 @@ +using NUnit.Framework; +using System.Threading.Tasks; + +namespace OpenQA.Selenium.BiDi.Browser; + +class BrowserTest : BiDiTestFixture +{ + [Test] + public async Task CanCreateUserContext() + { + var userContext = await bidi.Browser.CreateUserContextAsync(); + + Assert.That(userContext, Is.Not.Null); + } + + [Test] + public async Task CanGetUserContexts() + { + var userContext1 = await bidi.Browser.CreateUserContextAsync(); + var userContext2 = await bidi.Browser.CreateUserContextAsync(); + + var userContexts = await bidi.Browser.GetUserContextsAsync(); + + Assert.That(userContexts, Is.Not.Null); + Assert.That(userContexts.Count, Is.GreaterThanOrEqualTo(2)); + Assert.That(userContexts, Does.Contain(userContext1)); + Assert.That(userContexts, Does.Contain(userContext2)); + } + + [Test] + public async Task CanRemoveUserContext() + { + var userContext1 = await bidi.Browser.CreateUserContextAsync(); + var userContext2 = await bidi.Browser.CreateUserContextAsync(); + + await userContext2.UserContext.RemoveAsync(); + + var userContexts = await bidi.Browser.GetUserContextsAsync(); + + Assert.That(userContexts, Does.Contain(userContext1)); + Assert.That(userContexts, Does.Not.Contain(userContext2)); + } +} diff --git a/dotnet/test/common/BiDi/BrowsingContext/BrowsingContextTest.cs b/dotnet/test/common/BiDi/BrowsingContext/BrowsingContextTest.cs new file mode 100644 index 0000000000000..510daceddfb11 --- /dev/null +++ b/dotnet/test/common/BiDi/BrowsingContext/BrowsingContextTest.cs @@ -0,0 +1,301 @@ +using NUnit.Framework; +using OpenQA.Selenium.BiDi.Modules.BrowsingContext; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenQA.Selenium.BiDi.BrowsingContext; + +class BrowsingContextTest : BiDiTestFixture +{ + [Test] + public async Task CanCreateNewTab() + { + var tab = await bidi.BrowsingContext.CreateAsync(ContextType.Tab); + + Assert.That(tab, Is.Not.Null); + } + + [Test] + public async Task CanCreateNewTabWithReferencedContext() + { + var tab = await bidi.BrowsingContext.CreateAsync(ContextType.Tab, new() + { + ReferenceContext = context + }); + + Assert.That(tab, Is.Not.Null); + } + + [Test] + public async Task CanCreateNewWindow() + { + var window = await bidi.BrowsingContext.CreateAsync(ContextType.Window); + + Assert.That(window, Is.Not.Null); + } + + [Test] + public async Task CanCreateNewWindowWithReferencedContext() + { + var window = await bidi.BrowsingContext.CreateAsync(ContextType.Window, new() + { + ReferenceContext = context + }); + + Assert.That(window, Is.Not.Null); + } + + [Test] + public async Task CanCreateContextWithAllParameters() + { + var userContext = await bidi.Browser.CreateUserContextAsync(); + + var window = await bidi.BrowsingContext.CreateAsync(ContextType.Window, new() + { + ReferenceContext = context, + UserContext = userContext.UserContext, + Background = true + }); + + Assert.That(window, Is.Not.Null); + } + + [Test] + public async Task CanNavigateToUrl() + { + var info = await context.NavigateAsync(UrlBuilder.WhereIs("/bidi/logEntryAdded.html")); + + Assert.That(info.Url, Does.Contain("/bidi/logEntryAdded.html")); + } + + [Test] + public async Task CanNavigateToUrlWithReadinessState() + { + var info = await context.NavigateAsync(UrlBuilder.WhereIs("/bidi/logEntryAdded.html"), new() + { + Wait = ReadinessState.Complete + }); + + Assert.That(info, Is.Not.Null); + Assert.That(info.Url, Does.Contain("/bidi/logEntryAdded.html")); + } + + [Test] + public async Task CanGetTreeWithChild() + { + await context.NavigateAsync(UrlBuilder.WhereIs("iframes.html"), new() { Wait = ReadinessState.Complete }); + + var tree = await context.GetTreeAsync(); + + Assert.That(tree, Has.Count.EqualTo(1)); + Assert.That(tree[0].Context, Is.EqualTo(context)); + Assert.That(tree[0].Children, Has.Count.EqualTo(1)); + Assert.That(tree[0].Children[0].Url, Does.Contain("formPage.html")); + } + + [Test] + public async Task CanGetTreeWithDepth() + { + await context.NavigateAsync(UrlBuilder.WhereIs("iframes.html"), new() { Wait = ReadinessState.Complete }); + + var tree = await context.GetTreeAsync(new() { MaxDepth = 0 }); + + Assert.That(tree, Has.Count.EqualTo(1)); + Assert.That(tree[0].Context, Is.EqualTo(context)); + Assert.That(tree[0].Children, Is.Null); + } + + [Test] + public async Task CanGetTreeTopLevel() + { + var window1 = await bidi.BrowsingContext.CreateAsync(ContextType.Window); + var window2 = await bidi.BrowsingContext.CreateAsync(ContextType.Window); + + var tree = await bidi.BrowsingContext.GetTreeAsync(); + + Assert.That(tree, Has.Count.GreaterThanOrEqualTo(2)); + } + + [Test] + public async Task CanCloseWindow() + { + var window = await bidi.BrowsingContext.CreateAsync(ContextType.Window); + + await window.CloseAsync(); + + var tree = await bidi.BrowsingContext.GetTreeAsync(); + + Assert.That(tree.Select(i => i.Context), Does.Not.Contain(window)); + } + + [Test] + public async Task CanCloseTab() + { + var tab = await bidi.BrowsingContext.CreateAsync(ContextType.Tab); + + await tab.CloseAsync(); + + var tree = await bidi.BrowsingContext.GetTreeAsync(); + + Assert.That(tree.Select(i => i.Context), Does.Not.Contain(tab)); + } + + [Test] + public async Task CanActivate() + { + await context.ActivateAsync(); + + // TODO: Add assertion when https://w3c.github.io/webdriver-bidi/#type-browser-ClientWindowInfo is implemented + } + + [Test] + public async Task CanReload() + { + string url = UrlBuilder.WhereIs("/bidi/logEntryAdded.html"); + + await context.NavigateAsync(url, new() { Wait = ReadinessState.Complete }); + + var info = await context.ReloadAsync(); + + Assert.That(info, Is.Not.Null); + Assert.That(info.Url, Does.Contain("/bidi/logEntryAdded.html")); + } + + [Test] + public async Task CanReloadWithReadinessState() + { + string url = UrlBuilder.WhereIs("/bidi/logEntryAdded.html"); + + await context.NavigateAsync(url, new() { Wait = ReadinessState.Complete }); + + var info = await context.ReloadAsync(new() + { + Wait = ReadinessState.Complete + }); + + Assert.That(info, Is.Not.Null); + Assert.That(info.Url, Does.Contain("/bidi/logEntryAdded.html")); + } + + [Test] + public async Task CanHandleUserPrompt() + { + await context.NavigateAsync(UrlBuilder.WhereIs("alerts.html"), new() { Wait = ReadinessState.Complete }); + + driver.FindElement(By.Id("alert")).Click(); + + await context.HandleUserPromptAsync(); + } + + [Test] + public async Task CanAcceptUserPrompt() + { + await context.NavigateAsync(UrlBuilder.WhereIs("alerts.html"), new() { Wait = ReadinessState.Complete }); + + driver.FindElement(By.Id("alert")).Click(); + + await context.HandleUserPromptAsync(new() + { + Accept = true + }); + } + + [Test] + public async Task CanDismissUserPrompt() + { + await context.NavigateAsync(UrlBuilder.WhereIs("alerts.html"), new() { Wait = ReadinessState.Complete }); + + driver.FindElement(By.Id("alert")).Click(); + + await context.HandleUserPromptAsync(new() + { + Accept = false + }); + } + + [Test] + public async Task CanPassUserTextToPrompt() + { + await context.NavigateAsync(UrlBuilder.WhereIs("alerts.html"), new() { Wait = ReadinessState.Complete }); + + driver.FindElement(By.Id("alert")).Click(); + + await context.HandleUserPromptAsync(new() + { + UserText = "Selenium automates browsers" + }); + } + + [Test] + public async Task CanCaptureScreenshot() + { + var screenshot = await context.CaptureScreenshotAsync(); + + Assert.That(screenshot, Is.Not.Null); + Assert.That(screenshot.Data, Is.Not.Empty); + } + + [Test] + public async Task CanCaptureScreenshotWithParameters() + { + var screenshot = await context.CaptureScreenshotAsync(new() + { + Origin = Origin.Document, + Clip = new ClipRectangle.Box(5, 5, 10, 10) + }); + + Assert.That(screenshot, Is.Not.Null); + Assert.That(screenshot.Data, Is.Not.Empty); + } + + [Test] + public async Task CanCaptureScreenshotOfViewport() + { + var screenshot = await context.CaptureScreenshotAsync(new() + { + Origin = Origin.Viewport, + Clip = new ClipRectangle.Box(5, 5, 10, 10) + }); + + Assert.That(screenshot, Is.Not.Null); + Assert.That(screenshot.Data, Is.Not.Empty); + } + + [Test] + public async Task CanCaptureScreenshotOfElement() + { + await context.NavigateAsync(UrlBuilder.WhereIs("formPage.html"), new() { Wait = ReadinessState.Complete }); + + var nodes = await context.LocateNodesAsync(new Locator.Css("#checky")); + + var screenshot = await context.CaptureScreenshotAsync(new() + { + // TODO: Seems Node implements ISharedReference + Clip = new ClipRectangle.Element(new Modules.Script.SharedReference(nodes[0].SharedId)) + }); + + Assert.That(screenshot, Is.Not.Null); + Assert.That(screenshot.Data, Is.Not.Empty); + } + + [Test] + public async Task CanSetViewport() + { + await context.SetViewportAsync(new() { Viewport = new(250, 300) }); + } + + [Test] + public async Task CanSetViewportWithDevicePixelRatio() + { + await context.SetViewportAsync(new() { Viewport = new(250, 300), DevicePixelRatio = 5 }); + } + + [Test] + public async Task CanPrintPage() + { + var pdf = await context.PrintAsync(); + + Assert.That(pdf, Is.Not.Null); + Assert.That(pdf.Data, Is.Not.Empty); + } +} diff --git a/dotnet/test/common/BiDi/Input/CombinedInputActionsTest.cs b/dotnet/test/common/BiDi/Input/CombinedInputActionsTest.cs new file mode 100644 index 0000000000000..cb832cdeb9e41 --- /dev/null +++ b/dotnet/test/common/BiDi/Input/CombinedInputActionsTest.cs @@ -0,0 +1,55 @@ +using NUnit.Framework; +using OpenQA.Selenium.BiDi.Modules.BrowsingContext; +using OpenQA.Selenium.BiDi.Modules.Input; +using System.Threading.Tasks; + +namespace OpenQA.Selenium.BiDi.Input; + +class CombinedInputActionsTest : BiDiTestFixture +{ + //[Test] + public async Task Paint() + { + driver.Url = "https://kleki.com/"; + + await Task.Delay(3000); + + await context.Input.PerformActionsAsync([new PointerActions { + new Pointer.Move(300, 300), + new Pointer.Down(0), + new Pointer.Move(400, 400) { Duration = 2000, Width = 1, Twist = 1 }, + new Pointer.Up(0), + }]); + + await context.Input.PerformActionsAsync([new KeyActions { + new Key.Down('U'), + new Key.Up('U'), + new Pause { Duration = 3000 } + }]); + + await context.Input.PerformActionsAsync([new PointerActions { + new Pointer.Move(300, 300), + new Pointer.Down(0), + new Pointer.Move(400, 400) { Duration = 2000 }, + new Pointer.Up(0), + }]); + + await Task.Delay(3000); + } + + [Test] + public async Task TestShiftClickingOnMultiSelectionList() + { + driver.Url = UrlBuilder.WhereIs("formSelectionPage.html"); + + var options = await context.LocateNodesAsync(new Locator.Css("option")); + + await context.Input.PerformActionsAsync([ + new PointerActions + { + new Pointer.Down(1), + new Pointer.Up(1), + } + ]); + } +} diff --git a/dotnet/test/common/BiDi/Input/DefaultKeyboardTest.cs b/dotnet/test/common/BiDi/Input/DefaultKeyboardTest.cs new file mode 100644 index 0000000000000..f226719e17c0a --- /dev/null +++ b/dotnet/test/common/BiDi/Input/DefaultKeyboardTest.cs @@ -0,0 +1,88 @@ +//using NUnit.Framework; +//using OpenQA.Selenium.BiDi.Modules.BrowsingContext; +//using OpenQA.Selenium.BiDi.Modules.Input; +//using System.Threading.Tasks; + +//namespace OpenQA.Selenium.BiDi.Input; + +//class DefaultKeyboardTest : BiDiTestFixture +//{ +// [Test] +// public async Task TestBasicKeyboardInput() +// { +// driver.Url = UrlBuilder.WhereIs("single_text_input.html"); + +// var input = (await context.LocateNodesAsync(new Locator.Css("#textInput")))[0]; + +// await context.Input.PerformActionsAsync(new SequentialSourceActions() +// .PointerMove(0, 0, new() { Origin = new Modules.Input.Origin.Element(new Modules.Script.SharedReference(input.SharedId)) }) +// .PointerDown(0) +// .PointerUp(0) +// .Type("abc def")); + +// Assert.That(driver.FindElement(By.Id("textInput")).GetAttribute("value"), Is.EqualTo("abc def")); +// } + +// [Test] +// public async Task TestSendingKeyDownOnly() +// { +// driver.Url = UrlBuilder.WhereIs("key_logger.html"); + +// var input = (await context.LocateNodesAsync(new Locator.Css("#theworks")))[0]; + +// await context.Input.PerformActionsAsync(new SequentialSourceActions() +// .PointerMove(0, 0, new() { Origin = new Modules.Input.Origin.Element(new Modules.Script.SharedReference(input.SharedId)) }) +// .PointerDown(0) +// .PointerUp(0) +// .KeyDown(Key.Shift)); + +// Assert.That(driver.FindElement(By.Id("result")).Text, Does.EndWith("keydown")); +// } + +// [Test] +// public async Task TestSendingKeyUp() +// { +// driver.Url = UrlBuilder.WhereIs("key_logger.html"); + +// var input = (await context.LocateNodesAsync(new Locator.Css("#theworks")))[0]; + +// await context.Input.PerformActionsAsync(new SequentialSourceActions() +// .PointerMove(0, 0, new() { Origin = new Modules.Input.Origin.Element(new Modules.Script.SharedReference(input.SharedId)) }) +// .PointerDown(0) +// .PointerUp(0) +// .KeyDown(Key.Shift) +// .KeyUp(Key.Shift)); + +// Assert.That(driver.FindElement(By.Id("result")).Text, Does.EndWith("keyup")); +// } + +// [Test] +// public async Task TestSendingKeysWithShiftPressed() +// { +// driver.Url = UrlBuilder.WhereIs("key_logger.html"); + +// var input = (await context.LocateNodesAsync(new Locator.Css("#theworks")))[0]; + +// await context.Input.PerformActionsAsync(new SequentialSourceActions() +// .PointerMove(0, 0, new() { Origin = new Modules.Input.Origin.Element(new Modules.Script.SharedReference(input.SharedId)) }) +// .PointerDown(0) +// .PointerUp(0) +// .KeyDown(Key.Shift) +// .Type("ab") +// .KeyUp(Key.Shift)); + +// Assert.That(driver.FindElement(By.Id("result")).Text, Does.EndWith("keydown keydown keypress keyup keydown keypress keyup keyup")); +// Assert.That(driver.FindElement(By.Id("theworks")).GetAttribute("value"), Is.EqualTo("AB")); +// } + +// [Test] +// public async Task TestSendingKeysToActiveElement() +// { +// driver.Url = UrlBuilder.WhereIs("bodyTypingTest.html"); + +// await context.Input.PerformActionsAsync(new SequentialSourceActions().Type("ab")); + +// Assert.That(driver.FindElement(By.Id("body_result")).Text, Does.EndWith("keypress keypress")); +// Assert.That(driver.FindElement(By.Id("result")).Text, Is.EqualTo(" ")); +// } +//} diff --git a/dotnet/test/common/BiDi/Input/DefaultMouseTest.cs b/dotnet/test/common/BiDi/Input/DefaultMouseTest.cs new file mode 100644 index 0000000000000..c7408a83101f1 --- /dev/null +++ b/dotnet/test/common/BiDi/Input/DefaultMouseTest.cs @@ -0,0 +1,49 @@ +//using NUnit.Framework; +//using OpenQA.Selenium.BiDi.Modules.BrowsingContext; +//using OpenQA.Selenium.BiDi.Modules.Input; +//using System.Threading.Tasks; + +//namespace OpenQA.Selenium.BiDi.Input; + +//class DefaultMouseTest : BiDiTestFixture +//{ +// [Test] +// public async Task PerformDragAndDropWithMouse() +// { +// driver.Url = UrlBuilder.WhereIs("draggableLists.html"); + +// await context.Input.PerformActionsAsync([ +// new KeyActions +// { +// Actions = +// { +// new Key.Down('A'), +// new Key.Up('B') +// } +// } +// ]); + +// await context.Input.PerformActionsAsync([new KeyActions +// { +// new Key.Down('A'), +// new Key.Down('B'), +// new Pause() +// }]); + +// await context.Input.PerformActionsAsync([new PointerActions +// { +// new Pointer.Down(0), +// new Pointer.Up(0), +// }]); +// } + +// //[Test] +// public async Task PerformCombined() +// { +// await context.NavigateAsync("https://nuget.org", new() { Wait = ReadinessState.Complete }); + +// await context.Input.PerformActionsAsync(new SequentialSourceActions().Type("Hello").Pause(2000).KeyDown(Key.Shift).Type("World")); + +// await Task.Delay(3000); +// } +//} diff --git a/dotnet/test/common/BiDi/Log/LogTest.cs b/dotnet/test/common/BiDi/Log/LogTest.cs new file mode 100644 index 0000000000000..f67621bfc3b43 --- /dev/null +++ b/dotnet/test/common/BiDi/Log/LogTest.cs @@ -0,0 +1,75 @@ +using NUnit.Framework; +using OpenQA.Selenium.BiDi.Modules.Log; +using System; +using System.Threading.Tasks; + +namespace OpenQA.Selenium.BiDi.Log; + +class LogTest : BiDiTestFixture +{ + [Test] + public async Task CanListenToConsoleLog() + { + TaskCompletionSource tcs = new(); + + await using var subscription = await context.Log.OnEntryAddedAsync(tcs.SetResult); + + driver.Url = UrlBuilder.WhereIs("bidi/logEntryAdded.html"); + driver.FindElement(By.Id("consoleLog")).Click(); + + var logEntry = await tcs.Task.WaitAsync(TimeSpan.FromSeconds(5)); + + Assert.That(logEntry, Is.Not.Null); + Assert.That(logEntry.Source, Is.Not.Null); + Assert.That(logEntry.Source.Context, Is.EqualTo(context)); + Assert.That(logEntry.Source.Realm, Is.Not.Null); + Assert.That(logEntry.Text, Is.EqualTo("Hello, world!")); + Assert.That(logEntry.Level, Is.EqualTo(Level.Info)); + Assert.That(logEntry, Is.AssignableFrom()); + + var consoleLogEntry = logEntry as Entry.Console; + + Assert.That(consoleLogEntry.Method, Is.EqualTo("log")); + + Assert.That(consoleLogEntry.Args, Is.Not.Null); + Assert.That(consoleLogEntry.Args, Has.Count.EqualTo(1)); + Assert.That(consoleLogEntry.Args[0], Is.AssignableFrom()); + } + + [Test] + public async Task CanListenToJavascriptLog() + { + TaskCompletionSource tcs = new(); + + await using var subscription = await context.Log.OnEntryAddedAsync(tcs.SetResult); + + driver.Url = UrlBuilder.WhereIs("bidi/logEntryAdded.html"); + driver.FindElement(By.Id("jsException")).Click(); + + var logEntry = await tcs.Task.WaitAsync(TimeSpan.FromSeconds(5)); + + Assert.That(logEntry, Is.Not.Null); + Assert.That(logEntry.Source, Is.Not.Null); + Assert.That(logEntry.Source.Context, Is.EqualTo(context)); + Assert.That(logEntry.Source.Realm, Is.Not.Null); + Assert.That(logEntry.Text, Is.EqualTo("Error: Not working")); + Assert.That(logEntry.Level, Is.EqualTo(Level.Error)); + Assert.That(logEntry, Is.AssignableFrom()); + } + + [Test] + public async Task CanRetrieveStacktrace() + { + TaskCompletionSource tcs = new(); + + await using var subscription = await bidi.Log.OnEntryAddedAsync(tcs.SetResult); + + driver.Url = UrlBuilder.WhereIs("bidi/logEntryAdded.html"); + driver.FindElement(By.Id("logWithStacktrace")).Click(); + + var logEntry = await tcs.Task.WaitAsync(TimeSpan.FromSeconds(5)); + + Assert.That(logEntry, Is.Not.Null); + Assert.That(logEntry.StackTrace, Is.Not.Null); + } +} diff --git a/dotnet/test/common/BiDi/Network/NetworkEventsTest.cs b/dotnet/test/common/BiDi/Network/NetworkEventsTest.cs new file mode 100644 index 0000000000000..230351ba436df --- /dev/null +++ b/dotnet/test/common/BiDi/Network/NetworkEventsTest.cs @@ -0,0 +1,132 @@ +using NUnit.Framework; +using OpenQA.Selenium.BiDi.Modules.BrowsingContext; +using OpenQA.Selenium.BiDi.Modules.Network; +using System; +using System.Threading.Tasks; + +namespace OpenQA.Selenium.BiDi.Network; + +class NetworkEventsTest : BiDiTestFixture +{ + [Test] + public async Task CanListenToBeforeRequestSentEvent() + { + TaskCompletionSource tcs = new(); + + await using var subscription = await context.Network.OnBeforeRequestSentAsync(tcs.SetResult); + + await context.NavigateAsync(UrlBuilder.WhereIs("bidi/logEntryAdded.html"), new() { Wait = ReadinessState.Complete }); + + var req = await tcs.Task.WaitAsync(TimeSpan.FromSeconds(5)); + + Assert.That(req.Context, Is.EqualTo(context)); + Assert.That(req.Request, Is.Not.Null); + Assert.That(req.Request.Method, Is.EqualTo("GET")); + Assert.That(req.Request.Url, Does.Contain("bidi/logEntryAdded.html")); + Assert.That(req.Initiator.Type, Is.EqualTo(InitiatorType.Other)); + } + + [Test] + public async Task CanListenToResponseStartedEvent() + { + TaskCompletionSource tcs = new(); + + await using var subscription = await context.Network.OnResponseStartedAsync(tcs.SetResult); + + await context.NavigateAsync(UrlBuilder.WhereIs("bidi/logEntryAdded.html"), new() { Wait = ReadinessState.Complete }); + + var res = await tcs.Task.WaitAsync(TimeSpan.FromSeconds(5)); + + Assert.That(res.Context, Is.EqualTo(context)); + Assert.That(res.Request, Is.Not.Null); + Assert.That(res.Request.Method, Is.EqualTo("GET")); + Assert.That(res.Request.Url, Does.Contain("bidi/logEntryAdded.html")); + Assert.That(res.Response.Headers, Is.Not.Empty); + Assert.That(res.Response.Status, Is.EqualTo(200)); + } + + [Test] + public async Task CanListenToResponseCompletedEvent() + { + TaskCompletionSource tcs = new(); + + await using var subscription = await context.Network.OnResponseCompletedAsync(tcs.SetResult); + + await context.NavigateAsync(UrlBuilder.WhereIs("bidi/logEntryAdded.html"), new() { Wait = ReadinessState.Complete }); + + var res = await tcs.Task.WaitAsync(TimeSpan.FromSeconds(5)); + + Assert.That(res.Context, Is.EqualTo(context)); + Assert.That(res.Request, Is.Not.Null); + Assert.That(res.Request.Method, Is.EqualTo("GET")); + Assert.That(res.Request.Url, Does.Contain("bidi/logEntryAdded.html")); + Assert.That(res.Response.Url, Does.Contain("bidi/logEntryAdded.html")); + Assert.That(res.Response.Headers, Is.Not.Empty); + Assert.That(res.Response.Status, Is.EqualTo(200)); + } + + [Test] + public async Task CanListenToBeforeRequestSentEventWithCookie() + { + TaskCompletionSource tcs = new(); + + await context.NavigateAsync(UrlBuilder.WhereIs("bidi/logEntryAdded.html"), new() { Wait = ReadinessState.Complete }); + + driver.Manage().Cookies.AddCookie(new("foo", "bar")); + + await using var subscription = await bidi.Network.OnBeforeRequestSentAsync(tcs.SetResult); + + await context.ReloadAsync(); + + var req = await tcs.Task.WaitAsync(TimeSpan.FromSeconds(5)); + + Assert.That(req.Request.Cookies.Count, Is.EqualTo(1)); + Assert.That(req.Request.Cookies[0].Name, Is.EqualTo("foo")); + Assert.That((req.Request.Cookies[0].Value as BytesValue.String).Value, Is.EqualTo("bar")); + } + + [Test] + [IgnoreBrowser(Selenium.Browser.Chrome)] + [IgnoreBrowser(Selenium.Browser.Edge)] + public async Task CanListenToOnAuthRequiredEvent() + { + TaskCompletionSource tcs = new(); + + await using var subscription = await context.Network.OnAuthRequiredAsync(tcs.SetResult); + + driver.Url = UrlBuilder.WhereIs("basicAuth"); + + var res = await tcs.Task.WaitAsync(TimeSpan.FromSeconds(5)); + + Assert.That(res.Context, Is.EqualTo(context)); + Assert.That(res.Request, Is.Not.Null); + Assert.That(res.Request.Method, Is.EqualTo("GET")); + Assert.That(res.Request.Url, Does.Contain("basicAuth")); + Assert.That(res.Response.Headers, Is.Not.Null.And.Count.GreaterThanOrEqualTo(1)); + Assert.That(res.Response.Status, Is.EqualTo(401)); + } + + [Test] + public async Task CanListenToFetchError() + { + TaskCompletionSource tcs = new(); + + await using var subscription = await context.Network.OnFetchErrorAsync(tcs.SetResult); + + try + { + await context.NavigateAsync("https://not_a_valid_url.test", new() { Wait = ReadinessState.Complete }); + } + catch (Exception) { } + + var res = await tcs.Task.WaitAsync(TimeSpan.FromSeconds(5)); + + Assert.That(res.Context, Is.EqualTo(context)); + Assert.That(res.Request, Is.Not.Null); + Assert.That(res.Request.Method, Is.EqualTo("GET")); + Assert.That(res.Request.Url, Does.Contain("https://not_a_valid_url.test")); + Assert.That(res.Request.Headers.Count, Is.GreaterThanOrEqualTo(1)); + Assert.That(res.Navigation, Is.Not.Null); + Assert.That(res.ErrorText, Does.Contain("net::ERR_NAME_NOT_RESOLVED").Or.Contain("NS_ERROR_UNKNOWN_HOST")); + } +} diff --git a/dotnet/test/common/BiDi/Network/NetworkTest.cs b/dotnet/test/common/BiDi/Network/NetworkTest.cs new file mode 100644 index 0000000000000..b743378c385ea --- /dev/null +++ b/dotnet/test/common/BiDi/Network/NetworkTest.cs @@ -0,0 +1,195 @@ +using NUnit.Framework; +using OpenQA.Selenium.BiDi.Modules.BrowsingContext; +using OpenQA.Selenium.BiDi.Modules.Network; +using System.Threading.Tasks; + +namespace OpenQA.Selenium.BiDi.Network; + +class NetworkTest : BiDiTestFixture +{ + [Test] + public async Task CanAddIntercept() + { + await using var intercept = await bidi.Network.InterceptRequestAsync(e => Task.CompletedTask); + + Assert.That(intercept, Is.Not.Null); + } + + [Test] + public async Task CanAddInterceptStringUrlPattern() + { + await using var intercept = await bidi.Network.InterceptRequestAsync(e => Task.CompletedTask, new() + { + UrlPatterns = [ + new UrlPattern.String("http://localhost:4444"), + "http://localhost:4444/" + ] + }); + + Assert.That(intercept, Is.Not.Null); + } + + [Test] + public async Task CanAddInterceptUrlPattern() + { + await using var intercept = await bidi.Network.InterceptRequestAsync(e => Task.CompletedTask, interceptOptions: new() + { + UrlPatterns = [new UrlPattern.Pattern() + { + Hostname = "localhost", + Protocol = "http" + }] + }); + + Assert.That(intercept, Is.Not.Null); + } + + [Test] + public async Task CanContinueRequest() + { + int times = 0; + await using var intercept = await bidi.Network.InterceptRequestAsync(async e => + { + times++; + + await e.Request.Request.ContinueAsync(); + }); + + await context.NavigateAsync(UrlBuilder.WhereIs("bidi/logEntryAdded.html"), new() { Wait = ReadinessState.Complete }); + + Assert.That(intercept, Is.Not.Null); + Assert.That(times, Is.GreaterThan(0)); + } + + [Test] + public async Task CanContinueResponse() + { + int times = 0; + + await using var intercept = await bidi.Network.InterceptResponseAsync(async e => + { + times++; + + await e.Request.Request.ContinueResponseAsync(); + }); + + await context.NavigateAsync(UrlBuilder.WhereIs("bidi/logEntryAdded.html"), new() { Wait = ReadinessState.Complete }); + + Assert.That(intercept, Is.Not.Null); + Assert.That(times, Is.GreaterThan(0)); + } + + [Test] + public async Task CanProvideResponse() + { + int times = 0; + + await using var intercept = await bidi.Network.InterceptRequestAsync(async e => + { + times++; + + await e.Request.Request.ProvideResponseAsync(); + }); + + await context.NavigateAsync(UrlBuilder.WhereIs("bidi/logEntryAdded.html"), new() { Wait = ReadinessState.Complete }); + + Assert.That(intercept, Is.Not.Null); + Assert.That(times, Is.GreaterThan(0)); + } + + [Test] + public async Task CanProvideResponseWithParameters() + { + int times = 0; + + await using var intercept = await bidi.Network.InterceptRequestAsync(async e => + { + times++; + + await e.Request.Request.ProvideResponseAsync(new() { Body = """ + + + Hello + + + + + """ }); + }); + + await context.NavigateAsync(UrlBuilder.WhereIs("bidi/logEntryAdded.html"), new() { Wait = ReadinessState.Complete }); + + Assert.That(intercept, Is.Not.Null); + Assert.That(times, Is.GreaterThan(0)); + Assert.That(driver.Title, Is.EqualTo("Hello")); + } + + [Test] + public async Task CanRemoveIntercept() + { + var intercept = await bidi.Network.InterceptRequestAsync(_ => Task.CompletedTask); + + await intercept.RemoveAsync(); + + // or + + intercept = await context.Network.InterceptRequestAsync(_ => Task.CompletedTask); + + await intercept.DisposeAsync(); + } + + [Test] + public async Task CanContinueWithAuthCredentials() + { + await using var intercept = await bidi.Network.InterceptAuthAsync(async e => + { + //TODO Seems it would be better to have method which takes abstract options + await e.Request.Request.ContinueWithAuthAsync(new AuthCredentials.Basic("test", "test")); + }); + + await context.NavigateAsync(UrlBuilder.WhereIs("basicAuth"), new() { Wait = ReadinessState.Complete }); + + Assert.That(driver.FindElement(By.CssSelector("h1")).Text, Is.EqualTo("authorized")); + } + + [Test] + [IgnoreBrowser(Selenium.Browser.Firefox)] + public async Task CanContinueWithDefaultCredentials() + { + await using var intercept = await bidi.Network.InterceptAuthAsync(async e => + { + await e.Request.Request.ContinueWithAuthAsync(new ContinueWithDefaultAuthOptions()); + }); + + var action = async () => await context.NavigateAsync(UrlBuilder.WhereIs("basicAuth"), new() { Wait = ReadinessState.Complete }); + + Assert.That(action, Throws.TypeOf().With.Message.Contain("net::ERR_INVALID_AUTH_CREDENTIALS")); + } + + [Test] + [IgnoreBrowser(Selenium.Browser.Firefox)] + public async Task CanContinueWithCanceledCredentials() + { + await using var intercept = await bidi.Network.InterceptAuthAsync(async e => + { + await e.Request.Request.ContinueWithAuthAsync(new ContinueWithCancelledAuthOptions()); + }); + + var action = async () => await context.NavigateAsync(UrlBuilder.WhereIs("basicAuth"), new() { Wait = ReadinessState.Complete }); + + Assert.That(action, Throws.TypeOf().With.Message.Contain("net::ERR_HTTP_RESPONSE_CODE_FAILURE")); + } + + [Test] + public async Task CanFailRequest() + { + await using var intercept = await bidi.Network.InterceptRequestAsync(async e => + { + await e.Request.Request.FailAsync(); + }); + + var action = async () => await context.NavigateAsync(UrlBuilder.WhereIs("basicAuth"), new() { Wait = ReadinessState.Complete }); + + Assert.That(action, Throws.TypeOf().With.Message.Contain("net::ERR_FAILED").Or.Message.Contain("NS_ERROR_ABORT")); + } +} diff --git a/dotnet/test/common/BiDi/Script/CallFunctionParameterTest.cs b/dotnet/test/common/BiDi/Script/CallFunctionParameterTest.cs new file mode 100644 index 0000000000000..3fc11764fca2e --- /dev/null +++ b/dotnet/test/common/BiDi/Script/CallFunctionParameterTest.cs @@ -0,0 +1,203 @@ +using NUnit.Framework; +using OpenQA.Selenium.BiDi.Modules.Script; +using System.Threading.Tasks; + +namespace OpenQA.Selenium.BiDi.Script; + +class CallFunctionParameterTest : BiDiTestFixture +{ + [Test] + public async Task CanCallFunctionWithDeclaration() + { + var res = await context.Script.CallFunctionAsync("() => { return 1 + 2; }", false); + + Assert.That(res, Is.Not.Null); + Assert.That(res.Realm, Is.Not.Null); + Assert.That((res.Result as RemoteValue.Number).Value, Is.EqualTo(3)); + } + + [Test] + public async Task CanCallFunctionWithDeclarationImplicitCast() + { + var res = await context.Script.CallFunctionAsync("() => { return 1 + 2; }", false); + + Assert.That(res, Is.EqualTo(3)); + } + + [Test] + public async Task CanEvaluateScriptWithUserActivationTrue() + { + await context.Script.EvaluateAsync("window.open();", true, new() { UserActivation = true }); + + var res = await context.Script.CallFunctionAsync(""" + () => navigator.userActivation.isActive && navigator.userActivation.hasBeenActive + """, true, new() { UserActivation = true }); + + Assert.That(res, Is.True); + } + + [Test] + public async Task CanEvaluateScriptWithUserActivationFalse() + { + await context.Script.EvaluateAsync("window.open();", true); + + var res = await context.Script.CallFunctionAsync(""" + () => navigator.userActivation.isActive && navigator.userActivation.hasBeenActive + """, true); + + Assert.That(res, Is.False); + } + + [Test] + public async Task CanCallFunctionWithArguments() + { + var res = await context.Script.CallFunctionAsync("(...args)=>{return args}", false, new() + { + Arguments = ["abc", 42] + }); + + Assert.That(res.Result, Is.AssignableFrom()); + Assert.That((string)(res.Result as RemoteValue.Array).Value[0], Is.EqualTo("abc")); + Assert.That((int)(res.Result as RemoteValue.Array).Value[1], Is.EqualTo(42)); + } + + [Test] + public async Task CanCallFunctionToGetIFrameBrowsingContext() + { + driver.Url = UrlBuilder.WhereIs("click_too_big_in_frame.html"); + + var res = await context.Script.CallFunctionAsync(""" + () => document.querySelector('iframe[id="iframe1"]').contentWindow + """, false); + + Assert.That(res, Is.Not.Null); + Assert.That(res.Result, Is.AssignableFrom()); + Assert.That((res.Result as RemoteValue.WindowProxy).Value, Is.Not.Null); + } + + [Test] + public async Task CanCallFunctionToGetElement() + { + driver.Url = UrlBuilder.WhereIs("bidi/logEntryAdded.html"); + + var res = await context.Script.CallFunctionAsync(""" + () => document.getElementById("consoleLog") + """, false); + + Assert.That(res, Is.Not.Null); + Assert.That(res.Result, Is.AssignableFrom()); + Assert.That((res.Result as RemoteValue.Node).Value, Is.Not.Null); + } + + [Test] + public async Task CanCallFunctionWithAwaitPromise() + { + var res = await context.Script.CallFunctionAsync(""" + async function() { + await new Promise(r => setTimeout(() => r(), 0)); + return "SOME_DELAYED_RESULT"; + } + """, awaitPromise: true); + + Assert.That(res, Is.EqualTo("SOME_DELAYED_RESULT")); + } + + [Test] + public async Task CanCallFunctionWithAwaitPromiseFalse() + { + var res = await context.Script.CallFunctionAsync(""" + async function() { + await new Promise(r => setTimeout(() => r(), 0)); + return "SOME_DELAYED_RESULT"; + } + """, awaitPromise: false); + + Assert.That(res, Is.Not.Null); + Assert.That(res.Result, Is.AssignableFrom()); + } + + [Test] + public async Task CanCallFunctionWithThisParameter() + { + var thisParameter = new LocalValue.Object([["some_property", 42]]); + + var res = await context.Script.CallFunctionAsync(""" + function(){return this.some_property} + """, false, new() { This = thisParameter }); + + Assert.That(res, Is.EqualTo(42)); + } + + [Test] + public async Task CanCallFunctionWithOwnershipRoot() + { + var res = await context.Script.CallFunctionAsync("async function(){return {a:1}}", true, new() + { + ResultOwnership = ResultOwnership.Root + }); + + Assert.That(res, Is.Not.Null); + Assert.That((res.Result as RemoteValue.Object).Handle, Is.Not.Null); + Assert.That((string)(res.Result as RemoteValue.Object).Value[0][0], Is.EqualTo("a")); + Assert.That((int)(res.Result as RemoteValue.Object).Value[0][1], Is.EqualTo(1)); + } + + [Test] + public async Task CanCallFunctionWithOwnershipNone() + { + var res = await context.Script.CallFunctionAsync("async function(){return {a:1}}", true, new() + { + ResultOwnership = ResultOwnership.None + }); + + Assert.That(res, Is.Not.Null); + Assert.That((res.Result as RemoteValue.Object).Handle, Is.Null); + Assert.That((string)(res.Result as RemoteValue.Object).Value[0][0], Is.EqualTo("a")); + Assert.That((int)(res.Result as RemoteValue.Object).Value[0][1], Is.EqualTo(1)); + } + + [Test] + public void CanCallFunctionThatThrowsException() + { + var action = () => context.Script.CallFunctionAsync("))) !!@@## some invalid JS script (((", false); + + Assert.That(action, Throws.InstanceOf().And.Message.Contain("SyntaxError:")); + } + + [Test] + public async Task CanCallFunctionInASandBox() + { + // Make changes without sandbox + await context.Script.CallFunctionAsync("() => { window.foo = 1; }", true); + + var res = await context.Script.CallFunctionAsync("() => window.foo", true, targetOptions: new() { Sandbox = "sandbox" }); + + Assert.That(res.Result, Is.AssignableFrom()); + + // Make changes in the sandbox + await context.Script.CallFunctionAsync("() => { window.foo = 2; }", true, targetOptions: new() { Sandbox = "sandbox" }); + + // Check if the changes are present in the sandbox + res = await context.Script.CallFunctionAsync("() => window.foo", true, targetOptions: new() { Sandbox = "sandbox" }); + + Assert.That(res.Result, Is.AssignableFrom()); + Assert.That((res.Result as RemoteValue.Number).Value, Is.EqualTo(2)); + } + + [Test] + public async Task CanCallFunctionInARealm() + { + await bidi.BrowsingContext.CreateAsync(Modules.BrowsingContext.ContextType.Tab); + + var realms = await bidi.Script.GetRealmsAsync(); + + await bidi.Script.CallFunctionAsync("() => { window.foo = 3; }", true, new Target.Realm(realms[0].Realm)); + await bidi.Script.CallFunctionAsync("() => { window.foo = 5; }", true, new Target.Realm(realms[1].Realm)); + + var res1 = await bidi.Script.CallFunctionAsync("() => window.foo", true, new Target.Realm(realms[0].Realm)); + var res2 = await bidi.Script.CallFunctionAsync("() => window.foo", true, new Target.Realm(realms[1].Realm)); + + Assert.That(res1, Is.EqualTo(3)); + Assert.That(res2, Is.EqualTo(5)); + } +} diff --git a/dotnet/test/common/BiDi/Script/EvaluateParametersTest.cs b/dotnet/test/common/BiDi/Script/EvaluateParametersTest.cs new file mode 100644 index 0000000000000..bb526ff9a4d89 --- /dev/null +++ b/dotnet/test/common/BiDi/Script/EvaluateParametersTest.cs @@ -0,0 +1,109 @@ +using NUnit.Framework; +using OpenQA.Selenium.BiDi.Modules.Script; +using System.Threading.Tasks; + +namespace OpenQA.Selenium.BiDi.Script; + +class EvaluateParametersTest : BiDiTestFixture +{ + [Test] + public async Task CanEvaluateScript() + { + var res = await context.Script.EvaluateAsync("1 + 2", false); + + Assert.That(res, Is.Not.Null); + Assert.That(res.Realm, Is.Not.Null); + Assert.That((res.Result as RemoteValue.Number).Value, Is.EqualTo(3)); + } + + [Test] + public async Task CanEvaluateScriptImplicitCast() + { + var res = await context.Script.EvaluateAsync("1 + 2", false); + + Assert.That(res, Is.EqualTo(3)); + } + + [Test] + public async Task СanEvaluateScriptWithUserActivationTrue() + { + await context.Script.EvaluateAsync("window.open();", true, new() { UserActivation = true }); + + var res = await context.Script.EvaluateAsync(""" + navigator.userActivation.isActive && navigator.userActivation.hasBeenActive + """, true, new() { UserActivation = true }); + + Assert.That(res, Is.True); + } + + [Test] + public async Task СanEvaluateScriptWithUserActivationFalse() + { + await context.Script.EvaluateAsync("window.open();", true, new() { UserActivation = true }); + + var res = await context.Script.EvaluateAsync(""" + navigator.userActivation.isActive && navigator.userActivation.hasBeenActive + """, true, new() { UserActivation = false }); + + Assert.That(res, Is.False); + } + + [Test] + public void CanCallFunctionThatThrowsException() + { + var action = () => context.Script.EvaluateAsync("))) !!@@## some invalid JS script (((", false); + + Assert.That(action, Throws.InstanceOf().And.Message.Contain("SyntaxError:")); + } + + [Test] + public async Task CanEvaluateScriptWithResulWithOwnership() + { + var res = await context.Script.EvaluateAsync("Promise.resolve({a:1})", true, new() + { + ResultOwnership = ResultOwnership.Root + }); + + Assert.That(res, Is.Not.Null); + Assert.That((res.Result as RemoteValue.Object).Handle, Is.Not.Null); + Assert.That((string)(res.Result as RemoteValue.Object).Value[0][0], Is.EqualTo("a")); + Assert.That((int)(res.Result as RemoteValue.Object).Value[0][1], Is.EqualTo(1)); + } + + [Test] + public async Task CanEvaluateInASandBox() + { + // Make changes without sandbox + await context.Script.EvaluateAsync("window.foo = 1", true); + + var res = await context.Script.EvaluateAsync("window.foo", true, targetOptions: new() { Sandbox = "sandbox" }); + + Assert.That(res.Result, Is.AssignableFrom()); + + // Make changes in the sandbox + await context.Script.EvaluateAsync("window.foo = 2", true, targetOptions: new() { Sandbox = "sandbox" }); + + // Check if the changes are present in the sandbox + res = await context.Script.EvaluateAsync("window.foo", true, targetOptions: new() { Sandbox = "sandbox" }); + + Assert.That(res.Result, Is.AssignableFrom()); + Assert.That((res.Result as RemoteValue.Number).Value, Is.EqualTo(2)); + } + + [Test] + public async Task CanEvaluateInARealm() + { + await bidi.BrowsingContext.CreateAsync(Modules.BrowsingContext.ContextType.Tab); + + var realms = await bidi.Script.GetRealmsAsync(); + + await bidi.Script.EvaluateAsync("window.foo = 3", true, new Target.Realm(realms[0].Realm)); + await bidi.Script.EvaluateAsync("window.foo = 5", true, new Target.Realm(realms[1].Realm)); + + var res1 = await bidi.Script.EvaluateAsync("window.foo", true, new Target.Realm(realms[0].Realm)); + var res2 = await bidi.Script.EvaluateAsync("window.foo", true, new Target.Realm(realms[1].Realm)); + + Assert.That(res1, Is.EqualTo(3)); + Assert.That(res2, Is.EqualTo(5)); + } +} diff --git a/dotnet/test/common/BiDi/Script/ScriptCommandsTest.cs b/dotnet/test/common/BiDi/Script/ScriptCommandsTest.cs new file mode 100644 index 0000000000000..c013fbbbed2d4 --- /dev/null +++ b/dotnet/test/common/BiDi/Script/ScriptCommandsTest.cs @@ -0,0 +1,150 @@ +using NUnit.Framework; +using OpenQA.Selenium.BiDi.Modules.Script; +using System; +using System.Threading.Tasks; + +namespace OpenQA.Selenium.BiDi.Script; + +class ScriptCommandsTest : BiDiTestFixture +{ + [Test] + public async Task CanGetAllRealms() + { + _ = await bidi.BrowsingContext.CreateAsync(Modules.BrowsingContext.ContextType.Window); + + var realms = await bidi.Script.GetRealmsAsync(); + + Assert.That(realms, Is.Not.Null); + Assert.That(realms.Count, Is.EqualTo(2)); + + Assert.That(realms[0], Is.AssignableFrom()); + Assert.That(realms[0].Realm, Is.Not.Null); + + Assert.That(realms[1], Is.AssignableFrom()); + Assert.That(realms[1].Realm, Is.Not.Null); + } + + [Test] + public async Task CanGetAllRealmsByType() + { + _ = await bidi.BrowsingContext.CreateAsync(Modules.BrowsingContext.ContextType.Window); + + var realms = await bidi.Script.GetRealmsAsync(new() { Type = RealmType.Window }); + + Assert.That(realms, Is.Not.Null); + Assert.That(realms.Count, Is.EqualTo(2)); + + Assert.That(realms[0], Is.AssignableFrom()); + Assert.That(realms[0].Realm, Is.Not.Null); + + Assert.That(realms[1], Is.AssignableFrom()); + Assert.That(realms[1].Realm, Is.Not.Null); + } + + [Test] + public async Task CanGetRealmInBrowsingContext() + { + var tab = await bidi.BrowsingContext.CreateAsync(Modules.BrowsingContext.ContextType.Tab); + + var realms = await tab.Script.GetRealmsAsync(); + + var tabRealm = realms[0] as RealmInfo.Window; + + Assert.That(tabRealm, Is.Not.Null); + Assert.That(tabRealm.Context, Is.EqualTo(tab)); + } + + [Test] + public async Task CanGetRealmInBrowsingContextByType() + { + var tab = await bidi.BrowsingContext.CreateAsync(Modules.BrowsingContext.ContextType.Tab); + + var realms = await tab.Script.GetRealmsAsync(new() { Type = RealmType.Window }); + + var tabRealm = realms[0] as RealmInfo.Window; + + Assert.That(tabRealm, Is.Not.Null); + Assert.That(tabRealm.Context, Is.EqualTo(tab)); + } + + [Test] + public async Task CanAddPreloadScript() + { + var preloadScript = await bidi.Script.AddPreloadScriptAsync("() => { console.log('preload_script_console_text') }"); + + Assert.That(preloadScript, Is.Not.Null); + + TaskCompletionSource tcs = new(); + + await context.Log.OnEntryAddedAsync(tcs.SetResult); + + await context.ReloadAsync(new() { Wait = Modules.BrowsingContext.ReadinessState.Interactive }); + + var entry = await tcs.Task.WaitAsync(TimeSpan.FromSeconds(5)); + + Assert.That(entry.Level, Is.EqualTo(Modules.Log.Level.Info)); + Assert.That(entry.Text, Is.EqualTo("preload_script_console_text")); + } + + [Test] + public async Task CanAddPreloadScriptWithArguments() + { + var preloadScript = await bidi.Script.AddPreloadScriptAsync("(channel) => channel('will_be_send', 'will_be_ignored')", new() + { + Arguments = [new LocalValue.Channel(new(new("channel_name")))] + }); + + Assert.That(preloadScript, Is.Not.Null); + } + + + [Test] + public async Task CanAddPreloadScriptWithChannelOptions() + { + var preloadScript = await bidi.Script.AddPreloadScriptAsync("(channel) => channel('will_be_send', 'will_be_ignored')", new() + { + Arguments = [new LocalValue.Channel(new(new("channel_name")) + { + SerializationOptions = new() + { + MaxDomDepth = 0 + }, + Ownership = ResultOwnership.Root + })] + }); + + Assert.That(preloadScript, Is.Not.Null); + } + + [Test] + public async Task CanAddPreloadScriptInASandbox() + { + var preloadScript = await bidi.Script.AddPreloadScriptAsync("() => { window.bar = 2; }", new() { Sandbox = "sandbox" }); + + Assert.That(preloadScript, Is.Not.Null); + + await context.ReloadAsync(new() { Wait = Modules.BrowsingContext.ReadinessState.Interactive }); + + var bar = await context.Script.EvaluateAsync("window.bar", true, targetOptions: new() { Sandbox = "sandbox" }); + + Assert.That(bar, Is.EqualTo(2)); + } + + [Test] + public async Task CanRemovePreloadedScript() + { + var preloadScript = await context.Script.AddPreloadScriptAsync("() => { window.bar = 2; }"); + + await context.ReloadAsync(new() { Wait = Modules.BrowsingContext.ReadinessState.Interactive }); + + var bar = await context.Script.EvaluateAsync("window.bar", true); + + Assert.That(bar, Is.EqualTo(2)); + + await preloadScript.RemoveAsync(); + + var resultAfterRemoval = await context.Script.EvaluateAsync("window.bar", true, targetOptions: new() { Sandbox = "sandbox" }); + + Assert.That(resultAfterRemoval.Result, Is.AssignableFrom()); + } +} diff --git a/dotnet/test/common/BiDi/Script/ScriptEventsTest.cs b/dotnet/test/common/BiDi/Script/ScriptEventsTest.cs new file mode 100644 index 0000000000000..48fc3b5686371 --- /dev/null +++ b/dotnet/test/common/BiDi/Script/ScriptEventsTest.cs @@ -0,0 +1,63 @@ +using NUnit.Framework; +using OpenQA.Selenium.BiDi.Modules.Script; +using System; +using System.Threading.Tasks; + +namespace OpenQA.Selenium.BiDi.Script; + +class ScriptEventsTest : BiDiTestFixture +{ + [Test] + public async Task CanListenToChannelMessage() + { + TaskCompletionSource tcs = new(); + + await bidi.Script.OnMessageAsync(tcs.SetResult); + + await context.Script.CallFunctionAsync("(channel) => channel('foo')", false, new() + { + Arguments = [new LocalValue.Channel(new(new("channel_name")))] + }); + + var message = await tcs.Task.WaitAsync(TimeSpan.FromSeconds(5)); + + Assert.That(message, Is.Not.Null); + Assert.That(message.Channel.Id, Is.EqualTo("channel_name")); + Assert.That((string)message.Data, Is.EqualTo("foo")); + Assert.That(message.Source, Is.Not.Null); + Assert.That(message.Source.Realm, Is.Not.Null); + Assert.That(message.Source.Context, Is.EqualTo(context)); + } + + [Test] + public async Task CanListenToRealmCreatedEvent() + { + TaskCompletionSource tcs = new(); + + await bidi.Script.OnRealmCreatedAsync(tcs.SetResult); + + await bidi.BrowsingContext.CreateAsync(Modules.BrowsingContext.ContextType.Window); + + var realmInfo = await tcs.Task.WaitAsync(TimeSpan.FromSeconds(5)); + + Assert.That(realmInfo, Is.Not.Null); + Assert.That(realmInfo, Is.AssignableFrom()); + Assert.That(realmInfo.Realm, Is.Not.Null); + } + + [Test] + public async Task CanListenToRealmDestroyedEvent() + { + TaskCompletionSource tcs = new(); + + await bidi.Script.OnRealmDestroyedAsync(tcs.SetResult); + + var ctx = await bidi.BrowsingContext.CreateAsync(Modules.BrowsingContext.ContextType.Window); + await ctx.CloseAsync(); + + var args = await tcs.Task.WaitAsync(TimeSpan.FromSeconds(5)); + + Assert.That(args, Is.Not.Null); + Assert.That(args.Realm, Is.Not.Null); + } +} diff --git a/dotnet/test/common/BiDi/Storage/StorageTest.cs b/dotnet/test/common/BiDi/Storage/StorageTest.cs new file mode 100644 index 0000000000000..2f9877c4ca1aa --- /dev/null +++ b/dotnet/test/common/BiDi/Storage/StorageTest.cs @@ -0,0 +1,161 @@ +using NUnit.Framework; +using OpenQA.Selenium.BiDi.Modules.Network; +using System; +using System.Threading.Tasks; + +namespace OpenQA.Selenium.BiDi.Storage; + +class StorageTest : BiDiTestFixture +{ + [Test] + public async Task CanGetCookieByName() + { + driver.Url = UrlBuilder.WhereIs("animals"); + + var cookies = await bidi.Storage.GetCookiesAsync(new() + { + Filter = new() + { + Name = Guid.NewGuid().ToString(), + Value = "set" + } + }); + + Assert.That(cookies, Is.Not.Null); + Assert.That(cookies, Is.Empty); + } + + [Test] + public async Task CanGetCookieInDefaultUserContext() + { + driver.Url = UrlBuilder.WhereIs("animals"); + + var userContexts = await bidi.Browser.GetUserContextsAsync(); + + var cookies = await context.Storage.GetCookiesAsync(new() + { + Filter = new() + { + Name = Guid.NewGuid().ToString(), + Value = "set" + } + }); + + Assert.That(cookies, Is.Not.Null); + Assert.That(cookies, Is.Empty); + Assert.That(cookies.PartitionKey.UserContext, Is.EqualTo(userContexts[0].UserContext)); + } + + [Test] + public async Task CanAddCookie() + { + driver.Url = UrlBuilder.WhereIs("animals"); + + var partitionKey = await context.Storage.SetCookieAsync(new("fish", "cod", UrlBuilder.HostName)); + + Assert.That(partitionKey, Is.Not.Null); + } + + [Test] + public async Task CanAddAndGetCookie() + { + driver.Url = UrlBuilder.WhereIs("animals"); + + var expiry = DateTime.Now.AddDays(1); + + await context.Storage.SetCookieAsync(new("fish", "cod", UrlBuilder.HostName) + { + Path = "/common/animals", + HttpOnly = true, + Secure = false, + SameSite = SameSite.Lax, + Expiry = expiry + }); + + var cookies = await context.Storage.GetCookiesAsync(); + + Assert.That(cookies, Is.Not.Null); + Assert.That(cookies.Count, Is.EqualTo(1)); + + var cookie = cookies[0]; + + Assert.That(cookie.Name, Is.EqualTo("fish")); + Assert.That((cookie.Value as BytesValue.String).Value, Is.EqualTo("cod")); + Assert.That(cookie.Path, Is.EqualTo("/common/animals")); + Assert.That(cookie.HttpOnly, Is.True); + Assert.That(cookie.Secure, Is.False); + Assert.That(cookie.SameSite, Is.EqualTo(SameSite.Lax)); + Assert.That(cookie.Size, Is.EqualTo(7)); + // Assert.That(cookie.Expiry, Is.EqualTo(expiry)); // chrome issue + } + + [Test] + public async Task CanGetAllCookies() + { + driver.Url = UrlBuilder.WhereIs("animals"); + + driver.Manage().Cookies.AddCookie(new("key1", "value1")); + driver.Manage().Cookies.AddCookie(new("key2", "value2")); + + var cookies = await bidi.Storage.GetCookiesAsync(); + + Assert.That(cookies, Is.Not.Null); + Assert.That(cookies.Count, Is.EqualTo(2)); + Assert.That(cookies[0].Name, Is.EqualTo("key1")); + Assert.That(cookies[1].Name, Is.EqualTo("key2")); + } + + [Test] + public async Task CanDeleteAllCookies() + { + driver.Url = UrlBuilder.WhereIs("animals"); + + driver.Manage().Cookies.AddCookie(new("key1", "value1")); + driver.Manage().Cookies.AddCookie(new("key2", "value2")); + + var result = await bidi.Storage.DeleteCookiesAsync(); + + Assert.That(result, Is.Not.Null); + + var cookies = await bidi.Storage.GetCookiesAsync(); + + Assert.That(cookies, Is.Not.Null); + Assert.That(cookies.Count, Is.EqualTo(0)); + } + + [Test] + public async Task CanDeleteCookieWithName() + { + driver.Url = UrlBuilder.WhereIs("animals"); + + driver.Manage().Cookies.AddCookie(new("key1", "value1")); + driver.Manage().Cookies.AddCookie(new("key2", "value2")); + + var result = await bidi.Storage.DeleteCookiesAsync(new() { Filter = new() { Name = "key1" } }); + + Assert.That(result, Is.Not.Null); + + var cookies = await bidi.Storage.GetCookiesAsync(); + + Assert.That(cookies, Is.Not.Null); + Assert.That(cookies.Count, Is.EqualTo(1)); + Assert.That(cookies[0].Name, Is.EqualTo("key2")); + } + + [Test] + public async Task AddCookiesWithDifferentPathsThatAreRelatedToOurs() + { + driver.Url = UrlBuilder.WhereIs("animals"); + + await context.Storage.SetCookieAsync(new("fish", "cod", UrlBuilder.HostName) + { + Path = "/common/animals" + }); + + driver.Url = UrlBuilder.WhereIs("simpleTest"); + + var result = driver.Manage().Cookies.AllCookies; + + Assert.That(result, Is.Empty); + } +} diff --git a/dotnet/test/common/Environment/DriverFactory.cs b/dotnet/test/common/Environment/DriverFactory.cs index 8ce615235dc7d..5708ebda6495d 100644 --- a/dotnet/test/common/Environment/DriverFactory.cs +++ b/dotnet/test/common/Environment/DriverFactory.cs @@ -67,12 +67,6 @@ public IWebDriver CreateDriverWithOptions(Type driverType, DriverOptions driverO { browser = Browser.Chrome; options = GetDriverOptions(driverType, driverOptions); - // Disabling this since we do not have any BiDi tests currently. - //options.UseWebSocketUrl = true; - - // If BiDi is enabled above then the undhandler prompt behaviour needs to set accordingly. - // Reasoning : https://github.com/SeleniumHQ/selenium/pull/14429#issuecomment-2311614822 - //options.UnhandledPromptBehavior = UnhandledPromptBehavior.Ignore; var chromeOptions = (ChromeOptions)options; chromeOptions.AddArguments("--no-sandbox", "--disable-dev-shm-usage"); @@ -188,6 +182,8 @@ protected void OnDriverLaunching(DriverService service, DriverOptions options) options.ScriptTimeout = overriddenOptions.ScriptTimeout; options.PageLoadTimeout = overriddenOptions.PageLoadTimeout; options.ImplicitWaitTimeout = overriddenOptions.ImplicitWaitTimeout; + + options.UseWebSocketUrl = overriddenOptions.UseWebSocketUrl; } return options; diff --git a/java/maven_install.json b/java/maven_install.json index 8be2dd9b44a41..04f5468f594a2 100644 --- a/java/maven_install.json +++ b/java/maven_install.json @@ -1,11 +1,11 @@ { "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL", - "__INPUT_ARTIFACTS_HASH": -1369959342, - "__RESOLVED_ARTIFACTS_HASH": 2051378450, + "__INPUT_ARTIFACTS_HASH": 1327312787, + "__RESOLVED_ARTIFACTS_HASH": -2038995232, "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.28.0", - "com.google.guava:guava:31.1-jre": "com.google.guava:guava:33.3.0-jre", + "com.google.guava:guava:31.1-jre": "com.google.guava:guava:33.3.1-jre", "com.google.j2objc:j2objc-annotations:1.3": "com.google.j2objc:j2objc-annotations:3.0.0", "org.mockito:mockito-core:4.3.1": "org.mockito:mockito-core:5.13.0" }, @@ -159,10 +159,10 @@ }, "com.google.guava:guava": { "shasums": { - "jar": "dfadc3bce3101eff1452aae47d7c833fee443b47bdf9ef13311b6c7cab663ddf", - "sources": "f91f8619f533db55f37d13369c2fee39d5e1d2f72cef7f69f735d5be1a601f14" + "jar": "4bf0e2c5af8e4525c96e8fde17a4f7307f97f8478f11c4c8e35a0e3298ae4e90", + "sources": "b7cbdad958b791f2a036abff7724570bf9836531c460966f8a3d0df8eaa1c21d" }, - "version": "33.3.0-jre" + "version": "33.3.1-jre" }, "com.google.guava:guava-testlib": { "shasums": { diff --git a/java/src/org/openqa/selenium/grid/node/Node.java b/java/src/org/openqa/selenium/grid/node/Node.java index 09fe7d02ae9f5..bc2b5c75b5ab7 100644 --- a/java/src/org/openqa/selenium/grid/node/Node.java +++ b/java/src/org/openqa/selenium/grid/node/Node.java @@ -101,6 +101,12 @@ * by {@code sessionId}. This returns a boolean. * * + * POST + * /se/grid/node/connection/{sessionId} + * Allows the node to be ask about whether or not new websocket connections are allowed for the {@link Session} + * identified by {@code sessionId}. This returns a boolean. + * + * * * * /session/{sessionId}/* * The request is forwarded to the {@link Session} identified by {@code sessionId}. When the @@ -172,6 +178,9 @@ protected Node( get("/se/grid/node/owner/{sessionId}") .to(params -> new IsSessionOwner(this, sessionIdFrom(params))) .with(spanDecorator("node.is_session_owner").andThen(requiresSecret)), + post("/se/grid/node/connection/{sessionId}") + .to(params -> new TryAcquireConnection(this, sessionIdFrom(params))) + .with(spanDecorator("node.is_session_owner").andThen(requiresSecret)), delete("/se/grid/node/session/{sessionId}") .to(params -> new StopNodeSession(this, sessionIdFrom(params))) .with(spanDecorator("node.stop_session").andThen(requiresSecret)), @@ -244,6 +253,8 @@ public TemporaryFilesystem getDownloadsFilesystem(UUID uuid) throws IOException public abstract boolean isSessionOwner(SessionId id); + public abstract boolean tryAcquireConnection(SessionId id); + public abstract boolean isSupporting(Capabilities capabilities); public abstract NodeStatus getStatus(); diff --git a/java/src/org/openqa/selenium/grid/node/ProxyNodeWebsockets.java b/java/src/org/openqa/selenium/grid/node/ProxyNodeWebsockets.java index e3f656c069125..eff13dc5a40f5 100644 --- a/java/src/org/openqa/selenium/grid/node/ProxyNodeWebsockets.java +++ b/java/src/org/openqa/selenium/grid/node/ProxyNodeWebsockets.java @@ -94,6 +94,13 @@ public Optional> apply(String uri, Consumer downstrea return Optional.empty(); } + // ensure one session does not open to many connections, this might have a negative impact on + // the grid health + if (!node.tryAcquireConnection(id)) { + LOG.warning("Too many websocket connections initiated by " + id); + return Optional.empty(); + } + Session session = node.getSession(id); Capabilities caps = session.getCapabilities(); LOG.fine("Scanning for endpoint: " + caps); diff --git a/java/src/org/openqa/selenium/grid/node/TryAcquireConnection.java b/java/src/org/openqa/selenium/grid/node/TryAcquireConnection.java new file mode 100644 index 0000000000000..6c8822bea84cd --- /dev/null +++ b/java/src/org/openqa/selenium/grid/node/TryAcquireConnection.java @@ -0,0 +1,45 @@ +// 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.grid.node; + +import static org.openqa.selenium.remote.http.Contents.asJson; + +import com.google.common.collect.ImmutableMap; +import java.io.UncheckedIOException; +import org.openqa.selenium.internal.Require; +import org.openqa.selenium.remote.SessionId; +import org.openqa.selenium.remote.http.HttpHandler; +import org.openqa.selenium.remote.http.HttpRequest; +import org.openqa.selenium.remote.http.HttpResponse; + +class TryAcquireConnection implements HttpHandler { + + private final Node node; + private final SessionId id; + + TryAcquireConnection(Node node, SessionId id) { + this.node = Require.nonNull("Node", node); + this.id = Require.nonNull("Session id", id); + } + + @Override + public HttpResponse execute(HttpRequest req) throws UncheckedIOException { + return new HttpResponse() + .setContent(asJson(ImmutableMap.of("value", node.tryAcquireConnection(id)))); + } +} diff --git a/java/src/org/openqa/selenium/grid/node/config/NodeFlags.java b/java/src/org/openqa/selenium/grid/node/config/NodeFlags.java index 800a0798a4e17..b56e57b3dcb97 100644 --- a/java/src/org/openqa/selenium/grid/node/config/NodeFlags.java +++ b/java/src/org/openqa/selenium/grid/node/config/NodeFlags.java @@ -18,6 +18,7 @@ package org.openqa.selenium.grid.node.config; import static org.openqa.selenium.grid.config.StandardGridRoles.NODE_ROLE; +import static org.openqa.selenium.grid.node.config.NodeOptions.DEFAULT_CONNECTION_LIMIT; import static org.openqa.selenium.grid.node.config.NodeOptions.DEFAULT_DETECT_DRIVERS; import static org.openqa.selenium.grid.node.config.NodeOptions.DEFAULT_DRAIN_AFTER_SESSION_COUNT; import static org.openqa.selenium.grid.node.config.NodeOptions.DEFAULT_ENABLE_BIDI; @@ -77,6 +78,14 @@ public class NodeFlags implements HasRoles { @ConfigValue(section = NODE_SECTION, name = "session-timeout", example = "60") public int sessionTimeout = DEFAULT_SESSION_TIMEOUT; + @Parameter( + names = {"--connection-limit-per-session"}, + description = + "Let X be the maximum number of websocket connections per session.This will ensure one" + + " session is not able to exhaust the connection limit of the host") + @ConfigValue(section = NODE_SECTION, name = "connection-limit-per-session", example = "8") + public int connectionLimitPerSession = DEFAULT_CONNECTION_LIMIT; + @Parameter( names = {"--detect-drivers"}, arity = 1, diff --git a/java/src/org/openqa/selenium/grid/node/config/NodeOptions.java b/java/src/org/openqa/selenium/grid/node/config/NodeOptions.java index 7317f6e7c8870..ff8fc6d76667a 100644 --- a/java/src/org/openqa/selenium/grid/node/config/NodeOptions.java +++ b/java/src/org/openqa/selenium/grid/node/config/NodeOptions.java @@ -73,6 +73,7 @@ public class NodeOptions { public static final int DEFAULT_HEARTBEAT_PERIOD = 60; public static final int DEFAULT_SESSION_TIMEOUT = 300; public static final int DEFAULT_DRAIN_AFTER_SESSION_COUNT = 0; + public static final int DEFAULT_CONNECTION_LIMIT = 10; public static final boolean DEFAULT_ENABLE_CDP = true; public static final boolean DEFAULT_ENABLE_BIDI = true; static final String NODE_SECTION = "node"; @@ -262,6 +263,15 @@ public int getMaxSessions() { return Math.min(maxSessions, DEFAULT_MAX_SESSIONS); } + public int getConnectionLimitPerSession() { + int connectionLimit = + config + .getInt(NODE_SECTION, "connection-limit-per-session") + .orElse(DEFAULT_CONNECTION_LIMIT); + Require.positive("Session connection limit", connectionLimit); + return connectionLimit; + } + public Duration getSessionTimeout() { // If the user sets 10s or less, we default to 10s. int seconds = diff --git a/java/src/org/openqa/selenium/grid/node/k8s/OneShotNode.java b/java/src/org/openqa/selenium/grid/node/k8s/OneShotNode.java index d293d1c6ba78c..af8c05cf7a7c1 100644 --- a/java/src/org/openqa/selenium/grid/node/k8s/OneShotNode.java +++ b/java/src/org/openqa/selenium/grid/node/k8s/OneShotNode.java @@ -34,6 +34,7 @@ import java.util.Optional; import java.util.ServiceLoader; import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Logger; import java.util.stream.StreamSupport; import org.openqa.selenium.Capabilities; @@ -98,6 +99,8 @@ public class OneShotNode extends Node { private final Duration heartbeatPeriod; private final URI gridUri; private final UUID slotId = UUID.randomUUID(); + private final int connectionLimitPerSession; + private final AtomicInteger connectionCounter = new AtomicInteger(); private RemoteWebDriver driver; private SessionId sessionId; private HttpClient client; @@ -114,7 +117,8 @@ private OneShotNode( URI uri, URI gridUri, Capabilities stereotype, - WebDriverInfo driverInfo) { + WebDriverInfo driverInfo, + int connectionLimitPerSession) { super(tracer, id, uri, registrationSecret, Require.positive(sessionTimeout)); this.heartbeatPeriod = heartbeatPeriod; @@ -122,6 +126,7 @@ private OneShotNode( this.gridUri = Require.nonNull("Public Grid URI", gridUri); this.stereotype = ImmutableCapabilities.copyOf(Require.nonNull("Stereotype", stereotype)); this.driverInfo = Require.nonNull("Driver info", driverInfo); + this.connectionLimitPerSession = connectionLimitPerSession; new JMXHelper().register(this); } @@ -177,7 +182,8 @@ public static Node create(Config config) { .getPublicGridUri() .orElseThrow(() -> new ConfigException("Unable to determine public grid address")), stereotype, - driverInfo); + driverInfo, + nodeOptions.getConnectionLimitPerSession()); } @Override @@ -357,6 +363,11 @@ public boolean isSessionOwner(SessionId id) { return driver != null && sessionId.equals(id); } + @Override + public boolean tryAcquireConnection(SessionId id) { + return sessionId.equals(id) && connectionLimitPerSession > connectionCounter.getAndIncrement(); + } + @Override public boolean isSupporting(Capabilities capabilities) { return driverInfo.isSupporting(capabilities); diff --git a/java/src/org/openqa/selenium/grid/node/local/LocalNode.java b/java/src/org/openqa/selenium/grid/node/local/LocalNode.java index 7304db8a87847..b42c557c91008 100644 --- a/java/src/org/openqa/selenium/grid/node/local/LocalNode.java +++ b/java/src/org/openqa/selenium/grid/node/local/LocalNode.java @@ -59,6 +59,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; @@ -127,6 +128,7 @@ public class LocalNode extends Node { private final int configuredSessionCount; private final boolean cdpEnabled; private final boolean managedDownloadsEnabled; + private final int connectionLimitPerSession; private final boolean bidiEnabled; private final AtomicBoolean drainAfterSessions = new AtomicBoolean(); @@ -153,7 +155,8 @@ protected LocalNode( Duration heartbeatPeriod, List factories, Secret registrationSecret, - boolean managedDownloadsEnabled) { + boolean managedDownloadsEnabled, + int connectionLimitPerSession) { super( tracer, new NodeId(UUID.randomUUID()), @@ -176,6 +179,7 @@ protected LocalNode( this.cdpEnabled = cdpEnabled; this.bidiEnabled = bidiEnabled; this.managedDownloadsEnabled = managedDownloadsEnabled; + this.connectionLimitPerSession = connectionLimitPerSession; this.healthCheck = healthCheck == null @@ -579,6 +583,24 @@ public boolean isSessionOwner(SessionId id) { return currentSessions.getIfPresent(id) != null; } + @Override + public boolean tryAcquireConnection(SessionId id) throws NoSuchSessionException { + SessionSlot slot = currentSessions.getIfPresent(id); + + if (slot == null) { + return false; + } + + if (connectionLimitPerSession == -1) { + // no limit + return true; + } + + AtomicLong counter = slot.getConnectionCounter(); + + return connectionLimitPerSession > counter.getAndIncrement(); + } + @Override public Session getSession(SessionId id) throws NoSuchSessionException { Require.nonNull("Session ID", id); @@ -987,6 +1009,7 @@ public static class Builder { private HealthCheck healthCheck; private Duration heartbeatPeriod = Duration.ofSeconds(NodeOptions.DEFAULT_HEARTBEAT_PERIOD); private boolean managedDownloadsEnabled = false; + private int connectionLimitPerSession = -1; private Builder(Tracer tracer, EventBus bus, URI uri, URI gridUri, Secret registrationSecret) { this.tracer = Require.nonNull("Tracer", tracer); @@ -1041,6 +1064,11 @@ public Builder enableManagedDownloads(boolean enable) { return this; } + public Builder connectionLimitPerSession(int connectionLimitPerSession) { + this.connectionLimitPerSession = connectionLimitPerSession; + return this; + } + public LocalNode build() { return new LocalNode( tracer, @@ -1057,7 +1085,8 @@ public LocalNode build() { heartbeatPeriod, factories.build(), registrationSecret, - managedDownloadsEnabled); + managedDownloadsEnabled, + connectionLimitPerSession); } public Advanced advanced() { diff --git a/java/src/org/openqa/selenium/grid/node/local/LocalNodeFactory.java b/java/src/org/openqa/selenium/grid/node/local/LocalNodeFactory.java index 4224b2483f9db..600f516b02992 100644 --- a/java/src/org/openqa/selenium/grid/node/local/LocalNodeFactory.java +++ b/java/src/org/openqa/selenium/grid/node/local/LocalNodeFactory.java @@ -70,7 +70,8 @@ public static Node create(Config config) { .enableCdp(nodeOptions.isCdpEnabled()) .enableBiDi(nodeOptions.isBiDiEnabled()) .enableManagedDownloads(nodeOptions.isManagedDownloadsEnabled()) - .heartbeatPeriod(nodeOptions.getHeartbeatPeriod()); + .heartbeatPeriod(nodeOptions.getHeartbeatPeriod()) + .connectionLimitPerSession(nodeOptions.getConnectionLimitPerSession()); List> builders = new ArrayList<>(); ServiceLoader.load(DriverService.Builder.class).forEach(builders::add); diff --git a/java/src/org/openqa/selenium/grid/node/local/SessionSlot.java b/java/src/org/openqa/selenium/grid/node/local/SessionSlot.java index 5b84accc84c31..3c51b785c13c0 100644 --- a/java/src/org/openqa/selenium/grid/node/local/SessionSlot.java +++ b/java/src/org/openqa/selenium/grid/node/local/SessionSlot.java @@ -21,6 +21,7 @@ import java.util.ServiceLoader; import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; import java.util.function.Function; import java.util.function.Predicate; import java.util.logging.Level; @@ -59,6 +60,7 @@ public class SessionSlot private final AtomicBoolean reserved = new AtomicBoolean(false); private final boolean supportingCdp; private final boolean supportingBiDi; + private final AtomicLong connectionCounter; private ActiveSession currentSession; public SessionSlot(EventBus bus, Capabilities stereotype, SessionFactory factory) { @@ -68,6 +70,7 @@ public SessionSlot(EventBus bus, Capabilities stereotype, SessionFactory factory this.factory = Require.nonNull("Session factory", factory); this.supportingCdp = isSlotSupportingCdp(this.stereotype); this.supportingBiDi = isSlotSupportingBiDi(this.stereotype); + this.connectionCounter = new AtomicLong(); } public UUID getId() { @@ -112,6 +115,7 @@ public void stop() { LOG.log(Level.WARNING, "Unable to cleanly close session", e); } currentSession = null; + connectionCounter.set(0); release(); bus.fire(new SessionClosedEvent(id)); LOG.info(String.format("Stopping session %s", id)); @@ -148,6 +152,7 @@ public Either apply(CreateSessionRequest sess if (possibleSession.isRight()) { ActiveSession session = possibleSession.right(); currentSession = session; + connectionCounter.set(0); return Either.right(session); } else { return Either.left(possibleSession.left()); @@ -185,4 +190,8 @@ public boolean hasRelayFactory() { public boolean isRelayServiceUp() { return hasRelayFactory() && ((RelaySessionFactory) factory).isServiceUp(); } + + public AtomicLong getConnectionCounter() { + return connectionCounter; + } } diff --git a/java/src/org/openqa/selenium/grid/node/remote/RemoteNode.java b/java/src/org/openqa/selenium/grid/node/remote/RemoteNode.java index ae7cc8e1af9fb..5df5da5969c42 100644 --- a/java/src/org/openqa/selenium/grid/node/remote/RemoteNode.java +++ b/java/src/org/openqa/selenium/grid/node/remote/RemoteNode.java @@ -174,6 +174,18 @@ public boolean isSessionOwner(SessionId id) { return Boolean.TRUE.equals(Values.get(res, Boolean.class)); } + @Override + public boolean tryAcquireConnection(SessionId id) { + Require.nonNull("Session ID", id); + + HttpRequest req = new HttpRequest(POST, "/se/grid/node/connection/" + id); + HttpTracing.inject(tracer, tracer.getCurrentContext(), req); + + HttpResponse res = client.with(addSecret).execute(req); + + return Boolean.TRUE.equals(Values.get(res, Boolean.class)); + } + @Override public Session getSession(SessionId id) throws NoSuchSessionException { Require.nonNull("Session ID", id); diff --git a/java/test/org/openqa/selenium/grid/distributor/AddingNodesTest.java b/java/test/org/openqa/selenium/grid/distributor/AddingNodesTest.java index 0649e1bbee235..1485d04fca4c6 100644 --- a/java/test/org/openqa/selenium/grid/distributor/AddingNodesTest.java +++ b/java/test/org/openqa/selenium/grid/distributor/AddingNodesTest.java @@ -445,6 +445,11 @@ public boolean isSessionOwner(SessionId id) { return running != null && running.getId().equals(id); } + @Override + public boolean tryAcquireConnection(SessionId id) { + return false; + } + @Override public boolean isSupporting(Capabilities capabilities) { return Objects.equals("cake", capabilities.getCapability("cheese")); diff --git a/javascript/grid-ui/package.json b/javascript/grid-ui/package.json index add2c75d45847..5a59007ec2986 100644 --- a/javascript/grid-ui/package.json +++ b/javascript/grid-ui/package.json @@ -4,13 +4,13 @@ "private": true, "type": "module", "dependencies": { - "@apollo/client": "3.10.4", - "@emotion/react": "11.11.4", - "@emotion/styled": "11.11.5", + "@apollo/client": "3.11.8", + "@emotion/react": "11.13.3", + "@emotion/styled": "11.13.0", "@mui/icons-material": "5.15.18", "@mui/material": "5.15.18", "@novnc/novnc": "1.4.0", - "@types/jest": "29.5.12", + "@types/jest": "29.5.14", "@types/node": "20.12.12", "@types/react": "18.2.72", "@types/react-dom": "18.2.22", @@ -20,10 +20,10 @@ "graphql.macro": "1.4.2", "path-browserify": "1.0.1", "pretty-ms": "9.0.0", - "react": "18.2.0", - "react-dom": "18.2.0", + "react": "18.3.1", + "react-dom": "18.3.1", "react-modal": "3.16.1", - "react-router-dom": "6.22.3", + "react-router-dom": "6.27.0", "source-map-explorer": "2.5.3" }, "scripts": { @@ -47,13 +47,13 @@ ] }, "devDependencies": { - "@babel/preset-react": "7.24.7", - "@testing-library/jest-dom": "6.4.5", + "@babel/preset-react": "7.25.9", + "@testing-library/jest-dom": "6.6.2", "@testing-library/react": "14.3.1", "@testing-library/user-event": "14.5.2", - "esbuild": "0.19.12", + "esbuild": "0.24.0", "ts-standard": "12.0.2", - "typescript": "5.4.5" + "typescript": "5.6.3" }, "jest": { "testMatch": [ diff --git a/javascript/node/selenium-webdriver/lib/webdriver.js b/javascript/node/selenium-webdriver/lib/webdriver.js index cb60563695a06..e004e4505c1e4 100644 --- a/javascript/node/selenium-webdriver/lib/webdriver.js +++ b/javascript/node/selenium-webdriver/lib/webdriver.js @@ -2752,6 +2752,7 @@ class WebElement { keys = await this.driver_.fileDetector_.handleFile(this.driver_, keys.join('')) } catch (ex) { this.log_.severe('Error trying parse string as a file with file detector; sending keys instead' + ex) + keys = keys.join('') } return this.execute_( diff --git a/javascript/node/selenium-webdriver/package.json b/javascript/node/selenium-webdriver/package.json index 308b4a9caf5c6..31f7b92c3eeed 100644 --- a/javascript/node/selenium-webdriver/package.json +++ b/javascript/node/selenium-webdriver/package.json @@ -23,24 +23,24 @@ "node": ">= 14.21.0" }, "dependencies": { - "@bazel/runfiles": "^6.3.0", + "@bazel/runfiles": "^6.3.1", "jszip": "^3.10.1", "tmp": "^0.2.3", "ws": "^8.18.0" }, "devDependencies": { - "@eslint/js": "^9.12.0", + "@eslint/js": "^9.13.0", "clean-jsdoc-theme": "^4.3.0", - "eslint": "^9.12.0", + "eslint": "^9.13.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-mocha": "^10.5.0", - "eslint-plugin-n": "^17.10.3", + "eslint-plugin-n": "^17.11.1", "eslint-plugin-no-only-tests": "^3.3.0", "eslint-plugin-prettier": "^5.2.1", - "express": "^4.21.0", - "globals": "^15.10.0", + "express": "^4.21.1", + "globals": "^15.11.0", "has-flag": "^5.0.1", - "jsdoc": "^4.0.3", + "jsdoc": "^4.0.4", "mocha": "^10.7.3", "mocha-junit-reporter": "^2.2.1", "multer": "1.4.5-lts.1", diff --git a/javascript/node/selenium-webdriver/test/lib/webdriver_test.js b/javascript/node/selenium-webdriver/test/lib/webdriver_test.js index f850c3e4fcac8..419fdf6f80212 100644 --- a/javascript/node/selenium-webdriver/test/lib/webdriver_test.js +++ b/javascript/node/selenium-webdriver/test/lib/webdriver_test.js @@ -932,6 +932,32 @@ describe('WebDriver', function () { return driver.findElement(By.id('foo')).sendKeys('original/', 'path') }) + + it('sendKeysWithAFileDetector_handlerError', function () { + let executor = new FakeExecutor() + .expect(CName.FIND_ELEMENT, { + using: 'css selector', + value: '*[id="foo"]', + }) + .andReturnSuccess(WebElement.buildId('one')) + .expect(CName.SEND_KEYS_TO_ELEMENT, { + id: WebElement.buildId('one'), + text: 'original/path', + value: 'original/path'.split(''), + }) + .andReturnSuccess() + .end() + + let driver = executor.createDriver() + let handleFile = function (d, path) { + assert.strictEqual(driver, d) + assert.strictEqual(path, 'original/path') + return Promise.reject('unhandled file error') + } + driver.setFileDetector({ handleFile }) + + return driver.findElement(By.id('foo')).sendKeys('original/', 'path') + }) }) describe('switchTo()', function () { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9ba6191ac72a5..bd3089aee3d08 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,26 +11,26 @@ importers: javascript/grid-ui: dependencies: '@apollo/client': - specifier: 3.10.4 - version: 3.10.4(@types/react@18.2.72)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0) + specifier: 3.11.8 + version: 3.11.8(@types/react@18.2.72)(graphql@16.8.1)(react-dom@18.3.1)(react@18.3.1) '@emotion/react': - specifier: 11.11.4 - version: 11.11.4(@types/react@18.2.72)(react@18.2.0) + specifier: 11.13.3 + version: 11.13.3(@types/react@18.2.72)(react@18.3.1) '@emotion/styled': - specifier: 11.11.5 - version: 11.11.5(@emotion/react@11.11.4)(@types/react@18.2.72)(react@18.2.0) + specifier: 11.13.0 + version: 11.13.0(@emotion/react@11.13.3)(@types/react@18.2.72)(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.2.0) + version: 5.15.18(@mui/material@5.15.18)(@types/react@18.2.72)(react@18.3.1) '@mui/material': specifier: 5.15.18 - version: 5.15.18(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.2.72)(react-dom@18.2.0)(react@18.2.0) + version: 5.15.18(@emotion/react@11.13.3)(@emotion/styled@11.13.0)(@types/react@18.2.72)(react-dom@18.3.1)(react@18.3.1) '@novnc/novnc': specifier: 1.4.0 version: 1.4.0 '@types/jest': - specifier: 29.5.12 - version: 29.5.12 + specifier: 29.5.14 + version: 29.5.14 '@types/node': specifier: 20.12.12 version: 20.12.12 @@ -51,7 +51,7 @@ importers: version: 16.8.1 graphql.macro: specifier: 1.4.2 - version: 1.4.2(@babel/core@7.25.7)(graphql@16.8.1) + version: 1.4.2(@babel/core@7.26.0)(graphql@16.8.1) path-browserify: specifier: 1.0.1 version: 1.0.1 @@ -59,48 +59,48 @@ importers: specifier: 9.0.0 version: 9.0.0 react: - specifier: 18.2.0 - version: 18.2.0 + specifier: 18.3.1 + version: 18.3.1 react-dom: - specifier: 18.2.0 - version: 18.2.0(react@18.2.0) + specifier: 18.3.1 + version: 18.3.1(react@18.3.1) react-modal: specifier: 3.16.1 - version: 3.16.1(react-dom@18.2.0)(react@18.2.0) + version: 3.16.1(react-dom@18.3.1)(react@18.3.1) react-router-dom: - specifier: 6.22.3 - version: 6.22.3(react-dom@18.2.0)(react@18.2.0) + specifier: 6.27.0 + version: 6.27.0(react-dom@18.3.1)(react@18.3.1) source-map-explorer: specifier: 2.5.3 version: 2.5.3 devDependencies: '@babel/preset-react': - specifier: 7.24.7 - version: 7.24.7(@babel/core@7.25.7) + specifier: 7.25.9 + version: 7.25.9(@babel/core@7.26.0) '@testing-library/jest-dom': - specifier: 6.4.5 - version: 6.4.5(@types/jest@29.5.12) + specifier: 6.6.2 + version: 6.6.2 '@testing-library/react': specifier: 14.3.1 - version: 14.3.1(react-dom@18.2.0)(react@18.2.0) + version: 14.3.1(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) esbuild: - specifier: 0.19.12 - version: 0.19.12 + specifier: 0.24.0 + version: 0.24.0 ts-standard: specifier: 12.0.2 - version: 12.0.2(typescript@5.4.5) + version: 12.0.2(typescript@5.6.3) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.6.3 + version: 5.6.3 javascript/node/selenium-webdriver: dependencies: '@bazel/runfiles': - specifier: ^6.3.0 - version: 6.3.0 + specifier: ^6.3.1 + version: 6.3.1 jszip: specifier: ^3.10.1 version: 3.10.1 @@ -112,41 +112,41 @@ importers: version: 8.18.0 devDependencies: '@eslint/js': - specifier: ^9.12.0 - version: 9.12.0 + specifier: ^9.13.0 + version: 9.13.0 clean-jsdoc-theme: specifier: ^4.3.0 - version: 4.3.0(jsdoc@4.0.3) + version: 4.3.0(jsdoc@4.0.4) eslint: - specifier: ^9.12.0 - version: 9.12.0(supports-color@9.4.0) + specifier: ^9.13.0 + version: 9.13.0(supports-color@9.4.0) eslint-config-prettier: specifier: ^9.1.0 - version: 9.1.0(eslint@9.12.0) + version: 9.1.0(eslint@9.13.0) eslint-plugin-mocha: specifier: ^10.5.0 - version: 10.5.0(eslint@9.12.0) + version: 10.5.0(eslint@9.13.0) eslint-plugin-n: - specifier: ^17.10.3 - version: 17.10.3(eslint@9.12.0) + specifier: ^17.11.1 + version: 17.11.1(eslint@9.13.0) eslint-plugin-no-only-tests: specifier: ^3.3.0 version: 3.3.0 eslint-plugin-prettier: specifier: ^5.2.1 - version: 5.2.1(eslint-config-prettier@9.1.0)(eslint@9.12.0)(prettier@3.3.3) + version: 5.2.1(eslint-config-prettier@9.1.0)(eslint@9.13.0)(prettier@3.3.3) express: - specifier: ^4.21.0 - version: 4.21.0(supports-color@9.4.0) + specifier: ^4.21.1 + version: 4.21.1(supports-color@9.4.0) globals: - specifier: ^15.10.0 - version: 15.10.0 + specifier: ^15.11.0 + version: 15.11.0 has-flag: specifier: ^5.0.1 version: 5.0.1 jsdoc: - specifier: ^4.0.3 - version: 4.0.3 + specifier: ^4.0.4 + version: 4.0.4 mocha: specifier: ^10.7.3 version: 10.7.3 @@ -182,13 +182,13 @@ packages: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - /@apollo/client@3.10.4(@types/react@18.2.72)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-51gk0xOwN6Ls1EbTG5svFva1kdm2APHYTzmFhaAdvUQoJFDxfc0UwQgDxGptzH84vkPlo1qunY1FuboyF9LI3Q==} + /@apollo/client@3.11.8(@types/react@18.2.72)(graphql@16.8.1)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-CgG1wbtMjsV2pRGe/eYITmV5B8lXUCYljB2gB/6jWTFQcrvirUVvKg7qtFdjYkQSFbIffU1IDyxgeaN81eTjbA==} peerDependencies: graphql: ^15.0.0 || ^16.0.0 graphql-ws: ^5.5.5 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 subscriptions-transport-ws: ^0.9.0 || ^0.11.0 peerDependenciesMeta: graphql-ws: @@ -209,43 +209,44 @@ packages: hoist-non-react-statics: 3.3.2 optimism: 0.18.0 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - rehackt: 0.1.0(@types/react@18.2.72)(react@18.2.0) + 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) response-iterator: 0.2.6 symbol-observable: 4.0.0 ts-invariant: 0.10.3 - tslib: 2.7.0 + tslib: 2.8.0 zen-observable-ts: 1.2.5 transitivePeerDependencies: - '@types/react' dev: false - /@babel/code-frame@7.25.7: - resolution: {integrity: sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==} + /@babel/code-frame@7.26.0: + resolution: {integrity: sha512-INCKxTtbXtcNbUZ3YXutwMpEleqttcswhAdee7dhuoVrD2cnuc3PqtERBtxkX5nziX9vnBL8WXmSGwv8CuPV6g==} engines: {node: '>=6.9.0'} dependencies: - '@babel/highlight': 7.25.7 - picocolors: 1.1.0 + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 - /@babel/compat-data@7.25.7: - resolution: {integrity: sha512-9ickoLz+hcXCeh7jrcin+/SLWm+GkxE2kTvoYyp38p4WkdFXfQJxDFGWp/YHjiKLPx06z2A7W8XKuqbReXDzsw==} + /@babel/compat-data@7.26.0: + resolution: {integrity: sha512-qETICbZSLe7uXv9VE8T/RWOdIE5qqyTucOt4zLYMafj2MRO271VGgLd4RACJMeBO37UPWhXiKMBk7YlJ0fOzQA==} engines: {node: '>=6.9.0'} - /@babel/core@7.25.7: - resolution: {integrity: sha512-yJ474Zv3cwiSOO9nXJuqzvwEeM+chDuQ8GJirw+pZ91sCGCyOZ3dJkVE09fTV0VEVzXyLWhh3G/AolYTPX7Mow==} + /@babel/core@7.26.0: + resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} engines: {node: '>=6.9.0'} dependencies: '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.25.7 - '@babel/generator': 7.25.7 - '@babel/helper-compilation-targets': 7.25.7 - '@babel/helper-module-transforms': 7.25.7(@babel/core@7.25.7) - '@babel/helpers': 7.25.7 - '@babel/parser': 7.25.7 - '@babel/template': 7.25.7 - '@babel/traverse': 7.25.7 - '@babel/types': 7.25.7 + '@babel/code-frame': 7.26.0 + '@babel/generator': 7.26.0 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) + '@babel/helpers': 7.26.0 + '@babel/parser': 7.26.1 + '@babel/template': 7.25.9 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 convert-source-map: 2.0.0 debug: 4.3.7 gensync: 1.0.0-beta.2 @@ -254,225 +255,206 @@ packages: transitivePeerDependencies: - supports-color - /@babel/generator@7.25.7: - resolution: {integrity: sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==} + /@babel/generator@7.26.0: + resolution: {integrity: sha512-/AIkAmInnWwgEAJGQr9vY0c66Mj6kjkE2ZPB1PurTRaRAh3U+J45sAQMjQDJdh4WbR3l0x5xkimXBKyBXXAu2w==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.25.7 + '@babel/parser': 7.26.1 + '@babel/types': 7.26.0 '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.0.2 - /@babel/helper-annotate-as-pure@7.25.7: - resolution: {integrity: sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==} + /@babel/helper-annotate-as-pure@7.25.9: + resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.25.7 + '@babel/types': 7.26.0 dev: true - /@babel/helper-compilation-targets@7.25.7: - resolution: {integrity: sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==} + /@babel/helper-compilation-targets@7.25.9: + resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/compat-data': 7.25.7 - '@babel/helper-validator-option': 7.25.7 - browserslist: 4.24.0 + '@babel/compat-data': 7.26.0 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.2 lru-cache: 5.1.1 semver: 6.3.1 - /@babel/helper-module-imports@7.25.7: - resolution: {integrity: sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==} + /@babel/helper-module-imports@7.25.9: + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/traverse': 7.25.7 - '@babel/types': 7.25.7 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 transitivePeerDependencies: - supports-color - /@babel/helper-module-transforms@7.25.7(@babel/core@7.25.7): - resolution: {integrity: sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==} + /@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0): + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.25.7 - '@babel/helper-module-imports': 7.25.7 - '@babel/helper-simple-access': 7.25.7 - '@babel/helper-validator-identifier': 7.25.7 - '@babel/traverse': 7.25.7 + '@babel/core': 7.26.0 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.25.9 transitivePeerDependencies: - supports-color - /@babel/helper-plugin-utils@7.25.7: - resolution: {integrity: sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==} + /@babel/helper-plugin-utils@7.25.9: + resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==} engines: {node: '>=6.9.0'} dev: true - /@babel/helper-simple-access@7.25.7: - resolution: {integrity: sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/traverse': 7.25.7 - '@babel/types': 7.25.7 - transitivePeerDependencies: - - supports-color - - /@babel/helper-string-parser@7.25.7: - resolution: {integrity: sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==} + /@babel/helper-string-parser@7.25.9: + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-identifier@7.25.7: - resolution: {integrity: sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==} + /@babel/helper-validator-identifier@7.25.9: + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-option@7.25.7: - resolution: {integrity: sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==} + /@babel/helper-validator-option@7.25.9: + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} engines: {node: '>=6.9.0'} - /@babel/helpers@7.25.7: - resolution: {integrity: sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==} + /@babel/helpers@7.26.0: + resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/template': 7.25.7 - '@babel/types': 7.25.7 + '@babel/template': 7.25.9 + '@babel/types': 7.26.0 - /@babel/highlight@7.25.7: - resolution: {integrity: sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.25.7 - chalk: 2.4.2 - js-tokens: 4.0.0 - picocolors: 1.1.0 - - /@babel/parser@7.25.7: - resolution: {integrity: sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==} + /@babel/parser@7.26.1: + resolution: {integrity: sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw==} engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.25.7 + '@babel/types': 7.26.0 - /@babel/plugin-syntax-jsx@7.25.7(@babel/core@7.25.7): - resolution: {integrity: sha512-ruZOnKO+ajVL/MVx+PwNBPOkrnXTXoWMtte1MBpegfCArhqOe3Bj52avVj1huLLxNKYKXYaSxZ2F+woK1ekXfw==} + /@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.25.7 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 dev: true - /@babel/plugin-transform-react-display-name@7.25.7(@babel/core@7.25.7): - resolution: {integrity: sha512-r0QY7NVU8OnrwE+w2IWiRom0wwsTbjx4+xH2RTd7AVdof3uurXOF+/mXHQDRk+2jIvWgSaCHKMgggfvM4dyUGA==} + /@babel/plugin-transform-react-display-name@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.25.7 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 dev: true - /@babel/plugin-transform-react-jsx-development@7.25.7(@babel/core@7.25.7): - resolution: {integrity: sha512-5yd3lH1PWxzW6IZj+p+Y4OLQzz0/LzlOG8vGqonHfVR3euf1vyzyMUJk9Ac+m97BH46mFc/98t9PmYLyvgL3qg==} + /@babel/plugin-transform-react-jsx-development@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.25.7 - '@babel/plugin-transform-react-jsx': 7.25.7(@babel/core@7.25.7) + '@babel/core': 7.26.0 + '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.0) transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-react-jsx@7.25.7(@babel/core@7.25.7): - resolution: {integrity: sha512-vILAg5nwGlR9EXE8JIOX4NHXd49lrYbN8hnjffDtoULwpL9hUx/N55nqh2qd0q6FyNDfjl9V79ecKGvFbcSA0Q==} + /@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.25.7 - '@babel/helper-annotate-as-pure': 7.25.7 - '@babel/helper-module-imports': 7.25.7 - '@babel/helper-plugin-utils': 7.25.7 - '@babel/plugin-syntax-jsx': 7.25.7(@babel/core@7.25.7) - '@babel/types': 7.25.7 + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0) + '@babel/types': 7.26.0 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-react-pure-annotations@7.25.7(@babel/core@7.25.7): - resolution: {integrity: sha512-6YTHJ7yjjgYqGc8S+CbEXhLICODk0Tn92j+vNJo07HFk9t3bjFgAKxPLFhHwF2NjmQVSI1zBRfBWUeVBa2osfA==} + /@babel/plugin-transform-react-pure-annotations@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.25.7 - '@babel/helper-annotate-as-pure': 7.25.7 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 dev: true - /@babel/preset-react@7.24.7(@babel/core@7.25.7): - resolution: {integrity: sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==} + /@babel/preset-react@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-D3to0uSPiWE7rBrdIICCd0tJSIGpLaaGptna2+w7Pft5xMqLpA1sz99DK5TZ1TjGbdQ/VI1eCSZ06dv3lT4JOw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.25.7 - '@babel/helper-plugin-utils': 7.25.7 - '@babel/helper-validator-option': 7.25.7 - '@babel/plugin-transform-react-display-name': 7.25.7(@babel/core@7.25.7) - '@babel/plugin-transform-react-jsx': 7.25.7(@babel/core@7.25.7) - '@babel/plugin-transform-react-jsx-development': 7.25.7(@babel/core@7.25.7) - '@babel/plugin-transform-react-pure-annotations': 7.25.7(@babel/core@7.25.7) + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-validator-option': 7.25.9 + '@babel/plugin-transform-react-display-name': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-react-jsx-development': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-react-pure-annotations': 7.25.9(@babel/core@7.26.0) transitivePeerDependencies: - supports-color dev: true - /@babel/runtime@7.25.7: - resolution: {integrity: sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==} + /@babel/runtime@7.26.0: + resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.14.1 - /@babel/template@7.25.7: - resolution: {integrity: sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==} + /@babel/template@7.25.9: + resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.25.7 - '@babel/parser': 7.25.7 - '@babel/types': 7.25.7 + '@babel/code-frame': 7.26.0 + '@babel/parser': 7.26.1 + '@babel/types': 7.26.0 - /@babel/traverse@7.25.7: - resolution: {integrity: sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==} + /@babel/traverse@7.25.9: + resolution: {integrity: sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.25.7 - '@babel/generator': 7.25.7 - '@babel/parser': 7.25.7 - '@babel/template': 7.25.7 - '@babel/types': 7.25.7 + '@babel/code-frame': 7.26.0 + '@babel/generator': 7.26.0 + '@babel/parser': 7.26.1 + '@babel/template': 7.25.9 + '@babel/types': 7.26.0 debug: 4.3.7 globals: 11.12.0 transitivePeerDependencies: - supports-color - /@babel/types@7.25.7: - resolution: {integrity: sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==} + /@babel/types@7.26.0: + resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-string-parser': 7.25.7 - '@babel/helper-validator-identifier': 7.25.7 - to-fast-properties: 2.0.0 + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 - /@bazel/runfiles@6.3.0: - resolution: {integrity: sha512-2Q+KC0ys+BLIBp6zsI8E6htEw1/R1cjA1Yt+3JiqdEB597aGpZKiJJP6FeJSA4LIAWlH/FDVDtgvJ77eeLNyiA==} + /@bazel/runfiles@6.3.1: + resolution: {integrity: sha512-1uLNT5NZsUVIGS4syuHwTzZ8HycMPyr6POA3FCE4GbMtc4rhoJk8aZKtNIRthJYfL+iioppi+rTfH3olMPr9nA==} dev: false /@emotion/babel-plugin@11.12.0: resolution: {integrity: sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==} dependencies: - '@babel/helper-module-imports': 7.25.7 - '@babel/runtime': 7.25.7 + '@babel/helper-module-imports': 7.25.9 + '@babel/runtime': 7.26.0 '@emotion/hash': 0.9.2 '@emotion/memoize': 0.9.0 '@emotion/serialize': 1.3.2 @@ -510,8 +492,8 @@ packages: resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} dev: false - /@emotion/react@11.11.4(@types/react@18.2.72)(react@18.2.0): - resolution: {integrity: sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==} + /@emotion/react@11.13.3(@types/react@18.2.72)(react@18.3.1): + resolution: {integrity: sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==} peerDependencies: '@types/react': '*' react: '>=16.8.0' @@ -519,16 +501,16 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.26.0 '@emotion/babel-plugin': 11.12.0 '@emotion/cache': 11.13.1 '@emotion/serialize': 1.3.2 - '@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@18.2.0) + '@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@18.3.1) '@emotion/utils': 1.4.1 - '@emotion/weak-memoize': 0.3.1 + '@emotion/weak-memoize': 0.4.0 '@types/react': 18.2.72 hoist-non-react-statics: 3.3.2 - react: 18.2.0 + react: 18.3.1 transitivePeerDependencies: - supports-color dev: false @@ -547,8 +529,8 @@ packages: resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==} dev: false - /@emotion/styled@11.11.5(@emotion/react@11.11.4)(@types/react@18.2.72)(react@18.2.0): - resolution: {integrity: sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==} + /@emotion/styled@11.13.0(@emotion/react@11.13.3)(@types/react@18.2.72)(react@18.3.1): + resolution: {integrity: sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==} peerDependencies: '@emotion/react': ^11.0.0-rc.0 '@types/react': '*' @@ -557,15 +539,15 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.26.0 '@emotion/babel-plugin': 11.12.0 '@emotion/is-prop-valid': 1.3.1 - '@emotion/react': 11.11.4(@types/react@18.2.72)(react@18.2.0) + '@emotion/react': 11.13.3(@types/react@18.2.72)(react@18.3.1) '@emotion/serialize': 1.3.2 - '@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@18.2.0) + '@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@18.3.1) '@emotion/utils': 1.4.1 '@types/react': 18.2.72 - react: 18.2.0 + react: 18.3.1 transitivePeerDependencies: - supports-color dev: false @@ -574,235 +556,240 @@ packages: resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==} dev: false - /@emotion/use-insertion-effect-with-fallbacks@1.1.0(react@18.2.0): + /@emotion/use-insertion-effect-with-fallbacks@1.1.0(react@18.3.1): resolution: {integrity: sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==} peerDependencies: react: '>=16.8.0' dependencies: - react: 18.2.0 + react: 18.3.1 dev: false /@emotion/utils@1.4.1: resolution: {integrity: sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA==} dev: false - /@emotion/weak-memoize@0.3.1: - resolution: {integrity: sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==} - dev: false - /@emotion/weak-memoize@0.4.0: resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} dev: false - /@esbuild/aix-ppc64@0.19.12: - resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} - engines: {node: '>=12'} + /@esbuild/aix-ppc64@0.24.0: + resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} + engines: {node: '>=18'} cpu: [ppc64] os: [aix] requiresBuild: true dev: true optional: true - /@esbuild/android-arm64@0.19.12: - resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} - engines: {node: '>=12'} + /@esbuild/android-arm64@0.24.0: + resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} + engines: {node: '>=18'} cpu: [arm64] os: [android] requiresBuild: true dev: true optional: true - /@esbuild/android-arm@0.19.12: - resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} - engines: {node: '>=12'} + /@esbuild/android-arm@0.24.0: + resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} + engines: {node: '>=18'} cpu: [arm] os: [android] requiresBuild: true dev: true optional: true - /@esbuild/android-x64@0.19.12: - resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} - engines: {node: '>=12'} + /@esbuild/android-x64@0.24.0: + resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} + engines: {node: '>=18'} cpu: [x64] os: [android] requiresBuild: true dev: true optional: true - /@esbuild/darwin-arm64@0.19.12: - resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} - engines: {node: '>=12'} + /@esbuild/darwin-arm64@0.24.0: + resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} + engines: {node: '>=18'} cpu: [arm64] os: [darwin] requiresBuild: true dev: true optional: true - /@esbuild/darwin-x64@0.19.12: - resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} - engines: {node: '>=12'} + /@esbuild/darwin-x64@0.24.0: + resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} + engines: {node: '>=18'} cpu: [x64] os: [darwin] requiresBuild: true dev: true optional: true - /@esbuild/freebsd-arm64@0.19.12: - resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} - engines: {node: '>=12'} + /@esbuild/freebsd-arm64@0.24.0: + resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} + engines: {node: '>=18'} cpu: [arm64] os: [freebsd] requiresBuild: true dev: true optional: true - /@esbuild/freebsd-x64@0.19.12: - resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} - engines: {node: '>=12'} + /@esbuild/freebsd-x64@0.24.0: + resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} + engines: {node: '>=18'} cpu: [x64] os: [freebsd] requiresBuild: true dev: true optional: true - /@esbuild/linux-arm64@0.19.12: - resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} - engines: {node: '>=12'} + /@esbuild/linux-arm64@0.24.0: + resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} + engines: {node: '>=18'} cpu: [arm64] os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/linux-arm@0.19.12: - resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} - engines: {node: '>=12'} + /@esbuild/linux-arm@0.24.0: + resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} + engines: {node: '>=18'} cpu: [arm] os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/linux-ia32@0.19.12: - resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} - engines: {node: '>=12'} + /@esbuild/linux-ia32@0.24.0: + resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} + engines: {node: '>=18'} cpu: [ia32] os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/linux-loong64@0.19.12: - resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} - engines: {node: '>=12'} + /@esbuild/linux-loong64@0.24.0: + resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} + engines: {node: '>=18'} cpu: [loong64] os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/linux-mips64el@0.19.12: - resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} - engines: {node: '>=12'} + /@esbuild/linux-mips64el@0.24.0: + resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} + engines: {node: '>=18'} cpu: [mips64el] os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/linux-ppc64@0.19.12: - resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} - engines: {node: '>=12'} + /@esbuild/linux-ppc64@0.24.0: + resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} + engines: {node: '>=18'} cpu: [ppc64] os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/linux-riscv64@0.19.12: - resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} - engines: {node: '>=12'} + /@esbuild/linux-riscv64@0.24.0: + resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} + engines: {node: '>=18'} cpu: [riscv64] os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/linux-s390x@0.19.12: - resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} - engines: {node: '>=12'} + /@esbuild/linux-s390x@0.24.0: + resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} + engines: {node: '>=18'} cpu: [s390x] os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/linux-x64@0.19.12: - resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} - engines: {node: '>=12'} + /@esbuild/linux-x64@0.24.0: + resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} + engines: {node: '>=18'} cpu: [x64] os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/netbsd-x64@0.19.12: - resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} - engines: {node: '>=12'} + /@esbuild/netbsd-x64@0.24.0: + resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} + engines: {node: '>=18'} cpu: [x64] os: [netbsd] requiresBuild: true dev: true optional: true - /@esbuild/openbsd-x64@0.19.12: - resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} - engines: {node: '>=12'} + /@esbuild/openbsd-arm64@0.24.0: + resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.24.0: + resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} + engines: {node: '>=18'} cpu: [x64] os: [openbsd] requiresBuild: true dev: true optional: true - /@esbuild/sunos-x64@0.19.12: - resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} - engines: {node: '>=12'} + /@esbuild/sunos-x64@0.24.0: + resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} + engines: {node: '>=18'} cpu: [x64] os: [sunos] requiresBuild: true dev: true optional: true - /@esbuild/win32-arm64@0.19.12: - resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} - engines: {node: '>=12'} + /@esbuild/win32-arm64@0.24.0: + resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} + engines: {node: '>=18'} cpu: [arm64] os: [win32] requiresBuild: true dev: true optional: true - /@esbuild/win32-ia32@0.19.12: - resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} - engines: {node: '>=12'} + /@esbuild/win32-ia32@0.24.0: + resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} + engines: {node: '>=18'} cpu: [ia32] os: [win32] requiresBuild: true dev: true optional: true - /@esbuild/win32-x64@0.19.12: - resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} - engines: {node: '>=12'} + /@esbuild/win32-x64@0.24.0: + resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} + engines: {node: '>=18'} cpu: [x64] os: [win32] requiresBuild: true dev: true optional: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.57.1): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + /@eslint-community/eslint-utils@4.4.1(eslint@8.57.1): + resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 @@ -811,18 +798,18 @@ packages: eslint-visitor-keys: 3.4.3 dev: true - /@eslint-community/eslint-utils@4.4.0(eslint@9.12.0): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + /@eslint-community/eslint-utils@4.4.1(eslint@9.13.0): + resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} 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.12.0(supports-color@9.4.0) + eslint: 9.13.0(supports-color@9.4.0) eslint-visitor-keys: 3.4.3 dev: true - /@eslint-community/regexpp@4.11.1: - resolution: {integrity: sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==} + /@eslint-community/regexpp@4.11.2: + resolution: {integrity: sha512-2WwyTYNVaMNUWPZTOJdkax9iqTdirrApgTbk+Qoq5EPX6myqZvG8QGFRgdKmkjKVG6/G/a565vpPauHk0+hpBA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} dev: true @@ -837,8 +824,8 @@ packages: - supports-color dev: true - /@eslint/core@0.6.0: - resolution: {integrity: sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==} + /@eslint/core@0.7.0: + resolution: {integrity: sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dev: true @@ -881,8 +868,8 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@eslint/js@9.12.0: - resolution: {integrity: sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==} + /@eslint/js@9.13.0: + resolution: {integrity: sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dev: true @@ -891,8 +878,8 @@ packages: engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dev: true - /@eslint/plugin-kit@0.2.0: - resolution: {integrity: sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==} + /@eslint/plugin-kit@0.2.1: + resolution: {integrity: sha512-HFZ4Mp26nbWk9d/BpvP0YNL6W4UoZF0VFcTw/aPPA8RpOxeFQgK+ClABGgAUXs9Y/RGX/l1vOmrqz1MQt9MNuw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: levn: 0.4.1 @@ -911,15 +898,15 @@ packages: '@floating-ui/utils': 0.2.8 dev: false - /@floating-ui/react-dom@2.1.2(react-dom@18.2.0)(react@18.2.0): + /@floating-ui/react-dom@2.1.2(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' dependencies: '@floating-ui/dom': 1.6.11 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) dev: false /@floating-ui/utils@0.2.8: @@ -979,12 +966,14 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: jest-get-type: 29.6.3 + dev: false /@jest/schemas@29.6.3: resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@sinclair/typebox': 0.27.8 + dev: false /@jest/types@29.6.3: resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} @@ -996,6 +985,7 @@ packages: '@types/node': 20.12.12 '@types/yargs': 17.0.33 chalk: 4.1.2 + dev: false /@jridgewell/gen-mapping@0.3.5: resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} @@ -1036,7 +1026,7 @@ packages: lodash: 4.17.21 dev: true - /@mui/base@5.0.0-beta.40(@types/react@18.2.72)(react-dom@18.2.0)(react@18.2.0): + /@mui/base@5.0.0-beta.40(@types/react@18.2.72)(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==} engines: {node: '>=12.0.0'} peerDependencies: @@ -1047,23 +1037,23 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 - '@floating-ui/react-dom': 2.1.2(react-dom@18.2.0)(react@18.2.0) - '@mui/types': 7.2.17(@types/react@18.2.72) - '@mui/utils': 5.16.6(@types/react@18.2.72)(react@18.2.0) + '@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.18(@types/react@18.2.72) + '@mui/utils': 5.16.6(@types/react@18.2.72)(react@18.3.1) '@popperjs/core': 2.11.8 '@types/react': 18.2.72 clsx: 2.1.1 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) dev: false /@mui/core-downloads-tracker@5.16.7: resolution: {integrity: sha512-RtsCt4Geed2/v74sbihWzzRs+HsIQCfclHeORh5Ynu2fS4icIKozcSubwuG7vtzq2uW3fOR1zITSP84TNt2GoQ==} dev: false - /@mui/icons-material@5.15.18(@mui/material@5.15.18)(@types/react@18.2.72)(react@18.2.0): + /@mui/icons-material@5.15.18(@mui/material@5.15.18)(@types/react@18.2.72)(react@18.3.1): resolution: {integrity: sha512-jGhyw02TSLM0NgW+MDQRLLRUD/K4eN9rlK2pTBTL1OtzyZmQ8nB060zK1wA0b7cVrIiG+zyrRmNAvGWXwm2N9Q==} engines: {node: '>=12.0.0'} peerDependencies: @@ -1074,13 +1064,13 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 - '@mui/material': 5.15.18(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.2.72)(react-dom@18.2.0)(react@18.2.0) + '@babel/runtime': 7.26.0 + '@mui/material': 5.15.18(@emotion/react@11.13.3)(@emotion/styled@11.13.0)(@types/react@18.2.72)(react-dom@18.3.1)(react@18.3.1) '@types/react': 18.2.72 - react: 18.2.0 + react: 18.3.1 dev: false - /@mui/material@5.15.18(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.2.72)(react-dom@18.2.0)(react@18.2.0): + /@mui/material@5.15.18(@emotion/react@11.13.3)(@emotion/styled@11.13.0)(@types/react@18.2.72)(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: @@ -1097,26 +1087,26 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 - '@emotion/react': 11.11.4(@types/react@18.2.72)(react@18.2.0) - '@emotion/styled': 11.11.5(@emotion/react@11.11.4)(@types/react@18.2.72)(react@18.2.0) - '@mui/base': 5.0.0-beta.40(@types/react@18.2.72)(react-dom@18.2.0)(react@18.2.0) + '@babel/runtime': 7.26.0 + '@emotion/react': 11.13.3(@types/react@18.2.72)(react@18.3.1) + '@emotion/styled': 11.13.0(@emotion/react@11.13.3)(@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) '@mui/core-downloads-tracker': 5.16.7 - '@mui/system': 5.16.7(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.2.72)(react@18.2.0) - '@mui/types': 7.2.17(@types/react@18.2.72) - '@mui/utils': 5.16.6(@types/react@18.2.72)(react@18.2.0) + '@mui/system': 5.16.7(@emotion/react@11.13.3)(@emotion/styled@11.13.0)(@types/react@18.2.72)(react@18.3.1) + '@mui/types': 7.2.18(@types/react@18.2.72) + '@mui/utils': 5.16.6(@types/react@18.2.72)(react@18.3.1) '@types/react': 18.2.72 '@types/react-transition-group': 4.4.11 clsx: 2.1.1 csstype: 3.1.3 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) react-is: 18.3.1 - react-transition-group: 4.4.5(react-dom@18.2.0)(react@18.2.0) + react-transition-group: 4.4.5(react-dom@18.3.1)(react@18.3.1) dev: false - /@mui/private-theming@5.16.6(@types/react@18.2.72)(react@18.2.0): + /@mui/private-theming@5.16.6(@types/react@18.2.72)(react@18.3.1): resolution: {integrity: sha512-rAk+Rh8Clg7Cd7shZhyt2HGTTE5wYKNSJ5sspf28Fqm/PZ69Er9o6KX25g03/FG2dfpg5GCwZh/xOojiTfm3hw==} engines: {node: '>=12.0.0'} peerDependencies: @@ -1126,14 +1116,14 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 - '@mui/utils': 5.16.6(@types/react@18.2.72)(react@18.2.0) + '@babel/runtime': 7.26.0 + '@mui/utils': 5.16.6(@types/react@18.2.72)(react@18.3.1) '@types/react': 18.2.72 prop-types: 15.8.1 - react: 18.2.0 + react: 18.3.1 dev: false - /@mui/styled-engine@5.16.6(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(react@18.2.0): + /@mui/styled-engine@5.16.6(@emotion/react@11.13.3)(@emotion/styled@11.13.0)(react@18.3.1): resolution: {integrity: sha512-zaThmS67ZmtHSWToTiHslbI8jwrmITcN93LQaR2lKArbvS7Z3iLkwRoiikNWutx9MBs8Q6okKvbZq1RQYB3v7g==} engines: {node: '>=12.0.0'} peerDependencies: @@ -1146,16 +1136,16 @@ packages: '@emotion/styled': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.26.0 '@emotion/cache': 11.13.1 - '@emotion/react': 11.11.4(@types/react@18.2.72)(react@18.2.0) - '@emotion/styled': 11.11.5(@emotion/react@11.11.4)(@types/react@18.2.72)(react@18.2.0) + '@emotion/react': 11.13.3(@types/react@18.2.72)(react@18.3.1) + '@emotion/styled': 11.13.0(@emotion/react@11.13.3)(@types/react@18.2.72)(react@18.3.1) csstype: 3.1.3 prop-types: 15.8.1 - react: 18.2.0 + react: 18.3.1 dev: false - /@mui/system@5.16.7(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.2.72)(react@18.2.0): + /@mui/system@5.16.7(@emotion/react@11.13.3)(@emotion/styled@11.13.0)(@types/react@18.2.72)(react@18.3.1): resolution: {integrity: sha512-Jncvs/r/d/itkxh7O7opOunTqbbSSzMTHzZkNLM+FjAOg+cYAZHrPDlYe1ZGKUYORwwb2XexlWnpZp0kZ4AHuA==} engines: {node: '>=12.0.0'} peerDependencies: @@ -1171,22 +1161,22 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 - '@emotion/react': 11.11.4(@types/react@18.2.72)(react@18.2.0) - '@emotion/styled': 11.11.5(@emotion/react@11.11.4)(@types/react@18.2.72)(react@18.2.0) - '@mui/private-theming': 5.16.6(@types/react@18.2.72)(react@18.2.0) - '@mui/styled-engine': 5.16.6(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(react@18.2.0) - '@mui/types': 7.2.17(@types/react@18.2.72) - '@mui/utils': 5.16.6(@types/react@18.2.72)(react@18.2.0) + '@babel/runtime': 7.26.0 + '@emotion/react': 11.13.3(@types/react@18.2.72)(react@18.3.1) + '@emotion/styled': 11.13.0(@emotion/react@11.13.3)(@types/react@18.2.72)(react@18.3.1) + '@mui/private-theming': 5.16.6(@types/react@18.2.72)(react@18.3.1) + '@mui/styled-engine': 5.16.6(@emotion/react@11.13.3)(@emotion/styled@11.13.0)(react@18.3.1) + '@mui/types': 7.2.18(@types/react@18.2.72) + '@mui/utils': 5.16.6(@types/react@18.2.72)(react@18.3.1) '@types/react': 18.2.72 clsx: 2.1.1 csstype: 3.1.3 prop-types: 15.8.1 - react: 18.2.0 + react: 18.3.1 dev: false - /@mui/types@7.2.17(@types/react@18.2.72): - resolution: {integrity: sha512-oyumoJgB6jDV8JFzRqjBo2daUuHpzDjoO/e3IrRhhHo/FxJlaVhET6mcNrKHUq2E+R+q3ql0qAtvQ4rfWHhAeQ==} + /@mui/types@7.2.18(@types/react@18.2.72): + resolution: {integrity: sha512-uvK9dWeyCJl/3ocVnTOS6nlji/Knj8/tVqVX03UVTpdmTJYu/s4jtDd9Kvv0nRGE0CUSNW1UYAci7PYypjealg==} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: @@ -1196,7 +1186,7 @@ packages: '@types/react': 18.2.72 dev: false - /@mui/utils@5.16.6(@types/react@18.2.72)(react@18.2.0): + /@mui/utils@5.16.6(@types/react@18.2.72)(react@18.3.1): resolution: {integrity: sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==} engines: {node: '>=12.0.0'} peerDependencies: @@ -1206,13 +1196,13 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 - '@mui/types': 7.2.17(@types/react@18.2.72) + '@babel/runtime': 7.26.0 + '@mui/types': 7.2.18(@types/react@18.2.72) '@types/prop-types': 15.7.13 '@types/react': 18.2.72 clsx: 2.1.1 prop-types: 15.8.1 - react: 18.2.0 + react: 18.3.1 react-is: 18.3.1 dev: false @@ -1250,8 +1240,8 @@ packages: resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} dev: false - /@remix-run/router@1.15.3: - resolution: {integrity: sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==} + /@remix-run/router@1.20.0: + resolution: {integrity: sha512-mUnk8rPJBI9loFDZ+YzPGdeniYK+FTmRD1TMCz7ev2SNIozyKKpnGgsxO34u6Z4z/t0ITuu7voi/AshfsGsgFg==} engines: {node: '>=14.0.0'} dev: false @@ -1261,6 +1251,7 @@ packages: /@sinclair/typebox@0.27.8: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + dev: false /@sinonjs/commons@3.0.1: resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} @@ -1268,8 +1259,8 @@ packages: type-detect: 4.0.8 dev: true - /@sinonjs/fake-timers@13.0.2: - resolution: {integrity: sha512-4Bb+oqXZTSTZ1q27Izly9lv8B9dlV61CROxPiVtywwzv5SnytJqhvYe6FclHYuXml4cd1VHPo1zd5PmTeJozvA==} + /@sinonjs/fake-timers@13.0.4: + resolution: {integrity: sha512-wpUq+QiKxrWk7U2pdvNSY9fNX62/k+7eEdlQMO0A3rU8tQ+vvzY/WzBhMz+GbQlATXZlXWYQqFWNFcn1SVvThA==} dependencies: '@sinonjs/commons': 3.0.1 dev: true @@ -1290,8 +1281,8 @@ packages: resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} engines: {node: '>=18'} dependencies: - '@babel/code-frame': 7.25.7 - '@babel/runtime': 7.25.7 + '@babel/code-frame': 7.26.0 + '@babel/runtime': 7.26.0 '@types/aria-query': 5.0.4 aria-query: 5.3.0 chalk: 4.1.2 @@ -1304,8 +1295,8 @@ packages: resolution: {integrity: sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==} engines: {node: '>=14'} dependencies: - '@babel/code-frame': 7.25.7 - '@babel/runtime': 7.25.7 + '@babel/code-frame': 7.26.0 + '@babel/runtime': 7.26.0 '@types/aria-query': 5.0.4 aria-query: 5.1.3 chalk: 4.1.2 @@ -1314,30 +1305,11 @@ packages: pretty-format: 27.5.1 dev: true - /@testing-library/jest-dom@6.4.5(@types/jest@29.5.12): - resolution: {integrity: sha512-AguB9yvTXmCnySBP1lWjfNNUwpbElsaQ567lt2VdGqAdHtpieLgjmcVyv1q7PMIvLbgpDdkWV5Ydv3FEejyp2A==} + /@testing-library/jest-dom@6.6.2: + resolution: {integrity: sha512-P6GJD4yqc9jZLbe98j/EkyQDTPgqftohZF5FBkHY5BUERZmcf4HeO2k0XaefEg329ux2p21i1A1DmyQ1kKw2Jw==} engines: {node: '>=14', npm: '>=6', yarn: '>=1'} - peerDependencies: - '@jest/globals': '>= 28' - '@types/bun': latest - '@types/jest': '>= 28' - jest: '>= 28' - vitest: '>= 0.32' - peerDependenciesMeta: - '@jest/globals': - optional: true - '@types/bun': - optional: true - '@types/jest': - optional: true - jest: - optional: true - vitest: - optional: true dependencies: '@adobe/css-tools': 4.4.0 - '@babel/runtime': 7.25.7 - '@types/jest': 29.5.12 aria-query: 5.3.2 chalk: 3.0.0 css.escape: 1.5.1 @@ -1346,18 +1318,18 @@ packages: redent: 3.0.0 dev: true - /@testing-library/react@14.3.1(react-dom@18.2.0)(react@18.2.0): + /@testing-library/react@14.3.1(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-H99XjUhWQw0lTgyMN05W3xQG1Nh4lq574D8keFf1dDoNTJgp66VbJozRaczoF+wsiaPJNt/TcnfpLGufGxSrZQ==} engines: {node: '>=14'} peerDependencies: react: ^18.0.0 react-dom: ^18.0.0 dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.26.0 '@testing-library/dom': 9.3.4 '@types/react-dom': 18.2.22 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) dev: true /@testing-library/user-event@14.5.2(@testing-library/dom@10.4.0): @@ -1383,22 +1355,26 @@ packages: /@types/istanbul-lib-coverage@2.0.6: resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + dev: false /@types/istanbul-lib-report@3.0.3: resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} dependencies: '@types/istanbul-lib-coverage': 2.0.6 + dev: false /@types/istanbul-reports@3.0.4: resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} dependencies: '@types/istanbul-lib-report': 3.0.3 + dev: false - /@types/jest@29.5.12: - resolution: {integrity: sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==} + /@types/jest@29.5.14: + resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} dependencies: expect: 29.7.0 pretty-format: 29.7.0 + dev: false /@types/json-schema@7.0.15: resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -1427,6 +1403,7 @@ packages: resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==} dependencies: undici-types: 5.26.5 + dev: false /@types/parse-json@4.0.2: resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} @@ -1479,16 +1456,19 @@ packages: /@types/stack-utils@2.0.3: resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + dev: false /@types/yargs-parser@21.0.3: resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + dev: false /@types/yargs@17.0.33: resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} dependencies: '@types/yargs-parser': 21.0.3 + dev: false - /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.1)(typescript@5.4.5): + /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.1)(typescript@5.6.3): resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1499,24 +1479,24 @@ packages: typescript: optional: true dependencies: - '@eslint-community/regexpp': 4.11.1 - '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.4.5) + '@eslint-community/regexpp': 4.11.2 + '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.6.3) '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/type-utils': 5.62.0(eslint@8.57.1)(typescript@5.4.5) - '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.4.5) + '@typescript-eslint/type-utils': 5.62.0(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.6.3) debug: 4.3.7 eslint: 8.57.1 graphemer: 1.4.0 ignore: 5.3.2 natural-compare-lite: 1.4.0 semver: 7.6.3 - tsutils: 3.21.0(typescript@5.4.5) - typescript: 5.4.5 + tsutils: 3.21.0(typescript@5.6.3) + typescript: 5.6.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.4.5): + /@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3): resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1528,10 +1508,10 @@ packages: dependencies: '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.6.3) debug: 4.3.7 eslint: 8.57.1 - typescript: 5.4.5 + typescript: 5.6.3 transitivePeerDependencies: - supports-color dev: true @@ -1544,7 +1524,7 @@ packages: '@typescript-eslint/visitor-keys': 5.62.0 dev: true - /@typescript-eslint/type-utils@5.62.0(eslint@8.57.1)(typescript@5.4.5): + /@typescript-eslint/type-utils@5.62.0(eslint@8.57.1)(typescript@5.6.3): resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1554,12 +1534,12 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5) - '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.6.3) + '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.6.3) debug: 4.3.7 eslint: 8.57.1 - tsutils: 3.21.0(typescript@5.4.5) - typescript: 5.4.5 + tsutils: 3.21.0(typescript@5.6.3) + typescript: 5.6.3 transitivePeerDependencies: - supports-color dev: true @@ -1569,7 +1549,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/typescript-estree@5.62.0(typescript@5.4.5): + /@typescript-eslint/typescript-estree@5.62.0(typescript@5.6.3): resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1584,24 +1564,24 @@ packages: globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.3 - tsutils: 3.21.0(typescript@5.4.5) - typescript: 5.4.5 + tsutils: 3.21.0(typescript@5.6.3) + typescript: 5.6.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@5.4.5): + /@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@5.6.3): resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) '@types/json-schema': 7.0.15 '@types/semver': 7.5.8 '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.6.3) eslint: 8.57.1 eslint-scope: 5.1.1 semver: 7.6.3 @@ -1626,35 +1606,35 @@ packages: resolution: {integrity: sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA==} engines: {node: '>=8'} dependencies: - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@wry/context@0.7.4: resolution: {integrity: sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==} engines: {node: '>=8'} dependencies: - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@wry/equality@0.5.7: resolution: {integrity: sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==} engines: {node: '>=8'} dependencies: - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@wry/trie@0.4.3: resolution: {integrity: sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==} engines: {node: '>=8'} dependencies: - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@wry/trie@0.5.0: resolution: {integrity: sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==} engines: {node: '>=8'} dependencies: - tslib: 2.7.0 + tslib: 2.8.0 dev: false /accepts@1.3.8: @@ -1665,16 +1645,16 @@ packages: negotiator: 0.6.3 dev: true - /acorn-jsx@5.3.2(acorn@8.12.1): + /acorn-jsx@5.3.2(acorn@8.13.0): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - acorn: 8.12.1 + acorn: 8.13.0 dev: true - /acorn@8.12.1: - resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} + /acorn@8.13.0: + resolution: {integrity: sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==} engines: {node: '>=0.4.0'} hasBin: true dev: true @@ -1697,12 +1677,6 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - /ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -1855,15 +1829,15 @@ packages: possible-typed-array-names: 1.0.0 dev: true - /babel-literal-to-ast@2.1.0(@babel/core@7.25.7): + /babel-literal-to-ast@2.1.0(@babel/core@7.26.0): resolution: {integrity: sha512-CxfpQ0ysQ0bZOhlaPgcWjl79Em16Rhqc6++UAFn0A3duiXmuyhhj8yyl9PYbj0I0CyjrHovdDbp2QEKT7uIMxw==} peerDependencies: '@babel/core': ^7.1.2 dependencies: - '@babel/core': 7.25.7 - '@babel/parser': 7.25.7 - '@babel/traverse': 7.25.7 - '@babel/types': 7.25.7 + '@babel/core': 7.26.0 + '@babel/parser': 7.26.1 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 transitivePeerDependencies: - supports-color dev: false @@ -1871,7 +1845,7 @@ packages: /babel-plugin-macros@2.8.0: resolution: {integrity: sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==} dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.26.0 cosmiconfig: 6.0.0 resolve: 1.22.8 dev: false @@ -1880,7 +1854,7 @@ packages: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.26.0 cosmiconfig: 7.1.0 resolve: 1.22.8 dev: false @@ -1942,15 +1916,15 @@ packages: resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} dev: true - /browserslist@4.24.0: - resolution: {integrity: sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==} + /browserslist@4.24.2: + resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001667 - electron-to-chromium: 1.5.32 + caniuse-lite: 1.0.30001671 + electron-to-chromium: 1.5.47 node-releases: 2.0.18 - update-browserslist-db: 1.1.1(browserslist@4.24.0) + update-browserslist-db: 1.1.1(browserslist@4.24.2) /btoa@1.2.1: resolution: {integrity: sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==} @@ -1999,7 +1973,7 @@ packages: resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} dependencies: pascal-case: 3.1.2 - tslib: 2.7.0 + tslib: 2.8.0 dev: true /camelcase@6.3.0: @@ -2007,8 +1981,8 @@ packages: engines: {node: '>=10'} dev: true - /caniuse-lite@1.0.30001667: - resolution: {integrity: sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==} + /caniuse-lite@1.0.30001671: + resolution: {integrity: sha512-jocyVaSSfXg2faluE6hrWkMgDOiULBMca4QLtDT39hw1YxaIPHWc1CcTCKkPmHgGH6tKji6ZNbMSmUAvENf2/A==} /catharsis@0.9.0: resolution: {integrity: sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==} @@ -2017,14 +1991,6 @@ packages: lodash: 4.17.21 dev: true - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - /chalk@3.0.0: resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} engines: {node: '>=8'} @@ -2062,6 +2028,7 @@ packages: /ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} + dev: false /clean-css@5.3.3: resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} @@ -2070,7 +2037,7 @@ packages: source-map: 0.6.1 dev: true - /clean-jsdoc-theme@4.3.0(jsdoc@4.0.3): + /clean-jsdoc-theme@4.3.0(jsdoc@4.0.4): resolution: {integrity: sha512-QMrBdZ2KdPt6V2Ytg7dIt0/q32U4COpxvR0UDhPjRRKRL0o0MvRCR5YpY37/4rPF1SI1AYEKAWyof7ndCb/dzA==} peerDependencies: jsdoc: '>=3.x <=4.x' @@ -2078,7 +2045,7 @@ packages: '@jsdoc/salty': 0.2.8 fs-extra: 10.1.0 html-minifier-terser: 7.2.0 - jsdoc: 4.0.3 + jsdoc: 4.0.4 klaw-sync: 6.0.0 lodash: 4.17.21 showdown: 2.1.0 @@ -2096,20 +2063,12 @@ packages: engines: {node: '>=6'} dev: false - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - /color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} dependencies: color-name: 1.1.4 - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} @@ -2163,8 +2122,8 @@ packages: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} dev: true - /cookie@0.6.0: - resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + /cookie@0.7.1: + resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} engines: {node: '>= 0.6'} dev: true @@ -2374,6 +2333,7 @@ packages: /diff-sequences@29.6.3: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: false /diff@5.2.0: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} @@ -2417,7 +2377,7 @@ packages: /dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.26.0 csstype: 3.1.3 dev: false @@ -2425,7 +2385,7 @@ packages: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} dependencies: no-case: 3.0.4 - tslib: 2.7.0 + tslib: 2.8.0 dev: true /duplexer@0.1.2: @@ -2444,8 +2404,8 @@ packages: jake: 10.9.2 dev: false - /electron-to-chromium@1.5.32: - resolution: {integrity: sha512-M+7ph0VGBQqqpTT2YrabjNKSQ2fEl9PVx6AK3N558gDH9NO8O6XN9SXXFWRo9u9PbEg/bWq+tjXQr+eXmxubCw==} + /electron-to-chromium@1.5.47: + resolution: {integrity: sha512-zS5Yer0MOYw4rtK2iq43cJagHZ8sXN0jDHDKzB+86gSBSAI4v07S97mcq+Gs2vclAxSh1j7vOAHxSVgduiiuVQ==} /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2556,8 +2516,8 @@ packages: stop-iteration-iterator: 1.0.0 dev: true - /es-iterator-helpers@1.0.19: - resolution: {integrity: sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==} + /es-iterator-helpers@1.1.0: + resolution: {integrity: sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.7 @@ -2572,7 +2532,7 @@ packages: has-proto: 1.0.3 has-symbols: 1.0.3 internal-slot: 1.0.7 - iterator.prototype: 1.1.2 + iterator.prototype: 1.1.3 safe-array-concat: 1.1.2 dev: true @@ -2607,35 +2567,36 @@ packages: is-symbol: 1.0.4 dev: true - /esbuild@0.19.12: - resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} - engines: {node: '>=12'} + /esbuild@0.24.0: + resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} + engines: {node: '>=18'} hasBin: true requiresBuild: true optionalDependencies: - '@esbuild/aix-ppc64': 0.19.12 - '@esbuild/android-arm': 0.19.12 - '@esbuild/android-arm64': 0.19.12 - '@esbuild/android-x64': 0.19.12 - '@esbuild/darwin-arm64': 0.19.12 - '@esbuild/darwin-x64': 0.19.12 - '@esbuild/freebsd-arm64': 0.19.12 - '@esbuild/freebsd-x64': 0.19.12 - '@esbuild/linux-arm': 0.19.12 - '@esbuild/linux-arm64': 0.19.12 - '@esbuild/linux-ia32': 0.19.12 - '@esbuild/linux-loong64': 0.19.12 - '@esbuild/linux-mips64el': 0.19.12 - '@esbuild/linux-ppc64': 0.19.12 - '@esbuild/linux-riscv64': 0.19.12 - '@esbuild/linux-s390x': 0.19.12 - '@esbuild/linux-x64': 0.19.12 - '@esbuild/netbsd-x64': 0.19.12 - '@esbuild/openbsd-x64': 0.19.12 - '@esbuild/sunos-x64': 0.19.12 - '@esbuild/win32-arm64': 0.19.12 - '@esbuild/win32-ia32': 0.19.12 - '@esbuild/win32-x64': 0.19.12 + '@esbuild/aix-ppc64': 0.24.0 + '@esbuild/android-arm': 0.24.0 + '@esbuild/android-arm64': 0.24.0 + '@esbuild/android-x64': 0.24.0 + '@esbuild/darwin-arm64': 0.24.0 + '@esbuild/darwin-x64': 0.24.0 + '@esbuild/freebsd-arm64': 0.24.0 + '@esbuild/freebsd-x64': 0.24.0 + '@esbuild/linux-arm': 0.24.0 + '@esbuild/linux-arm64': 0.24.0 + '@esbuild/linux-ia32': 0.24.0 + '@esbuild/linux-loong64': 0.24.0 + '@esbuild/linux-mips64el': 0.24.0 + '@esbuild/linux-ppc64': 0.24.0 + '@esbuild/linux-riscv64': 0.24.0 + '@esbuild/linux-s390x': 0.24.0 + '@esbuild/linux-x64': 0.24.0 + '@esbuild/netbsd-x64': 0.24.0 + '@esbuild/openbsd-arm64': 0.24.0 + '@esbuild/openbsd-x64': 0.24.0 + '@esbuild/sunos-x64': 0.24.0 + '@esbuild/win32-arm64': 0.24.0 + '@esbuild/win32-ia32': 0.24.0 + '@esbuild/win32-x64': 0.24.0 dev: true /escalade@3.2.0: @@ -2645,10 +2606,6 @@ packages: /escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - /escape-string-regexp@2.0.0: resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} engines: {node: '>=8'} @@ -2657,36 +2614,36 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - /eslint-compat-utils@0.5.1(eslint@9.12.0): + /eslint-compat-utils@0.5.1(eslint@9.13.0): resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} engines: {node: '>=12'} peerDependencies: eslint: '>=6.0.0' dependencies: - eslint: 9.12.0(supports-color@9.4.0) + eslint: 9.13.0(supports-color@9.4.0) semver: 7.6.3 dev: true - /eslint-config-prettier@9.1.0(eslint@9.12.0): + /eslint-config-prettier@9.1.0(eslint@9.13.0): resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 9.12.0(supports-color@9.4.0) + eslint: 9.13.0(supports-color@9.4.0) dev: true - /eslint-config-standard-jsx@11.0.0(eslint-plugin-react@7.37.1)(eslint@8.57.1): + /eslint-config-standard-jsx@11.0.0(eslint-plugin-react@7.37.2)(eslint@8.57.1): resolution: {integrity: sha512-+1EV/R0JxEK1L0NGolAr8Iktm3Rgotx3BKwgaX+eAuSX8D952LULKtjgZD3F+e6SvibONnhLwoTi9DPxN5LvvQ==} peerDependencies: eslint: ^8.8.0 eslint-plugin-react: ^7.28.0 dependencies: eslint: 8.57.1 - eslint-plugin-react: 7.37.1(eslint@8.57.1) + eslint-plugin-react: 7.37.2(eslint@8.57.1) dev: true - /eslint-config-standard-with-typescript@23.0.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint-plugin-import@2.31.0)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.6.0)(eslint@8.57.1)(typescript@5.4.5): + /eslint-config-standard-with-typescript@23.0.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint-plugin-import@2.31.0)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.6.0)(eslint@8.57.1)(typescript@5.6.3): resolution: {integrity: sha512-iaaWifImn37Z1OXbNW1es7KI+S7D408F9ys0bpaQf2temeBWlvb0Nc5qHkOgYaRb5QxTZT32GGeN1gtswASOXA==} deprecated: Please use eslint-config-love, instead. peerDependencies: @@ -2697,14 +2654,14 @@ packages: eslint-plugin-promise: ^6.0.0 typescript: '*' dependencies: - '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.1)(typescript@5.4.5) - '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.4.5) + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.6.3) eslint: 8.57.1 eslint-config-standard: 17.0.0(eslint-plugin-import@2.31.0)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.6.0)(eslint@8.57.1) eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.1) eslint-plugin-n: 15.7.0(eslint@8.57.1) eslint-plugin-promise: 6.6.0(eslint@8.57.1) - typescript: 5.4.5 + typescript: 5.6.3 transitivePeerDependencies: - supports-color dev: true @@ -2754,7 +2711,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.4.5) + '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.6.3) debug: 3.2.7 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 @@ -2762,16 +2719,16 @@ packages: - supports-color dev: true - /eslint-plugin-es-x@7.8.0(eslint@9.12.0): + /eslint-plugin-es-x@7.8.0(eslint@9.13.0): resolution: {integrity: sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: eslint: '>=8' dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.12.0) - '@eslint-community/regexpp': 4.11.1 - eslint: 9.12.0(supports-color@9.4.0) - eslint-compat-utils: 0.5.1(eslint@9.12.0) + '@eslint-community/eslint-utils': 4.4.1(eslint@9.13.0) + '@eslint-community/regexpp': 4.11.2 + eslint: 9.13.0(supports-color@9.4.0) + eslint-compat-utils: 0.5.1(eslint@9.13.0) dev: true /eslint-plugin-es@4.1.0(eslint@8.57.1): @@ -2796,7 +2753,7 @@ packages: optional: true dependencies: '@rtsao/scc': 1.1.0 - '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.4.5) + '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.6.3) array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 array.prototype.flat: 1.3.2 @@ -2822,14 +2779,14 @@ packages: - supports-color dev: true - /eslint-plugin-mocha@10.5.0(eslint@9.12.0): + /eslint-plugin-mocha@10.5.0(eslint@9.13.0): resolution: {integrity: sha512-F2ALmQVPT1GoP27O1JTZGrV9Pqg8k79OeIuvw63UxMtQKREZtmkK1NFgkZQ2TW7L2JSSFKHFPTtHu5z8R9QNRw==} engines: {node: '>=14.0.0'} peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 9.12.0(supports-color@9.4.0) - eslint-utils: 3.0.0(eslint@9.12.0) + eslint: 9.13.0(supports-color@9.4.0) + eslint-utils: 3.0.0(eslint@9.13.0) globals: 13.24.0 rambda: 7.5.0 dev: true @@ -2851,18 +2808,18 @@ packages: semver: 7.6.3 dev: true - /eslint-plugin-n@17.10.3(eslint@9.12.0): - resolution: {integrity: sha512-ySZBfKe49nQZWR1yFaA0v/GsH6Fgp8ah6XV0WDz6CN8WO0ek4McMzb7A2xnf4DCYV43frjCygvb9f/wx7UUxRw==} + /eslint-plugin-n@17.11.1(eslint@9.13.0): + resolution: {integrity: sha512-93IUD82N6tIEgjztVI/l3ElHtC2wTa9boJHrD8iN+NyDxjxz/daZUZKfkedjBZNdg6EqDk4irybUsiPwDqXAEA==} 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.12.0) + '@eslint-community/eslint-utils': 4.4.1(eslint@9.13.0) enhanced-resolve: 5.17.1 - eslint: 9.12.0(supports-color@9.4.0) - eslint-plugin-es-x: 7.8.0(eslint@9.12.0) + eslint: 9.13.0(supports-color@9.4.0) + eslint-plugin-es-x: 7.8.0(eslint@9.13.0) get-tsconfig: 4.8.1 - globals: 15.10.0 + globals: 15.11.0 ignore: 5.3.2 minimatch: 9.0.5 semver: 7.6.3 @@ -2873,7 +2830,7 @@ packages: engines: {node: '>=5.0.0'} dev: true - /eslint-plugin-prettier@5.2.1(eslint-config-prettier@9.1.0)(eslint@9.12.0)(prettier@3.3.3): + /eslint-plugin-prettier@5.2.1(eslint-config-prettier@9.1.0)(eslint@9.13.0)(prettier@3.3.3): resolution: {integrity: sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -2887,8 +2844,8 @@ packages: eslint-config-prettier: optional: true dependencies: - eslint: 9.12.0(supports-color@9.4.0) - eslint-config-prettier: 9.1.0(eslint@9.12.0) + eslint: 9.13.0(supports-color@9.4.0) + eslint-config-prettier: 9.1.0(eslint@9.13.0) prettier: 3.3.3 prettier-linter-helpers: 1.0.0 synckit: 0.9.2 @@ -2903,8 +2860,8 @@ packages: eslint: 8.57.1 dev: true - /eslint-plugin-react@7.37.1(eslint@8.57.1): - resolution: {integrity: sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==} + /eslint-plugin-react@7.37.2(eslint@8.57.1): + resolution: {integrity: sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==} engines: {node: '>=4'} peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 @@ -2914,7 +2871,7 @@ packages: array.prototype.flatmap: 1.3.2 array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 - es-iterator-helpers: 1.0.19 + es-iterator-helpers: 1.1.0 eslint: 8.57.1 estraverse: 5.3.0 hasown: 2.0.2 @@ -2971,13 +2928,13 @@ packages: eslint-visitor-keys: 2.1.0 dev: true - /eslint-utils@3.0.0(eslint@9.12.0): + /eslint-utils@3.0.0(eslint@9.13.0): resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} peerDependencies: eslint: '>=5' dependencies: - eslint: 9.12.0(supports-color@9.4.0) + eslint: 9.13.0(supports-color@9.4.0) eslint-visitor-keys: 2.1.0 dev: true @@ -3007,8 +2964,8 @@ packages: deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) - '@eslint-community/regexpp': 4.11.1 + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) + '@eslint-community/regexpp': 4.11.2 '@eslint/eslintrc': 2.1.4 '@eslint/js': 8.57.1 '@humanwhocodes/config-array': 0.13.0 @@ -3049,8 +3006,8 @@ packages: - supports-color dev: true - /eslint@9.12.0(supports-color@9.4.0): - resolution: {integrity: sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==} + /eslint@9.13.0(supports-color@9.4.0): + resolution: {integrity: sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -3059,13 +3016,13 @@ packages: jiti: optional: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.12.0) - '@eslint-community/regexpp': 4.11.1 + '@eslint-community/eslint-utils': 4.4.1(eslint@9.13.0) + '@eslint-community/regexpp': 4.11.2 '@eslint/config-array': 0.18.0(supports-color@9.4.0) - '@eslint/core': 0.6.0 + '@eslint/core': 0.7.0 '@eslint/eslintrc': 3.1.0(supports-color@9.4.0) - '@eslint/js': 9.12.0 - '@eslint/plugin-kit': 0.2.0 + '@eslint/js': 9.13.0 + '@eslint/plugin-kit': 0.2.1 '@humanfs/node': 0.16.5 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.3.1 @@ -3102,8 +3059,8 @@ packages: resolution: {integrity: sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: - acorn: 8.12.1 - acorn-jsx: 5.3.2(acorn@8.12.1) + acorn: 8.13.0 + acorn-jsx: 5.3.2(acorn@8.13.0) eslint-visitor-keys: 4.1.0 dev: true @@ -3111,8 +3068,8 @@ packages: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - acorn: 8.12.1 - acorn-jsx: 5.3.2(acorn@8.12.1) + acorn: 8.13.0 + acorn-jsx: 5.3.2(acorn@8.13.0) eslint-visitor-keys: 3.4.3 dev: true @@ -3163,9 +3120,10 @@ packages: jest-matcher-utils: 29.7.0 jest-message-util: 29.7.0 jest-util: 29.7.0 + dev: false - /express@4.21.0(supports-color@9.4.0): - resolution: {integrity: sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==} + /express@4.21.1(supports-color@9.4.0): + resolution: {integrity: sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==} engines: {node: '>= 0.10.0'} dependencies: accepts: 1.3.8 @@ -3173,7 +3131,7 @@ packages: body-parser: 1.20.3(supports-color@9.4.0) content-disposition: 0.5.4 content-type: 1.0.5 - cookie: 0.6.0 + cookie: 0.7.1 cookie-signature: 1.0.6 debug: 2.6.9(supports-color@9.4.0) depd: 2.0.0 @@ -3475,8 +3433,8 @@ packages: engines: {node: '>=18'} dev: true - /globals@15.10.0: - resolution: {integrity: sha512-tqFIbz83w4Y5TCbtgjZjApohbuh7K9BxGYFm7ifwDR240tvdb7P9x+/9VvUKlmkPoiknoJtanI8UOrqxS3a7lQ==} + /globals@15.11.0: + resolution: {integrity: sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==} engines: {node: '>=18'} dev: true @@ -3520,14 +3478,14 @@ packages: graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: graphql: 16.8.1 - tslib: 2.7.0 + tslib: 2.8.0 dev: false - /graphql.macro@1.4.2(@babel/core@7.25.7)(graphql@16.8.1): + /graphql.macro@1.4.2(@babel/core@7.26.0)(graphql@16.8.1): resolution: {integrity: sha512-vcIaStPgS65gp5i1M3DSBimNVkyus0Z7k4VObWAyZS319tKlpX/TEIJSWTgOZU5k8dn4RRzGoS/elQhX2E6yBw==} dependencies: - '@babel/template': 7.25.7 - babel-literal-to-ast: 2.1.0(@babel/core@7.25.7) + '@babel/template': 7.25.9 + babel-literal-to-ast: 2.1.0(@babel/core@7.26.0) babel-plugin-macros: 2.8.0 graphql-tag: 2.12.6(graphql@16.8.1) transitivePeerDependencies: @@ -3552,10 +3510,6 @@ packages: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} dev: true - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -3616,7 +3570,7 @@ packages: entities: 4.5.0 param-case: 3.0.4 relateurl: 0.2.7 - terser: 5.34.1 + terser: 5.36.0 dev: true /http-errors@1.6.3: @@ -3926,8 +3880,9 @@ packages: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: true - /iterator.prototype@1.1.2: - resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} + /iterator.prototype@1.1.3: + resolution: {integrity: sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==} + engines: {node: '>= 0.4'} dependencies: define-properties: 1.2.1 get-intrinsic: 1.2.4 @@ -3955,10 +3910,12 @@ packages: diff-sequences: 29.6.3 jest-get-type: 29.6.3 pretty-format: 29.7.0 + dev: false /jest-get-type@29.6.3: resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: false /jest-matcher-utils@29.7.0: resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} @@ -3968,12 +3925,13 @@ packages: jest-diff: 29.7.0 jest-get-type: 29.6.3 pretty-format: 29.7.0 + dev: false /jest-message-util@29.7.0: resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@babel/code-frame': 7.25.7 + '@babel/code-frame': 7.26.0 '@jest/types': 29.6.3 '@types/stack-utils': 2.0.3 chalk: 4.1.2 @@ -3982,6 +3940,7 @@ packages: pretty-format: 29.7.0 slash: 3.0.0 stack-utils: 2.0.6 + dev: false /jest-util@29.7.0: resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} @@ -3993,6 +3952,7 @@ packages: ci-info: 3.9.0 graceful-fs: 4.2.11 picomatch: 2.3.1 + dev: false /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -4010,12 +3970,12 @@ packages: xmlcreate: 2.0.4 dev: true - /jsdoc@4.0.3: - resolution: {integrity: sha512-Nu7Sf35kXJ1MWDZIMAuATRQTg1iIPdzh7tqJ6jjvaU/GfDf+qi5UV8zJR3Mo+/pYFvm8mzay4+6O5EWigaQBQw==} + /jsdoc@4.0.4: + resolution: {integrity: sha512-zeFezwyXeG4syyYHbvh1A967IAqq/67yXtXvuL5wnqCkFZe8I0vKfm+EO+YEvLguo6w9CDUbrAXVtJSHh2E8rw==} engines: {node: '>=12.0.0'} hasBin: true dependencies: - '@babel/parser': 7.25.7 + '@babel/parser': 7.26.1 '@jsdoc/salty': 0.2.8 '@types/markdown-it': 14.1.2 bluebird: 3.7.2 @@ -4208,7 +4168,7 @@ packages: /lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} dependencies: - tslib: 2.7.0 + tslib: 2.8.0 dev: true /lru-cache@5.1.1: @@ -4428,7 +4388,7 @@ packages: resolution: {integrity: sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==} dependencies: '@sinonjs/commons': 3.0.1 - '@sinonjs/fake-timers': 13.0.2 + '@sinonjs/fake-timers': 13.0.4 '@sinonjs/text-encoding': 0.7.3 just-extend: 6.2.0 path-to-regexp: 8.2.0 @@ -4438,7 +4398,7 @@ packages: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} dependencies: lower-case: 2.0.2 - tslib: 2.7.0 + tslib: 2.8.0 dev: true /node-releases@2.0.18: @@ -4544,7 +4504,7 @@ packages: '@wry/caches': 1.0.1 '@wry/context': 0.7.4 '@wry/trie': 0.4.3 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /optionator@0.9.4: @@ -4614,7 +4574,7 @@ packages: resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} dependencies: dot-case: 3.0.4 - tslib: 2.7.0 + tslib: 2.8.0 dev: true /parent-module@1.0.1: @@ -4635,7 +4595,7 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} dependencies: - '@babel/code-frame': 7.25.7 + '@babel/code-frame': 7.26.0 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -4655,7 +4615,7 @@ packages: resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} dependencies: no-case: 3.0.4 - tslib: 2.7.0 + tslib: 2.8.0 dev: true /path-browserify@1.0.1: @@ -4702,8 +4662,8 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - /picocolors@1.1.0: - resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + /picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} /picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -4769,6 +4729,7 @@ packages: '@jest/schemas': 29.6.3 ansi-styles: 5.2.0 react-is: 18.3.1 + dev: false /pretty-ms@9.0.0: resolution: {integrity: sha512-E9e9HJ9R9NasGOgPaPE8VMeiPKAyWR5jcFpNnwIejslIhWqdqOrb2wShBsncMPUb+BcCd2OPYfh7p2W6oemTng==} @@ -4841,13 +4802,13 @@ packages: unpipe: 1.0.0 dev: true - /react-dom@18.2.0(react@18.2.0): - resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + /react-dom@18.3.1(react@18.3.1): + resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: - react: ^18.2.0 + react: ^18.3.1 dependencies: loose-envify: 1.4.0 - react: 18.2.0 + react: 18.3.1 scheduler: 0.23.2 /react-is@16.13.1: @@ -4859,12 +4820,13 @@ packages: /react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + dev: false /react-lifecycles-compat@3.0.4: resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==} dev: false - /react-modal@3.16.1(react-dom@18.2.0)(react@18.2.0): + /react-modal@3.16.1(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==} engines: {node: '>=8'} peerDependencies: @@ -4873,51 +4835,51 @@ packages: dependencies: exenv: 1.2.2 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) react-lifecycles-compat: 3.0.4 warning: 4.0.3 dev: false - /react-router-dom@6.22.3(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw==} + /react-router-dom@6.27.0(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-+bvtFWMC0DgAFrfKXKG9Fc+BcXWRUO1aJIihbB79xaeq0v5UzfvnM5houGUm1Y461WVRcgAQ+Clh5rdb1eCx4g==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' react-dom: '>=16.8' dependencies: - '@remix-run/router': 1.15.3 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-router: 6.22.3(react@18.2.0) + '@remix-run/router': 1.20.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-router: 6.27.0(react@18.3.1) dev: false - /react-router@6.22.3(react@18.2.0): - resolution: {integrity: sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==} + /react-router@6.27.0(react@18.3.1): + resolution: {integrity: sha512-YA+HGZXz4jaAkVoYBE98VQl+nVzI+cVI2Oj/06F5ZM+0u3TgedN9Y9kmMRo2mnkSK2nCpNQn0DVob4HCsY/WLw==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' dependencies: - '@remix-run/router': 1.15.3 - react: 18.2.0 + '@remix-run/router': 1.20.0 + react: 18.3.1 dev: false - /react-transition-group@4.4.5(react-dom@18.2.0)(react@18.2.0): + /react-transition-group@4.4.5(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} peerDependencies: react: '>=16.6.0' react-dom: '>=16.6.0' dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.26.0 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) dev: false - /react@18.2.0: - resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} + /react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} dependencies: loose-envify: 1.4.0 @@ -4979,7 +4941,7 @@ packages: engines: {node: '>=8'} dev: true - /rehackt@0.1.0(@types/react@18.2.72)(react@18.2.0): + /rehackt@0.1.0(@types/react@18.2.72)(react@18.3.1): resolution: {integrity: sha512-7kRDOuLHB87D/JESKxQoRwv4DzbIdwkAGQ7p6QKGdVlY1IZheUnVhlk/4UZlNUVxdAXpyxikE3URsG067ybVzw==} peerDependencies: '@types/react': '*' @@ -4991,7 +4953,7 @@ packages: optional: true dependencies: '@types/react': 18.2.72 - react: 18.2.0 + react: 18.3.1 dev: false /relateurl@0.2.7: @@ -5232,7 +5194,7 @@ packages: resolution: {integrity: sha512-euuToqM+PjO4UgXeLETsfQiuoyPXlqFezr6YZDFwHR3t4qaX0fZUe1MfPMznTL5f8BWrVS89KduLdMUsxFCO6g==} dependencies: '@sinonjs/commons': 3.0.1 - '@sinonjs/fake-timers': 13.0.2 + '@sinonjs/fake-timers': 13.0.4 '@sinonjs/samsam': 8.0.2 diff: 7.0.0 nise: 6.1.1 @@ -5289,6 +5251,7 @@ packages: engines: {node: '>=10'} dependencies: escape-string-regexp: 2.0.0 + dev: false /standard-engine@15.1.0: resolution: {integrity: sha512-VHysfoyxFu/ukT+9v49d4BRXIokFRZuH3z1VRxzFArZdjSCFpro6rEIU3ji7e4AoAtuSfKBkiOmsrDqKW5ZSRw==} @@ -5414,12 +5377,6 @@ packages: resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} dev: false - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - /supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -5452,7 +5409,7 @@ packages: engines: {node: ^14.18.0 || >=16.0.0} dependencies: '@pkgr/core': 0.1.1 - tslib: 2.7.0 + tslib: 2.8.0 dev: true /tapable@2.2.1: @@ -5468,13 +5425,13 @@ packages: rimraf: 2.6.3 dev: false - /terser@5.34.1: - resolution: {integrity: sha512-FsJZ7iZLd/BXkz+4xrRTGJ26o/6VTjQytUk8b8OxkwcD2I+79VPJlz7qss1+zE7h8GNIScFqXcDyJ/KqBYZFVA==} + /terser@5.36.0: + resolution: {integrity: sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==} engines: {node: '>=10'} hasBin: true dependencies: '@jridgewell/source-map': 0.3.6 - acorn: 8.12.1 + acorn: 8.13.0 commander: 2.20.3 source-map-support: 0.5.21 dev: true @@ -5488,10 +5445,6 @@ packages: engines: {node: '>=14.14'} dev: false - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -5507,29 +5460,29 @@ packages: resolution: {integrity: sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==} engines: {node: '>=8'} dependencies: - tslib: 2.7.0 + tslib: 2.8.0 dev: false - /ts-standard@12.0.2(typescript@5.4.5): + /ts-standard@12.0.2(typescript@5.6.3): resolution: {integrity: sha512-XX2wrB9fKKTfBj4yD3ABm9iShzZcS2iWcPK8XzlBvuL20+wMiLgiz/k5tXgZwTaYq5wRhbks1Y9PelhujF/9ag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true peerDependencies: typescript: '*' dependencies: - '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.1)(typescript@5.4.5) - '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.4.5) + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.6.3) eslint: 8.57.1 - eslint-config-standard-jsx: 11.0.0(eslint-plugin-react@7.37.1)(eslint@8.57.1) - eslint-config-standard-with-typescript: 23.0.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint-plugin-import@2.31.0)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.6.0)(eslint@8.57.1)(typescript@5.4.5) + eslint-config-standard-jsx: 11.0.0(eslint-plugin-react@7.37.2)(eslint@8.57.1) + eslint-config-standard-with-typescript: 23.0.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint-plugin-import@2.31.0)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.6.0)(eslint@8.57.1)(typescript@5.6.3) eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.1) eslint-plugin-n: 15.7.0(eslint@8.57.1) eslint-plugin-promise: 6.6.0(eslint@8.57.1) - eslint-plugin-react: 7.37.1(eslint@8.57.1) + eslint-plugin-react: 7.37.2(eslint@8.57.1) minimist: 1.2.8 pkg-conf: 4.0.0 standard-engine: 15.1.0 - typescript: 5.4.5 + typescript: 5.6.3 transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -5549,17 +5502,17 @@ packages: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} dev: true - /tslib@2.7.0: - resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + /tslib@2.8.0: + resolution: {integrity: sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==} - /tsutils@3.21.0(typescript@5.4.5): + /tsutils@3.21.0(typescript@5.6.3): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} peerDependencies: typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' dependencies: tslib: 1.14.1 - typescript: 5.4.5 + typescript: 5.6.3 dev: true /type-check@0.4.0: @@ -5645,8 +5598,8 @@ packages: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} dev: true - /typescript@5.4.5: - resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + /typescript@5.6.3: + resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} engines: {node: '>=14.17'} hasBin: true dev: true @@ -5670,6 +5623,7 @@ packages: /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: false /universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} @@ -5681,15 +5635,15 @@ packages: engines: {node: '>= 0.8'} dev: true - /update-browserslist-db@1.1.1(browserslist@4.24.0): + /update-browserslist-db@1.1.1(browserslist@4.24.2): resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' dependencies: - browserslist: 4.24.0 + browserslist: 4.24.2 escalade: 3.2.0 - picocolors: 1.1.0 + picocolors: 1.1.1 /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} diff --git a/py/mypy.ini b/py/mypy.ini deleted file mode 100644 index 9ccefe45dd10c..0000000000000 --- a/py/mypy.ini +++ /dev/null @@ -1,39 +0,0 @@ -; The aim in future here is we would be able to turn (most) of these flags on, however the typing technical -; debt is quite colossal right now. For now we should maybe get everything working with the config here -; then look at going after partially or completely untyped defs as a phase-2. -[mypy] -files = selenium -; warn about per-module sections in the config file that do not match any files processed. -warn_unused_configs = True -; disallows subclassing of typing.Any. -disallow_subclassing_any = False -; disallow usage of generic types that do not specify explicit type parameters. -disallow_any_generics = False -; disallow calling functions without type annotations from functions that have type annotations. -disallow_untyped_calls = False -; disallow defining functions without type annotations or with incomplete annotations. -disallow_untyped_defs = False -; disallow defining functions with incomplete type annotations. -disallow_incomplete_defs = False -; type-checks the interior of functions without type annotations. -check_untyped_defs = False -; reports an error whenever a function with type annotations is decorated with a decorator without annotations. -disallow_untyped_decorators = False -; changes the treatment of arguments with a default value of None by not implicitly making their type `typing.Optional`. -no_implicit_optional = False -; warns about casting an expression to it's inferred type. -warn_redundant_casts = True -; warns about unneeded `# type: ignore` comments. -warn_unused_ignores = True -; warns when returning a value with typing.Any from a function with a non typing.Any return type. -warn_return_any = False -; Shows a warning when encountering any code inferred to be unreachable after performing type analysis. -warn_unreachable = False - -[mypy-trio_websocket] -; suppress error messages about imports that cannot be resolved. -ignore_missing_imports = True - -[mypy-_winreg] -; suppress error messages about imports that cannot be resolved. -ignore_missing_imports = True diff --git a/py/pyproject.toml b/py/pyproject.toml index c17be72be8eb3..8a5e26071de6a 100644 --- a/py/pyproject.toml +++ b/py/pyproject.toml @@ -19,3 +19,61 @@ markers = [ ] python_files = ["test_*.py", "*_test.py"] testpaths = ["test"] + +# mypy global options +[tool.mypy] +# The aim in future here is we would be able to turn (most) of these flags on, however the typing technical +# debt is quite colossal right now. For now we should maybe get everything working with the config here +# then look at going after partially or completely untyped defs as a phase-2. +files = "selenium" +# warn about per-module sections in the config file that do not match any files processed. +warn_unused_configs = true +# disallows subclassing of typing.Any. +disallow_subclassing_any = false +# disallow usage of generic types that do not specify explicit type parameters. +disallow_any_generics = false +# disallow calling functions without type annotations from functions that have type annotations. +disallow_untyped_calls = false +# disallow defining functions without type annotations or with incomplete annotations. +disallow_untyped_defs = false +# disallow defining functions with incomplete type annotations. +disallow_incomplete_defs = false +# type-checks the interior of functions without type annotations. +check_untyped_defs = false +# reports an error whenever a function with type annotations is decorated with a decorator without annotations. +disallow_untyped_decorators = false +# changes the treatment of arguments with a default value of None by not implicitly making their type `typing.Optional`. +no_implicit_optional = false +# warns about casting an expression to it's inferred type. +warn_redundant_casts = true +# warns about unneeded `# type: ignore` comments. +warn_unused_ignores = true +# warns when returning a value with typing.Any from a function with a non typing.Any return type. +warn_return_any = false +# Shows a warning when encountering any code inferred to be unreachable after performing type analysis. +warn_unreachable = false + +# mypy module specific options +[[tool.mypy.trio_websocket]] +# suppress error messages about imports that cannot be resolved. +ignore_missing_imports = true + +[[tool.mypy._winreg]] +# suppress error messages about imports that cannot be resolved. +ignore_missing_imports = true + +[tool.isort] +# isort is a common python tool for keeping imports nicely formatted. +# Automatically keep imports alphabetically sorted, on single lines in +# PEP recommended sections (https://peps.python.org/pep-0008/#imports) +# files or individual lines can be ignored via `# isort:skip|# isort:skip_file`. +profile = "black" +py_version=38 +force_single_line = true + +[tool.black] +line-length = 120 +target-version = ['py38'] + +[tool.docformatter] +recursive = true diff --git a/py/requirements.txt b/py/requirements.txt index 7520086bbd7f0..38085a1181db8 100644 --- a/py/requirements.txt +++ b/py/requirements.txt @@ -3,7 +3,7 @@ attrs==23.2.0 certifi==2023.11.17 cffi==1.16.0 cryptography==42.0.8 -debugpy==1.8.5 +debugpy==1.8.7 h11==0.14.0 idna==3.7 importlib-metadata==6.8.0 diff --git a/py/selenium/webdriver/common/bidi/cdp.py b/py/selenium/webdriver/common/bidi/cdp.py index c4cb0feeedf40..c9ed47825e4da 100644 --- a/py/selenium/webdriver/common/bidi/cdp.py +++ b/py/selenium/webdriver/common/bidi/cdp.py @@ -211,13 +211,19 @@ async def execute(self, cmd: typing.Generator[dict, T, typing.Any]) -> T: if self.session_id: request["sessionId"] = self.session_id request_str = json.dumps(request) + if logger.isEnabledFor(logging.DEBUG): + logger.debug(f"Sending CDP message: {cmd_id} {cmd_event}: {request_str}") try: await self.ws.send_message(request_str) except WsConnectionClosed as wcc: raise CdpConnectionClosed(wcc.reason) from None await cmd_event.wait() response = self.inflight_result.pop(cmd_id) + if logger.isEnabledFor(logging.DEBUG): + logger.debug(f"Received CDP message: {response}") if isinstance(response, Exception): + if logger.isEnabledFor(logging.DEBUG): + logger.debug(f"Exception raised by {cmd_event} message: {type(response).__name__}") raise response return response diff --git a/py/selenium/webdriver/support/wait.py b/py/selenium/webdriver/support/wait.py index 949b47238d20e..35bd74a695eb8 100644 --- a/py/selenium/webdriver/support/wait.py +++ b/py/selenium/webdriver/support/wait.py @@ -99,9 +99,9 @@ def until(self, method: Callable[[D], Union[Literal[False], T]], message: str = except self._ignored_exceptions as exc: screen = getattr(exc, "screen", None) stacktrace = getattr(exc, "stacktrace", None) - time.sleep(self._poll) if time.monotonic() > end_time: break + time.sleep(self._poll) raise TimeoutException(message, screen, stacktrace) def until_not(self, method: Callable[[D], T], message: str = "") -> Union[T, Literal[True]]: @@ -122,7 +122,7 @@ def until_not(self, method: Callable[[D], T], message: str = "") -> Union[T, Lit return value except self._ignored_exceptions: return True - time.sleep(self._poll) if time.monotonic() > end_time: break + time.sleep(self._poll) raise TimeoutException(message) diff --git a/py/selenium/webdriver/webkitgtk/service.py b/py/selenium/webdriver/webkitgtk/service.py index 92cea26c535f3..5f42d31486143 100644 --- a/py/selenium/webdriver/webkitgtk/service.py +++ b/py/selenium/webdriver/webkitgtk/service.py @@ -15,6 +15,7 @@ # specific language governing permissions and limitations # under the License. import typing +import warnings from selenium.webdriver.common import service @@ -28,7 +29,7 @@ class Service(service.Service): :param executable_path: install path of the WebKitWebDriver executable, defaults to `WebKitWebDriver`. :param port: Port for the service to run on, defaults to 0 where the operating system will decide. :param service_args: (Optional) List of args to be passed to the subprocess when launching the executable. - :param log_path: (Optional) File path for the file to be opened and passed as the subprocess stdout/stderr handler. + :param log_output: (Optional) File path for the file to be opened and passed as the subprocess stdout/stderr handler. :param env: (Optional) Mapping of environment variables for the new process, defaults to `os.environ`. """ @@ -37,16 +38,20 @@ def __init__( executable_path: str = DEFAULT_EXECUTABLE_PATH, port: int = 0, log_path: typing.Optional[str] = None, + log_output: typing.Optional[str] = None, service_args: typing.Optional[typing.List[str]] = None, env: typing.Optional[typing.Mapping[str, str]] = None, **kwargs, ) -> None: self.service_args = service_args or [] - log_file = open(log_path, "wb") if log_path else None + if log_path is not None: + warnings.warn("log_path is deprecated, use log_output instead", DeprecationWarning, stacklevel=2) + log_path = open(log_path, "wb") + log_output = open(log_output, "wb") if log_output else None super().__init__( executable_path=executable_path, port=port, - log_file=log_file, + log_output=log_path or log_output, env=env, **kwargs, ) diff --git a/py/setup.cfg b/py/setup.cfg index 0cda7cace9e8c..c8eb38080b7d3 100644 --- a/py/setup.cfg +++ b/py/setup.cfg @@ -4,8 +4,3 @@ exclude = .tox,docs/source/conf.py,*venv extend-ignore = E501, E203 # This does nothing for now as E501 is ignored. max-line-length = 120 - -[tool:pytest] -addopts = -ra -python_files = test_*.py *_tests.py -testpaths = test diff --git a/py/tox.ini b/py/tox.ini index f454af1ee3347..fefb4daa3997f 100644 --- a/py/tox.ini +++ b/py/tox.ini @@ -25,17 +25,6 @@ deps = trio-typing==0.7.0 commands = mypy --install-types {posargs} - -[isort] -; isort is a common python tool for keeping imports nicely formatted. -; Automatically keep imports alphabetically sorted, on single lines in -; PEP recommended sections (https://peps.python.org/pep-0008/#imports) -; files or individual lines can be ignored via `# isort:skip|# isort:skip_file`. -profile = black -py_version=38 -force_single_line = True - - [testenv:linting-ci] ; checks linting for CI with stricter exiting when failing. skip_install = true diff --git a/rb/sig/lib/selenium/webdriver/bidi.rbs b/rb/sig/lib/selenium/webdriver/bidi.rbs index fa6b8757f6815..9f8395be94270 100644 --- a/rb/sig/lib/selenium/webdriver/bidi.rbs +++ b/rb/sig/lib/selenium/webdriver/bidi.rbs @@ -13,7 +13,7 @@ module Selenium def callbacks: () -> Hash[untyped, untyped] - def remove_callback: -> Array[Integer] + def remove_callback: (String event, Integer id) -> Error::WebDriverError? def session: () -> Session diff --git a/rb/sig/lib/selenium/webdriver/bidi/log_handler.rbs b/rb/sig/lib/selenium/webdriver/bidi/log_handler.rbs index 703729d9c74ec..47f94107b14ec 100644 --- a/rb/sig/lib/selenium/webdriver/bidi/log_handler.rbs +++ b/rb/sig/lib/selenium/webdriver/bidi/log_handler.rbs @@ -14,13 +14,13 @@ module Selenium def add_message_handler: (String type) { (untyped) -> untyped } -> Integer - def remove_message_handler: (Integer id) -> false + def remove_message_handler: (Integer id) -> bool private - def subscribe_log_entry: () -> false + def subscribe_log_entry: () -> bool - def unsubscribe_log_entry: () -> false + def unsubscribe_log_entry: () -> bool end end end diff --git a/rb/sig/lib/selenium/webdriver/common/driver_finder.rbs b/rb/sig/lib/selenium/webdriver/common/driver_finder.rbs index d012a5ec38f3c..4373fec706895 100644 --- a/rb/sig/lib/selenium/webdriver/common/driver_finder.rbs +++ b/rb/sig/lib/selenium/webdriver/common/driver_finder.rbs @@ -1,7 +1,24 @@ module Selenium module WebDriver class DriverFinder + @options: untyped + + @paths: untyped + @service: untyped + + def initialize: (untyped options,untyped service) -> void + def self.path: (untyped options, untyped klass) -> untyped + + def browser_path: -> untyped + + def browser_path?: -> untyped + + def driver_path: -> untyped + + private + + def paths: -> untyped end end end diff --git a/rb/sig/lib/selenium/webdriver/common/search_context.rbs b/rb/sig/lib/selenium/webdriver/common/search_context.rbs index 5f8f227156cb6..c240e68d5ce5b 100644 --- a/rb/sig/lib/selenium/webdriver/common/search_context.rbs +++ b/rb/sig/lib/selenium/webdriver/common/search_context.rbs @@ -5,6 +5,10 @@ module Selenium FINDERS: untyped + attr_accessor self.extra_finders: untyped + + def self.finders: -> untyped + def find_element: (*untyped args) -> untyped def find_elements: (*untyped args) -> untyped diff --git a/rb/sig/lib/selenium/webdriver/common/service.rbs b/rb/sig/lib/selenium/webdriver/common/service.rbs index e07af9ac3e1ce..788728741d3e1 100644 --- a/rb/sig/lib/selenium/webdriver/common/service.rbs +++ b/rb/sig/lib/selenium/webdriver/common/service.rbs @@ -47,12 +47,14 @@ module Selenium attr_accessor args: untyped - def env_path: -> String + def env_path: -> String? alias extra_args args def initialize: (?path: untyped?, ?port: untyped?, ?log: untyped?, ?args: untyped?) -> void + def find_driver_path: -> untyped + def launch: () -> untyped def shutdown_supported: () -> untyped diff --git a/rb/sig/lib/selenium/webdriver/common/websocket_connection.rbs b/rb/sig/lib/selenium/webdriver/common/websocket_connection.rbs index 411f09d91e948..b0276a246d815 100644 --- a/rb/sig/lib/selenium/webdriver/common/websocket_connection.rbs +++ b/rb/sig/lib/selenium/webdriver/common/websocket_connection.rbs @@ -35,10 +35,14 @@ module Selenium def initialize: (url: untyped) -> void + def add_callback: (untyped event, untyped id) -> untyped + def close: () -> untyped def callbacks: () -> untyped + def remove_callback: (untyped event, untyped id) -> untyped + def send_cmd: (**untyped payload) -> untyped private diff --git a/rb/sig/lib/selenium/webdriver/fedcm/dialog.rbs b/rb/sig/lib/selenium/webdriver/fedcm/dialog.rbs index c16ef91d6c930..98e4ff81a283e 100644 --- a/rb/sig/lib/selenium/webdriver/fedcm/dialog.rbs +++ b/rb/sig/lib/selenium/webdriver/fedcm/dialog.rbs @@ -7,6 +7,8 @@ module Selenium @bridge: Remote::Bridge + def initialize: (Remote::Bridge bridge) -> void + def accounts: -> Array[Account] def cancel: -> Remote::Response? diff --git a/rb/sig/lib/selenium/webdriver/firefox/options.rbs b/rb/sig/lib/selenium/webdriver/firefox/options.rbs index d4087e414024c..2fcb015d6430e 100644 --- a/rb/sig/lib/selenium/webdriver/firefox/options.rbs +++ b/rb/sig/lib/selenium/webdriver/firefox/options.rbs @@ -6,6 +6,8 @@ module Selenium @profile: untyped + @options: Hash[Symbol, untyped] + attr_accessor debugger_address: untyped KEY: String diff --git a/rb/sig/lib/selenium/webdriver/remote/http/common.rbs b/rb/sig/lib/selenium/webdriver/remote/http/common.rbs index 3e1e2ecc26be3..dfafbbf8456bf 100644 --- a/rb/sig/lib/selenium/webdriver/remote/http/common.rbs +++ b/rb/sig/lib/selenium/webdriver/remote/http/common.rbs @@ -9,21 +9,31 @@ module Selenium DEFAULT_HEADERS: Hash[String, untyped] - attr_writer server_url: untyped + @common_headers: Hash[String, untyped] + + attr_accessor self.extra_headers: Hash[String, untyped] + + attr_writer self.user_agent: String + + def self.user_agent: -> String + + attr_writer server_url: String def quit_errors: () -> Array[untyped] - def close: () -> untyped + def close: () -> nil def call: (untyped verb, untyped url, untyped command_hash) -> untyped private - def server_url: () -> untyped + def common_headers: -> Hash[String, untyped] + + def server_url: () -> String def request: (*untyped) -> untyped - def create_response: (untyped code, untyped body, untyped content_type) -> untyped + def create_response: (Integer code, Hash[String, untyped] body, String content_type) -> Remote::Response end end end diff --git a/rb/sig/lib/selenium/webdriver/support/guards/guard.rbs b/rb/sig/lib/selenium/webdriver/support/guards/guard.rbs index d5e312b9ee43f..70c13b3cb0312 100644 --- a/rb/sig/lib/selenium/webdriver/support/guards/guard.rbs +++ b/rb/sig/lib/selenium/webdriver/support/guards/guard.rbs @@ -15,6 +15,7 @@ module Selenium attr_reader guarded: untyped + attr_reader tracker: String attr_reader type: untyped attr_reader messages: untyped diff --git a/rb/sig/selenium/web_driver/script.rbs b/rb/sig/selenium/web_driver/script.rbs index f2dc066174df0..73804ed7d280a 100644 --- a/rb/sig/selenium/web_driver/script.rbs +++ b/rb/sig/selenium/web_driver/script.rbs @@ -4,17 +4,17 @@ module Selenium @bidi: BiDi @log_entry_subscribed: bool - def add_console_message_handler: -> untyped + @log_handler: BiDi::LogHandler - def add_javascript_error_handler: -> untyped + def initialize: (BiDi bidi) -> void - def remove_console_message_handler: -> untyped + def add_console_message_handler: -> Integer - alias remove_javascript_error_handler remove_console_message_handler + def add_javascript_error_handler: -> Integer - private + def remove_console_message_handler: (Integer id) -> bool - def subscribe_log_entry: -> untyped + alias remove_javascript_error_handler remove_console_message_handler end end end