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 with WebDriverBiDi dependency #14052

Draft
wants to merge 5 commits into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
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
3 changes: 2 additions & 1 deletion dotnet/paket.dependencies
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ nuget System.Diagnostics.Tools 4.3.0
nuget System.Drawing.Common 7.0.0
nuget System.Runtime 4.3.1
nuget System.Runtime.InteropServices 4.3.0
nuget System.Text.Json 6.0.9
nuget System.Text.Json 8.0.3
nuget Runfiles 0.12.0
nuget WebDriverBiDi 0.0.3
30 changes: 18 additions & 12 deletions dotnet/paket.lock
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ NUGET
System.Reflection.TypeExtensions (>= 4.4)
Humanizer.Core (2.8.26)
Microsoft.AspNetCore.App.Ref (6.0.9)
Microsoft.Bcl.AsyncInterfaces (7.0) - restriction: || (&& (== net7.0) (>= net461)) (&& (== net7.0) (< netcoreapp3.1)) (== netstandard2.0)
Microsoft.Bcl.AsyncInterfaces (8.0) - restriction: || (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0)
System.Threading.Tasks.Extensions (>= 4.5.4) - restriction: || (&& (== net7.0) (>= net462)) (&& (== net7.0) (< netstandard2.1)) (== netstandard2.0)
Microsoft.Bcl.HashCode (1.1.1)
Microsoft.CSharp (4.5)
Microsoft.Extensions.DependencyInjection (3.1.9)
Microsoft.Bcl.AsyncInterfaces (>= 1.1.1) - restriction: || (&& (== net7.0) (>= net461)) (&& (== net7.0) (< netstandard2.1)) (== netstandard2.0)
Expand All @@ -42,7 +43,7 @@ NUGET
NETStandard.Library (>= 2.0)
NUnit (3.13.2)
Runfiles (0.12)
System.Buffers (4.5.1) - restriction: || (&& (== net7.0) (>= net461)) (&& (== net7.0) (< netcoreapp3.1)) (== netstandard2.0)
System.Buffers (4.5.1) - restriction: || (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0)
System.Diagnostics.EventLog (7.0)
System.Security.Principal.Windows (>= 5.0) - restriction: || (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0)
System.Diagnostics.Tools (4.3)
Expand All @@ -61,7 +62,7 @@ NUGET
System.Buffers (>= 4.5.1) - restriction: || (&& (== net7.0) (>= monotouch)) (&& (== net7.0) (>= net461)) (&& (== net7.0) (< netcoreapp2.0)) (&& (== net7.0) (< netstandard1.1)) (&& (== net7.0) (< netstandard2.0)) (&& (== net7.0) (>= xamarinios)) (&& (== net7.0) (>= xamarinmac)) (&& (== net7.0) (>= xamarintvos)) (&& (== net7.0) (>= xamarinwatchos)) (== netstandard2.0)
System.Numerics.Vectors (>= 4.4) - restriction: || (&& (== net7.0) (< netcoreapp2.0)) (== netstandard2.0)
System.Runtime.CompilerServices.Unsafe (>= 4.5.3) - restriction: || (&& (== net7.0) (>= monotouch)) (&& (== net7.0) (>= net461)) (&& (== net7.0) (< netcoreapp2.0)) (&& (== net7.0) (< netcoreapp2.1)) (&& (== net7.0) (< netstandard1.1)) (&& (== net7.0) (< netstandard2.0)) (&& (== net7.0) (>= uap10.1)) (&& (== net7.0) (>= xamarinios)) (&& (== net7.0) (>= xamarinmac)) (&& (== net7.0) (>= xamarintvos)) (&& (== net7.0) (>= xamarinwatchos)) (== netstandard2.0)
System.Numerics.Vectors (4.5) - restriction: || (&& (== net7.0) (>= net461)) (&& (== net7.0) (< netcoreapp3.1)) (== netstandard2.0)
System.Numerics.Vectors (4.5) - restriction: || (&& (== net7.0) (>= net462)) (&& (== net7.0) (< netcoreapp2.0)) (== netstandard2.0)
System.Reflection (4.3)
Microsoft.NETCore.Platforms (>= 1.1)
Microsoft.NETCore.Targets (>= 1.1)
Expand All @@ -79,7 +80,7 @@ NUGET
System.Runtime (4.3.1)
Microsoft.NETCore.Platforms (>= 1.1.1)
Microsoft.NETCore.Targets (>= 1.1.3)
System.Runtime.CompilerServices.Unsafe (6.0)
System.Runtime.CompilerServices.Unsafe (6.0) - restriction: || (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0)
System.Runtime.Handles (4.3)
Microsoft.NETCore.Platforms (>= 1.1)
Microsoft.NETCore.Targets (>= 1.1)
Expand All @@ -100,17 +101,22 @@ NUGET
System.Buffers (>= 4.5.1) - restriction: || (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0)
System.Memory (>= 4.5.5) - restriction: || (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0)
System.Runtime.CompilerServices.Unsafe (>= 6.0) - restriction: || (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0)
System.Text.Json (6.0.9)
Microsoft.Bcl.AsyncInterfaces (>= 6.0) - restriction: || (&& (== net7.0) (>= net461)) (&& (== net7.0) (< netcoreapp3.1)) (== netstandard2.0)
System.Buffers (>= 4.5.1) - restriction: || (&& (== net7.0) (>= net461)) (&& (== net7.0) (< netcoreapp3.1)) (== netstandard2.0)
System.Memory (>= 4.5.4) - restriction: || (&& (== net7.0) (>= net461)) (&& (== net7.0) (< netcoreapp3.1)) (== netstandard2.0)
System.Numerics.Vectors (>= 4.5) - restriction: || (&& (== net7.0) (>= net461)) (&& (== net7.0) (< netcoreapp3.1)) (== netstandard2.0)
System.Runtime.CompilerServices.Unsafe (>= 6.0)
System.Text.Encodings.Web (>= 6.0)
System.Threading.Tasks.Extensions (>= 4.5.4) - restriction: || (&& (== net7.0) (>= net461)) (&& (== net7.0) (< netcoreapp3.1)) (== netstandard2.0)
System.Text.Json (8.0.3)
Microsoft.Bcl.AsyncInterfaces (>= 8.0) - restriction: || (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0)
System.Buffers (>= 4.5.1) - restriction: || (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0)
System.Memory (>= 4.5.5) - restriction: || (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0)
System.Runtime.CompilerServices.Unsafe (>= 6.0) - restriction: || (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0)
System.Text.Encodings.Web (>= 8.0)
System.Threading.Tasks.Extensions (>= 4.5.4) - restriction: || (&& (== net7.0) (>= net462)) (&& (== net7.0) (< net6.0)) (== netstandard2.0)
System.Threading.Channels (8.0)
System.Threading.Tasks.Extensions (>= 4.5.4) - restriction: || (&& (== net7.0) (>= net462)) (&& (== net7.0) (< netstandard2.1)) (== netstandard2.0)
System.Threading.Tasks (4.3)
Microsoft.NETCore.Platforms (>= 1.1)
Microsoft.NETCore.Targets (>= 1.1)
System.Runtime (>= 4.3)
System.Threading.Tasks.Extensions (4.5.4)
System.Runtime.CompilerServices.Unsafe (>= 4.5.3) - restriction: || (&& (== net7.0) (>= net461)) (&& (== net7.0) (< netcoreapp2.1)) (&& (== net7.0) (< netstandard1.0)) (&& (== net7.0) (< netstandard2.0)) (&& (== net7.0) (>= wp8)) (== netstandard2.0)
WebDriverBiDi (0.0.3)
Microsoft.Bcl.HashCode (>= 1.1.1)
System.Text.Json (>= 8.0.3)
System.Threading.Channels (>= 8.0)
7 changes: 5 additions & 2 deletions dotnet/paket.nuget.bzl

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions dotnet/src/webdriver/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ csharp_library(
deps = [
framework("nuget", "NETStandard.Library"),
framework("nuget", "Newtonsoft.Json"),
framework("nuget", "WebDriverBiDi"),
],
)

Expand Down Expand Up @@ -82,6 +83,7 @@ csharp_library(
deps = [
framework("nuget", "NETStandard.Library"),
framework("nuget", "Newtonsoft.Json"),
framework("nuget", "WebDriverBiDi"),
],
)

Expand Down
70 changes: 62 additions & 8 deletions dotnet/src/webdriver/Navigator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using WebDriverBiDi.BrowsingContext;

namespace OpenQA.Selenium
{
Expand All @@ -28,6 +29,14 @@ namespace OpenQA.Selenium
internal class Navigator : INavigation
{
private WebDriver driver;
private string browsingContextId;
private static readonly Dictionary<string, ReadinessState> PageLoadStrategyMapper = new()
{
{"normal", ReadinessState.Complete},
{"eager", ReadinessState.Interactive},
{"none", ReadinessState.None}
};
private ReadinessState readinessState;

/// <summary>
/// Initializes a new instance of the <see cref="Navigator"/> class
Expand All @@ -36,6 +45,9 @@ internal class Navigator : INavigation
public Navigator(WebDriver driver)
{
this.driver = driver;
this.browsingContextId = driver.CurrentWindowHandle;
string strategyCap = driver.Capabilities.GetCapability("pageLoadStrategy") as string;
this.readinessState = strategyCap == null ? ReadinessState.Complete : PageLoadStrategyMapper[strategyCap];
}

/// <summary>
Expand All @@ -55,7 +67,17 @@ public void Back()
/// <returns>A task object representing the asynchronous operation.</returns>
public async Task BackAsync()
{
await this.driver.InternalExecuteAsync(DriverCommand.GoBack, null).ConfigureAwait(false);
if (this.driver.BiDiDriver != null)
{
var traverseHistoryCommandParameters =
new TraverseHistoryCommandParameters(this.browsingContextId, -1);
await this.driver.BiDiDriver.BrowsingContext.TraverseHistoryAsync(traverseHistoryCommandParameters)
.ConfigureAwait(false);
}
else
{
await this.driver.InternalExecuteAsync(DriverCommand.GoBack, null).ConfigureAwait(false);
}
}

/// <summary>
Expand All @@ -75,7 +97,17 @@ public void Forward()
/// <returns>A task object representing the asynchronous operation.</returns>
public async Task ForwardAsync()
{
await this.driver.InternalExecuteAsync(DriverCommand.GoForward, null).ConfigureAwait(false);
if (this.driver.BiDiDriver != null)
{
var traverseHistoryCommandParameters =
new TraverseHistoryCommandParameters(this.browsingContextId, 1);
await this.driver.BiDiDriver.BrowsingContext.TraverseHistoryAsync(traverseHistoryCommandParameters)
.ConfigureAwait(false);
}
else
{
await this.driver.InternalExecuteAsync(DriverCommand.GoForward, null).ConfigureAwait(false);
}
}

/// <summary>
Expand All @@ -102,11 +134,22 @@ public async Task GoToUrlAsync(string url)
throw new ArgumentNullException(nameof(url), "URL cannot be null.");
}

Dictionary<string, object> parameters = new Dictionary<string, object>
if (this.driver.BiDiDriver != null)
{
NavigateCommandParameters navigateCommandParameters = new NavigateCommandParameters(this.browsingContextId, url)
{
Wait = this.readinessState
};
await driver.BiDiDriver.BrowsingContext.NavigateAsync(navigateCommandParameters).ConfigureAwait(false);
}
else
{
{ "url", url }
};
await this.driver.InternalExecuteAsync(DriverCommand.Get, parameters).ConfigureAwait(false);
Dictionary<string, object> parameters = new Dictionary<string, object>
{
{ "url", url }
};
await this.driver.InternalExecuteAsync(DriverCommand.Get, parameters).ConfigureAwait(false);
}
}

/// <summary>
Expand Down Expand Up @@ -153,8 +196,19 @@ public void Refresh()
/// <returns>A task object representing the asynchronous operation.</returns>
public async Task RefreshAsync()
{
// driver.SwitchTo().DefaultContent();
await this.driver.InternalExecuteAsync(DriverCommand.Refresh, null).ConfigureAwait(false);
if (this.driver.BiDiDriver != null)
{
var reloadCommandParameters =
new ReloadCommandParameters(this.browsingContextId)
{
Wait = this.readinessState
};
await this.driver.BiDiDriver.BrowsingContext.ReloadAsync(reloadCommandParameters).ConfigureAwait(false);
}
else
{
await this.driver.InternalExecuteAsync(DriverCommand.Refresh, null).ConfigureAwait(false);
}
}
}
}
17 changes: 17 additions & 0 deletions dotnet/src/webdriver/WebDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
using System.Collections.ObjectModel;
using System.Globalization;
using System.Threading.Tasks;
using WebDriverBiDi;

namespace OpenQA.Selenium
{
Expand All @@ -46,6 +47,7 @@ public class WebDriver : IWebDriver, ISearchContext, IJavaScriptExecutor, IFinds
private SessionId sessionId;
private String authenticatorId;
private List<string> registeredCommands = new List<string>();
private BiDiDriver biDiDriver;

/// <summary>
/// Initializes a new instance of the <see cref="WebDriver"/> class.
Expand Down Expand Up @@ -189,6 +191,14 @@ public SessionId SessionId
get { return this.sessionId; }
}

/// <summary>
/// Gets the <see cref="BiDiDriver"/> for the current session of this driver.
/// </summary>
internal BiDiDriver BiDiDriver
{
get { return this.biDiDriver; }
}

/// <summary>
/// Gets or sets the <see cref="IFileDetector"/> responsible for detecting
/// sequences of keystrokes representing file paths and names.
Expand Down Expand Up @@ -654,6 +664,13 @@ protected void StartSession(ICapabilities capabilities)
ReturnedCapabilities returnedCapabilities = new ReturnedCapabilities(rawCapabilities);
this.capabilities = returnedCapabilities;
this.sessionId = new SessionId(response.SessionId);

if (!string.IsNullOrEmpty((string)this.capabilities.GetCapability("webSocketUrl")))
{
this.biDiDriver = new BiDiDriver(DefaultCommandTimeout);
string webSocketUrl = this.capabilities.GetCapability("webSocketUrl").ToString();
Task.Run(() => this.biDiDriver.StartAsync(webSocketUrl)).GetAwaiter().GetResult();
}
}

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions dotnet/src/webdriver/WebDriver.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="WebDriverBiDi" Version="0.0.1" />
</ItemGroup>

<PropertyGroup>
Expand Down
2 changes: 2 additions & 0 deletions dotnet/test/common/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ csharp_library(
"@rules_dotnet//tools/runfiles",
framework("nuget", "Newtonsoft.Json"),
framework("nuget", "NUnit"),
framework("nuget", "WebDriverBiDi"),
],
)

Expand Down Expand Up @@ -92,5 +93,6 @@ dotnet_nunit_test_suite(
framework("nuget", "BenderProxy"),
framework("nuget", "Newtonsoft.Json"),
framework("nuget", "NUnit"),
framework("nuget", "WebDriverBiDi"),
],
)
6 changes: 5 additions & 1 deletion dotnet/test/common/Environment/DriverFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ public IWebDriver CreateDriverWithOptions(Type driverType, DriverOptions driverO
{
browser = Browser.Chrome;
options = GetDriverOptions<ChromeOptions>(driverType, driverOptions);
options.UseWebSocketUrl = true;

var chromeOptions = (ChromeOptions)options;
chromeOptions.AddArguments("--no-sandbox", "--disable-dev-shm-usage");
Expand Down Expand Up @@ -185,6 +184,11 @@ protected void OnDriverLaunching(DriverService service, DriverOptions options)
options.ImplicitWaitTimeout = overriddenOptions.ImplicitWaitTimeout;
}

if (System.Environment.GetEnvironmentVariable("WEBDRIVER_BIDI") == "true")
{
options.UseWebSocketUrl = true;
}

return options;
}

Expand Down
43 changes: 32 additions & 11 deletions dotnet/test/common/NavigationTest.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using NUnit.Framework;
using System;
using System.Threading.Tasks;
using WebDriverBiDi;

namespace OpenQA.Selenium
{
Expand All @@ -13,10 +14,20 @@ public class NavigationTest : DriverTestFixture
[NeedsFreshDriver(IsCreatedBeforeTest = true)]
public void ShouldNotHaveProblemNavigatingWithNoPagesBrowsed()
{
INavigation navigation;
navigation = driver.Navigate();
navigation.Back();
navigation.Forward();
INavigation navigation = driver.Navigate();

if (((WebDriver)driver).Capabilities.HasCapability("webSocketUrl"))
{
var ex1 = Assert.Throws<WebDriverBiDiException>(() => navigation.Back());
Assert.True(ex1!.Message.Contains("no such history entry"));
var ex2 = Assert.Throws<WebDriverBiDiException>(() => navigation.Forward());
Assert.True(ex2!.Message.Contains("no such history entry"));
}
else
{
Assert.DoesNotThrow(() => navigation.Back());
Assert.DoesNotThrow(() => navigation.Forward());
}
}

[Test]
Expand All @@ -25,8 +36,8 @@ public void ShouldGoBackAndForward()
INavigation navigation;
navigation = driver.Navigate();

driver.Url = macbethPage;
driver.Url = simpleTestPage;
navigation.GoToUrl(macbethPage);
navigation.GoToUrl(simpleTestPage);

navigation.Back();
Assert.AreEqual(macbethTitle, driver.Title);
Expand Down Expand Up @@ -96,8 +107,18 @@ public void ShouldRefreshPage()
public Task ShouldNotHaveProblemNavigatingWithNoPagesBrowsedAsync()
{
var navigation = driver.Navigate();
Assert.DoesNotThrowAsync(async () => await navigation.BackAsync());
Assert.DoesNotThrowAsync(async () => await navigation.ForwardAsync());
if (((WebDriver)driver).Capabilities.HasCapability("webSocketUrl"))
{
var ex1 = Assert.ThrowsAsync<WebDriverBiDiException>(async () => await navigation.BackAsync());
Assert.True(ex1!.Message.Contains("no such history entry"));
var ex2 = Assert.ThrowsAsync<WebDriverBiDiException>(async () => await navigation.ForwardAsync());
Assert.True(ex2!.Message.Contains("no such history entry"));
}
else
{
Assert.DoesNotThrow(() => navigation.Back());
Assert.DoesNotThrow(() =>navigation.Forward());
}
return Task.CompletedTask;
}

Expand Down Expand Up @@ -141,9 +162,9 @@ 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);
Assert.AreEqual(macbethTitle, driver.Title);
navigation.GoToUrlAsync(new Uri(simpleTestPage));
Assert.AreEqual(driver.Title, simpleTestTitle);
}

[Test]
Expand Down
Binary file not shown.
Loading