Skip to content
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 79 additions & 18 deletions dotnet/src/webdriver/DriverOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,37 @@

namespace OpenQA.Selenium;

public abstract record UnhandledPromptBehaviorOption
Copy link
Member Author

Choose a reason for hiding this comment

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

I will add xml docs as soon as we approve the approach.

Copy link
Member Author

Choose a reason for hiding this comment

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

Move out from this file to dedicated (with "nested/related" types).

{
public static implicit operator UnhandledPromptBehaviorOption(UnhandledPromptBehavior? value)
=> Single(value);

public static UnhandledPromptBehaviorOption Single(UnhandledPromptBehavior? value)
=> new UnhandledPromptBehaviorSingleOption(value);

public static UnhandledPromptBehaviorOption Multi(UnhandledPromptBehavior? alert = null,
Copy link
Member Author

Choose a reason for hiding this comment

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

Do we really need static factory? Even with optional method arguments? We can, but optional arguments are risky in the library (breaking change if we add new arg)

UnhandledPromptBehavior? confirm = null,
UnhandledPromptBehavior? prompt = null,
UnhandledPromptBehavior? beforeUnload = null,
UnhandledPromptBehavior? @default = null)
=> new UnhandledPromptBehaviorMultiOption() with { Alert = alert, Confirm = confirm, Prompt = prompt, BeforeUnload = beforeUnload, Default = @default };
}

public sealed record UnhandledPromptBehaviorSingleOption(UnhandledPromptBehavior? Value) : UnhandledPromptBehaviorOption;

public sealed record UnhandledPromptBehaviorMultiOption : UnhandledPromptBehaviorOption
Copy link
Member Author

Choose a reason for hiding this comment

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

@RenderMichael any alternative names for these records? I like UnhandledPromptBehavior*Option pattern.

{
public UnhandledPromptBehavior? Alert { get; set; }

public UnhandledPromptBehavior? Confirm { get; set; }

public UnhandledPromptBehavior? Prompt { get; set; }

public UnhandledPromptBehavior? BeforeUnload { get; set; }

public UnhandledPromptBehavior? Default { get; set; }
}

/// <summary>
/// Specifies the behavior of handling unexpected alerts in the IE driver.
/// </summary>
Expand Down Expand Up @@ -164,7 +195,7 @@ protected DriverOptions()
/// Gets or sets the value for describing how unexpected alerts are to be handled in the browser.
/// Defaults to <see cref="UnhandledPromptBehavior.Default"/>.
/// </summary>
public UnhandledPromptBehavior UnhandledPromptBehavior { get; set; } = UnhandledPromptBehavior.Default;
public UnhandledPromptBehaviorOption? UnhandledPromptBehavior { get; set; }

/// <summary>
/// Gets or sets the value for describing how the browser is to wait for pages to load in the browser.
Expand Down Expand Up @@ -303,7 +334,7 @@ public virtual DriverOptionsMergeResult GetMergeResult(DriverOptions other)
return result;
}

if (this.UnhandledPromptBehavior != UnhandledPromptBehavior.Default && other.UnhandledPromptBehavior != UnhandledPromptBehavior.Default)
if (this.UnhandledPromptBehavior is not null && other.UnhandledPromptBehavior is not null)
Copy link
Member Author

Choose a reason for hiding this comment

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

Hm, != operator for records?

Copy link
Contributor

Choose a reason for hiding this comment

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

It does feel like this method should tolerate it when both values are the same.

However, we should investigate the history of this method before making those decisions.

Copy link
Member Author

Choose a reason for hiding this comment

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

I understand it as don't send anything over wire if default.

Copy link
Member Author

Choose a reason for hiding this comment

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

However, we should investigate the history of this method before making those decisions.

Oh yes, we should understand the purpose of this method, not obvious to me at glance.

{
result.IsMergeConflict = true;
result.MergeConflictOptionName = "UnhandledPromptBehavior";
Expand Down Expand Up @@ -508,29 +539,59 @@ protected IWritableCapabilities GenerateDesiredCapabilities(bool isSpecification
capabilities.SetCapability(CapabilityType.PageLoadStrategy, pageLoadStrategySetting);
}

if (this.UnhandledPromptBehavior != UnhandledPromptBehavior.Default)
[return: NotNullIfNotNull(nameof(behavior))]
static string? UnhandledPromptBehaviorToString(UnhandledPromptBehavior? behavior) => behavior switch
{
string unhandledPropmtBehaviorSetting = "ignore";
switch (this.UnhandledPromptBehavior)
Selenium.UnhandledPromptBehavior.Ignore => "ignore",
Selenium.UnhandledPromptBehavior.Accept => "accept",
Selenium.UnhandledPromptBehavior.Dismiss => "dismiss",
Selenium.UnhandledPromptBehavior.AcceptAndNotify => "accept and notify",
Selenium.UnhandledPromptBehavior.DismissAndNotify => "dismiss and notify",
_ => null
};

if (this.UnhandledPromptBehavior is UnhandledPromptBehaviorSingleOption singleOption)
{
var stringValue = UnhandledPromptBehaviorToString(singleOption.Value);

if (stringValue is not null)
{
case UnhandledPromptBehavior.Accept:
unhandledPropmtBehaviorSetting = "accept";
break;
capabilities.SetCapability(CapabilityType.UnhandledPromptBehavior, stringValue);
}
}
else if (this.UnhandledPromptBehavior is UnhandledPromptBehaviorMultiOption multiOption)
{
Dictionary<string, string> multiOptionDictionary = [];

case UnhandledPromptBehavior.Dismiss:
unhandledPropmtBehaviorSetting = "dismiss";
break;
if (multiOption.Alert is not null)
{
multiOptionDictionary["alert"] = UnhandledPromptBehaviorToString(multiOption.Alert);
}

case UnhandledPromptBehavior.AcceptAndNotify:
unhandledPropmtBehaviorSetting = "accept and notify";
break;
if (multiOption.Confirm is not null)
{
multiOptionDictionary["confirm"] = UnhandledPromptBehaviorToString(multiOption.Confirm);
}

case UnhandledPromptBehavior.DismissAndNotify:
unhandledPropmtBehaviorSetting = "dismiss and notify";
break;
if (multiOption.Prompt is not null)
{
multiOptionDictionary["prompt"] = UnhandledPromptBehaviorToString(multiOption.Prompt);
}

capabilities.SetCapability(CapabilityType.UnhandledPromptBehavior, unhandledPropmtBehaviorSetting);
if (multiOption.BeforeUnload is not null)
{
multiOptionDictionary["beforeUnload"] = UnhandledPromptBehaviorToString(multiOption.BeforeUnload);
}

if (multiOption.Default is not null)
{
multiOptionDictionary["default"] = UnhandledPromptBehaviorToString(multiOption.Default);
}

if (multiOptionDictionary.Count != 0)
{
capabilities.SetCapability(CapabilityType.UnhandledPromptBehavior, multiOptionDictionary);
}
}

if (this.Proxy != null)
Expand Down