Skip to content

Commit

Permalink
Adding support for opening new browser windows in .NET
Browse files Browse the repository at this point in the history
Since support has been added to the W3C WebDriver Specification for
creating a new top-level browser context (a "new tab" or "new window"),
this change implements the new command in the .NET language bindings.
The method creates a new browser tab/window and switches to it. As
an argument, the method takes a type hint to indicate what type of
browser context the user wants (a tab or a window). Example usage:

    driver.SwitchTo().NewWindow(WindowType.Tab);

Note carefully, however, this type hint is only a suggestion. If a
browser driver does not support creating new top-level browsers of
the type desired by the user, it will still create the new top-level
browser using whatever type it does support. This is perfectly
compliant with the specification language for this command. As a
concrete example, at the time of this commit, executing the above
sample code against the IE driver will create a new top-level browser
context, but as a window, not a tab, in spite of the fact that a new
tab was explicitly requested. Even though the browser itself supports
creation of new tabs, the driver does not. This will not be considered
a valid bug, and issue reports claiming it is so will be summarily
closed, possibly without comment.
  • Loading branch information
jimevans committed Jan 28, 2019
1 parent e7f334d commit 4949267
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 2 deletions.
25 changes: 25 additions & 0 deletions dotnet/src/support/Events/EventFiringWebDriver.cs
Expand Up @@ -1017,6 +1017,31 @@ public IWebDriver Window(string windowName)
return driver;
}

/// <summary>
/// Creates a new browser window and switches the focus for future commands
/// of this driver to the new window.
/// </summary>
/// <param name="typeHint">The type of new browser window to be created.
/// The created window is not guaranteed to be of the requested type; if
/// the driver does not support the requested type, a new browser window
/// will be created of whatever type the driver does support.</param>
/// <returns>An <see cref="IWebDriver"/> instance focused on the new browser.</returns>
public IWebDriver NewWindow(WindowType typeHint)
{
IWebDriver driver = null;
try
{
driver = this.wrappedLocator.NewWindow(typeHint);
}
catch (Exception ex)
{
this.parentDriver.OnException(new WebDriverExceptionEventArgs(this.parentDriver, ex));
throw;
}

return driver;
}

/// <summary>
/// Change the active frame to the default
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions dotnet/src/webdriver/ITargetLocator.cs
Expand Up @@ -62,6 +62,17 @@ public interface ITargetLocator
/// <exception cref="NoSuchWindowException">If the window cannot be found.</exception>
IWebDriver Window(string windowName);

/// <summary>
/// Creates a new browser window and switches the focus for future commands
/// of this driver to the new window.
/// </summary>
/// <param name="typeHint">The type of new browser window to be created.
/// The created window is not guaranteed to be of the requested type; if
/// the driver does not support the requested type, a new browser window
/// will be created of whatever type the driver does support.</param>
/// <returns>An <see cref="IWebDriver"/> instance focused on the new browser.</returns>
IWebDriver NewWindow(WindowType typeHint);

/// <summary>
/// Selects either the first frame on the page or the main document when a page contains iFrames.
/// </summary>
Expand Down
7 changes: 6 additions & 1 deletion dotnet/src/webdriver/Remote/DriverCommand.cs
@@ -1,4 +1,4 @@
// <copyright file="DriverCommand.cs" company="WebDriver Committers">
// <copyright file="DriverCommand.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
Expand Down Expand Up @@ -168,6 +168,11 @@ public static class DriverCommand
/// </summary>
public static readonly string SwitchToWindow = "switchToWindow";

/// <summary>
/// Represents NewWindow command
/// </summary>
public static readonly string NewWindow = "newWindow";

/// <summary>
/// Represents SwitchToFrame command
/// </summary>
Expand Down
22 changes: 21 additions & 1 deletion dotnet/src/webdriver/Remote/RemoteTargetLocator.cs
@@ -1,4 +1,4 @@
// <copyright file="RemoteTargetLocator.cs" company="WebDriver Committers">
// <copyright file="RemoteTargetLocator.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
Expand Down Expand Up @@ -181,6 +181,26 @@ public IWebDriver Window(string windowHandleOrName)
return this.driver;
}

/// <summary>
/// Creates a new browser window and switches the focus for future commands
/// of this driver to the new window.
/// </summary>
/// <param name="typeHint">The type of new browser window to be created.
/// The created window is not guaranteed to be of the requested type; if
/// the driver does not support the requested type, a new browser window
/// will be created of whatever type the driver does support.</param>
/// <returns>An <see cref="IWebDriver"/> instance focused on the new browser.</returns>
public IWebDriver NewWindow(WindowType typeHint)
{
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("type", typeHint.ToString().ToLowerInvariant());
Response response = this.driver.InternalExecute(DriverCommand.NewWindow, parameters);
Dictionary<string, object> result = response.Value as Dictionary<string, object>;
string newWindowHandle = result["handle"].ToString();
this.Window(newWindowHandle);
return this.driver;
}

/// <summary>
/// Change the active frame to the default
/// </summary>
Expand Down
Expand Up @@ -62,6 +62,7 @@ protected override void InitializeCommandDictionary()
this.TryAddCommand(DriverCommand.Close, new CommandInfo(CommandInfo.DeleteCommand, "/session/{sessionId}/window"));
this.TryAddCommand(DriverCommand.SwitchToWindow, new CommandInfo(CommandInfo.PostCommand, "/session/{sessionId}/window"));
this.TryAddCommand(DriverCommand.GetWindowHandles, new CommandInfo(CommandInfo.GetCommand, "/session/{sessionId}/window/handles"));
this.TryAddCommand(DriverCommand.NewWindow, new CommandInfo(CommandInfo.PostCommand, "/session/{sessionId}/window/new"));
this.TryAddCommand(DriverCommand.SwitchToFrame, new CommandInfo(CommandInfo.PostCommand, "/session/{sessionId}/frame"));
this.TryAddCommand(DriverCommand.SwitchToParentFrame, new CommandInfo(CommandInfo.PostCommand, "/session/{sessionId}/frame/parent"));

Expand Down
36 changes: 36 additions & 0 deletions dotnet/src/webdriver/WindowType.cs
@@ -0,0 +1,36 @@
// <copyright file="WindowType.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>

namespace OpenQA.Selenium
{
/// <summary>
/// Represents the type of a new browser window that may be created
/// </summary>
public enum WindowType
{
/// <summary>
/// Create a new browser window using a new top-level window.
/// </summary>
Window,

/// <summary>
/// Create a new browser window using a new tab.
/// </summary>
Tab
}
}
15 changes: 15 additions & 0 deletions dotnet/test/common/WindowSwitchingTest.cs
Expand Up @@ -424,6 +424,21 @@ public void CloseShouldCloseCurrentHandleOnly()
Assert.That(handles, Contains.Item(handle1), "Valid handle not in handle list");
}

[Test]
[IgnoreBrowser(Browser.Chrome, "Driver does not yet support new window command")]
[IgnoreBrowser(Browser.Edge, "Driver does not yet support new window command")]
public void ShouldBeAbleToCreateANewWindow()
{
driver.Url = xhtmlTestPage;
string originalHandle = driver.CurrentWindowHandle;
driver.SwitchTo().NewWindow(WindowType.Tab);
WaitFor(WindowCountToBe(2), "Window count was not 2");
string newWindowHandle = driver.CurrentWindowHandle;
driver.Close();
driver.SwitchTo().Window(originalHandle);
Assert.That(newWindowHandle, Is.Not.EqualTo(originalHandle));
}

private void SleepBecauseWindowsTakeTimeToOpen()
{
try
Expand Down

0 comments on commit 4949267

Please sign in to comment.