Skip to content

Commit 328ae61

Browse files
authoredNov 10, 2024··
[dotnet] Allow RemoteSessionSettings to use any value for metadata (#14726)
1 parent a14b659 commit 328ae61

File tree

2 files changed

+73
-73
lines changed

2 files changed

+73
-73
lines changed
 

‎dotnet/src/webdriver/Remote/RemoteSessionSettings.cs

+9-73
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
using OpenQA.Selenium.Remote;
2121
using System;
22-
using System.Collections;
2322
using System.Collections.Generic;
2423
using System.Globalization;
2524
using System.Text.Json;
@@ -71,18 +70,12 @@ public RemoteSessionSettings(DriverOptions mustMatchDriverOptions, params Driver
7170
/// <summary>
7271
/// Gets a value indicating the options that must be matched by the remote end to create a session.
7372
/// </summary>
74-
internal DriverOptions MustMatchDriverOptions
75-
{
76-
get { return this.mustMatchDriverOptions; }
77-
}
73+
internal DriverOptions MustMatchDriverOptions => this.mustMatchDriverOptions;
7874

7975
/// <summary>
8076
/// Gets a value indicating the number of options that may be matched by the remote end to create a session.
8177
/// </summary>
82-
internal int FirstMatchOptionsCount
83-
{
84-
get { return this.firstMatchOptions.Count; }
85-
}
78+
internal int FirstMatchOptionsCount => this.firstMatchOptions.Count;
8679

8780
/// <summary>
8881
/// Gets the capability value with the specified name.
@@ -92,6 +85,7 @@ internal int FirstMatchOptionsCount
9285
/// <exception cref="ArgumentException">
9386
/// The specified capability name is not in the set of capabilities.
9487
/// </exception>
88+
/// <exception cref="ArgumentNullException">If <paramref name="capabilityName"/> is null.</exception>
9589
public object this[string capabilityName]
9690
{
9791
get
@@ -121,18 +115,10 @@ public object this[string capabilityName]
121115
/// </summary>
122116
/// <param name="settingName">The name of the setting to set.</param>
123117
/// <param name="settingValue">The value of the setting.</param>
124-
/// <remarks>
125-
/// The value to be set must be serializable to JSON for transmission
126-
/// across the wire to the remote end. To be JSON-serializable, the value
127-
/// must be a string, a numeric value, a boolean value, an object that
128-
/// implmeents <see cref="IEnumerable"/> that contains JSON-serializable
129-
/// objects, or a <see cref="Dictionary{TKey, TValue}"/> where the keys
130-
/// are strings and the values are JSON-serializable.
131-
/// </remarks>
132118
/// <exception cref="ArgumentException">
133-
/// Thrown if the setting name is null, the empty string, or one of the
134-
/// reserved names of metadata settings; or if the setting value is not
135-
/// JSON serializable.
119+
/// <para>If the setting name is null or empty.</para>
120+
/// <para>-or-</para>
121+
/// <para>If one of the reserved names of metadata settings.</para>
136122
/// </exception>
137123
public void AddMetadataSetting(string settingName, object settingValue)
138124
{
@@ -146,11 +132,6 @@ public void AddMetadataSetting(string settingName, object settingValue)
146132
throw new ArgumentException(string.Format("'{0}' is a reserved name for a metadata setting, and cannot be used as a name.", settingName), nameof(settingName));
147133
}
148134

149-
if (!this.IsJsonSerializable(settingValue))
150-
{
151-
throw new ArgumentException("Metadata setting value must be JSON serializable.", nameof(settingValue));
152-
}
153-
154135
this.remoteMetadataSettings[settingName] = settingValue;
155136
}
156137

@@ -161,9 +142,9 @@ public void AddMetadataSetting(string settingName, object settingValue)
161142
/// <param name="options">The <see cref="DriverOptions"/> to add to the list of "first matched" options.</param>
162143
public void AddFirstMatchDriverOption(DriverOptions options)
163144
{
164-
if (mustMatchDriverOptions != null)
145+
if (this.mustMatchDriverOptions != null)
165146
{
166-
DriverOptionsMergeResult mergeResult = mustMatchDriverOptions.GetMergeResult(options);
147+
DriverOptionsMergeResult mergeResult = this.mustMatchDriverOptions.GetMergeResult(options);
167148
if (mergeResult.IsMergeConflict)
168149
{
169150
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,58 +278,13 @@ private IDictionary<string, object> GetAlwaysMatchOptionsAsSerializableDictionar
297278

298279
private List<object> GetFirstMatchOptionsAsSerializableList()
299280
{
300-
List<object> optionsMatches = new List<object>();
281+
List<object> optionsMatches = new List<object>(this.firstMatchOptions.Count);
301282
foreach (DriverOptions options in this.firstMatchOptions)
302283
{
303284
optionsMatches.Add(options.ToDictionary());
304285
}
305286

306287
return optionsMatches;
307288
}
308-
309-
private bool IsJsonSerializable(object arg)
310-
{
311-
IEnumerable argAsEnumerable = arg as IEnumerable;
312-
IDictionary argAsDictionary = arg as IDictionary;
313-
314-
if (arg is string || arg is float || arg is double || arg is int || arg is long || arg is bool || arg == null)
315-
{
316-
return true;
317-
}
318-
else if (argAsDictionary != null)
319-
{
320-
foreach (object key in argAsDictionary.Keys)
321-
{
322-
if (!(key is string))
323-
{
324-
return false;
325-
}
326-
}
327-
328-
foreach (object value in argAsDictionary.Values)
329-
{
330-
if (!IsJsonSerializable(value))
331-
{
332-
return false;
333-
}
334-
}
335-
}
336-
else if (argAsEnumerable != null)
337-
{
338-
foreach (object item in argAsEnumerable)
339-
{
340-
if (!IsJsonSerializable(item))
341-
{
342-
return false;
343-
}
344-
}
345-
}
346-
else
347-
{
348-
return false;
349-
}
350-
351-
return true;
352-
}
353289
}
354290
}

‎dotnet/test/remote/RemoteSessionCreationTests.cs

+64
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
// </copyright>
1919

2020
using NUnit.Framework;
21+
using System.Collections.Generic;
22+
using System.Text.Json;
23+
using System.Text.Json.Nodes;
2124

2225
namespace OpenQA.Selenium.Remote
2326
{
@@ -68,5 +71,66 @@ public void CreateEdgeRemoteSession()
6871
edge.Quit();
6972
}
7073
}
74+
75+
[Test]
76+
public void ShouldSetRemoteSessionSettingsMetadata()
77+
{
78+
var settings = new RemoteSessionSettings();
79+
80+
Assert.That(settings.HasCapability("a"), Is.False);
81+
82+
settings.AddMetadataSetting("a", null);
83+
Assert.That(settings.HasCapability("a"));
84+
Assert.That(settings.GetCapability("a"), Is.Null);
85+
86+
settings.AddMetadataSetting("a", true);
87+
Assert.That(settings.HasCapability("a"));
88+
Assert.That(settings.GetCapability("a"), Is.True);
89+
90+
settings.AddMetadataSetting("a", false);
91+
Assert.That(settings.HasCapability("a"));
92+
Assert.That(settings.GetCapability("a"), Is.False);
93+
94+
settings.AddMetadataSetting("a", 123);
95+
Assert.That(settings.HasCapability("a"));
96+
Assert.That(settings.GetCapability("a"), Is.TypeOf<int>().And.EqualTo(123));
97+
98+
settings.AddMetadataSetting("a", 123f);
99+
Assert.That(settings.HasCapability("a"));
100+
Assert.That(settings.GetCapability("a"), Is.TypeOf<float>().And.EqualTo(123f));
101+
102+
settings.AddMetadataSetting("a", 123d);
103+
Assert.That(settings.HasCapability("a"));
104+
Assert.That(settings.GetCapability("a"), Is.TypeOf<double>().And.EqualTo(123d));
105+
106+
JsonNode trueName = JsonValue.Create(true);
107+
settings.AddMetadataSetting("a", trueName);
108+
Assert.That(settings.HasCapability("a"));
109+
Assert.That(settings.GetCapability("a"), Is.InstanceOf<JsonNode>().And.EqualTo(trueName).Using<JsonNode>(JsonNode.DeepEquals));
110+
111+
var reader = new Utf8JsonReader("false"u8);
112+
JsonElement trueElement = JsonElement.ParseValue(ref reader);
113+
114+
settings.AddMetadataSetting("a", trueElement);
115+
Assert.That(settings.HasCapability("a"));
116+
Assert.That(settings.GetCapability("a"), Is.TypeOf<JsonElement>().And.Matches<JsonElement>(static left =>
117+
{
118+
return left.ValueKind == JsonValueKind.False;
119+
}));
120+
121+
List<int> intValues = [1, 2, 3];
122+
settings.AddMetadataSetting("a", intValues);
123+
Assert.That(settings.HasCapability("a"));
124+
Assert.That(settings.GetCapability("a"), Is.TypeOf<List<int>>().And.EqualTo(intValues));
125+
126+
Dictionary<string, int> dictionaryValues = new Dictionary<string, int>
127+
{
128+
{"value1", 1 },
129+
{"value2", 1 },
130+
};
131+
settings.AddMetadataSetting("a", dictionaryValues);
132+
Assert.That(settings.HasCapability("a"));
133+
Assert.That(settings.GetCapability("a"), Is.TypeOf<Dictionary<string, int>>().And.EqualTo(dictionaryValues));
134+
}
71135
}
72136
}

0 commit comments

Comments
 (0)
Please sign in to comment.