Skip to content

Commit d9f2bb8

Browse files
committed
[dotnet] Refactor registration and execution of custom WebDriver commands
1 parent dcd36f6 commit d9f2bb8

14 files changed

+739
-233
lines changed

dotnet/src/webdriver/Chrome/ChromeDriver.cs

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@
1717
// </copyright>
1818

1919
using System;
20+
using System.Collections.Generic;
21+
using System.Collections.ObjectModel;
2022
using OpenQA.Selenium.Remote;
2123
using OpenQA.Selenium.Chromium;
22-
using System.Collections.Generic;
2324

2425
namespace OpenQA.Selenium.Chrome
2526
{
@@ -58,12 +59,21 @@ namespace OpenQA.Selenium.Chrome
5859
/// </example>
5960
public class ChromeDriver : ChromiumDriver
6061
{
62+
private static Dictionary<string, CommandInfo> chromeCustomCommands = new Dictionary<string, CommandInfo>()
63+
{
64+
{ ExecuteCdp, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/goog/cdp/execute") },
65+
{ GetCastSinksCommand, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/goog/cast/get_sinks") },
66+
{ SelectCastSinkCommand, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/goog/cast/set_sink_to_use") },
67+
{ StartCastTabMirroringCommand, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/goog/cast/start_tab_mirroring") },
68+
{ GetCastIssueMessageCommand, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/goog/cast/get_issue_message") },
69+
{ StopCastingCommand, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/goog/cast/stop_casting") }
70+
};
6171

6272
/// <summary>
6373
/// Initializes a new instance of the <see cref="ChromeDriver"/> class.
6474
/// </summary>
6575
public ChromeDriver()
66-
: this(new ChromeOptions())
76+
: this(new ChromeOptions())
6777
{
6878
}
6979

@@ -138,13 +148,39 @@ public ChromeDriver(ChromeDriverService service, ChromeOptions options)
138148
public ChromeDriver(ChromeDriverService service, ChromeOptions options, TimeSpan commandTimeout)
139149
: base(service, options, commandTimeout)
140150
{
141-
this.AddCustomChromeCommand(ExecuteCdp, HttpCommandInfo.PostCommand, "/session/{sessionId}/goog/cdp/execute");
142-
this.AddCustomChromeCommand(GetCastSinksCommand, HttpCommandInfo.GetCommand, "/session/{sessionId}/goog/cast/get_sinks");
143-
this.AddCustomChromeCommand(SelectCastSinkCommand, HttpCommandInfo.PostCommand, "/session/{sessionId}/goog/cast/set_sink_to_use");
144-
this.AddCustomChromeCommand(StartCastTabMirroringCommand, HttpCommandInfo.PostCommand, "/session/{sessionId}/goog/cast/start_tab_mirroring");
145-
this.AddCustomChromeCommand(GetCastIssueMessageCommand, HttpCommandInfo.GetCommand, "/session/{sessionId}/goog/cast/get_issue_message");
146-
this.AddCustomChromeCommand(StopCastingCommand, HttpCommandInfo.PostCommand, "/session/{sessionId}/goog/cast/stop_casting");
151+
this.AddCustomChromeCommands();
152+
}
153+
154+
/// <summary>
155+
/// Gets a read-only dictionary of the custom WebDriver commands defined for ChromeDriver.
156+
/// The keys of the dictionary are the names assigned to the command; the values are the
157+
/// <see cref="CommandInfo"/> objects describing the command behavior.
158+
/// </summary>
159+
public static IReadOnlyDictionary<string, CommandInfo> CustomCommandDefinitions
160+
{
161+
get
162+
{
163+
Dictionary<string, CommandInfo> customCommands = new Dictionary<string, CommandInfo>();
164+
foreach (KeyValuePair<string, CommandInfo> entry in ChromiumCustomCommands)
165+
{
166+
customCommands[entry.Key] = entry.Value;
167+
}
168+
169+
foreach (KeyValuePair<string, CommandInfo> entry in chromeCustomCommands)
170+
{
171+
customCommands[entry.Key] = entry.Value;
172+
}
173+
174+
return new ReadOnlyDictionary<string, CommandInfo>(customCommands);
175+
}
147176
}
148177

178+
private void AddCustomChromeCommands()
179+
{
180+
foreach (KeyValuePair<string, CommandInfo> entry in CustomCommandDefinitions)
181+
{
182+
this.RegisterInternalDriverCommand(entry.Key, entry.Value);
183+
}
184+
}
149185
}
150186
}

dotnet/src/webdriver/Chromium/ChromiumDriver.cs

Lines changed: 87 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,7 @@
1818

1919
using System;
2020
using System.Collections.Generic;
21-
using System.Globalization;
22-
using System.Net.Http;
23-
using System.Threading.Tasks;
24-
using Newtonsoft.Json;
25-
using Newtonsoft.Json.Linq;
21+
using System.Collections.ObjectModel;
2622
using OpenQA.Selenium.DevTools;
2723
using OpenQA.Selenium.Remote;
2824

@@ -31,70 +27,107 @@ namespace OpenQA.Selenium.Chromium
3127
/// <summary>
3228
/// Provides an abstract way to access Chromium-based browsers to run tests.
3329
/// </summary>
34-
public abstract class ChromiumDriver : WebDriver, ISupportsLogs, IDevTools
30+
public class ChromiumDriver : WebDriver, ISupportsLogs, IDevTools
3531
{
3632
/// <summary>
3733
/// Accept untrusted SSL Certificates
3834
/// </summary>
3935
public static readonly bool AcceptUntrustedCertificates = true;
4036

41-
protected const string ExecuteCdp = "executeCdpCommand";
42-
protected const string GetCastSinksCommand = "getCastSinks";
43-
protected const string SelectCastSinkCommand = "selectCastSink";
44-
protected const string StartCastTabMirroringCommand = "startCastTabMirroring";
45-
protected const string GetCastIssueMessageCommand = "getCastIssueMessage";
46-
protected const string StopCastingCommand = "stopCasting";
47-
private const string GetNetworkConditionsCommand = "getNetworkConditions";
48-
private const string SetNetworkConditionsCommand = "setNetworkConditions";
49-
private const string DeleteNetworkConditionsCommand = "deleteNetworkConditions";
50-
private const string SendChromeCommand = "sendChromeCommand";
51-
private const string SendChromeCommandWithResult = "sendChromeCommandWithResult";
52-
private const string LaunchAppCommand = "launchAppCommand";
53-
private const string SetPermissionCommand = "setPermission";
37+
/// <summary>
38+
/// Command for executing a Chrome DevTools Protocol command in a driver for a Chromium-based browser.
39+
/// </summary>
40+
public static readonly string ExecuteCdp = "executeCdpCommand";
5441

55-
private readonly string optionsCapabilityName;
56-
private DevToolsSession devToolsSession;
42+
/// <summary>
43+
/// Command for getting cast sinks in a driver for a Chromium-based browser.
44+
/// </summary>
45+
public static readonly string GetCastSinksCommand = "getCastSinks";
5746

5847
/// <summary>
59-
/// Initializes a new instance of the <see cref="ChromiumDriver"/> class using the specified
60-
/// <see cref="ChromiumDriverService"/> and options.
48+
/// Command for selecting a cast sink in a driver for a Chromium-based browser.
6149
/// </summary>
62-
/// <param name="service">The <see cref="ChromiumDriverService"/> to use.</param>
63-
/// <param name="options">The <see cref="ChromiumOptions"/> used to initialize the driver.</param>
64-
public ChromiumDriver(ChromiumDriverService service, ChromiumOptions options)
65-
: this(service, options, RemoteWebDriver.DefaultCommandTimeout)
50+
public static readonly string SelectCastSinkCommand = "selectCastSink";
51+
52+
/// <summary>
53+
/// Command for starting cast tab mirroring in a driver for a Chromium-based browser.
54+
/// </summary>
55+
public static readonly string StartCastTabMirroringCommand = "startCastTabMirroring";
56+
57+
/// <summary>
58+
/// Command for getting a cast issued message in a driver for a Chromium-based browser.
59+
/// </summary>
60+
public static readonly string GetCastIssueMessageCommand = "getCastIssueMessage";
61+
62+
/// <summary>
63+
/// Command for stopping casting in a driver for a Chromium-based browser.
64+
/// </summary>
65+
public static readonly string StopCastingCommand = "stopCasting";
66+
67+
/// <summary>
68+
/// Command for getting the simulated network conditions in a driver for a Chromium-based browser.
69+
/// </summary>
70+
public static readonly string GetNetworkConditionsCommand = "getNetworkConditions";
71+
72+
/// <summary>
73+
/// Command for setting the simulated network conditions in a driver for a Chromium-based browser.
74+
/// </summary>
75+
public static readonly string SetNetworkConditionsCommand = "setNetworkConditions";
76+
77+
/// <summary>
78+
/// Command for deleting the simulated network conditions in a driver for a Chromium-based browser.
79+
/// </summary>
80+
public static readonly string DeleteNetworkConditionsCommand = "deleteNetworkConditions";
81+
82+
/// <summary>
83+
/// Command for executing a Chrome DevTools Protocol command in a driver for a Chromium-based browser.
84+
/// </summary>
85+
public static readonly string SendChromeCommand = "sendChromeCommand";
86+
87+
/// <summary>
88+
/// Command for executing a Chrome DevTools Protocol command that returns a result in a driver for a Chromium-based browser.
89+
/// </summary>
90+
public static readonly string SendChromeCommandWithResult = "sendChromeCommandWithResult";
91+
92+
/// <summary>
93+
/// Command for launching an app in a driver for a Chromium-based browser.
94+
/// </summary>
95+
public static readonly string LaunchAppCommand = "launchAppCommand";
96+
97+
/// <summary>
98+
/// Command for setting permissions in a driver for a Chromium-based browser.
99+
/// </summary>
100+
public static readonly string SetPermissionCommand = "setPermission";
101+
102+
private readonly string optionsCapabilityName;
103+
private DevToolsSession devToolsSession;
104+
105+
private static Dictionary<string, CommandInfo> chromiumCustomCommands = new Dictionary<string, CommandInfo>()
66106
{
67-
}
107+
{ GetNetworkConditionsCommand, new HttpCommandInfo(HttpCommandInfo.GetCommand, "/session/{sessionId}/chromium/network_conditions") },
108+
{ SetNetworkConditionsCommand, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/chromium/network_conditions") },
109+
{ DeleteNetworkConditionsCommand, new HttpCommandInfo(HttpCommandInfo.DeleteCommand, "/session/{sessionId}/chromium/network_conditions") },
110+
{ SendChromeCommand, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/chromium/send_command") },
111+
{ SendChromeCommandWithResult, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/chromium/send_command_and_get_result") },
112+
{ LaunchAppCommand, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/chromium/launch_app") },
113+
{ SetPermissionCommand, new HttpCommandInfo(HttpCommandInfo.PostCommand, "/session/{sessionId}/permissions") }
114+
};
68115

69116
/// <summary>
70117
/// Initializes a new instance of the <see cref="ChromiumDriver"/> class using the specified <see cref="ChromiumDriverService"/>.
71118
/// </summary>
72119
/// <param name="service">The <see cref="ChromiumDriverService"/> to use.</param>
73120
/// <param name="options">The <see cref="ChromiumOptions"/> to be used with the ChromiumDriver.</param>
74121
/// <param name="commandTimeout">The maximum amount of time to wait for each command.</param>
75-
public ChromiumDriver(ChromiumDriverService service, ChromiumOptions options, TimeSpan commandTimeout)
122+
protected ChromiumDriver(ChromiumDriverService service, ChromiumOptions options, TimeSpan commandTimeout)
76123
: base(new DriverServiceCommandExecutor(service, commandTimeout), ConvertOptionsToCapabilities(options))
77124
{
78125
this.optionsCapabilityName = options.CapabilityName;
79-
80-
// Add the custom commands unique to Chrome
81-
this.AddCustomChromeCommand(GetNetworkConditionsCommand, HttpCommandInfo.GetCommand, "/session/{sessionId}/chromium/network_conditions");
82-
this.AddCustomChromeCommand(SetNetworkConditionsCommand, HttpCommandInfo.PostCommand, "/session/{sessionId}/chromium/network_conditions");
83-
this.AddCustomChromeCommand(DeleteNetworkConditionsCommand, HttpCommandInfo.DeleteCommand, "/session/{sessionId}/chromium/network_conditions");
84-
this.AddCustomChromeCommand(SendChromeCommand, HttpCommandInfo.PostCommand, "/session/{sessionId}/chromium/send_command");
85-
this.AddCustomChromeCommand(SendChromeCommandWithResult, HttpCommandInfo.PostCommand, "/session/{sessionId}/chromium/send_command_and_get_result");
86-
this.AddCustomChromeCommand(LaunchAppCommand, HttpCommandInfo.PostCommand, "/session/{sessionId}/chromium/launch_app");
87-
this.AddCustomChromeCommand(SetPermissionCommand, HttpCommandInfo.PostCommand, "/session/{sessionId}/permissions");
88126
}
89127

90-
/// <summary>
91-
/// Initializes a new instance of the <see cref="ChromiumDriver"/> class
92-
/// </summary>
93-
/// <param name="commandExecutor">An <see cref="ICommandExecutor"/> object which executes commands for the driver.</param>
94-
/// <param name="desiredCapabilities">An <see cref="ICapabilities"/> object containing the desired capabilities of the browser.</param>
95-
protected ChromiumDriver(ICommandExecutor commandExecutor, ICapabilities desiredCapabilities)
96-
: base(commandExecutor, desiredCapabilities)
128+
protected static IReadOnlyDictionary<string, CommandInfo> ChromiumCustomCommands
97129
{
130+
get { return new ReadOnlyDictionary<string, CommandInfo>(chromiumCustomCommands); }
98131
}
99132

100133
/// <summary>
@@ -140,7 +173,7 @@ public ChromiumNetworkConditions NetworkConditions
140173
}
141174

142175
Dictionary<string, object> parameters = new Dictionary<string, object>();
143-
parameters["network_conditions"] = value.ToDictionary();
176+
parameters["network_conditions"] = value;
144177
this.Execute(SetNetworkConditionsCommand, parameters);
145178
}
146179
}
@@ -291,6 +324,14 @@ public void CloseDevToolsSession()
291324
}
292325
}
293326

327+
/// <summary>
328+
/// Clears simulated network conditions.
329+
/// </summary>
330+
public void ClearNetworkConditions()
331+
{
332+
this.Execute(DeleteNetworkConditionsCommand, null);
333+
}
334+
294335
/// <summary>
295336
/// Returns the list of cast sinks (Cast devices) available to the Chrome media router.
296337
/// </summary>
@@ -401,11 +442,5 @@ private static ICapabilities ConvertOptionsToCapabilities(ChromiumOptions option
401442

402443
return options.ToCapabilities();
403444
}
404-
405-
protected void AddCustomChromeCommand(string commandName, string method, string resourcePath)
406-
{
407-
HttpCommandInfo commandInfoToAdd = new HttpCommandInfo(method, resourcePath);
408-
this.CommandExecutor.TryAddCommand(commandName, commandInfoToAdd);
409-
}
410445
}
411446
}

dotnet/src/webdriver/Chromium/ChromiumNetworkConditions.cs

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,25 @@
1818

1919
using System;
2020
using System.Collections.Generic;
21-
using System.Linq;
22-
using System.Text;
21+
using Newtonsoft.Json;
2322

2423
namespace OpenQA.Selenium.Chromium
2524
{
2625
/// <summary>
2726
/// Provides manipulation of getting and setting network conditions from Chromium.
2827
/// </summary>
28+
[JsonObject(MemberSerialization.OptIn)]
2929
public class ChromiumNetworkConditions
3030
{
3131
private bool offline;
3232
private TimeSpan latency = TimeSpan.Zero;
33-
private long downloadThroughput = -1;
34-
private long uploadThroughput = -1;
33+
private long downloadThroughput = 0;
34+
private long uploadThroughput = 0;
3535

3636
/// <summary>
3737
/// Gets or sets a value indicating whether the network is offline. Defaults to <see langword="false"/>.
3838
/// </summary>
39+
[JsonProperty("offline")]
3940
public bool IsOffline
4041
{
4142
get { return this.offline; }
@@ -54,22 +55,49 @@ public TimeSpan Latency
5455
/// <summary>
5556
/// Gets or sets the throughput of the network connection in bytes/second for downloading.
5657
/// </summary>
58+
[JsonProperty("download_throughput")]
5759
public long DownloadThroughput
5860
{
5961
get { return this.downloadThroughput; }
60-
set { this.downloadThroughput = value; }
62+
set
63+
{
64+
if (value < 0)
65+
{
66+
throw new WebDriverException("Downlod throughput cannot be negative.");
67+
}
68+
69+
this.downloadThroughput = value;
70+
}
6171
}
6272

6373
/// <summary>
6474
/// Gets or sets the throughput of the network connection in bytes/second for uploading.
6575
/// </summary>
76+
[JsonProperty("upload_throughput")]
6677
public long UploadThroughput
6778
{
6879
get { return this.uploadThroughput; }
69-
set { this.uploadThroughput = value; }
80+
set
81+
{
82+
if (value < 0)
83+
{
84+
throw new WebDriverException("Upload throughput cannot be negative.");
85+
}
86+
87+
this.uploadThroughput = value;
88+
}
7089
}
7190

72-
static internal ChromiumNetworkConditions FromDictionary(Dictionary<string, object> dictionary)
91+
[JsonProperty("latency", NullValueHandling = NullValueHandling.Ignore)]
92+
internal long? SerializableLatency
93+
{
94+
get
95+
{
96+
return Convert.ToInt64(this.latency.TotalMilliseconds);
97+
}
98+
}
99+
100+
public static ChromiumNetworkConditions FromDictionary(Dictionary<string, object> dictionary)
73101
{
74102
ChromiumNetworkConditions conditions = new ChromiumNetworkConditions();
75103
if (dictionary.ContainsKey("offline"))
@@ -95,26 +123,19 @@ static internal ChromiumNetworkConditions FromDictionary(Dictionary<string, obje
95123
return conditions;
96124
}
97125

98-
internal Dictionary<string, object> ToDictionary()
126+
/// <summary>
127+
/// Sets the upload and download throughput properties to the same value.
128+
/// </summary>
129+
/// <param name="throughput">The throughput of the network connection in bytes/second for both upload and download.</param>
130+
public void SetBidirectionalThroughput(long throughput)
99131
{
100-
Dictionary<string, object> dictionary = new Dictionary<string, object>();
101-
dictionary["offline"] = this.offline;
102-
if (this.latency != TimeSpan.Zero)
103-
{
104-
dictionary["latency"] = Convert.ToInt64(this.latency.TotalMilliseconds);
105-
}
106-
107-
if (this.downloadThroughput >= 0)
108-
{
109-
dictionary["download_throughput"] = this.downloadThroughput;
110-
}
111-
112-
if (this.uploadThroughput >= 0)
132+
if (throughput < 0)
113133
{
114-
dictionary["upload_throughput"] = this.uploadThroughput;
134+
throw new ArgumentException("Throughput values cannot be negative.", nameof(throughput));
115135
}
116136

117-
return dictionary;
137+
this.uploadThroughput = throughput;
138+
this.downloadThroughput = throughput;
118139
}
119140
}
120141
}

0 commit comments

Comments
 (0)