diff --git a/dotnet/src/webdriver/Remote/RemoteSessionSettings.cs b/dotnet/src/webdriver/Remote/RemoteSessionSettings.cs index 3061c3504c67f..685d51363e1f9 100644 --- a/dotnet/src/webdriver/Remote/RemoteSessionSettings.cs +++ b/dotnet/src/webdriver/Remote/RemoteSessionSettings.cs @@ -19,7 +19,6 @@ using OpenQA.Selenium.Remote; using System; -using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Text.Json; @@ -71,18 +70,12 @@ public RemoteSessionSettings(DriverOptions mustMatchDriverOptions, params Driver /// /// Gets a value indicating the options that must be matched by the remote end to create a session. /// - internal DriverOptions MustMatchDriverOptions - { - get { return this.mustMatchDriverOptions; } - } + internal DriverOptions MustMatchDriverOptions => this.mustMatchDriverOptions; /// /// Gets a value indicating the number of options that may be matched by the remote end to create a session. /// - internal int FirstMatchOptionsCount - { - get { return this.firstMatchOptions.Count; } - } + internal int FirstMatchOptionsCount => this.firstMatchOptions.Count; /// /// Gets the capability value with the specified name. @@ -92,6 +85,7 @@ internal int FirstMatchOptionsCount /// /// The specified capability name is not in the set of capabilities. /// + /// If is null. public object this[string capabilityName] { get @@ -121,18 +115,10 @@ public object this[string capabilityName] /// /// The name of the setting to set. /// The value of the setting. - /// - /// The value to be set must be serializable to JSON for transmission - /// across the wire to the remote end. To be JSON-serializable, the value - /// must be a string, a numeric value, a boolean value, an object that - /// implmeents that contains JSON-serializable - /// objects, or a where the keys - /// are strings and the values are JSON-serializable. - /// /// - /// Thrown if the setting name is null, the empty string, or one of the - /// reserved names of metadata settings; or if the setting value is not - /// JSON serializable. + /// If the setting name is null or empty. + /// -or- + /// If one of the reserved names of metadata settings. /// public void AddMetadataSetting(string settingName, object settingValue) { @@ -146,11 +132,6 @@ public void AddMetadataSetting(string settingName, object settingValue) throw new ArgumentException(string.Format("'{0}' is a reserved name for a metadata setting, and cannot be used as a name.", settingName), nameof(settingName)); } - if (!this.IsJsonSerializable(settingValue)) - { - throw new ArgumentException("Metadata setting value must be JSON serializable.", nameof(settingValue)); - } - this.remoteMetadataSettings[settingName] = settingValue; } @@ -161,9 +142,9 @@ public void AddMetadataSetting(string settingName, object settingValue) /// The to add to the list of "first matched" options. public void AddFirstMatchDriverOption(DriverOptions options) { - if (mustMatchDriverOptions != null) + if (this.mustMatchDriverOptions != null) { - DriverOptionsMergeResult mergeResult = mustMatchDriverOptions.GetMergeResult(options); + DriverOptionsMergeResult mergeResult = this.mustMatchDriverOptions.GetMergeResult(options); if (mergeResult.IsMergeConflict) { string msg = string.Format(CultureInfo.InvariantCulture, "You cannot request the same capability in both must-match and first-match capabilities. You are attempting to add a first-match driver options object that defines a capability, '{0}', that is already defined in the must-match driver options.", mergeResult.MergeConflictOptionName); @@ -297,7 +278,7 @@ private IDictionary GetAlwaysMatchOptionsAsSerializableDictionar private List GetFirstMatchOptionsAsSerializableList() { - List optionsMatches = new List(); + List optionsMatches = new List(this.firstMatchOptions.Count); foreach (DriverOptions options in this.firstMatchOptions) { optionsMatches.Add(options.ToDictionary()); @@ -305,50 +286,5 @@ private List GetFirstMatchOptionsAsSerializableList() return optionsMatches; } - - private bool IsJsonSerializable(object arg) - { - IEnumerable argAsEnumerable = arg as IEnumerable; - IDictionary argAsDictionary = arg as IDictionary; - - if (arg is string || arg is float || arg is double || arg is int || arg is long || arg is bool || arg == null) - { - return true; - } - else if (argAsDictionary != null) - { - foreach (object key in argAsDictionary.Keys) - { - if (!(key is string)) - { - return false; - } - } - - foreach (object value in argAsDictionary.Values) - { - if (!IsJsonSerializable(value)) - { - return false; - } - } - } - else if (argAsEnumerable != null) - { - foreach (object item in argAsEnumerable) - { - if (!IsJsonSerializable(item)) - { - return false; - } - } - } - else - { - return false; - } - - return true; - } } } diff --git a/dotnet/test/remote/RemoteSessionCreationTests.cs b/dotnet/test/remote/RemoteSessionCreationTests.cs index ace8d71120b14..685b234cd1b57 100644 --- a/dotnet/test/remote/RemoteSessionCreationTests.cs +++ b/dotnet/test/remote/RemoteSessionCreationTests.cs @@ -18,6 +18,9 @@ // using NUnit.Framework; +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Nodes; namespace OpenQA.Selenium.Remote { @@ -68,5 +71,66 @@ public void CreateEdgeRemoteSession() edge.Quit(); } } + + [Test] + public void ShouldSetRemoteSessionSettingsMetadata() + { + var settings = new RemoteSessionSettings(); + + Assert.That(settings.HasCapability("a"), Is.False); + + settings.AddMetadataSetting("a", null); + Assert.That(settings.HasCapability("a")); + Assert.That(settings.GetCapability("a"), Is.Null); + + settings.AddMetadataSetting("a", true); + Assert.That(settings.HasCapability("a")); + Assert.That(settings.GetCapability("a"), Is.True); + + settings.AddMetadataSetting("a", false); + Assert.That(settings.HasCapability("a")); + Assert.That(settings.GetCapability("a"), Is.False); + + settings.AddMetadataSetting("a", 123); + Assert.That(settings.HasCapability("a")); + Assert.That(settings.GetCapability("a"), Is.TypeOf().And.EqualTo(123)); + + settings.AddMetadataSetting("a", 123f); + Assert.That(settings.HasCapability("a")); + Assert.That(settings.GetCapability("a"), Is.TypeOf().And.EqualTo(123f)); + + settings.AddMetadataSetting("a", 123d); + Assert.That(settings.HasCapability("a")); + Assert.That(settings.GetCapability("a"), Is.TypeOf().And.EqualTo(123d)); + + JsonNode trueName = JsonValue.Create(true); + settings.AddMetadataSetting("a", trueName); + Assert.That(settings.HasCapability("a")); + Assert.That(settings.GetCapability("a"), Is.InstanceOf().And.EqualTo(trueName).Using(JsonNode.DeepEquals)); + + var reader = new Utf8JsonReader("false"u8); + JsonElement trueElement = JsonElement.ParseValue(ref reader); + + settings.AddMetadataSetting("a", trueElement); + Assert.That(settings.HasCapability("a")); + Assert.That(settings.GetCapability("a"), Is.TypeOf().And.Matches(static left => + { + return left.ValueKind == JsonValueKind.False; + })); + + List intValues = [1, 2, 3]; + settings.AddMetadataSetting("a", intValues); + Assert.That(settings.HasCapability("a")); + Assert.That(settings.GetCapability("a"), Is.TypeOf>().And.EqualTo(intValues)); + + Dictionary dictionaryValues = new Dictionary + { + {"value1", 1 }, + {"value2", 1 }, + }; + settings.AddMetadataSetting("a", dictionaryValues); + Assert.That(settings.HasCapability("a")); + Assert.That(settings.GetCapability("a"), Is.TypeOf>().And.EqualTo(dictionaryValues)); + } } }