diff --git a/dotnet/src/webdriver/DriverOptions.cs b/dotnet/src/webdriver/DriverOptions.cs
index bfcb2107c1ea6..2de9dd2cbb4c9 100644
--- a/dotnet/src/webdriver/DriverOptions.cs
+++ b/dotnet/src/webdriver/DriverOptions.cs
@@ -24,44 +24,6 @@
namespace OpenQA.Selenium;
-///
-/// Specifies the behavior of handling unexpected alerts in the IE driver.
-///
-public enum UnhandledPromptBehavior
-{
- ///
- /// Indicates the behavior is not set.
- ///
- Default,
-
- ///
- /// Ignore unexpected alerts, such that the user must handle them.
- ///
- Ignore,
-
- ///
- /// Accept unexpected alerts.
- ///
- Accept,
-
- ///
- /// Dismiss unexpected alerts.
- ///
- Dismiss,
-
- ///
- /// Accepts unexpected alerts and notifies the user that the alert has
- /// been accepted by throwing an
- ///
- AcceptAndNotify,
-
- ///
- /// Dismisses unexpected alerts and notifies the user that the alert has
- /// been dismissed by throwing an
- ///
- DismissAndNotify
-}
-
///
/// Specifies the behavior of waiting for page loads in the driver.
///
@@ -160,9 +122,9 @@ protected DriverOptions()
///
/// Gets or sets the value for describing how unexpected alerts are to be handled in the browser.
- /// Defaults to .
+ /// Defaults to , leaving the behavior unset.
///
- public UnhandledPromptBehavior UnhandledPromptBehavior { get; set; } = UnhandledPromptBehavior.Default;
+ public UserPromptHandler? UnhandledPromptBehavior { get; set; }
///
/// Gets or sets the value for describing how the browser is to wait for pages to load in the browser.
@@ -298,7 +260,7 @@ public virtual DriverOptionsMergeResult GetMergeResult(DriverOptions other)
return result;
}
- if (this.UnhandledPromptBehavior != UnhandledPromptBehavior.Default && other.UnhandledPromptBehavior != UnhandledPromptBehavior.Default)
+ if (this.UnhandledPromptBehavior != other.UnhandledPromptBehavior)
{
result.IsMergeConflict = true;
result.MergeConflictOptionName = "UnhandledPromptBehavior";
@@ -503,29 +465,11 @@ protected IWritableCapabilities GenerateDesiredCapabilities(bool isSpecification
capabilities.SetCapability(CapabilityType.PageLoadStrategy, pageLoadStrategySetting);
}
- if (this.UnhandledPromptBehavior != UnhandledPromptBehavior.Default)
- {
- string unhandledPropmtBehaviorSetting = "ignore";
- switch (this.UnhandledPromptBehavior)
- {
- case UnhandledPromptBehavior.Accept:
- unhandledPropmtBehaviorSetting = "accept";
- break;
+ var unhandledPromptBehaviorCapability = this.UnhandledPromptBehavior?.ToCapabilities();
- case UnhandledPromptBehavior.Dismiss:
- unhandledPropmtBehaviorSetting = "dismiss";
- break;
-
- case UnhandledPromptBehavior.AcceptAndNotify:
- unhandledPropmtBehaviorSetting = "accept and notify";
- break;
-
- case UnhandledPromptBehavior.DismissAndNotify:
- unhandledPropmtBehaviorSetting = "dismiss and notify";
- break;
- }
-
- capabilities.SetCapability(CapabilityType.UnhandledPromptBehavior, unhandledPropmtBehaviorSetting);
+ if (unhandledPromptBehaviorCapability != null)
+ {
+ capabilities.SetCapability(CapabilityType.UnhandledPromptBehavior, unhandledPromptBehaviorCapability);
}
if (this.Proxy != null)
diff --git a/dotnet/src/webdriver/UserPromptHandler.cs b/dotnet/src/webdriver/UserPromptHandler.cs
new file mode 100644
index 0000000000000..e226c79aab1fa
--- /dev/null
+++ b/dotnet/src/webdriver/UserPromptHandler.cs
@@ -0,0 +1,195 @@
+//
+// Licensed to the Software Freedom Conservancy (SFC) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The SFC licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+namespace OpenQA.Selenium;
+
+///
+/// Represents a WebDriver session's user prompt handler, which defines how unhandled browser prompts
+/// (alerts, confirms, prompts, beforeunload dialogs, file selection dialogs) are managed during automation.
+///
+///
+/// This corresponds to the W3C WebDriver unhandledPromptBehavior capability, which may be expressed
+/// either as a single string applied to all prompt types, or as a per-prompt-type map.
+///
+/// Available variants:
+///
+/// - - Wraps a single value applied to all prompt types. Create via the implicit conversion from or by constructing directly.
+/// - - Allows configuring per-prompt behaviors (Alert, Confirm, Prompt, BeforeUnload, File, Default).
+///
+///
+///
+public abstract record UserPromptHandler
+{
+ private UserPromptHandler() { }
+
+ ///
+ /// Converts a nullable to a instance,
+ /// or when is .
+ ///
+ /// The value to convert.
+ public static implicit operator UserPromptHandler?(UnhandledPromptBehavior? value)
+ => value is { } v ? new Uniform(v) : null;
+
+ internal abstract object? ToCapabilities();
+
+ private static string ConvertBehaviorToString(UnhandledPromptBehavior behavior) =>
+ behavior switch
+ {
+ UnhandledPromptBehavior.Ignore => "ignore",
+ UnhandledPromptBehavior.Accept => "accept",
+ UnhandledPromptBehavior.Dismiss => "dismiss",
+ UnhandledPromptBehavior.AcceptAndNotify => "accept and notify",
+ UnhandledPromptBehavior.DismissAndNotify => "dismiss and notify",
+ _ => throw new InvalidOperationException($"UnhandledPromptBehavior value '{behavior}' is not recognized."),
+ };
+
+ ///
+ /// Represents a user prompt handler that applies a single value
+ /// as the fallback default for all prompt types.
+ ///
+ /// The unhandled prompt behavior to apply. Specifies how unexpected browser prompts are handled during automation.
+ public sealed record Uniform(UnhandledPromptBehavior Value) : UserPromptHandler
+ {
+ internal override object? ToCapabilities()
+ {
+#pragma warning disable CS0618 // UnhandledPromptBehavior.Default is obsolete
+ if (Value == UnhandledPromptBehavior.Default)
+ {
+ return null;
+ }
+#pragma warning restore CS0618
+
+ return ConvertBehaviorToString(Value);
+ }
+ }
+
+ ///
+ /// Represents a user prompt handler that specifies distinct values
+ /// for individual prompt types (alert, confirm, prompt, beforeunload, file), with a fallback default.
+ ///
+ /// Use this variant to configure distinct behaviors for alert, confirm, prompt, beforeunload, and file
+ /// selection dialogs encountered during browser automation. Each property allows you to control the response to a
+ /// specific type of unhandled prompt, enabling fine-grained handling beyond a single global setting.
+ public sealed record PerPromptType : UserPromptHandler
+ {
+ ///
+ /// Gets the behavior to use when an unexpected alert is encountered during automation,
+ /// or to leave it unset.
+ ///
+ public UnhandledPromptBehavior? Alert { get; init; }
+
+ ///
+ /// Gets the behavior to use when a confirmation prompt is encountered,
+ /// or to leave it unset.
+ ///
+ public UnhandledPromptBehavior? Confirm { get; init; }
+
+ ///
+ /// Gets the behavior to use when an unexpected prompt is encountered during automation,
+ /// or to leave it unset.
+ ///
+ public UnhandledPromptBehavior? Prompt { get; init; }
+
+ ///
+ /// Gets the behavior to use when an unexpected beforeunload dialog is encountered,
+ /// or to leave it unset.
+ ///
+ public UnhandledPromptBehavior? BeforeUnload { get; init; }
+
+ ///
+ /// Gets the behavior to use when an unexpected file selection dialog is encountered,
+ /// or to leave it unset.
+ ///
+ /// The "file" prompt type is respected only in WebDriver BiDi sessions.
+ public UnhandledPromptBehavior? File { get; init; }
+
+ ///
+ /// Gets the fallback behavior to use when no specific handler is defined for a given prompt type,
+ /// or to leave it unset.
+ ///
+ public UnhandledPromptBehavior? Default { get; init; }
+
+ internal override object? ToCapabilities()
+ {
+ Dictionary capabilities = [];
+ AddIfSet(capabilities, "alert", Alert);
+ AddIfSet(capabilities, "confirm", Confirm);
+ AddIfSet(capabilities, "prompt", Prompt);
+ AddIfSet(capabilities, "beforeUnload", BeforeUnload);
+ AddIfSet(capabilities, "file", File);
+ AddIfSet(capabilities, "default", Default);
+ return capabilities;
+ }
+
+ private static void AddIfSet(Dictionary capabilities, string key, UnhandledPromptBehavior? value)
+ {
+#pragma warning disable CS0618 // UnhandledPromptBehavior.Default is obsolete
+ if (value is { } v && v != UnhandledPromptBehavior.Default)
+ {
+ capabilities[key] = ConvertBehaviorToString(v);
+ }
+#pragma warning restore CS0618
+ }
+ }
+}
+
+///
+/// Specifies how a WebDriver session handles an unhandled user prompt.
+///
+///
+/// Corresponds to the handler values defined for the W3C WebDriver
+/// unhandledPromptBehavior capability:
+/// dismiss, accept, dismiss and notify, accept and notify, and ignore.
+/// When no handler is configured, the spec's implicit default is .
+///
+public enum UnhandledPromptBehavior
+{
+ ///
+ /// Sentinel value meaning "behavior not set". Not part of the W3C WebDriver spec.
+ ///
+ [Obsolete("Use a nullable UnhandledPromptBehavior? and pass null to leave the behavior unset. This member will be removed in v4.46.")]
+ Default,
+
+ ///
+ /// Ignore unexpected alerts, such that the user must handle them.
+ ///
+ Ignore,
+
+ ///
+ /// Accept unexpected alerts.
+ ///
+ Accept,
+
+ ///
+ /// Dismiss unexpected alerts.
+ ///
+ Dismiss,
+
+ ///
+ /// Accepts unexpected alerts and notifies the user that the alert has
+ /// been accepted by throwing an
+ ///
+ AcceptAndNotify,
+
+ ///
+ /// Dismisses unexpected alerts and notifies the user that the alert has
+ /// been dismissed by throwing an
+ ///
+ DismissAndNotify
+}
diff --git a/dotnet/test/webdriver/AlertsTests.cs b/dotnet/test/webdriver/AlertsTests.cs
index bd13810b1c948..49486304d0c5d 100644
--- a/dotnet/test/webdriver/AlertsTests.cs
+++ b/dotnet/test/webdriver/AlertsTests.cs
@@ -555,5 +555,4 @@ private Func WindowHandleCountToBe(int count)
return driver.WindowHandles.Count == count;
};
}
-
}
diff --git a/dotnet/test/webdriver/UnexpectedAlertBehaviorTests.cs b/dotnet/test/webdriver/UnexpectedAlertBehaviorTests.cs
index f93e1f54a113a..45e875c1a4129 100644
--- a/dotnet/test/webdriver/UnexpectedAlertBehaviorTests.cs
+++ b/dotnet/test/webdriver/UnexpectedAlertBehaviorTests.cs
@@ -71,56 +71,49 @@ public void CanSilentlyDismissUnhandledAlert()
[Test]
public void CanDismissUnhandledAlertsByDefault()
{
- ExecuteTestWithUnhandledPrompt(UnhandledPromptBehavior.Default, "null");
+ ExecuteTestWithUnhandledPrompt(null, "null");
+ }
+
+ [Test]
+ public void CanDismissUnhandledAlertsViaPerType()
+ {
+ ExecuteTestWithUnhandledPrompt(new UserPromptHandler.PerPromptType
+ {
+ Alert = UnhandledPromptBehavior.Dismiss
+ }, "null");
+ }
+
+ [Test]
+ public void CanDismissUnhandledAlertsViaDefaultPerType()
+ {
+ ExecuteTestWithUnhandledPrompt(new UserPromptHandler.PerPromptType(), "null");
}
[Test]
[IgnoreBrowser(Browser.Safari, "Test hangs waiting for alert acknowledgement in Safari, but works in Tech Preview")]
public void CanIgnoreUnhandledAlert()
{
- Assert.That(() => ExecuteTestWithUnhandledPrompt(UnhandledPromptBehavior.Ignore, "Text ignored"), Throws.InstanceOf().With.InnerException.InstanceOf());
+ Assert.That(
+ () => ExecuteTestWithUnhandledPrompt(UnhandledPromptBehavior.Ignore, "Text ignored"),
+ Throws.InstanceOf().With.InnerException.InstanceOf());
localDriver.SwitchTo().Alert().Dismiss();
}
- private void ExecuteTestWithUnhandledPrompt(UnhandledPromptBehavior behavior, string expectedAlertText)
+ private void ExecuteTestWithUnhandledPrompt(UserPromptHandler behavior, string expectedAlertText)
{
- bool silentlyHandlePrompt = behavior == UnhandledPromptBehavior.Accept || behavior == UnhandledPromptBehavior.Dismiss;
- UnhandledPromptBehaviorOptions options = new UnhandledPromptBehaviorOptions();
- if (behavior != UnhandledPromptBehavior.Default)
+ UnhandledPromptBehaviorOptions options = new()
{
- options.UnhandledPromptBehavior = behavior;
- }
+ UnhandledPromptBehavior = behavior,
+ };
localDriver = EnvironmentManager.Instance.CreateDriverInstance(options);
localDriver.Url = alertsPage;
IWebElement resultElement = localDriver.FindElement(By.Id("text"));
localDriver.FindElement(By.Id("prompt-with-default")).Click();
- WaitFor(ElementTextToBeEqual(resultElement, expectedAlertText, silentlyHandlePrompt), "Did not find text");
+ WaitFor(() => resultElement.Text == expectedAlertText, "Did not find text");
}
- private Func ElementTextToBeEqual(IWebElement resultElement, string expectedAlertText, bool silentlyHandlePrompt)
- {
- return () =>
- {
- try
- {
- return resultElement.Text == expectedAlertText;
- }
- catch (UnhandledAlertException)
- {
- if (!silentlyHandlePrompt)
- {
- throw;
- }
- }
- catch (NoSuchElementException)
- {
- }
-
- return false;
- };
- }
public class UnhandledPromptBehaviorOptions : DriverOptions
{