diff --git a/dotnet/src/support/Events/EventFiringWebDriver.cs b/dotnet/src/support/Events/EventFiringWebDriver.cs index ac428cf2830b5..a7e824235a1a5 100644 --- a/dotnet/src/support/Events/EventFiringWebDriver.cs +++ b/dotnet/src/support/Events/EventFiringWebDriver.cs @@ -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 { @@ -845,12 +847,21 @@ public EventFiringNavigation(EventFiringWebDriver driver) /// Move the browser back /// public void Back() + { + AsyncHelper.RunSync(this.BackAsync); + } + + /// + /// Move the browser backward 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) @@ -864,12 +875,21 @@ public void Back() /// Move the browser forward /// public void Forward() + { + AsyncHelper.RunSync(this.ForwardAsync); + } + + /// + /// Move the browser forward 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) @@ -879,17 +899,33 @@ 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) { + AsyncHelper.RunSync(() => this.GoToUrlAsync(url)); + } + + /// + /// Navigate to a url as an asynchronous task + /// + /// String of where you want the browser to go to + /// 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 +936,46 @@ 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) + { + AsyncHelper.RunSync(() => this.GoToUrlAsync(url)); + } + + /// + /// Navigate to a url as an asynchronous task + /// + /// Uri object of where you want the browser to go to + /// 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 /// public void Refresh() + { + AsyncHelper.RunSync(this.RefreshAsync); + } + + /// + /// Refresh the browser 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) { @@ -939,6 +983,7 @@ public void Refresh() throw; } } + } /// diff --git a/dotnet/src/webdriver/ICommandExecutor.cs b/dotnet/src/webdriver/ICommandExecutor.cs index 68cfe200391f4..8635f413ba71b 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 Asynchronously + /// + /// 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..e81cd1041a5fa 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. + /// + /// 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. + /// + /// 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); + /// + /// Load a new web page in the current browser window. + /// + /// The URL to load. It is best to use a fully qualified URL + /// 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); + /// + /// Load a new web page in the current browser window. + /// + /// The URL to load. + /// A task object representing the asynchronous operation + Task GoToUrlAsync(Uri url); + /// /// Refreshes the current page. /// void Refresh(); + + /// + /// Refreshes the current page. + /// + /// A task object representing the asynchronous operation + Task RefreshAsync(); } } diff --git a/dotnet/src/webdriver/Internal/AsyncHelper.cs b/dotnet/src/webdriver/Internal/AsyncHelper.cs new file mode 100644 index 0000000000000..0ffaef76f0618 --- /dev/null +++ b/dotnet/src/webdriver/Internal/AsyncHelper.cs @@ -0,0 +1,49 @@ +// +// 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. +// + +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace OpenQA.Selenium.Internal +{ + /// + /// Encapsulates methods for working with asynchronous tasks. + /// + public static class AsyncHelper + { + private static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None, + TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default); + + public static TResult RunSync(Func> func) + { + return _myTaskFactory.StartNew(() => + { + return func(); + }).Unwrap().ConfigureAwait(false).GetAwaiter().GetResult(); + } + + public static void RunSync(Func func) + { + _myTaskFactory.StartNew(() => + { + return func(); + }).Unwrap().ConfigureAwait(false).GetAwaiter().GetResult(); + } + } +} diff --git a/dotnet/src/webdriver/Navigator.cs b/dotnet/src/webdriver/Navigator.cs index f8f6047e91f5a..9b7062c183267 100644 --- a/dotnet/src/webdriver/Navigator.cs +++ b/dotnet/src/webdriver/Navigator.cs @@ -17,7 +17,10 @@ // using System; +using System.Threading.Tasks; +using OpenQA.Selenium.Internal; using System.Collections.Generic; +using WebDriverBiDi.BrowsingContext; namespace OpenQA.Selenium { @@ -27,6 +30,14 @@ namespace OpenQA.Selenium internal class Navigator : INavigation { private WebDriver driver; + private static readonly Dictionary PageLoadStrategyMapper = new() + { + {"normal", ReadinessState.Complete}, + {"default", ReadinessState.Complete}, + {"eager", ReadinessState.Interactive}, + {"none", ReadinessState.None} + }; + private ReadinessState readinessState; /// /// Initializes a new instance of the class @@ -35,6 +46,7 @@ internal class Navigator : INavigation public Navigator(WebDriver driver) { this.driver = driver; + this.readinessState = PageLoadStrategyMapper[(string)driver.Capabilities.GetCapability("pageLoadStrategy")]; } /// @@ -42,7 +54,26 @@ public Navigator(WebDriver driver) /// public void Back() { - this.driver.InternalExecute(DriverCommand.GoBack, null); + AsyncHelper.RunSync(this.BackAsync); + } + + /// + /// 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() + { + if (this.driver.BiDiDriver != null) + { + var traverseHistoryCommandParameters = + new TraverseHistoryCommandParameters(driver.BrowsingContextId, -1); + await this.driver.BiDiDriver.BrowsingContext.TraverseHistoryAsync(traverseHistoryCommandParameters) + .ConfigureAwait(false); + } + else + { + await this.driver.InternalExecuteAsync(DriverCommand.GoBack, null).ConfigureAwait(false); + } } /// @@ -50,40 +81,89 @@ public void Back() /// public void Forward() { - this.driver.InternalExecute(DriverCommand.GoForward, null); + AsyncHelper.RunSync(this.ForwardAsync); + } + + /// + /// Move the browser forward as an asynchronous task + /// + /// A task object representing the asynchronous operation + public async Task ForwardAsync() + { + if (this.driver.BiDiDriver != null) + { + var traverseHistoryCommandParameters = + new TraverseHistoryCommandParameters(driver.BrowsingContextId, 1); + await this.driver.BiDiDriver.BrowsingContext.TraverseHistoryAsync(traverseHistoryCommandParameters) + .ConfigureAwait(false); + } + else + { + 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) + { + AsyncHelper.RunSync(() => this.GoToUrlAsync(url)); + } + + /// + /// Navigate to a url as an asynchronous task + /// + /// String of where you want the browser to go to + /// 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."); } - Dictionary parameters = new Dictionary + if (this.driver.BiDiDriver != null) { - { "url", url } - }; - this.driver.InternalExecute(DriverCommand.Get, parameters); - + NavigateCommandParameters navigateCommandParameters = new NavigateCommandParameters(driver.BrowsingContextId, url) + { + Wait = this.readinessState + }; + await driver.BiDiDriver.BrowsingContext.NavigateAsync(navigateCommandParameters).ConfigureAwait(false); + } + else + { + Dictionary parameters = new Dictionary + { + { "url", url } + }; + this.driver.InternalExecute(DriverCommand.Get, parameters); + } } /// - /// 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) + { + AsyncHelper.RunSync(() => this.GoToUrlAsync(url)); + } + + /// + /// Navigate to a url as an asynchronous task + /// + /// Uri of where you want the browser to go to + /// 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); } /// @@ -91,8 +171,28 @@ public void GoToUrl(Uri url) /// public void Refresh() { - // driver.SwitchTo().DefaultContent(); - this.driver.InternalExecute(DriverCommand.Refresh, null); + AsyncHelper.RunSync(this.RefreshAsync); + } + + /// + /// Refresh the browser as an asynchronous task + /// + /// A task object representing the asynchronous operation + public async Task RefreshAsync() + { + if (this.driver.BiDiDriver != null) + { + var reloadCommandParameters = + new ReloadCommandParameters(driver.BrowsingContextId) + { + Wait = this.readinessState + }; + await this.driver.BiDiDriver.BrowsingContext.ReloadAsync(reloadCommandParameters).ConfigureAwait(false); + } + else + { + 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..e543f6ec386cf 100644 --- a/dotnet/src/webdriver/Remote/DriverServiceCommandExecutor.cs +++ b/dotnet/src/webdriver/Remote/DriverServiceCommandExecutor.cs @@ -17,6 +17,8 @@ // using System; +using System.Threading.Tasks; +using OpenQA.Selenium.Internal; namespace OpenQA.Selenium.Remote { @@ -92,6 +94,16 @@ public HttpCommandExecutor HttpExecutor /// The command you wish to execute /// A response from the browser public Response Execute(Command commandToExecute) + { + return AsyncHelper.RunSync(() => this.ExecuteAsync(commandToExecute)); + } + + /// + /// Executes a command Asynchronously + /// + /// The command you wish to execute + /// A task object representing the asynchronous operation + public async Task ExecuteAsync(Command commandToExecute) { if (commandToExecute == null) { @@ -108,7 +120,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); } finally { diff --git a/dotnet/src/webdriver/Remote/HttpCommandExecutor.cs b/dotnet/src/webdriver/Remote/HttpCommandExecutor.cs index 3dbb5e4efd179..4ba91797d6a80 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 AsyncHelper.RunSync(() => this.ExecuteAsync(commandToExecute)); + } + + /// + /// Executes a command Asynchronously + /// + /// 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); } catch (HttpRequestException ex) { diff --git a/dotnet/src/webdriver/WebDriver.cs b/dotnet/src/webdriver/WebDriver.cs index 3de43e25c452f..887247b692791 100644 --- a/dotnet/src/webdriver/WebDriver.cs +++ b/dotnet/src/webdriver/WebDriver.cs @@ -24,6 +24,9 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; +using System.Threading.Tasks; +using WebDriverBiDi; +using WebDriverBiDi.BrowsingContext; namespace OpenQA.Selenium { @@ -45,6 +48,8 @@ public class WebDriver : IWebDriver, ISearchContext, IJavaScriptExecutor, IFinds private SessionId sessionId; private String authenticatorId; private List registeredCommands = new List(); + private string browsingContextId = string.Empty; + private BiDiDriver biDiDriver; /// /// Initializes a new instance of the class. @@ -556,7 +561,25 @@ internal ReadOnlyCollection GetElementsFromResponse(Response respon /// WebDriver Response internal Response InternalExecute(string driverCommandToExecute, Dictionary parameters) { - return this.Execute(driverCommandToExecute, parameters); + return AsyncHelper.RunSync(() => this.InternalExecuteAsync(driverCommandToExecute, parameters)); + } + + /// + /// 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 AsyncHelper.RunSync(() => this.ExecuteAsync(driverCommandToExecute, parameters)); } /// @@ -565,7 +588,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 +596,7 @@ protected virtual Response Execute(string driverCommandToExecute, Dictionary this.biDiDriver.StartAsync(webSocketUrl)); + GetTreeCommandResult tree = AsyncHelper.RunSync(() => this.biDiDriver.BrowsingContext.GetTreeAsync(new GetTreeCommandParameters())); + this.browsingContextId = tree.ContextTree[0].BrowsingContextId; + } } /// @@ -1018,6 +1050,10 @@ public void RemoveVirtualAuthenticator(string authenticatorId) /// public string AuthenticatorId { get; } + internal string BrowsingContextId => browsingContextId; + + internal BiDiDriver BiDiDriver => biDiDriver; + /// /// Add a credential to the Virtual Authenticator/ /// diff --git a/dotnet/src/webdriver/WebDriver.csproj b/dotnet/src/webdriver/WebDriver.csproj index 354284b328755..f0cd4c48ebbe9 100644 --- a/dotnet/src/webdriver/WebDriver.csproj +++ b/dotnet/src/webdriver/WebDriver.csproj @@ -53,6 +53,7 @@ + diff --git a/dotnet/test/common/Environment/DriverFactory.cs b/dotnet/test/common/Environment/DriverFactory.cs index 448dfc61d1a98..7c90a4cf5fff9 100644 --- a/dotnet/test/common/Environment/DriverFactory.cs +++ b/dotnet/test/common/Environment/DriverFactory.cs @@ -67,7 +67,7 @@ public IWebDriver CreateDriverWithOptions(Type driverType, DriverOptions driverO { browser = Browser.Chrome; options = GetDriverOptions(driverType, driverOptions); - options.UseWebSocketUrl = true; + options.UseWebSocketUrl = System.Environment.GetEnvironmentVariable("WEBDRIVER_BIDI") == "true"; var chromeOptions = (ChromeOptions)options; chromeOptions.AddArguments("--no-sandbox", "--disable-dev-shm-usage"); @@ -114,6 +114,8 @@ public IWebDriver CreateDriverWithOptions(Type driverType, DriverOptions driverO { browser = Browser.Firefox; options = GetDriverOptions(driverType, driverOptions); + options.UseWebSocketUrl = System.Environment.GetEnvironmentVariable("WEBDRIVER_BIDI") == "true"; + service = CreateService(); if (!string.IsNullOrEmpty(this.browserBinaryLocation)) { diff --git a/dotnet/test/common/Environment/EnvironmentManager.cs b/dotnet/test/common/Environment/EnvironmentManager.cs index 3fc16fac54222..dd21805b51cb6 100644 --- a/dotnet/test/common/Environment/EnvironmentManager.cs +++ b/dotnet/test/common/Environment/EnvironmentManager.cs @@ -24,9 +24,10 @@ public class EnvironmentManager private EnvironmentManager() { string dataFilePath; - var runfiles = Runfiles.Create(); + Runfiles runfiles = null; try { + runfiles = Runfiles.Create(); dataFilePath = runfiles.Rlocation("_main/dotnet/test/common/appconfig.json"); } catch (FileNotFoundException) @@ -143,6 +144,8 @@ private EnvironmentManager() try { string managerFilePath = ""; + runfiles ??= Runfiles.Create(); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { managerFilePath = runfiles.Rlocation("_main/dotnet/src/webdriver/manager/windows/selenium-manager.exe"); diff --git a/dotnet/test/common/Environment/TestWebServer.cs b/dotnet/test/common/Environment/TestWebServer.cs index f0e58d32fed19..50ec56c7a27c2 100644 --- a/dotnet/test/common/Environment/TestWebServer.cs +++ b/dotnet/test/common/Environment/TestWebServer.cs @@ -20,14 +20,16 @@ public class TestWebServer private string javaHomeDirectory; private string port; - private StringBuilder outputData = new StringBuilder(); - public TestWebServer(string projectRoot, TestWebServerConfig config) { this.projectRootPath = projectRoot; this.captureWebServerOutput = config.CaptureConsoleOutput; this.hideCommandPrompt = config.HideCommandPromptWindow; this.javaHomeDirectory = config.JavaHomeDirectory; + if (string.IsNullOrEmpty(this.javaHomeDirectory)) + { + this.javaHomeDirectory = System.Environment.GetEnvironmentVariable("JAVA_HOME"); + } this.port = config.Port; } @@ -39,16 +41,15 @@ public void Start() { var runfiles = Runfiles.Create(); standaloneTestJar = runfiles.Rlocation(standaloneTestJar); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + standaloneTestJar += ".exe"; + } } catch (FileNotFoundException) { var baseDirectory = AppContext.BaseDirectory; - standaloneTestJar = Path.Combine(baseDirectory, "../../../../../../bazel-bin/java/test/org/openqa/selenium/environment/appserver"); - } - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - standaloneTestJar += ".exe"; + standaloneTestJar = Path.Combine(baseDirectory, "../../../../../../bazel-bin/java/test/org/openqa/selenium/environment/appserver_deploy.jar"); } Console.Write("Standalone jar is " + standaloneTestJar); @@ -59,65 +60,49 @@ public void Start() string.Format( "Test webserver jar at {0} didn't exist. Project root is {2}. Please build it using something like {1}.", standaloneTestJar, - "bazel build //java/test/org/openqa/selenium/environment:appserver_deploy.jar", + "bazel build //java/test/org/openqa/selenium/environment:appserver", projectRootPath)); } - //List javaSystemProperties = new List(); - StringBuilder processArgsBuilder = new StringBuilder(); - // foreach (string systemProperty in javaSystemProperties) - // { - // if (processArgsBuilder.Length > 0) - // { - // processArgsBuilder.Append(" "); - // } - // - // processArgsBuilder.AppendFormat("-D{0}", systemProperty); - // } - // - // if (processArgsBuilder.Length > 0) - // { - // processArgsBuilder.Append(" "); - // } - // - // processArgsBuilder.AppendFormat("-jar {0}", standaloneTestJar); - processArgsBuilder.AppendFormat(" {0}", this.port); - - Console.Write(processArgsBuilder.ToString()); + ProcessStartInfo startInfo = new ProcessStartInfo + { + WorkingDirectory = projectRootPath, + UseShellExecute = !(hideCommandPrompt || captureWebServerOutput), + CreateNoWindow = hideCommandPrompt, + RedirectStandardOutput = captureWebServerOutput, + RedirectStandardError = captureWebServerOutput + }; + + if (standaloneTestJar != null && standaloneTestJar.EndsWith(".jar")) + { + processArgsBuilder.AppendFormat("-jar \"{0}\" {1}", standaloneTestJar, this.port); + string javaExecutable = Path.Combine(javaHomeDirectory, "bin", "java"); + if (!File.Exists(javaExecutable)) + { + throw new FileNotFoundException($"Java executable not found at {javaExecutable}"); + } - webserverProcess = new Process(); - webserverProcess.StartInfo.FileName = standaloneTestJar; - // if (!string.IsNullOrEmpty(javaExecutablePath)) - // { - // webserverProcess.StartInfo.FileName = Path.Combine(javaExecutablePath, javaExecutableName); - // } - // else - // { - // webserverProcess.StartInfo.FileName = javaExecutableName; - // } - - webserverProcess.StartInfo.Arguments = processArgsBuilder.ToString(); - webserverProcess.StartInfo.WorkingDirectory = projectRootPath; - webserverProcess.StartInfo.UseShellExecute = !(hideCommandPrompt || captureWebServerOutput); - webserverProcess.StartInfo.CreateNoWindow = hideCommandPrompt; - if (!string.IsNullOrEmpty(this.javaHomeDirectory)) + startInfo.FileName = javaExecutable; + } + else { - webserverProcess.StartInfo.EnvironmentVariables["JAVA_HOME"] = this.javaHomeDirectory; + processArgsBuilder.AppendFormat(" {0}", this.port); + startInfo.FileName = standaloneTestJar; } - captureWebServerOutput = true; - - if (captureWebServerOutput) + Console.Write(processArgsBuilder.ToString()); + startInfo.Arguments = processArgsBuilder.ToString(); + if (!string.IsNullOrEmpty(this.javaHomeDirectory)) { - webserverProcess.StartInfo.RedirectStandardOutput = true; - webserverProcess.StartInfo.RedirectStandardError = true; + startInfo.EnvironmentVariables["JAVA_HOME"] = this.javaHomeDirectory; } + webserverProcess = new Process { StartInfo = startInfo }; webserverProcess.Start(); TimeSpan timeout = TimeSpan.FromSeconds(30); - DateTime endTime = DateTime.Now.Add(TimeSpan.FromSeconds(30)); + DateTime endTime = DateTime.Now.Add(timeout); bool isRunning = false; // Poll until the webserver is correctly serving pages. @@ -161,7 +146,14 @@ public void Stop() { using (var httpClient = new HttpClient()) { - using (var quitResponse = httpClient.GetAsync(EnvironmentManager.Instance.UrlBuilder.LocalWhereIs("quitquitquit")).GetAwaiter().GetResult()) + try + { + using (httpClient.GetAsync(EnvironmentManager.Instance.UrlBuilder.LocalWhereIs("quitquitquit")).GetAwaiter().GetResult()) + { + + } + } + catch (HttpRequestException) { } diff --git a/dotnet/test/common/NavigationTest.cs b/dotnet/test/common/NavigationTest.cs index ee40894aa047c..15f4e5c02287c 100644 --- a/dotnet/test/common/NavigationTest.cs +++ b/dotnet/test/common/NavigationTest.cs @@ -1,5 +1,6 @@ using NUnit.Framework; using System; +using WebDriverBiDi; namespace OpenQA.Selenium { @@ -12,10 +13,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(() => navigation.Back()); + Assert.True(ex1.Message.Contains("no such history entry")); + var ex2 = Assert.Throws(() => navigation.Forward()); + Assert.True(ex2.Message.Contains("no such history entry")); + } + else + { + navigation.Back(); + navigation.Forward(); + } } [Test] @@ -40,7 +51,7 @@ public void ShouldAcceptInvalidUrlsUsingUris() INavigation navigation; navigation = driver.Navigate(); Assert.That(() => 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. } @@ -89,6 +100,5 @@ public void ShouldRefreshPage() changedDiv = driver.FindElement(By.Id("dynamo")); Assert.AreEqual("What's for dinner?", changedDiv.Text); } - } } diff --git a/third_party/dotnet/nuget/packages/webdriverbidi.0.0.1.nupkg b/third_party/dotnet/nuget/packages/webdriverbidi.0.0.1.nupkg new file mode 100644 index 0000000000000..99afa6c504946 Binary files /dev/null and b/third_party/dotnet/nuget/packages/webdriverbidi.0.0.1.nupkg differ