diff --git a/dotnet/src/support/Events/EventFiringWebDriver.cs b/dotnet/src/support/Events/EventFiringWebDriver.cs
index ac428cf2830b5..77a3b5f3b50a5 100644
--- a/dotnet/src/support/Events/EventFiringWebDriver.cs
+++ b/dotnet/src/support/Events/EventFiringWebDriver.cs
@@ -20,6 +20,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
+using System.Threading.Tasks;
namespace OpenQA.Selenium.Support.Events
{
@@ -845,12 +846,24 @@ public EventFiringNavigation(EventFiringWebDriver driver)
/// Move the browser back
///
public void Back()
+ {
+ Task.Run(async delegate
+ {
+ await this.BackAsync();
+ }).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Move the browser back as an asynchronous task.
+ ///
+ /// A task object representing the asynchronous operation
+ public async Task BackAsync()
{
try
{
WebDriverNavigationEventArgs e = new WebDriverNavigationEventArgs(this.parentDriver);
this.parentDriver.OnNavigatingBack(e);
- this.wrappedNavigation.Back();
+ await this.wrappedNavigation.BackAsync().ConfigureAwait(false);
this.parentDriver.OnNavigatedBack(e);
}
catch (Exception ex)
@@ -861,15 +874,27 @@ public void Back()
}
///
- /// Move the browser forward
+ /// Move a single "item" forward in the browser's history.
///
public void Forward()
+ {
+ Task.Run(async delegate
+ {
+ await this.ForwardAsync();
+ }).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Move a single "item" forward in the browser's history as an asynchronous task.
+ ///
+ /// A task object representing the asynchronous operation.
+ public async Task ForwardAsync()
{
try
{
WebDriverNavigationEventArgs e = new WebDriverNavigationEventArgs(this.parentDriver);
this.parentDriver.OnNavigatingForward(e);
- this.wrappedNavigation.Forward();
+ await this.wrappedNavigation.ForwardAsync().ConfigureAwait(false);
this.parentDriver.OnNavigatedForward(e);
}
catch (Exception ex)
@@ -880,16 +905,34 @@ public void Forward()
}
///
- /// Navigate to a url for your test
+ /// Navigate to a url.
///
/// String of where you want the browser to go to
public void GoToUrl(string url)
{
+ Task.Run(async delegate
+ {
+ await this.GoToUrlAsync(url);
+ }).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Navigate to a url as an asynchronous task.
+ ///
+ /// String of where you want the browser to go.
+ /// A task object representing the asynchronous operation.
+ public async Task GoToUrlAsync(string url)
+ {
+ if (url == null)
+ {
+ throw new ArgumentNullException(nameof(url), "url cannot be null");
+ }
+
try
{
WebDriverNavigationEventArgs e = new WebDriverNavigationEventArgs(this.parentDriver, url);
this.parentDriver.OnNavigating(e);
- this.wrappedNavigation.GoToUrl(url);
+ await this.wrappedNavigation.GoToUrlAsync(url).ConfigureAwait(false);
this.parentDriver.OnNavigated(e);
}
catch (Exception ex)
@@ -900,38 +943,52 @@ public void GoToUrl(string url)
}
///
- /// Navigate to a url for your test
+ /// Navigate to a url.
///
/// Uri object of where you want the browser to go to
public void GoToUrl(Uri url)
+ {
+ Task.Run(async delegate
+ {
+ await this.GoToUrlAsync(url);
+ }).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Navigate to a url as an asynchronous task.
+ ///
+ /// Uri object of where you want the browser to go.
+ /// A task object representing the asynchronous operation.
+ public async Task GoToUrlAsync(Uri url)
{
if (url == null)
{
throw new ArgumentNullException(nameof(url), "url cannot be null");
}
- try
- {
- WebDriverNavigationEventArgs e = new WebDriverNavigationEventArgs(this.parentDriver, url.ToString());
- this.parentDriver.OnNavigating(e);
- this.wrappedNavigation.GoToUrl(url);
- this.parentDriver.OnNavigated(e);
- }
- catch (Exception ex)
- {
- this.parentDriver.OnException(new WebDriverExceptionEventArgs(this.parentDriver, ex));
- throw;
- }
+ await this.GoToUrlAsync(url.ToString()).ConfigureAwait(false);
}
///
- /// Refresh the browser
+ /// Reload the current page.
///
public void Refresh()
+ {
+ Task.Run(async delegate
+ {
+ await this.RefreshAsync();
+ }).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Reload the current page as an asynchronous task.
+ ///
+ /// A task object representing the asynchronous operation.
+ public async Task RefreshAsync()
{
try
{
- this.wrappedNavigation.Refresh();
+ await this.wrappedNavigation.RefreshAsync().ConfigureAwait(false);
}
catch (Exception ex)
{
diff --git a/dotnet/src/webdriver/ICommandExecutor.cs b/dotnet/src/webdriver/ICommandExecutor.cs
index 68cfe200391f4..3bcfb520166d3 100644
--- a/dotnet/src/webdriver/ICommandExecutor.cs
+++ b/dotnet/src/webdriver/ICommandExecutor.cs
@@ -17,6 +17,7 @@
//
using System;
+using System.Threading.Tasks;
namespace OpenQA.Selenium
{
@@ -39,5 +40,13 @@ public interface ICommandExecutor : IDisposable
/// The command you wish to execute
/// A response from the browser
Response Execute(Command commandToExecute);
+
+
+ ///
+ /// Executes a command as an asynchronous task.
+ ///
+ /// The command you wish to execute
+ /// A task object representing the asynchronous operation
+ Task ExecuteAsync(Command commandToExecute);
}
}
diff --git a/dotnet/src/webdriver/INavigation.cs b/dotnet/src/webdriver/INavigation.cs
index bff75d4743e6b..a55b4dfda12bf 100644
--- a/dotnet/src/webdriver/INavigation.cs
+++ b/dotnet/src/webdriver/INavigation.cs
@@ -17,6 +17,7 @@
//
using System;
+using System.Threading.Tasks;
namespace OpenQA.Selenium
{
@@ -31,12 +32,24 @@ public interface INavigation
///
void Back();
+ ///
+ /// Move back a single entry in the browser's history as an asynchronous task.
+ ///
+ /// A task object representing the asynchronous operation.
+ Task BackAsync();
+
///
/// Move a single "item" forward in the browser's history.
///
/// Does nothing if we are on the latest page viewed.
void Forward();
+ ///
+ /// Move a single "item" forward in the browser's history as an asynchronous task.
+ ///
+ /// A task object representing the asynchronous operation.
+ Task ForwardAsync();
+
///
/// Load a new web page in the current browser window.
///
@@ -52,6 +65,13 @@ public interface INavigation
///
void GoToUrl(string url);
+ ///
+ /// Navigate to a url as an asynchronous task.
+ ///
+ /// String of where you want the browser to go.
+ /// A task object representing the asynchronous operation.
+ Task GoToUrlAsync(string url);
+
///
/// Load a new web page in the current browser window.
///
@@ -67,9 +87,22 @@ public interface INavigation
///
void GoToUrl(Uri url);
+ ///
+ /// Navigate to a url as an asynchronous task.
+ ///
+ /// Uri object of where you want the browser to go.
+ /// A task object representing the asynchronous operation.
+ Task GoToUrlAsync(Uri url);
+
///
/// Refreshes the current page.
///
void Refresh();
+
+ ///
+ /// Reload the current page as an asynchronous task.
+ ///
+ /// A task object representing the asynchronous operation.
+ Task RefreshAsync();
}
}
diff --git a/dotnet/src/webdriver/Navigator.cs b/dotnet/src/webdriver/Navigator.cs
index f8f6047e91f5a..48683a03c9fe1 100644
--- a/dotnet/src/webdriver/Navigator.cs
+++ b/dotnet/src/webdriver/Navigator.cs
@@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
namespace OpenQA.Selenium
{
@@ -38,26 +39,63 @@ public Navigator(WebDriver driver)
}
///
- /// Move the browser back
+ /// Move back a single entry in the browser's history.
///
public void Back()
{
- this.driver.InternalExecute(DriverCommand.GoBack, null);
+ Task.Run(async delegate
+ {
+ await this.BackAsync();
+ }).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Move back a single entry in the browser's history as an asynchronous task.
+ ///
+ /// A task object representing the asynchronous operation.
+ public async Task BackAsync()
+ {
+ await this.driver.InternalExecuteAsync(DriverCommand.GoBack, null).ConfigureAwait(false);
}
///
- /// Move the browser forward
+ /// Move a single "item" forward in the browser's history.
///
public void Forward()
{
- this.driver.InternalExecute(DriverCommand.GoForward, null);
+ Task.Run(async delegate
+ {
+ await this.ForwardAsync();
+ }).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Move a single "item" forward in the browser's history as an asynchronous task.
+ ///
+ /// A task object representing the asynchronous operation.
+ public async Task ForwardAsync()
+ {
+ await this.driver.InternalExecuteAsync(DriverCommand.GoForward, null).ConfigureAwait(false);
}
///
- /// Navigate to a url for your test
+ /// Navigate to a url.
///
/// String of where you want the browser to go to
public void GoToUrl(string url)
+ {
+ Task.Run(async delegate
+ {
+ await this.GoToUrlAsync(url);
+ }).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Navigate to a url as an asynchronous task.
+ ///
+ /// String of where you want the browser to go.
+ /// A task object representing the asynchronous operation.
+ public async Task GoToUrlAsync(string url)
{
if (url == null)
{
@@ -68,31 +106,55 @@ public void GoToUrl(string url)
{
{ "url", url }
};
- this.driver.InternalExecute(DriverCommand.Get, parameters);
-
+ await this.driver.InternalExecuteAsync(DriverCommand.Get, parameters).ConfigureAwait(false);
}
///
- /// Navigate to a url for your test
+ /// Navigate to a url.
///
- /// Uri object of where you want the browser to go to
+ /// Uri object of where you want the browser to go.
public void GoToUrl(Uri url)
+ {
+ Task.Run(async delegate
+ {
+ await this.GoToUrlAsync(url);
+ }).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Navigate to a url as an asynchronous task.
+ ///
+ /// Uri object of where you want the browser to go.
+ /// A task object representing the asynchronous operation.
+ public async Task GoToUrlAsync(Uri url)
{
if (url == null)
{
throw new ArgumentNullException(nameof(url), "URL cannot be null.");
}
- this.GoToUrl(url.ToString());
+ await this.GoToUrlAsync(url.ToString()).ConfigureAwait(false);
}
///
- /// Refresh the browser
+ /// Reload the current page.
///
public void Refresh()
+ {
+ Task.Run(async delegate
+ {
+ await this.RefreshAsync();
+ }).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Reload the current page as an asynchronous task.
+ ///
+ /// A task object representing the asynchronous operation.
+ public async Task RefreshAsync()
{
// driver.SwitchTo().DefaultContent();
- this.driver.InternalExecute(DriverCommand.Refresh, null);
+ await this.driver.InternalExecuteAsync(DriverCommand.Refresh, null).ConfigureAwait(false);
}
}
}
diff --git a/dotnet/src/webdriver/Remote/DriverServiceCommandExecutor.cs b/dotnet/src/webdriver/Remote/DriverServiceCommandExecutor.cs
index 4b0fcb27ed7fc..1e486ad96f98d 100644
--- a/dotnet/src/webdriver/Remote/DriverServiceCommandExecutor.cs
+++ b/dotnet/src/webdriver/Remote/DriverServiceCommandExecutor.cs
@@ -17,6 +17,7 @@
//
using System;
+using System.Threading.Tasks;
namespace OpenQA.Selenium.Remote
{
@@ -92,6 +93,16 @@ public HttpCommandExecutor HttpExecutor
/// The command you wish to execute
/// A response from the browser
public Response Execute(Command commandToExecute)
+ {
+ return Task.Run(() => this.ExecuteAsync(commandToExecute)).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Executes a command as an asynchronous task.
+ ///
+ /// The command you wish to execute
+ /// A task object representing the asynchronous operation
+ public async Task ExecuteAsync(Command commandToExecute)
{
if (commandToExecute == null)
{
@@ -108,7 +119,7 @@ public Response Execute(Command commandToExecute)
// command, so that we can get the finally block.
try
{
- toReturn = this.internalExecutor.Execute(commandToExecute);
+ toReturn = await this.internalExecutor.ExecuteAsync(commandToExecute).ConfigureAwait(false);
}
finally
{
diff --git a/dotnet/src/webdriver/Remote/HttpCommandExecutor.cs b/dotnet/src/webdriver/Remote/HttpCommandExecutor.cs
index 3dbb5e4efd179..1872e418a7888 100644
--- a/dotnet/src/webdriver/Remote/HttpCommandExecutor.cs
+++ b/dotnet/src/webdriver/Remote/HttpCommandExecutor.cs
@@ -158,6 +158,16 @@ public bool TryAddCommand(string commandName, CommandInfo info)
/// The command you wish to execute
/// A response from the browser
public virtual Response Execute(Command commandToExecute)
+ {
+ return Task.Run(() => this.ExecuteAsync(commandToExecute)).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Executes a command as an asynchronous task.
+ ///
+ /// The command you wish to execute
+ /// A task object representing the asynchronous operation
+ public virtual async Task ExecuteAsync(Command commandToExecute)
{
if (commandToExecute == null)
{
@@ -184,7 +194,7 @@ public virtual Response Execute(Command commandToExecute)
HttpResponseInfo responseInfo = null;
try
{
- responseInfo = Task.Run(async () => await this.MakeHttpRequest(requestInfo)).GetAwaiter().GetResult();
+ responseInfo = await this.MakeHttpRequest(requestInfo).ConfigureAwait(false);
}
catch (HttpRequestException ex)
{
diff --git a/dotnet/src/webdriver/WebDriver.cs b/dotnet/src/webdriver/WebDriver.cs
index 3de43e25c452f..d063e8f5905ea 100644
--- a/dotnet/src/webdriver/WebDriver.cs
+++ b/dotnet/src/webdriver/WebDriver.cs
@@ -24,6 +24,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
+using System.Threading.Tasks;
namespace OpenQA.Selenium
{
@@ -556,7 +557,25 @@ internal ReadOnlyCollection GetElementsFromResponse(Response respon
/// WebDriver Response
internal Response InternalExecute(string driverCommandToExecute, Dictionary parameters)
{
- return this.Execute(driverCommandToExecute, parameters);
+ return Task.Run(() => this.InternalExecuteAsync(driverCommandToExecute, parameters)).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Executes commands with the driver asynchronously
+ ///
+ /// Command that needs executing
+ /// Parameters needed for the command
+ /// A task object representing the asynchronous operation
+ internal Task InternalExecuteAsync(string driverCommandToExecute,
+ Dictionary parameters)
+ {
+ return this.ExecuteAsync(driverCommandToExecute, parameters);
+ }
+
+ internal Response Execute(string driverCommandToExecute,
+ Dictionary parameters)
+ {
+ return Task.Run(() => this.ExecuteAsync(driverCommandToExecute, parameters)).GetAwaiter().GetResult();
}
///
@@ -565,7 +584,7 @@ internal Response InternalExecute(string driverCommandToExecute, DictionaryA value representing the command to execute.
/// A containing the names and values of the parameters of the command.
/// A containing information about the success or failure of the command and any data returned by the command.
- protected virtual Response Execute(string driverCommandToExecute, Dictionary parameters)
+ protected virtual async Task ExecuteAsync(string driverCommandToExecute, Dictionary parameters)
{
Command commandToExecute = new Command(this.sessionId, driverCommandToExecute, parameters);
@@ -573,7 +592,7 @@ protected virtual Response Execute(string driverCommandToExecute, Dictionary navigation.GoToUrl((Uri)null), Throws.InstanceOf());
- // new Uri("") and new Uri("isidsji30342??éåµñ©æ")
+ // new Uri("") and new Uri("isidsji30342??éåµñ©æ")
// throw an exception, so we needn't worry about them.
}
@@ -90,5 +91,73 @@ public void ShouldRefreshPage()
Assert.AreEqual("What's for dinner?", changedDiv.Text);
}
+ [Test]
+ [NeedsFreshDriver(IsCreatedBeforeTest = true)]
+ public Task ShouldNotHaveProblemNavigatingWithNoPagesBrowsedAsync()
+ {
+ var navigation = driver.Navigate();
+ Assert.DoesNotThrowAsync(async () => await navigation.BackAsync());
+ Assert.DoesNotThrowAsync(async () => await navigation.ForwardAsync());
+ return Task.CompletedTask;
+ }
+
+ [Test]
+ public async Task ShouldGoBackAndForwardAsync()
+ {
+ INavigation navigation = driver.Navigate();
+
+ await navigation.GoToUrlAsync(macbethPage);
+ await navigation.GoToUrlAsync(simpleTestPage);
+
+ await navigation.BackAsync();
+ Assert.AreEqual(macbethTitle, driver.Title);
+
+ await navigation.ForwardAsync();
+ Assert.AreEqual(simpleTestTitle, driver.Title);
+ }
+
+ [Test]
+ public void ShouldAcceptInvalidUrlsUsingUrisAsync()
+ {
+ INavigation navigation = driver.Navigate();
+ Assert.That(async () => await navigation.GoToUrlAsync((Uri)null), Throws.InstanceOf());
+ }
+
+ [Test]
+ public async Task ShouldGoToUrlUsingStringAsync()
+ {
+ var navigation = driver.Navigate();
+
+ await navigation.GoToUrlAsync(macbethPage);
+ Assert.AreEqual(macbethTitle, driver.Title);
+
+ await navigation.GoToUrlAsync(simpleTestPage);
+ Assert.AreEqual(simpleTestTitle, driver.Title);
+ }
+
+ [Test]
+ public void ShouldGoToUrlUsingUriAsync()
+ {
+ var navigation = driver.Navigate();
+
+ navigation.GoToUrlAsync(new Uri(macbethPage));
+ Assert.AreEqual(driver.Title, macbethTitle);
+ navigation.GoToUrl(new Uri(simpleTestPage));
+ Assert.AreEqual(simpleTestTitle, driver.Title);
+ }
+
+ [Test]
+ public async Task ShouldRefreshPageAsync()
+ {
+ await driver.Navigate().GoToUrlAsync(javascriptPage);
+ IWebElement changedDiv = driver.FindElement(By.Id("dynamo"));
+ driver.FindElement(By.Id("updatediv")).Click();
+
+ Assert.AreEqual("Fish and chips!", changedDiv.Text);
+ await driver.Navigate().RefreshAsync();
+
+ changedDiv = driver.FindElement(By.Id("dynamo"));
+ Assert.AreEqual("What's for dinner?", changedDiv.Text);
+ }
}
}
diff --git a/dotnet/test/support/Events/EventFiringWebDriverTest.cs b/dotnet/test/support/Events/EventFiringWebDriverTest.cs
index 972be725adfa9..3d59f056f3ee8 100644
--- a/dotnet/test/support/Events/EventFiringWebDriverTest.cs
+++ b/dotnet/test/support/Events/EventFiringWebDriverTest.cs
@@ -58,12 +58,15 @@ Navigated back
Navigating forward
Navigated forward
";
+ string normalizedExpectedLog = expectedLog.Replace("\r\n", "\n").Replace("\r", "\n");
mockDriver.VerifySet(x => x.Url = "http://www.get.com", Times.Once);
mockDriver.Verify(x => x.Navigate(), Times.Exactly(3));
- mockNavigation.Verify(x => x.GoToUrl("http://www.navigate-to.com"), Times.Once);
- mockNavigation.Verify(x => x.Back(), Times.Once);
- mockNavigation.Verify(x => x.Forward(), Times.Once);
- Assert.AreEqual(expectedLog, log.ToString());
+ mockNavigation.Verify(x => x.GoToUrlAsync("http://www.navigate-to.com"), Times.Once);
+ mockNavigation.Verify(x => x.BackAsync(), Times.Once);
+ mockNavigation.Verify(x => x.ForwardAsync(), Times.Once);
+
+ string normalizedActualLog = log.ToString().Replace("\r\n", "\n").Replace("\r", "\n");
+ Assert.AreEqual(normalizedExpectedLog, normalizedActualLog);
}
[Test]