diff --git a/dotnet/src/webdriver/Interactions/Actions.cs b/dotnet/src/webdriver/Interactions/Actions.cs
index e3672dd5a5c7a..13eb5481b5728 100644
--- a/dotnet/src/webdriver/Interactions/Actions.cs
+++ b/dotnet/src/webdriver/Interactions/Actions.cs
@@ -19,6 +19,9 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+
+#nullable enable
namespace OpenQA.Selenium.Interactions
{
@@ -29,9 +32,9 @@ public class Actions : IAction
{
private readonly TimeSpan duration;
private ActionBuilder actionBuilder = new ActionBuilder();
- private PointerInputDevice activePointer;
- private KeyInputDevice activeKeyboard;
- private WheelInputDevice activeWheel;
+ private PointerInputDevice? activePointer;
+ private KeyInputDevice? activeKeyboard;
+ private WheelInputDevice? activeWheel;
///
/// Initializes a new instance of the class.
@@ -51,14 +54,10 @@ public Actions(IWebDriver driver)
/// If does not implement .
public Actions(IWebDriver driver, TimeSpan duration)
{
- IActionExecutor actionExecutor = GetDriverAs(driver);
- if (actionExecutor == null)
- {
- throw new ArgumentException("The IWebDriver object must implement or wrap a driver that implements IActionExecutor.", nameof(driver));
- }
+ IActionExecutor actionExecutor = GetDriverAs(driver)
+ ?? throw new ArgumentException("The IWebDriver object must implement or wrap a driver that implements IActionExecutor.", nameof(driver));
this.ActionExecutor = actionExecutor;
-
this.duration = duration;
}
@@ -74,9 +73,10 @@ public Actions(IWebDriver driver, TimeSpan duration)
/// The name of the pointer device to set as active.
/// A self-reference to this Actions class.
/// If a device with this name exists but is not a pointer.
+ [MemberNotNull(nameof(activePointer))]
public Actions SetActivePointer(PointerKind kind, string name)
{
- InputDevice device = FindDeviceById(name);
+ InputDevice? device = FindDeviceById(name);
this.activePointer = device switch
{
@@ -94,9 +94,10 @@ public Actions SetActivePointer(PointerKind kind, string name)
/// The name of the keyboard device to set as active.
/// A self-reference to this Actions class.
/// If a device with this name exists but is not a keyboard.
+ [MemberNotNull(nameof(activeKeyboard))]
public Actions SetActiveKeyboard(string name)
{
- InputDevice device = FindDeviceById(name);
+ InputDevice? device = FindDeviceById(name);
this.activeKeyboard = device switch
{
@@ -114,9 +115,10 @@ public Actions SetActiveKeyboard(string name)
/// The name of the wheel device to set as active.
/// A self-reference to this Actions class.
/// If a device with this name exists but is not a wheel.
+ [MemberNotNull(nameof(activeWheel))]
public Actions SetActiveWheel(string name)
{
- InputDevice device = FindDeviceById(name);
+ InputDevice? device = FindDeviceById(name);
this.activeWheel = device switch
{
@@ -128,7 +130,7 @@ public Actions SetActiveWheel(string name)
return this;
}
- private InputDevice FindDeviceById(string name)
+ private InputDevice? FindDeviceById(string? name)
{
foreach (var sequence in this.actionBuilder.ToActionSequenceList())
{
@@ -211,14 +213,14 @@ public Actions KeyDown(string theKey)
/// of , , ,
/// , ,,
/// ,.
- public Actions KeyDown(IWebElement element, string theKey)
+ public Actions KeyDown(IWebElement? element, string theKey)
{
if (string.IsNullOrEmpty(theKey))
{
throw new ArgumentException("The key value must not be null or empty", nameof(theKey));
}
- ILocatable target = GetLocatableFromElement(element);
+ ILocatable? target = GetLocatableFromElement(element);
if (element != null)
{
this.actionBuilder.AddAction(this.GetActivePointer().CreatePointerMove(element, 0, 0, duration));
@@ -255,14 +257,14 @@ public Actions KeyUp(string theKey)
/// of , , ,
/// , ,,
/// ,.
- public Actions KeyUp(IWebElement element, string theKey)
+ public Actions KeyUp(IWebElement? element, string theKey)
{
if (string.IsNullOrEmpty(theKey))
{
throw new ArgumentException("The key value must not be null or empty", nameof(theKey));
}
- ILocatable target = GetLocatableFromElement(element);
+ ILocatable? target = GetLocatableFromElement(element);
if (element != null)
{
this.actionBuilder.AddAction(this.GetActivePointer().CreatePointerMove(element, 0, 0, duration));
@@ -279,6 +281,7 @@ public Actions KeyUp(IWebElement element, string theKey)
///
/// The keystrokes to send to the browser.
/// A self-reference to this .
+ /// If is or .
public Actions SendKeys(string keysToSend)
{
return this.SendKeys(null, keysToSend);
@@ -290,14 +293,15 @@ public Actions SendKeys(string keysToSend)
/// The element to which to send the keystrokes.
/// The keystrokes to send to the browser.
/// A self-reference to this .
- public Actions SendKeys(IWebElement element, string keysToSend)
+ /// If is or .
+ public Actions SendKeys(IWebElement? element, string keysToSend)
{
if (string.IsNullOrEmpty(keysToSend))
{
throw new ArgumentException("The key value must not be null or empty", nameof(keysToSend));
}
- ILocatable target = GetLocatableFromElement(element);
+ ILocatable? target = GetLocatableFromElement(element);
if (element != null)
{
this.actionBuilder.AddAction(this.GetActivePointer().CreatePointerMove(element, 0, 0, duration));
@@ -319,6 +323,7 @@ public Actions SendKeys(IWebElement element, string keysToSend)
///
/// The element on which to click and hold.
/// A self-reference to this .
+ /// If is null.
public Actions ClickAndHold(IWebElement onElement)
{
this.MoveToElement(onElement).ClickAndHold();
@@ -340,6 +345,7 @@ public Actions ClickAndHold()
///
/// The element on which to release the button.
/// A self-reference to this .
+ /// If is null.
public Actions Release(IWebElement onElement)
{
this.MoveToElement(onElement).Release();
@@ -361,6 +367,7 @@ public Actions Release()
///
/// The element on which to click.
/// A self-reference to this .
+ /// If is null.
public Actions Click(IWebElement onElement)
{
this.MoveToElement(onElement).Click();
@@ -383,6 +390,7 @@ public Actions Click()
///
/// The element on which to double-click.
/// A self-reference to this .
+ /// If is null.
public Actions DoubleClick(IWebElement onElement)
{
this.MoveToElement(onElement).DoubleClick();
@@ -407,6 +415,7 @@ public Actions DoubleClick()
///
/// The element to which to move the mouse.
/// A self-reference to this .
+ /// If is null.
public Actions MoveToElement(IWebElement toElement)
{
if (toElement == null)
@@ -460,6 +469,7 @@ public Actions MoveToLocation(int offsetX, int offsetY)
///
/// The element on which to right-click.
/// A self-reference to this .
+ /// If is null.
public Actions ContextClick(IWebElement onElement)
{
this.MoveToElement(onElement).ContextClick();
@@ -483,6 +493,7 @@ public Actions ContextClick()
/// The element on which the drag operation is started.
/// The element on which the drop is performed.
/// A self-reference to this .
+ /// If or are null.
public Actions DragAndDrop(IWebElement source, IWebElement target)
{
this.ClickAndHold(source).MoveToElement(target).Release(target);
@@ -496,6 +507,7 @@ public Actions DragAndDrop(IWebElement source, IWebElement target)
/// The horizontal offset to which to move the mouse.
/// The vertical offset to which to move the mouse.
/// A self-reference to this .
+ /// If is null.
public Actions DragAndDropToOffset(IWebElement source, int offsetX, int offsetY)
{
this.ClickAndHold(source).MoveByOffset(offsetX, offsetY).Release();
@@ -507,6 +519,7 @@ public Actions DragAndDropToOffset(IWebElement source, int offsetX, int offsetY)
///
/// Which element to scroll into the viewport.
/// A self-reference to this .
+ /// If is null.
public Actions ScrollToElement(IWebElement element)
{
this.actionBuilder.AddAction(this.GetActiveWheel().CreateWheelScroll(element, 0, 0, 0, 0, duration));
@@ -540,8 +553,15 @@ public Actions ScrollByAmount(int deltaX, int deltaY)
/// Distance along Y axis to scroll using the wheel. A negative value scrolls up.
/// A self-reference to this .
/// If the origin with offset is outside the viewport.
+ /// If is null.
+ /// If both or either of Viewport and Element are set.
public Actions ScrollFromOrigin(WheelInputDevice.ScrollOrigin scrollOrigin, int deltaX, int deltaY)
{
+ if (scrollOrigin is null)
+ {
+ throw new ArgumentNullException(nameof(scrollOrigin));
+ }
+
if (scrollOrigin.Viewport && scrollOrigin.Element != null)
{
throw new ArgumentException("viewport can not be true if an element is defined.", nameof(scrollOrigin));
@@ -554,7 +574,7 @@ public Actions ScrollFromOrigin(WheelInputDevice.ScrollOrigin scrollOrigin, int
}
else
{
- this.actionBuilder.AddAction(this.GetActiveWheel().CreateWheelScroll(scrollOrigin.Element,
+ this.actionBuilder.AddAction(this.GetActiveWheel().CreateWheelScroll(scrollOrigin.Element!,
scrollOrigin.XOffset, scrollOrigin.YOffset, deltaX, deltaY, duration));
}
@@ -566,6 +586,7 @@ public Actions ScrollFromOrigin(WheelInputDevice.ScrollOrigin scrollOrigin, int
///
/// How long to pause the action chain.
/// A self-reference to this .
+ /// If is negative.
public Actions Pause(TimeSpan duration)
{
this.actionBuilder.AddAction(new PauseInteraction(this.GetActivePointer(), duration));
@@ -603,15 +624,16 @@ public void Reset()
///
/// The to get the location of.
/// The of the .
- protected static ILocatable GetLocatableFromElement(IWebElement element)
+ [return: NotNullIfNotNull(nameof(element))]
+ protected static ILocatable? GetLocatableFromElement(IWebElement? element)
{
if (element == null)
{
return null;
}
- ILocatable target = null;
- IWrapsElement wrapper = element as IWrapsElement;
+ ILocatable? target = null;
+ IWrapsElement? wrapper = element as IWrapsElement;
while (wrapper != null)
{
target = wrapper.WrappedElement as ILocatable;
@@ -631,12 +653,12 @@ protected static ILocatable GetLocatableFromElement(IWebElement element)
return target;
}
- private T GetDriverAs(IWebDriver driver) where T : class
+ private static T? GetDriverAs(IWebDriver? driver) where T : class
{
- T driverAsType = driver as T;
+ T? driverAsType = driver as T;
if (driverAsType == null)
{
- IWrapsDriver wrapper = driver as IWrapsDriver;
+ IWrapsDriver? wrapper = driver as IWrapsDriver;
while (wrapper != null)
{
driverAsType = wrapper.WrappedDriver as T;
diff --git a/dotnet/src/webdriver/Interactions/InputDevice.cs b/dotnet/src/webdriver/Interactions/InputDevice.cs
index f73c0578e2586..f3adbf78128a8 100644
--- a/dotnet/src/webdriver/Interactions/InputDevice.cs
+++ b/dotnet/src/webdriver/Interactions/InputDevice.cs
@@ -77,6 +77,7 @@ public Interaction CreatePause()
/// of the pause. Note that pauses to synchronize
/// with other action sequences for other devices.
/// The representing the action.
+ /// If is negative.
public Interaction CreatePause(TimeSpan duration)
{
return new PauseInteraction(this, duration);
diff --git a/dotnet/src/webdriver/Interactions/PauseInteraction.cs b/dotnet/src/webdriver/Interactions/PauseInteraction.cs
index d571f2c30a1f0..6510ef24b51af 100644
--- a/dotnet/src/webdriver/Interactions/PauseInteraction.cs
+++ b/dotnet/src/webdriver/Interactions/PauseInteraction.cs
@@ -46,6 +46,7 @@ public PauseInteraction(InputDevice sourceDevice)
///
/// The input device on which to execute the pause.
/// The length of time to pause for.
+ /// If is negative.
public PauseInteraction(InputDevice sourceDevice, TimeSpan duration)
: base(sourceDevice)
{
diff --git a/dotnet/src/webdriver/Keys.cs b/dotnet/src/webdriver/Keys.cs
index 7fa250a4c2720..c824c68f86acf 100644
--- a/dotnet/src/webdriver/Keys.cs
+++ b/dotnet/src/webdriver/Keys.cs
@@ -21,6 +21,8 @@
using System.Collections.Generic;
using System.Globalization;
+#nullable enable
+
namespace OpenQA.Selenium
{
///
@@ -352,13 +354,14 @@ public static class Keys
///
public static readonly string ZenkakuHankaku = Convert.ToString(Convert.ToChar(0xE040, CultureInfo.InvariantCulture), CultureInfo.InvariantCulture);
- private static Dictionary descriptions;
+ private static Dictionary? descriptions;
///
/// Gets the description of a specific key.
///
/// The key value for which to get the description.
/// The description of the key.
+ /// If is .
internal static object GetDescription(string value)
{
if (descriptions == null)
@@ -423,9 +426,9 @@ internal static object GetDescription(string value)
descriptions.Add(ZenkakuHankaku, "Zenkaku Hankaku");
}
- if (descriptions.ContainsKey(value))
+ if (descriptions.TryGetValue(value, out string? description))
{
- return descriptions[value];
+ return description;
}
return value;