Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[dotnet] Enable NRT on exceptional types #14672

Open
wants to merge 10 commits into
base: trunk
Choose a base branch
from
8 changes: 7 additions & 1 deletion dotnet/src/webdriver/DefaultFileDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
// limitations under the License.
// </copyright>

#nullable enable

namespace OpenQA.Selenium
{
/// <summary>
Expand All @@ -30,7 +32,11 @@ public class DefaultFileDetector : IFileDetector
/// </summary>
/// <param name="keySequence">The sequence to test for file existence.</param>
/// <returns>This method always returns <see langword="false"/> in this implementation.</returns>
public bool IsFile(string keySequence)
public bool IsFile(
#if NET8_0_OR_GREATER
[System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
#endif
string? keySequence)
{
return false;
}
Expand Down
7 changes: 4 additions & 3 deletions dotnet/src/webdriver/DetachedShadowRootException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
// </copyright>

using System;
using System.Runtime.Serialization;

#nullable enable
RenderMichael marked this conversation as resolved.
Show resolved Hide resolved

namespace OpenQA.Selenium
{
Expand All @@ -40,7 +41,7 @@ public DetachedShadowRootException()
/// a specified error message.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public DetachedShadowRootException(string message)
public DetachedShadowRootException(string? message)
: base(message)
{
}
Expand All @@ -53,7 +54,7 @@ public DetachedShadowRootException(string message)
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception,
/// or <see langword="null"/> if no inner exception is specified.</param>
public DetachedShadowRootException(string message, Exception innerException)
public DetachedShadowRootException(string? message, Exception? innerException)
: base(message, innerException)
{
}
Expand Down
6 changes: 4 additions & 2 deletions dotnet/src/webdriver/DevTools/CommandResponseException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

using System;

#nullable enable

namespace OpenQA.Selenium.DevTools
{
/// <summary>
Expand All @@ -38,7 +40,7 @@ public CommandResponseException()
/// Initializes a new instance of the <see cref="CommandResponseException"/> class with the specified message.
/// </summary>
/// <param name="message">The message of the exception.</param>
public CommandResponseException(string message)
public CommandResponseException(string? message)
: base(message)
{
}
Expand All @@ -48,7 +50,7 @@ public CommandResponseException(string message)
/// </summary>
/// <param name="message">The message of the exception.</param>
/// <param name="innerException">The inner exception for this exception.</param>
public CommandResponseException(string message, Exception innerException)
public CommandResponseException(string? message, Exception? innerException)
: base(message, innerException)
{
}
Expand Down
9 changes: 5 additions & 4 deletions dotnet/src/webdriver/DriverServiceNotFoundException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
// </copyright>

using System;
using System.Runtime.Serialization;

#nullable enable

namespace OpenQA.Selenium
{
/// <summary>
/// The exception that is thrown when an element is not visible.
/// The exception that is thrown when the driver service is not available.
/// </summary>
[Serializable]
public class DriverServiceNotFoundException : WebDriverException
Expand All @@ -40,7 +41,7 @@ public DriverServiceNotFoundException()
/// a specified error message.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public DriverServiceNotFoundException(string message)
public DriverServiceNotFoundException(string? message)
: base(message)
{
}
Expand All @@ -53,7 +54,7 @@ public DriverServiceNotFoundException(string message)
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception,
/// or <see langword="null"/> if no inner exception is specified.</param>
public DriverServiceNotFoundException(string message, Exception innerException)
public DriverServiceNotFoundException(string? message, Exception? innerException)
: base(message, innerException)
{
}
Expand Down
7 changes: 4 additions & 3 deletions dotnet/src/webdriver/ElementClickInterceptedException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
// </copyright>

using System;
using System.Runtime.Serialization;

#nullable enable

namespace OpenQA.Selenium
{
Expand All @@ -40,7 +41,7 @@ public ElementClickInterceptedException()
/// a specified error message.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public ElementClickInterceptedException(string message)
public ElementClickInterceptedException(string? message)
: base(message)
{
}
Expand All @@ -53,7 +54,7 @@ public ElementClickInterceptedException(string message)
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception,
/// or <see langword="null"/> if no inner exception is specified.</param>
public ElementClickInterceptedException(string message, Exception innerException)
public ElementClickInterceptedException(string? message, Exception? innerException)
: base(message, innerException)
{
}
Expand Down
9 changes: 5 additions & 4 deletions dotnet/src/webdriver/ElementNotInteractableException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
// </copyright>

using System;
using System.Runtime.Serialization;

#nullable enable

namespace OpenQA.Selenium
{
/// <summary>
/// The exception that is thrown when an element is not visible.
/// The exception that is thrown when an element is not interactable.
/// </summary>
[Serializable]
public class ElementNotInteractableException : InvalidElementStateException
Expand All @@ -40,7 +41,7 @@ public ElementNotInteractableException()
/// a specified error message.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public ElementNotInteractableException(string message)
public ElementNotInteractableException(string? message)
: base(message)
{
}
Expand All @@ -53,7 +54,7 @@ public ElementNotInteractableException(string message)
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception,
/// or <see langword="null"/> if no inner exception is specified.</param>
public ElementNotInteractableException(string message, Exception innerException)
public ElementNotInteractableException(string? message, Exception? innerException)
: base(message, innerException)
{
}
Expand Down
9 changes: 5 additions & 4 deletions dotnet/src/webdriver/ElementNotSelectableException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
// </copyright>

using System;
using System.Runtime.Serialization;

#nullable enable

namespace OpenQA.Selenium
{
/// <summary>
/// The exception that is thrown when an element is not visible.
/// The exception that is thrown when an element is not selectable.
/// </summary>
[Serializable]
public class ElementNotSelectableException : InvalidElementStateException
Expand All @@ -40,7 +41,7 @@ public ElementNotSelectableException()
/// a specified error message.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public ElementNotSelectableException(string message)
public ElementNotSelectableException(string? message)
: base(message)
{
}
Expand All @@ -53,7 +54,7 @@ public ElementNotSelectableException(string message)
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception,
/// or <see langword="null"/> if no inner exception is specified.</param>
public ElementNotSelectableException(string message, Exception innerException)
public ElementNotSelectableException(string? message, Exception? innerException)
: base(message, innerException)
{
}
Expand Down
7 changes: 4 additions & 3 deletions dotnet/src/webdriver/ElementNotVisibleException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
// </copyright>

using System;
using System.Runtime.Serialization;

#nullable enable

namespace OpenQA.Selenium
{
Expand All @@ -40,7 +41,7 @@ public ElementNotVisibleException()
/// a specified error message.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public ElementNotVisibleException(string message)
public ElementNotVisibleException(string? message)
: base(message)
{
}
Expand All @@ -53,7 +54,7 @@ public ElementNotVisibleException(string message)
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception,
/// or <see langword="null"/> if no inner exception is specified.</param>
public ElementNotVisibleException(string message, Exception innerException)
public ElementNotVisibleException(string? message, Exception? innerException)
: base(message, innerException)
{
}
Expand Down
82 changes: 25 additions & 57 deletions dotnet/src/webdriver/ErrorResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,15 @@

using System.Collections.Generic;

#nullable enable

namespace OpenQA.Selenium
{
/// <summary>
/// Provides a way to store errors from a response
/// </summary>
public class ErrorResponse
{
private StackTraceElement[] stackTrace;
private string message = string.Empty;
private string className = string.Empty;
private string screenshot = string.Empty;

/// <summary>
/// Initializes a new instance of the <see cref="ErrorResponse"/> class.
/// </summary>
Expand All @@ -42,58 +39,45 @@ public ErrorResponse()
/// </summary>
/// <param name="responseValue">A <see cref="Dictionary{K, V}"/> containing names and values of
/// the properties of this <see cref="ErrorResponse"/>.</param>
public ErrorResponse(Dictionary<string, object> responseValue)
public ErrorResponse(Dictionary<string, object?>? responseValue)
{
if (responseValue != null)
{
if (responseValue.ContainsKey("message"))
if (responseValue.TryGetValue("message", out object? messageObj)
&& messageObj?.ToString() is string message)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

&& messageObj is not null instead of && messageObj?.ToString() is string message?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is, untyped object.ToString() is annotated to return a string?. we need to handle that potentially null value too.

We can suppress it like before, with messageObj.ToString()!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I like objects in selenium.. Looked through where and how this class used, and seems it makes sense to make fields nullable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reworked the class to allow nullable fields. Let me know if it needs any more changes

{
if (responseValue["message"] != null)
{
this.message = responseValue["message"].ToString();
}
else
{
this.message = "The error did not contain a message.";
}
this.Message = message;
}

if (responseValue.ContainsKey("screen") && responseValue["screen"] != null)
else
{
this.screenshot = responseValue["screen"].ToString();
this.Message = "The error did not contain a message.";
}

if (responseValue.ContainsKey("class") && responseValue["class"] != null)
if (responseValue.TryGetValue("screen", out object? screenObj))
{
this.className = responseValue["class"].ToString();
this.Screenshot = screenObj?.ToString();
}

if (responseValue.ContainsKey("stackTrace") || responseValue.ContainsKey("stacktrace"))
if (responseValue.TryGetValue("class", out object? classObj))
{
object[] stackTraceArray = null;

if (responseValue.ContainsKey("stackTrace"))
{
stackTraceArray = responseValue["stackTrace"] as object[];
}
else if (responseValue.ContainsKey("stacktrace"))
{
stackTraceArray = responseValue["stacktrace"] as object[];
}
this.ClassName = classObj?.ToString();
}

if (stackTraceArray != null)
if (responseValue.TryGetValue("stackTrace", out object? stackTraceObj)
|| responseValue.TryGetValue("stacktrace", out stackTraceObj))
{
if (stackTraceObj is object?[] stackTraceArray)
{
List<StackTraceElement> stackTraceList = new List<StackTraceElement>();
foreach (object rawStackTraceElement in stackTraceArray)
foreach (object? rawStackTraceElement in stackTraceArray)
{
Dictionary<string, object> elementAsDictionary = rawStackTraceElement as Dictionary<string, object>;
if (elementAsDictionary != null)
if (rawStackTraceElement is Dictionary<string, object?> elementAsDictionary)
{
stackTraceList.Add(new StackTraceElement(elementAsDictionary));
}
}

this.stackTrace = stackTraceList.ToArray();
this.StackTrace = stackTraceList.ToArray();
}
}
}
Expand All @@ -102,38 +86,22 @@ public ErrorResponse(Dictionary<string, object> responseValue)
/// <summary>
/// Gets or sets the message from the response
/// </summary>
public string Message
{
get { return this.message; }
set { this.message = value; }
}
public string? Message { get; } = string.Empty;

/// <summary>
/// Gets or sets the class name that threw the error
/// </summary>
public string ClassName
{
get { return this.className; }
set { this.className = value; }
}
public string? ClassName { get; }

// TODO: (JimEvans) Change this to return an Image.
/// <summary>
/// Gets or sets the screenshot of the error
/// </summary>
public string Screenshot
{
// TODO: (JimEvans) Change this to return an Image.
get { return this.screenshot; }
set { this.screenshot = value; }
}
public string? Screenshot { get; }

/// <summary>
/// Gets or sets the stack trace of the error
/// </summary>
public StackTraceElement[] StackTrace
{
get { return this.stackTrace; }
set { this.stackTrace = value; }
}
public StackTraceElement[]? StackTrace { get; }
}
}
Loading