Skip to content
Open
Changes from all 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
89 changes: 71 additions & 18 deletions dotnet/src/webdriver/DriverOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,33 @@

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()
=> new UnhandledPromptBehaviorMultiOption();
}

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; } = UnhandledPromptBehavior.Default;

public UnhandledPromptBehavior Confirm { get; set; } = UnhandledPromptBehavior.Default;

public UnhandledPromptBehavior Prompt { get; set; } = UnhandledPromptBehavior.Default;

public UnhandledPromptBehavior BeforeUnload { get; set; } = UnhandledPromptBehavior.Default;

public UnhandledPromptBehavior Default { get; set; } = UnhandledPromptBehavior.Default;
}

/// <summary>
/// Specifies the behavior of handling unexpected alerts in the IE driver.
/// </summary>
Expand Down Expand Up @@ -164,7 +191,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 +330,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 +535,55 @@ protected IWritableCapabilities GenerateDesiredCapabilities(bool isSpecification
capabilities.SetCapability(CapabilityType.PageLoadStrategy, pageLoadStrategySetting);
}

if (this.UnhandledPromptBehavior != UnhandledPromptBehavior.Default)
static string UnhandledPromptBehaviorToString(UnhandledPromptBehavior behavior) => behavior switch
{
Selenium.UnhandledPromptBehavior.Ignore => "ignore",
Selenium.UnhandledPromptBehavior.Accept => "accept",
Selenium.UnhandledPromptBehavior.Dismiss => "dismiss",
Selenium.UnhandledPromptBehavior.AcceptAndNotify => "accept and notify",
Selenium.UnhandledPromptBehavior.DismissAndNotify => "dismiss and notify",
_ => throw new ArgumentOutOfRangeException(nameof(behavior), $"UnhandledPromptBehavior value '{behavior}' is not recognized."),
};

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

capabilities.SetCapability(CapabilityType.UnhandledPromptBehavior, stringValue);
}
else if (this.UnhandledPromptBehavior is UnhandledPromptBehaviorMultiOption multiOption)
{
string unhandledPropmtBehaviorSetting = "ignore";
switch (this.UnhandledPromptBehavior)
Dictionary<string, string> multiOptionDictionary = [];

if (multiOption.Alert is not Selenium.UnhandledPromptBehavior.Default)
{
case UnhandledPromptBehavior.Accept:
unhandledPropmtBehaviorSetting = "accept";
break;
multiOptionDictionary["alert"] = UnhandledPromptBehaviorToString(multiOption.Alert);
}

case UnhandledPromptBehavior.Dismiss:
unhandledPropmtBehaviorSetting = "dismiss";
break;
if (multiOption.Confirm is not Selenium.UnhandledPromptBehavior.Default)
{
multiOptionDictionary["confirm"] = UnhandledPromptBehaviorToString(multiOption.Confirm);
}

case UnhandledPromptBehavior.AcceptAndNotify:
unhandledPropmtBehaviorSetting = "accept and notify";
break;
if (multiOption.Prompt is not Selenium.UnhandledPromptBehavior.Default)
{
multiOptionDictionary["prompt"] = UnhandledPromptBehaviorToString(multiOption.Prompt);
}

case UnhandledPromptBehavior.DismissAndNotify:
unhandledPropmtBehaviorSetting = "dismiss and notify";
break;
if (multiOption.BeforeUnload is not Selenium.UnhandledPromptBehavior.Default)
{
multiOptionDictionary["beforeUnload"] = UnhandledPromptBehaviorToString(multiOption.BeforeUnload);
}

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

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

if (this.Proxy != null)
Expand Down