diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/BiDiJsonSerializerContext.cs b/dotnet/src/webdriver/BiDi/Communication/Json/BiDiJsonSerializerContext.cs index 3be20de67c742..617e90ce37af7 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/BiDiJsonSerializerContext.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/BiDiJsonSerializerContext.cs @@ -140,8 +140,6 @@ namespace OpenQA.Selenium.BiDi.Communication.Json; [JsonSerializable(typeof(Modules.Network.FetchErrorEventArgs))] [JsonSerializable(typeof(Modules.Network.AuthRequiredEventArgs))] -[JsonSerializable(typeof(Modules.Script.Channel), TypeInfoPropertyName = "Script_Channel")] -[JsonSerializable(typeof(Modules.Script.LocalValue.String), TypeInfoPropertyName = "Script_LocalValue_String")] [JsonSerializable(typeof(Modules.Script.Target.Realm), TypeInfoPropertyName = "Script_Target_Realm")] [JsonSerializable(typeof(Modules.Script.Target.Context), TypeInfoPropertyName = "Script_Target_Context")] diff --git a/dotnet/src/webdriver/BiDi/Modules/Script/AddPreloadScriptCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Script/AddPreloadScriptCommand.cs index 096bc67f1f109..2f72438115465 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/AddPreloadScriptCommand.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/AddPreloadScriptCommand.cs @@ -25,7 +25,7 @@ namespace OpenQA.Selenium.BiDi.Modules.Script; internal class AddPreloadScriptCommand(AddPreloadScriptCommandParameters @params) : Command(@params, "script.addPreloadScript"); -internal record AddPreloadScriptCommandParameters(string FunctionDeclaration, IEnumerable? Arguments, IEnumerable? Contexts, string? Sandbox) : CommandParameters; +internal record AddPreloadScriptCommandParameters(string FunctionDeclaration, IEnumerable? Arguments, IEnumerable? Contexts, string? Sandbox) : CommandParameters; public record AddPreloadScriptOptions : CommandOptions { @@ -37,7 +37,7 @@ internal AddPreloadScriptOptions(BrowsingContextAddPreloadScriptOptions? options Sandbox = options?.Sandbox; } - public IEnumerable? Arguments { get; set; } + public IEnumerable? Arguments { get; set; } public IEnumerable? Contexts { get; set; } @@ -46,7 +46,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/LocalValue.cs b/dotnet/src/webdriver/BiDi/Modules/Script/LocalValue.cs index 6132a3247f0c5..fe8cd5d8da3f2 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Script/LocalValue.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Script/LocalValue.cs @@ -23,21 +23,23 @@ namespace OpenQA.Selenium.BiDi.Modules.Script; [JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] -[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")] +[JsonDerivedType(typeof(NumberLocalValue), "number")] +[JsonDerivedType(typeof(StringLocalValue), "string")] +[JsonDerivedType(typeof(NullLocalValue), "null")] +[JsonDerivedType(typeof(UndefinedLocalValue), "undefined")] +[JsonDerivedType(typeof(BooleanLocalValue), "boolean")] +[JsonDerivedType(typeof(BigIntLocalValue), "bigint")] +[JsonDerivedType(typeof(ChannelLocalValue), "channel")] +[JsonDerivedType(typeof(ArrayLocalValue), "array")] +[JsonDerivedType(typeof(DateLocalValue), "date")] +[JsonDerivedType(typeof(MapLocalValue), "map")] +[JsonDerivedType(typeof(ObjectLocalValue), "object")] +[JsonDerivedType(typeof(RegExpLocalValue), "regexp")] +[JsonDerivedType(typeof(SetLocalValue), "set")] public abstract record LocalValue { - public static implicit operator LocalValue(int value) { return new Number(value); } - public static implicit operator LocalValue(string value) { return new String(value); } + public static implicit operator LocalValue(int value) { return new NumberLocalValue(value); } + public static implicit operator LocalValue(string? value) { return value is null ? new NullLocalValue() : new StringLocalValue(value); } // TODO: Extend converting from types public static LocalValue ConvertFrom(object? value) @@ -47,7 +49,7 @@ public static LocalValue ConvertFrom(object? value) case LocalValue: return (LocalValue)value; case null: - return new Null(); + return new NullLocalValue(); case int: return (int)value; case string: @@ -65,52 +67,57 @@ public static LocalValue ConvertFrom(object? value) values.Add([property.Name, ConvertFrom(property.GetValue(value))]); } - return new Object(values); + return new ObjectLocalValue(values); } } } +} - public abstract record PrimitiveProtocolLocalValue : LocalValue; +public abstract record PrimitiveProtocolLocalValue : LocalValue; - public record Number(double Value) : PrimitiveProtocolLocalValue - { - public static explicit operator Number(double n) => new Number(n); - } +public record NumberLocalValue(double Value) : PrimitiveProtocolLocalValue +{ + public static explicit operator NumberLocalValue(double n) => new NumberLocalValue(n); +} - public record String(string Value) : PrimitiveProtocolLocalValue; +public record StringLocalValue(string Value) : PrimitiveProtocolLocalValue; - public record Null : PrimitiveProtocolLocalValue; +public record NullLocalValue : PrimitiveProtocolLocalValue; - public record Undefined : PrimitiveProtocolLocalValue; +public record UndefinedLocalValue : PrimitiveProtocolLocalValue; - public record Channel(Channel.ChannelProperties Value) : LocalValue - { - [JsonInclude] - internal string type = "channel"; +public record BooleanLocalValue(bool Value) : PrimitiveProtocolLocalValue; - public record ChannelProperties(Script.Channel Channel) - { - public SerializationOptions? SerializationOptions { get; set; } +public record BigIntLocalValue(string Value) : PrimitiveProtocolLocalValue; - public ResultOwnership? Ownership { get; set; } - } +public record ChannelLocalValue(ChannelLocalValue.ChannelProperties Value) : LocalValue +{ + // TODO: Revise why we need it + [JsonInclude] + internal string type = "channel"; + + public record ChannelProperties(Channel Channel) + { + public SerializationOptions? SerializationOptions { get; set; } + + public ResultOwnership? Ownership { get; set; } } +} - public record Array(IEnumerable Value) : LocalValue; +public record ArrayLocalValue(IEnumerable Value) : LocalValue; - public record Date(string Value) : LocalValue; +public record DateLocalValue(string Value) : LocalValue; - public record Map(IEnumerable> Value) : LocalValue; +public record MapLocalValue(IEnumerable> Value) : LocalValue; - public record Object(IEnumerable> Value) : LocalValue; +public record ObjectLocalValue(IEnumerable> Value) : LocalValue; - public record RegExp(RegExp.RegExpValue Value) : LocalValue +public record RegExpLocalValue(RegExpLocalValue.RegExpValue Value) : LocalValue +{ + public record RegExpValue(string Pattern) { - public record RegExpValue(string Pattern) - { - public string? Flags { get; set; } - } + public string? Flags { get; set; } } - - public record Set(IEnumerable Value) : LocalValue; } + +public record SetLocalValue(IEnumerable Value) : LocalValue; diff --git a/dotnet/test/common/BiDi/Script/CallFunctionLocalValueTest.cs b/dotnet/test/common/BiDi/Script/CallFunctionLocalValueTest.cs index 9a3f2dbda6f7b..670c813e0cd62 100644 --- a/dotnet/test/common/BiDi/Script/CallFunctionLocalValueTest.cs +++ b/dotnet/test/common/BiDi/Script/CallFunctionLocalValueTest.cs @@ -27,7 +27,7 @@ class CallFunctionLocalValueTest : BiDiTestFixture [Test] public void CanCallFunctionWithArgumentUndefined() { - var arg = new LocalValue.Undefined(); + var arg = new UndefinedLocalValue(); Assert.That(async () => { await context.Script.CallFunctionAsync($$""" @@ -43,7 +43,7 @@ await context.Script.CallFunctionAsync($$""" [Test] public void CanCallFunctionWithArgumentNull() { - var arg = new LocalValue.Null(); + var arg = new NullLocalValue(); Assert.That(async () => { await context.Script.CallFunctionAsync($$""" @@ -56,10 +56,42 @@ await context.Script.CallFunctionAsync($$""" }, Throws.Nothing); } + [Test] + public void CanCallFunctionWithArgumentBoolean() + { + var arg = new BooleanLocalValue(true); + Assert.That(async () => + { + await context.Script.CallFunctionAsync($$""" + (arg) => { + if (arg !== true) { + throw new Error("Assert failed: " + arg); + } + } + """, false, new() { Arguments = [arg] }); + }, Throws.Nothing); + } + + [Test] + public void CanCallFunctionWithArgumentBigInt() + { + var arg = new BigIntLocalValue("12345"); + Assert.That(async () => + { + await context.Script.CallFunctionAsync($$""" + (arg) => { + if (arg !== 12345n) { + throw new Error("Assert failed: " + arg); + } + } + """, false, new() { Arguments = [arg] }); + }, Throws.Nothing); + } + [Test] public void CanCallFunctionWithArgumentEmptyString() { - var arg = new LocalValue.String(string.Empty); + var arg = new StringLocalValue(string.Empty); Assert.That(async () => { await context.Script.CallFunctionAsync($$""" @@ -75,7 +107,7 @@ await context.Script.CallFunctionAsync($$""" [Test] public void CanCallFunctionWithArgumentNonEmptyString() { - var arg = new LocalValue.String("whoa"); + var arg = new StringLocalValue("whoa"); Assert.That(async () => { await context.Script.CallFunctionAsync($$""" @@ -93,7 +125,7 @@ public void CanCallFunctionWithArgumentRecentDate() { const string PinnedDateTimeString = "2025-03-09T00:30:33.083Z"; - var arg = new LocalValue.Date(PinnedDateTimeString); + var arg = new DateLocalValue(PinnedDateTimeString); Assert.That(async () => { @@ -112,7 +144,7 @@ public void CanCallFunctionWithArgumentEpochDate() { const string EpochString = "1970-01-01T00:00:00.000Z"; - var arg = new LocalValue.Date(EpochString); + var arg = new DateLocalValue(EpochString); Assert.That(async () => { @@ -129,7 +161,7 @@ await context.Script.CallFunctionAsync($$""" [Test] public void CanCallFunctionWithArgumentNumberFive() { - var arg = new LocalValue.Number(5); + var arg = new NumberLocalValue(5); Assert.That(async () => { @@ -146,7 +178,7 @@ await context.Script.CallFunctionAsync($$""" [Test] public void CanCallFunctionWithArgumentNumberNegativeFive() { - var arg = new LocalValue.Number(-5); + var arg = new NumberLocalValue(-5); Assert.That(async () => { @@ -163,7 +195,7 @@ await context.Script.CallFunctionAsync($$""" [Test] public void CanCallFunctionWithArgumentNumberZero() { - var arg = new LocalValue.Number(0); + var arg = new NumberLocalValue(0); Assert.That(async () => { @@ -182,7 +214,7 @@ await context.Script.CallFunctionAsync($$""" [IgnoreBrowser(Selenium.Browser.Chrome, "Chromium can't handle -0 argument as a number: https://github.com/w3c/webdriver-bidi/issues/887")] public void CanCallFunctionWithArgumentNumberNegativeZero() { - var arg = new LocalValue.Number(double.NegativeZero); + var arg = new NumberLocalValue(double.NegativeZero); Assert.That(async () => { @@ -199,7 +231,7 @@ await context.Script.CallFunctionAsync($$""" [Test] public void CanCallFunctionWithArgumentNumberPositiveInfinity() { - var arg = new LocalValue.Number(double.PositiveInfinity); + var arg = new NumberLocalValue(double.PositiveInfinity); Assert.That(async () => { @@ -216,7 +248,7 @@ await context.Script.CallFunctionAsync($$""" [Test] public void CanCallFunctionWithArgumentNumberNegativeInfinity() { - var arg = new LocalValue.Number(double.NegativeInfinity); + var arg = new NumberLocalValue(double.NegativeInfinity); Assert.That(async () => { @@ -233,7 +265,7 @@ await context.Script.CallFunctionAsync($$""" [Test] public void CanCallFunctionWithArgumentNumberNaN() { - var arg = new LocalValue.Number(double.NaN); + var arg = new NumberLocalValue(double.NaN); Assert.That(async () => { await context.Script.CallFunctionAsync($$""" @@ -249,7 +281,7 @@ await context.Script.CallFunctionAsync($$""" [Test] public void CanCallFunctionWithArgumentRegExp() { - var arg = new LocalValue.RegExp(new LocalValue.RegExp.RegExpValue("foo*") { Flags = "g" }); + var arg = new RegExpLocalValue(new RegExpLocalValue.RegExpValue("foo*") { Flags = "g" }); Assert.That(async () => { @@ -266,7 +298,7 @@ await context.Script.CallFunctionAsync($$""" [Test] public void CanCallFunctionWithArgumentArray() { - var arg = new LocalValue.Array([new LocalValue.String("hi")]); + var arg = new ArrayLocalValue([new StringLocalValue("hi")]); Assert.That(async () => { @@ -283,7 +315,7 @@ await context.Script.CallFunctionAsync($$""" [Test] public void CanCallFunctionWithArgumentObject() { - var arg = new LocalValue.Object([[new LocalValue.String("objKey"), new LocalValue.String("objValue")]]); + var arg = new ObjectLocalValue([[new StringLocalValue("objKey"), new StringLocalValue("objValue")]]); Assert.That(async () => { @@ -300,7 +332,7 @@ await context.Script.CallFunctionAsync($$""" [Test] public void CanCallFunctionWithArgumentMap() { - var arg = new LocalValue.Map([[new LocalValue.String("mapKey"), new LocalValue.String("mapValue")]]); + var arg = new MapLocalValue([[new StringLocalValue("mapKey"), new StringLocalValue("mapValue")]]); Assert.That(async () => { @@ -317,7 +349,7 @@ await context.Script.CallFunctionAsync($$""" [Test] public void CanCallFunctionWithArgumentSet() { - var arg = new LocalValue.Set([new LocalValue.String("setKey")]); + var arg = new SetLocalValue([new StringLocalValue("setKey")]); Assert.That(async () => { diff --git a/dotnet/test/common/BiDi/Script/CallFunctionParameterTest.cs b/dotnet/test/common/BiDi/Script/CallFunctionParameterTest.cs index d1e2608ddb431..06b973ecdaa28 100644 --- a/dotnet/test/common/BiDi/Script/CallFunctionParameterTest.cs +++ b/dotnet/test/common/BiDi/Script/CallFunctionParameterTest.cs @@ -138,7 +138,7 @@ async function() { [Test] public async Task CanCallFunctionWithThisParameter() { - var thisParameter = new LocalValue.Object([["some_property", 42]]); + var thisParameter = new ObjectLocalValue([["some_property", 42]]); var res = await context.Script.CallFunctionAsync(""" function(){return this.some_property} diff --git a/dotnet/test/common/BiDi/Script/ScriptCommandsTest.cs b/dotnet/test/common/BiDi/Script/ScriptCommandsTest.cs index 798ea1cbbf9f2..bdc33e9d897c0 100644 --- a/dotnet/test/common/BiDi/Script/ScriptCommandsTest.cs +++ b/dotnet/test/common/BiDi/Script/ScriptCommandsTest.cs @@ -110,7 +110,7 @@ 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")))] + Arguments = [new ChannelLocalValue(new(new("channel_name")))] }); Assert.That(preloadScript, Is.Not.Null); @@ -122,7 +122,7 @@ 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")) + Arguments = [new ChannelLocalValue(new(new("channel_name")) { SerializationOptions = new() { diff --git a/dotnet/test/common/BiDi/Script/ScriptEventsTest.cs b/dotnet/test/common/BiDi/Script/ScriptEventsTest.cs index c2490b8e1431d..e9bc8d7b48298 100644 --- a/dotnet/test/common/BiDi/Script/ScriptEventsTest.cs +++ b/dotnet/test/common/BiDi/Script/ScriptEventsTest.cs @@ -35,7 +35,7 @@ public async Task CanListenToChannelMessage() await context.Script.CallFunctionAsync("(channel) => channel('foo')", false, new() { - Arguments = [new LocalValue.Channel(new(new("channel_name")))] + Arguments = [new ChannelLocalValue(new(new("channel_name")))] }); var message = await tcs.Task.WaitAsync(TimeSpan.FromSeconds(5));