Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[dotnet] implement WebDriver BiDi #14012

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
81 changes: 63 additions & 18 deletions dotnet/src/support/Events/EventFiringWebDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Threading.Tasks;
using OpenQA.Selenium.Internal;

namespace OpenQA.Selenium.Support.Events
{
Expand Down Expand Up @@ -845,12 +847,21 @@ public EventFiringNavigation(EventFiringWebDriver driver)
/// Move the browser back
/// </summary>
public void Back()
{
AsyncHelper.RunSync(this.BackAsync);
}

/// <summary>
/// Move the browser backward as an asynchronous task
/// </summary>
/// <returns>A task object representing the asynchronous operation</returns>
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)
Expand All @@ -864,12 +875,21 @@ public void Back()
/// Move the browser forward
/// </summary>
public void Forward()
{
AsyncHelper.RunSync(this.ForwardAsync);
}

/// <summary>
/// Move the browser forward as an asynchronous task
/// </summary>
/// <returns>A task object representing the asynchronous operation</returns>
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)
Expand All @@ -879,17 +899,33 @@ public void Forward()
}
}


/// <summary>
/// Navigate to a url for your test
/// Navigate to a url
/// </summary>
/// <param name="url">String of where you want the browser to go to</param>
public void GoToUrl(string url)
{
AsyncHelper.RunSync(() => this.GoToUrlAsync(url));
}

/// <summary>
/// Navigate to a url as an asynchronous task
/// </summary>
/// <param name="url">String of where you want the browser to go to</param>
/// <returns>A task object representing the asynchronous operation</returns>
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)
Expand All @@ -900,45 +936,54 @@ public void GoToUrl(string url)
}

/// <summary>
/// Navigate to a url for your test
/// Navigate to a url
/// </summary>
/// <param name="url">Uri object of where you want the browser to go to</param>
public void GoToUrl(Uri url)
{
AsyncHelper.RunSync(() => this.GoToUrlAsync(url));
}

/// <summary>
/// Navigate to a url as an asynchronous task
/// </summary>
/// <param name="url">Uri object of where you want the browser to go to</param>
/// <returns>A task object representing the asynchronous operation</returns>
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);
}

/// <summary>
/// Refresh the browser
/// </summary>
public void Refresh()
{
AsyncHelper.RunSync(this.RefreshAsync);
}

/// <summary>
/// Refresh the browser as an asynchronous task
/// </summary>
/// <returns>A task object representing the asynchronous operation</returns>
public async Task RefreshAsync()
{
try
{
this.wrappedNavigation.Refresh();
await this.wrappedNavigation.RefreshAsync().ConfigureAwait(false);
}
catch (Exception ex)
{
this.parentDriver.OnException(new WebDriverExceptionEventArgs(this.parentDriver, ex));
throw;
}
}

}

/// <summary>
Expand Down
9 changes: 9 additions & 0 deletions dotnet/src/webdriver/ICommandExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
// </copyright>

using System;
using System.Threading.Tasks;

namespace OpenQA.Selenium
{
Expand All @@ -39,5 +40,13 @@ public interface ICommandExecutor : IDisposable
/// <param name="commandToExecute">The command you wish to execute</param>
/// <returns>A response from the browser</returns>
Response Execute(Command commandToExecute);


/// <summary>
/// Executes a command Asynchronously
/// </summary>
/// <param name="commandToExecute">The command you wish to execute</param>
/// <returns>A task object representing the asynchronous operation</returns>
Task<Response> ExecuteAsync(Command commandToExecute);
}
}
33 changes: 33 additions & 0 deletions dotnet/src/webdriver/INavigation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
// </copyright>

using System;
using System.Threading.Tasks;

namespace OpenQA.Selenium
{
Expand All @@ -31,12 +32,24 @@ public interface INavigation
/// </summary>
void Back();

/// <summary>
/// Move back a single entry in the browser's history.
/// </summary>
/// <returns>A task object representing the asynchronous operation</returns>
Task BackAsync();

/// <summary>
/// Move a single "item" forward in the browser's history.
/// </summary>
/// <remarks>Does nothing if we are on the latest page viewed.</remarks>
void Forward();

/// <summary>
/// Move a single "item" forward in the browser's history.
/// </summary>
/// <returns>A task object representing the asynchronous operation</returns>
Task ForwardAsync();

/// <summary>
/// Load a new web page in the current browser window.
/// </summary>
Expand All @@ -52,6 +65,13 @@ public interface INavigation
/// </remarks>
void GoToUrl(string url);

/// <summary>
/// Load a new web page in the current browser window.
/// </summary>
/// <param name="url">The URL to load. It is best to use a fully qualified URL</param>
/// <returns>A task object representing the asynchronous operation</returns>
Task GoToUrlAsync(string url);

/// <summary>
/// Load a new web page in the current browser window.
/// </summary>
Expand All @@ -67,9 +87,22 @@ public interface INavigation
/// </remarks>
void GoToUrl(Uri url);

/// <summary>
/// Load a new web page in the current browser window.
/// </summary>
/// <param name="url">The URL to load.</param>
/// <returns>A task object representing the asynchronous operation</returns>
Task GoToUrlAsync(Uri url);

/// <summary>
/// Refreshes the current page.
/// </summary>
void Refresh();

/// <summary>
/// Refreshes the current page.
/// </summary>
/// <returns>A task object representing the asynchronous operation</returns>
Task RefreshAsync();
}
}
49 changes: 49 additions & 0 deletions dotnet/src/webdriver/Internal/AsyncHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// <copyright file="AsyncHelper.cs" company="WebDriver Committers">
// 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.
// </copyright>

using System;
using System.Threading;
using System.Threading.Tasks;

namespace OpenQA.Selenium.Internal
{
/// <summary>
/// Encapsulates methods for working with asynchronous tasks.
/// </summary>
public static class AsyncHelper
{
private static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None,
TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default);

public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{
return _myTaskFactory.StartNew(() =>
{
return func();
}).Unwrap().ConfigureAwait(false).GetAwaiter().GetResult();
}

public static void RunSync(Func<Task> func)
{
_myTaskFactory.StartNew(() =>
{
return func();
}).Unwrap().ConfigureAwait(false).GetAwaiter().GetResult();
}
}
}