Skip to content

Commit

Permalink
Adding initial implementation of .NET bindings OperaDriver
Browse files Browse the repository at this point in the history
The .NET bindings will now support the Chromium-based Opera driver without
requiring the use of the Java remote WebDriver server. This driver will
work with Opera 26 and above, and requires the download of the Opera
driver executable. Code cleanup and refactoring will take place under a
separate commit.

Note that there is still no support in the .NET bindings for the
Presto-based Opera without using the remote server, nor is there likely to
be.
  • Loading branch information
jimevans committed Dec 9, 2014
1 parent c6431d5 commit 4cf6168
Show file tree
Hide file tree
Showing 12 changed files with 1,042 additions and 0 deletions.
16 changes: 16 additions & 0 deletions WebDriver.sln
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "webdriver-firefox-latest",
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "civetweb", "third_party\cpp\civetweb\civetweb.vcxproj", "{231A8BED-6F2D-4688-A3BD-920310621BBF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebDriver.Opera.Tests", "dotnet\test\opera\WebDriver.Opera.Tests.csproj", "{52FA53EC-6F39-4893-9E73-9F6A2D09E2A6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|.NET = Debug|.NET
Expand Down Expand Up @@ -456,6 +458,20 @@ Global
{231A8BED-6F2D-4688-A3BD-920310621BBF}.Release|Win32.Build.0 = Release|Win32
{231A8BED-6F2D-4688-A3BD-920310621BBF}.Release|x64.ActiveCfg = Release|x64
{231A8BED-6F2D-4688-A3BD-920310621BBF}.Release|x64.Build.0 = Release|x64
{52FA53EC-6F39-4893-9E73-9F6A2D09E2A6}.Debug|.NET.ActiveCfg = Debug|Any CPU
{52FA53EC-6F39-4893-9E73-9F6A2D09E2A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{52FA53EC-6F39-4893-9E73-9F6A2D09E2A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{52FA53EC-6F39-4893-9E73-9F6A2D09E2A6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{52FA53EC-6F39-4893-9E73-9F6A2D09E2A6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{52FA53EC-6F39-4893-9E73-9F6A2D09E2A6}.Debug|Win32.ActiveCfg = Debug|Any CPU
{52FA53EC-6F39-4893-9E73-9F6A2D09E2A6}.Debug|x64.ActiveCfg = Debug|Any CPU
{52FA53EC-6F39-4893-9E73-9F6A2D09E2A6}.Release|.NET.ActiveCfg = Release|Any CPU
{52FA53EC-6F39-4893-9E73-9F6A2D09E2A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{52FA53EC-6F39-4893-9E73-9F6A2D09E2A6}.Release|Any CPU.Build.0 = Release|Any CPU
{52FA53EC-6F39-4893-9E73-9F6A2D09E2A6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{52FA53EC-6F39-4893-9E73-9F6A2D09E2A6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{52FA53EC-6F39-4893-9E73-9F6A2D09E2A6}.Release|Win32.ActiveCfg = Release|Any CPU
{52FA53EC-6F39-4893-9E73-9F6A2D09E2A6}.Release|x64.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
1 change: 1 addition & 0 deletions dotnet/src/webdriver/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "OpenQA.Selenium.PhantomJS", Justification = "Namespaces are properly scoped.")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "OpenQA.Selenium.Interactions", Justification = "Namespaces are properly scoped.")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "OpenQA.Selenium.Chrome", Justification = "Namespaces are properly scoped.")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "OpenQA.Selenium.Opera", Justification = "Namespaces are properly scoped.")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Scope = "member", Target = "OpenQA.Selenium.ITakesScreenshot.#GetScreenshot()", Justification = "API specification demands method.")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1027:MarkEnumsWithFlags", Scope = "type", Target = "OpenQA.Selenium.ProxyKind", Justification = "The ProxyKind enum is not a set of flags, but has values determined by an external API.")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1027:MarkEnumsWithFlags", Scope = "type", Target = "OpenQA.Selenium.WebDriverResult", Justification = "The WebDriverResult enum is not a set of flags, but has values determined by an external API.")]
Expand Down
157 changes: 157 additions & 0 deletions dotnet/src/webdriver/Opera/OperaDriver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// <copyright file="OperaDriver.cs" company="WebDriver Committers">
// Copyright 2007-2011 WebDriver committers
// Copyright 2007-2011 Google Inc.
// Portions copyright 2011 Software Freedom Conservancy
//
// Licensed 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.Collections.Generic;
using System.Collections.ObjectModel;
using OpenQA.Selenium.Internal;
using OpenQA.Selenium.Remote;

namespace OpenQA.Selenium.Opera
{
/// <summary>
/// Provides a mechanism to write tests against Opera
/// </summary>
/// <example>
/// <code>
/// [TestFixture]
/// public class Testing
/// {
/// private IWebDriver driver;
/// <para></para>
/// [SetUp]
/// public void SetUp()
/// {
/// driver = new OperaDriver();
/// }
/// <para></para>
/// [Test]
/// public void TestGoogle()
/// {
/// driver.Navigate().GoToUrl("http://www.google.co.uk");
/// /*
/// * Rest of the test
/// */
/// }
/// <para></para>
/// [TearDown]
/// public void TearDown()
/// {
/// driver.Quit();
/// }
/// }
/// </code>
/// </example>
public class OperaDriver : RemoteWebDriver
{
/// <summary>
/// Accept untrusted SSL Certificates
/// </summary>
public static readonly bool AcceptUntrustedCertificates = true;

#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="OperaDriver"/> class.
/// </summary>
public OperaDriver()
: this(new OperaOptions())
{
}

/// <summary>
/// Initializes a new instance of the <see cref="OperaDriver"/> class using the specified options.
/// </summary>
/// <param name="options">The <see cref="OperaOptions"/> to be used with the Opera driver.</param>
public OperaDriver(OperaOptions options)
: this(OperaDriverService.CreateDefaultService(), options, RemoteWebDriver.DefaultCommandTimeout)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="OperaDriver"/> class using the specified path
/// to the directory containing OperaDriver.exe.
/// </summary>
/// <param name="operaDriverDirectory">The full path to the directory containing OperaDriver.exe.</param>
public OperaDriver(string operaDriverDirectory)
: this(operaDriverDirectory, new OperaOptions())
{
}

/// <summary>
/// Initializes a new instance of the <see cref="OperaDriver"/> class using the specified path
/// to the directory containing OperaDriver.exe and options.
/// </summary>
/// <param name="operaDriverDirectory">The full path to the directory containing OperaDriver.exe.</param>
/// <param name="options">The <see cref="OperaOptions"/> to be used with the Opera driver.</param>
public OperaDriver(string operaDriverDirectory, OperaOptions options)
: this(operaDriverDirectory, options, RemoteWebDriver.DefaultCommandTimeout)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="OperaDriver"/> class using the specified path
/// to the directory containing OperaDriver.exe, options, and command timeout.
/// </summary>
/// <param name="operaDriverDirectory">The full path to the directory containing OperaDriver.exe.</param>
/// <param name="options">The <see cref="OperaOptions"/> to be used with the Opera driver.</param>
/// <param name="commandTimeout">The maximum amount of time to wait for each command.</param>
public OperaDriver(string operaDriverDirectory, OperaOptions options, TimeSpan commandTimeout)
: this(OperaDriverService.CreateDefaultService(operaDriverDirectory), options, commandTimeout)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="OperaDriver"/> class using the specified
/// <see cref="OperaDriverService"/> and options.
/// </summary>
/// <param name="service">The <see cref="OperaDriverService"/> to use.</param>
/// <param name="options">The <see cref="OperaOptions"/> used to initialize the driver.</param>
public OperaDriver(OperaDriverService service, OperaOptions options)
: this(service, options, RemoteWebDriver.DefaultCommandTimeout)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="OperaDriver"/> class using the specified <see cref="OperaDriverService"/>.
/// </summary>
/// <param name="service">The <see cref="OperaDriverService"/> to use.</param>
/// <param name="options">The <see cref="OperaOptions"/> to be used with the Opera driver.</param>
/// <param name="commandTimeout">The maximum amount of time to wait for each command.</param>
public OperaDriver(OperaDriverService service, OperaOptions options, TimeSpan commandTimeout)
: base(new DriverServiceCommandExecutor(service, commandTimeout), options.ToCapabilities())
{
}
#endregion

/// <summary>
/// Gets or sets the <see cref="IFileDetector"/> responsible for detecting
/// sequences of keystrokes representing file paths and names.
/// </summary>
/// <remarks>The Opera driver does not allow a file detector to be set,
/// as the server component of the Opera driver (OperaDriver.exe) only
/// allows uploads from the local computer environment. Attempting to set
/// this property has no effect, but does not throw an exception. If you
/// are attempting to run the Opera driver remotely, use <see cref="RemoteWebDriver"/>
/// in conjunction with a standalone WebDriver server.</remarks>
public override IFileDetector FileDetector
{
get { return base.FileDetector; }
set { }
}
}
}
171 changes: 171 additions & 0 deletions dotnet/src/webdriver/Opera/OperaDriverService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// <copyright file="OperaDriverService.cs" company="WebDriver Committers">
// Copyright 2007-2011 WebDriver committers
// Copyright 2007-2011 Google Inc.
// Portions copyright 2011 Software Freedom Conservancy
//
// Licensed 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.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using OpenQA.Selenium.Internal;

namespace OpenQA.Selenium.Opera
{
/// <summary>
/// Exposes the service provided by the native OperaDriver executable.
/// </summary>
public sealed class OperaDriverService : DriverService
{
private const string OperaDriverServiceFileName = "operadriver-0.1.0-win32.exe";
private static readonly Uri OperaDriverDownloadUrl = new Uri("https://github.com/operasoftware/operachromiumdriver/releases");
private string logPath = string.Empty;
private string urlPathPrefix = string.Empty;
private string portServerAddress = string.Empty;
private int adbPort = -1;
private bool enableVerboseLogging;

/// <summary>
/// Initializes a new instance of the OperaDriverService class.
/// </summary>
/// <param name="executablePath">The full path to the OperaDriver executable.</param>
/// <param name="executableFileName">The file name of the OperaDriver executable.</param>
/// <param name="port">The port on which the OperaDriver executable should listen.</param>
private OperaDriverService(string executablePath, string executableFileName, int port)
: base(executablePath, port, executableFileName, OperaDriverDownloadUrl)
{
}

/// <summary>
/// Gets or sets the location of the log file written to by the OperaDriver executable.
/// </summary>
public string LogPath
{
get { return this.logPath; }
set { this.logPath = value; }
}

/// <summary>
/// Gets or sets the base URL path prefix for commands (e.g., "wd/url").
/// </summary>
public string UrlPathPrefix
{
get { return this.urlPathPrefix; }
set { this.urlPathPrefix = value; }
}

/// <summary>
/// Gets or sets the address of a server to contact for reserving a port.
/// </summary>
public string PortServerAddress
{
get { return this.portServerAddress; }
set { this.portServerAddress = value; }
}

/// <summary>
/// Gets or sets the port on which the Android Debug Bridge is listening for commands.
/// </summary>
public int AndroidDebugBridgePort
{
get { return this.adbPort; }
set { this.adbPort = value; }
}

/// <summary>
/// Gets or sets a value indicating whether to enable verbose logging for the OperaDriver executable.
/// Defaults to <see langword="false"/>.
/// </summary>
public bool EnableVerboseLogging
{
get { return this.enableVerboseLogging; }
set { this.enableVerboseLogging = value; }
}

/// <summary>
/// Gets the command-line arguments for the driver service.
/// </summary>
protected override string CommandLineArguments
{
get
{
StringBuilder argsBuilder = new StringBuilder(base.CommandLineArguments);
if (this.adbPort > 0)
{
argsBuilder.AppendFormat(CultureInfo.InvariantCulture, " --adb-port={0}", this.adbPort);
}

if (this.SuppressInitialDiagnosticInformation)
{
argsBuilder.Append(" --silent");
}

if (this.enableVerboseLogging)
{
argsBuilder.Append(" --verbose");
}

if (!string.IsNullOrEmpty(this.logPath))
{
argsBuilder.AppendFormat(CultureInfo.InvariantCulture, " --log-path={0}", this.logPath);
}

if (!string.IsNullOrEmpty(this.urlPathPrefix))
{
argsBuilder.AppendFormat(CultureInfo.InvariantCulture, " --url-base={0}", this.urlPathPrefix);
}

if (!string.IsNullOrEmpty(this.portServerAddress))
{
argsBuilder.AppendFormat(CultureInfo.InvariantCulture, " --port-server={0}", this.portServerAddress);
}

return argsBuilder.ToString();
}
}

/// <summary>
/// Creates a default instance of the OperaDriverService.
/// </summary>
/// <returns>A OperaDriverService that implements default settings.</returns>
public static OperaDriverService CreateDefaultService()
{
string serviceDirectory = DriverService.FindDriverServiceExecutable(OperaDriverServiceFileName, OperaDriverDownloadUrl);
return CreateDefaultService(serviceDirectory);
}

/// <summary>
/// Creates a default instance of the OperaDriverService using a specified path to the OperaDriver executable.
/// </summary>
/// <param name="driverPath">The directory containing the OperaDriver executable.</param>
/// <returns>A OperaDriverService using a random port.</returns>
public static OperaDriverService CreateDefaultService(string driverPath)
{
return CreateDefaultService(driverPath, OperaDriverServiceFileName);
}

/// <summary>
/// Creates a default instance of the OperaDriverService using a specified path to the OperaDriver executable with the given name.
/// </summary>
/// <param name="driverPath">The directory containing the OperaDriver executable.</param>
/// <param name="driverExecutableFileName">The name of the OperaDriver executable file.</param>
/// <returns>A OperaDriverService using a random port.</returns>
public static OperaDriverService CreateDefaultService(string driverPath, string driverExecutableFileName)
{
return new OperaDriverService(driverPath, driverExecutableFileName, PortUtilities.FindFreePort());
}
}
}
Loading

0 comments on commit 4cf6168

Please sign in to comment.