Skip to content

Commit

Permalink
[dotnet] Support setting timeouts in capabilities (#13698)
Browse files Browse the repository at this point in the history
Setting timeout values in driver options
  • Loading branch information
nvborisenko committed Mar 23, 2024
1 parent e7db08f commit 7c1fae3
Show file tree
Hide file tree
Showing 4 changed files with 219 additions and 0 deletions.
79 changes: 79 additions & 0 deletions dotnet/src/webdriver/DriverOptions.cs
Expand Up @@ -89,6 +89,24 @@ public enum PageLoadStrategy
None
}

internal class Timeout
{
public TimeSpan? Script { get; set; }
public TimeSpan? PageLoad { get; set; }
public TimeSpan? ImplicitWait { get; set; }

public Dictionary<string, object> ToCapabilities()
{
var timeoutCapabilities = new Dictionary<string, object>();

if (Script.HasValue) timeoutCapabilities.Add("script", Script.Value.TotalMilliseconds);
if (PageLoad.HasValue) timeoutCapabilities.Add("pageLoad", PageLoad.Value.TotalMilliseconds);
if (ImplicitWait.HasValue) timeoutCapabilities.Add("implicit", ImplicitWait.Value.TotalMilliseconds);

return timeoutCapabilities;
}
}

/// <summary>
/// Base class for managing options specific to a browser driver.
/// </summary>
Expand All @@ -102,6 +120,9 @@ public abstract class DriverOptions
private bool? useWebSocketUrl;
private bool useStrictFileInteractability;
private bool? enableDownloads;
private TimeSpan? scriptTimeout;
private TimeSpan? pageLoadTimeout;
private TimeSpan? implicitWaitTimeout;
private UnhandledPromptBehavior unhandledPromptBehavior = UnhandledPromptBehavior.Default;
private PageLoadStrategy pageLoadStrategy = PageLoadStrategy.Default;
private Dictionary<string, object> additionalCapabilities = new Dictionary<string, object>();
Expand Down Expand Up @@ -219,6 +240,52 @@ public bool UseStrictFileInteractability
set { this.enableDownloads = value; }
}

/// <summary>
/// Gets or sets the asynchronous script timeout, which is the amount
/// of time the driver should wait when executing JavaScript asynchronously.
/// This timeout only affects the <see cref="IJavaScriptExecutor.ExecuteAsyncScript(string, object[])"/>
/// method.
/// </summary>
public TimeSpan? ScriptTimeout
{
get { return this.scriptTimeout; }
set { this.scriptTimeout = value; }
}

/// <summary>
/// Gets or sets the page load timeout, which is the amount of time the driver
/// should wait for a page to load when setting the <see cref="IWebDriver.Url"/>
/// property.
/// </summary>
public TimeSpan? PageLoadTimeout
{
get { return this.pageLoadTimeout; }
set { this.pageLoadTimeout = value; }
}

/// <summary>
/// Gets or sets the implicit wait timeout, which is the amount of time the
/// driver should wait when searching for an element if it is not immediately
/// present.
/// </summary>
/// <remarks>
/// When searching for a single element, the driver should poll the page
/// until the element has been found, or this timeout expires before throwing
/// a <see cref="NoSuchElementException"/>. When searching for multiple elements,
/// the driver should poll the page until at least one element has been found
/// or this timeout has expired.
/// <para>
/// Increasing the implicit wait timeout should be used judiciously as it
/// will have an adverse effect on test run time, especially when used with
/// slower location strategies like XPath.
/// </para>
/// </remarks>
public TimeSpan? ImplicitWaitTimeout
{
get { return this.implicitWaitTimeout; }
set { this.implicitWaitTimeout = value; }
}

/// <summary>
/// Set or Get the location of the browser
/// Override in subclass
Expand Down Expand Up @@ -537,6 +604,18 @@ protected IWritableCapabilities GenerateDesiredCapabilities(bool isSpecification
}
}

if (this.scriptTimeout.HasValue || this.pageLoadTimeout.HasValue || this.implicitWaitTimeout.HasValue)
{
var timeouts = new Timeout
{
Script = this.scriptTimeout,
PageLoad = this.pageLoadTimeout,
ImplicitWait = this.implicitWaitTimeout
};

capabilities.SetCapability(CapabilityType.Timeouts, timeouts.ToCapabilities());
}

foreach (KeyValuePair<string, object> pair in this.additionalCapabilities)
{
capabilities.SetCapability(pair.Key, pair.Value);
Expand Down
13 changes: 13 additions & 0 deletions dotnet/src/webdriver/Timeouts.cs
Expand Up @@ -63,6 +63,9 @@ public Timeouts(WebDriver driver)
/// will have an adverse effect on test run time, especially when used with
/// slower location strategies like XPath.
/// </para>
/// <para>
/// Also can be managed via driver <see cref="DriverOptions.ImplicitWaitTimeout"/> option.
/// </para>
/// </remarks>
public TimeSpan ImplicitWait
{
Expand All @@ -76,6 +79,11 @@ public TimeSpan ImplicitWait
/// This timeout only affects the <see cref="IJavaScriptExecutor.ExecuteAsyncScript(string, object[])"/>
/// method.
/// </summary>
/// <remarks>
/// <para>
/// Also can be managed via driver <see cref="DriverOptions.ScriptTimeout"/> option.
/// </para>
/// </remarks>
public TimeSpan AsynchronousJavaScript
{
get { return this.ExecuteGetTimeout(AsyncScriptTimeoutName); }
Expand All @@ -87,6 +95,11 @@ public TimeSpan AsynchronousJavaScript
/// should wait for a page to load when setting the <see cref="IWebDriver.Url"/>
/// property.
/// </summary>
/// <remarks>
/// <para>
/// Also can be managed via driver <see cref="DriverOptions.PageLoadTimeout"/> option.
/// </para>
/// </remarks>
public TimeSpan PageLoad
{
get
Expand Down
4 changes: 4 additions & 0 deletions dotnet/test/common/Environment/DriverFactory.cs
Expand Up @@ -179,6 +179,10 @@ private T GetDriverOptions<T>(Type driverType, DriverOptions overriddenOptions)
options.PageLoadStrategy = overriddenOptions.PageLoadStrategy;
options.UnhandledPromptBehavior = overriddenOptions.UnhandledPromptBehavior;
options.Proxy = overriddenOptions.Proxy;

options.ScriptTimeout = overriddenOptions.ScriptTimeout;
options.PageLoadTimeout = overriddenOptions.PageLoadTimeout;
options.ImplicitWaitTimeout = overriddenOptions.ImplicitWaitTimeout;
}

return options;
Expand Down
123 changes: 123 additions & 0 deletions dotnet/test/common/TimeoutDriverOptionsTest.cs
@@ -0,0 +1,123 @@
using NUnit.Framework;
using OpenQA.Selenium.Environment;
using System;

namespace OpenQA.Selenium
{
[TestFixture]
public class TimeoutDriverOptionsTest
{
private IWebDriver driver;

private readonly TimeSpan defaultScriptTimeout = TimeSpan.FromMilliseconds(30_000);
private readonly TimeSpan defaultPageLoadTimeout = TimeSpan.FromMilliseconds(300_000);
private readonly TimeSpan defaultImplicitWaitTimeout = TimeSpan.Zero;

[TearDown]
public void TearDown()
{
driver?.Quit();
}

[Test]
public void CanSetScriptTimeout()
{
var expectedScriptTimeout = TimeSpan.FromSeconds(5);

var options = new TestDriverOptions()
{
ScriptTimeout = expectedScriptTimeout,
};

Assert.That(options.ScriptTimeout, Is.EqualTo(expectedScriptTimeout));
Assert.That(options.PageLoadTimeout, Is.Null);
Assert.That(options.ImplicitWaitTimeout, Is.Null);

driver = EnvironmentManager.Instance.CreateDriverInstance(options);

Assert.That(driver.Manage().Timeouts().AsynchronousJavaScript, Is.EqualTo(expectedScriptTimeout));

// other timeout options are still default
Assert.That(driver.Manage().Timeouts().PageLoad, Is.EqualTo(defaultPageLoadTimeout));
Assert.That(driver.Manage().Timeouts().ImplicitWait, Is.EqualTo(defaultImplicitWaitTimeout));
}

[Test]
public void CanSetPageLoadTimeout()
{
var expectedPageLoadTimeout = TimeSpan.FromSeconds(5);

var options = new TestDriverOptions()
{
PageLoadTimeout = expectedPageLoadTimeout,
};

Assert.That(options.PageLoadTimeout, Is.EqualTo(expectedPageLoadTimeout));
Assert.That(options.ScriptTimeout, Is.Null);
Assert.That(options.ImplicitWaitTimeout, Is.Null);

driver = EnvironmentManager.Instance.CreateDriverInstance(options);

Assert.That(driver.Manage().Timeouts().PageLoad, Is.EqualTo(expectedPageLoadTimeout));

// other timeout options are still default
Assert.That(driver.Manage().Timeouts().AsynchronousJavaScript, Is.EqualTo(defaultScriptTimeout));
Assert.That(driver.Manage().Timeouts().ImplicitWait, Is.EqualTo(defaultImplicitWaitTimeout));
}

[Test]
public void CanSetImplicitWaitTimeout()
{
var expectedImplicitWaitTimeout = TimeSpan.FromSeconds(5);

var options = new TestDriverOptions()
{
ImplicitWaitTimeout = expectedImplicitWaitTimeout,
};

Assert.That(options.ImplicitWaitTimeout, Is.EqualTo(expectedImplicitWaitTimeout));
Assert.That(options.ScriptTimeout, Is.Null);
Assert.That(options.PageLoadTimeout, Is.Null);

driver = EnvironmentManager.Instance.CreateDriverInstance(options);

Assert.That(driver.Manage().Timeouts().ImplicitWait, Is.EqualTo(expectedImplicitWaitTimeout));

// other timeout options are still default
Assert.That(driver.Manage().Timeouts().AsynchronousJavaScript, Is.EqualTo(defaultScriptTimeout));
Assert.That(driver.Manage().Timeouts().PageLoad, Is.EqualTo(defaultPageLoadTimeout));
}
[Test]
public void CanSetTimeout()
{
var expectedScriptTimeout = TimeSpan.FromSeconds(3);
var expectedPageLoadTimeout = TimeSpan.FromSeconds(4);
var expectedImplicitWaitTimeout = TimeSpan.FromSeconds(5);

var options = new TestDriverOptions()
{
ScriptTimeout = expectedScriptTimeout,
PageLoadTimeout = expectedPageLoadTimeout,
ImplicitWaitTimeout = expectedImplicitWaitTimeout,
};

Assert.That(options.ScriptTimeout, Is.EqualTo(expectedScriptTimeout));
Assert.That(options.PageLoadTimeout, Is.EqualTo(expectedPageLoadTimeout));
Assert.That(options.ImplicitWaitTimeout, Is.EqualTo(expectedImplicitWaitTimeout));

driver = EnvironmentManager.Instance.CreateDriverInstance(options);

Assert.That(driver.Manage().Timeouts().AsynchronousJavaScript, Is.EqualTo(expectedScriptTimeout));
Assert.That(driver.Manage().Timeouts().PageLoad, Is.EqualTo(expectedPageLoadTimeout));
Assert.That(driver.Manage().Timeouts().ImplicitWait, Is.EqualTo(expectedImplicitWaitTimeout));
}

class TestDriverOptions : DriverOptions
{
public override ICapabilities ToCapabilities()
{
return null;
}
}
}
}

0 comments on commit 7c1fae3

Please sign in to comment.