Skip to content

Commit

Permalink
Move to Aquality.Selenium.Core (#152) +semver: major
Browse files Browse the repository at this point in the history
* Add core nuget package #148

* #148 Move to Selenium.Core

* #148 Rename ApplicationFactory to BrowserFactory

* #148 Override ElementStateProvider

* #148 Fix SonarQube CodeSmells

* Update ChromeDriver version

* Update test for implicit wait

* Add detailes to the error message
  • Loading branch information
paveliam authored Oct 24, 2019
1 parent 5fe6fa1 commit 2fa3f91
Show file tree
Hide file tree
Showing 81 changed files with 389 additions and 2,006 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Aquality.Selenium.Core" Version="0.2.0" />
<PackageReference Include="NLog" Version="4.6.6" />
<PackageReference Include="Selenium.Support" Version="3.141.0" />
<PackageReference Include="Selenium.WebDriver" Version="3.141.0" />
Expand Down
76 changes: 41 additions & 35 deletions Aquality.Selenium/src/Aquality.Selenium/Browsers/Browser.cs
Original file line number Diff line number Diff line change
@@ -1,41 +1,47 @@
using Aquality.Selenium.Configurations;
using Aquality.Selenium.Localization;
using Aquality.Selenium.Logging;
using Aquality.Selenium.Waitings;
using Aquality.Selenium.Core.Applications;
using Aquality.Selenium.Core.Localization;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Support.Extensions;
using System;
using System.Drawing;
using System.Reflection;
using System;
using Microsoft.Extensions.DependencyInjection;
using Aquality.Selenium.Core.Waitings;

namespace Aquality.Selenium.Browsers
{
/// <summary>
/// Provides functionality to work with browser via Selenium WebDriver.
/// </summary>
public class Browser
public class Browser : IApplication
{
private readonly IConfiguration configuration;
private TimeSpan implicitWaitTimeout;
private TimeSpan pageLoadTimeout;
private readonly IBrowserProfile browserProfile;
private readonly ConditionalWait conditionalWait;

/// <summary>
/// Instantiate browser.
/// </summary>
/// <param name="webDriver">Instance of Selenium WebDriver for desired web browser.</param>
/// <param name="configuration">Configuration.</param>
public Browser(RemoteWebDriver webDriver, IConfiguration configuration)
public Browser(RemoteWebDriver webDriver, IServiceProvider serviceProvider)
{
this.configuration = configuration;
Driver = webDriver;
BrowserName = configuration.BrowserProfile.BrowserName;
SetImplicitWaitTimeout(configuration.TimeoutConfiguration.Implicit);
SetPageLoadTimeout(configuration.TimeoutConfiguration.PageLoad);
SetScriptTimeout(configuration.TimeoutConfiguration.Script);
Logger = serviceProvider.GetRequiredService<LocalizationLogger>();
LocalizationManager = serviceProvider.GetRequiredService<LocalizationManager>();
browserProfile = serviceProvider.GetRequiredService<IBrowserProfile>();
conditionalWait = serviceProvider.GetRequiredService<ConditionalWait>();
var timeoutConfiguration = serviceProvider.GetRequiredService<ITimeoutConfiguration>();
SetImplicitWaitTimeout(timeoutConfiguration.Implicit);
SetPageLoadTimeout(timeoutConfiguration.PageLoad);
SetScriptTimeout(timeoutConfiguration.Script);
}

private Logger Logger => Logger.Instance;
private LocalizationLogger Logger { get; }

private LocalizationManager LocalizationManager { get; }

/// <summary>
/// Gets instance of Selenium WebDriver.
Expand All @@ -47,7 +53,7 @@ public Browser(RemoteWebDriver webDriver, IConfiguration configuration)
/// Gets name of desired browser from configuration.
/// </summary>
/// <value>Name of browser.</value>
public BrowserName BrowserName { get; }
public BrowserName BrowserName => browserProfile.BrowserName;

/// <summary>
/// Sets Selenium WebDriver ImplicitWait timeout.
Expand All @@ -71,7 +77,7 @@ public void SetImplicitWaitTimeout(TimeSpan timeout)
/// <param name="timeout">Desired page load timeout.</param>
public void SetPageLoadTimeout(TimeSpan timeout)
{
if (!configuration.BrowserProfile.BrowserName.Equals(BrowserName.Safari))
if (!BrowserName.Equals(BrowserName.Safari))
{
Driver.Manage().Timeouts().PageLoad = timeout;
pageLoadTimeout = timeout;
Expand All @@ -91,7 +97,7 @@ public void SetScriptTimeout(TimeSpan timeout)
/// <summary>
/// Gets browser configured download directory.
/// </summary>
public string DownloadDirectory => configuration.BrowserProfile.DriverSettings.DownloadDir;
public string DownloadDirectory => browserProfile.DriverSettings.DownloadDir;

/// <summary>
/// Gets URL of currently opened page in web browser.
Expand All @@ -101,7 +107,7 @@ public string CurrentUrl
{
get
{
Logger.InfoLoc("loc.browser.getUrl");
Logger.Info("loc.browser.getUrl");
return Driver.Url;
}
}
Expand All @@ -111,7 +117,7 @@ public string CurrentUrl
/// </summary>
public void Quit()
{
Logger.InfoLoc("loc.browser.driver.quit");
Logger.Info("loc.browser.driver.quit");
Driver?.Quit();
}

Expand Down Expand Up @@ -189,7 +195,7 @@ public void HandleAlert(AlertAction alertAction, string text = null)
}
catch (NoAlertPresentException ex)
{
Logger.FatalLoc("loc.browser.alert.fail", ex);
Logger.Fatal("loc.browser.alert.fail", ex);
throw;
}
}
Expand All @@ -199,7 +205,7 @@ public void HandleAlert(AlertAction alertAction, string text = null)
/// </summary>
public void Maximize()
{
Logger.InfoLoc("loc.browser.maximize");
Logger.Info("loc.browser.maximize");
Driver.Manage().Window.Maximize();
}

Expand All @@ -209,8 +215,8 @@ public void Maximize()
/// <exception cref="TimeoutException">Throws when timeout exceeded and page is not loaded.</exception>
public void WaitForPageToLoad()
{
var errorMessage = LocalizationManager.Instance.GetLocalizedMessage("loc.browser.page.timeout");
ConditionalWait.WaitForTrue(() => ExecuteScript<bool>(JavaScript.IsPageLoaded), pageLoadTimeout, message: errorMessage);
var errorMessage = LocalizationManager.GetLocalizedMessage("loc.browser.page.timeout");
conditionalWait.WaitForTrue(() => ExecuteScript<bool>(JavaScript.IsPageLoaded), pageLoadTimeout, message: errorMessage);
}

/// <summary>
Expand Down Expand Up @@ -242,6 +248,18 @@ public void ExecuteScriptFromFile(string embeddedResourcePath, params object[] a
ExecuteScript(embeddedResourcePath.GetScript(Assembly.GetCallingAssembly()), arguments);
}

/// <summary>
/// Executes JS script from embedded resource file (*.js) and gets result value.
/// </summary>
/// <param name="embeddedResourcePath">Embedded resource path.</param>
/// <param name="arguments">Script arguments.</param>
/// <typeparam name="T">Type of return value.</typeparam>
/// <returns>Script execution result.</returns>
public T ExecuteScriptFromFile<T>(string embeddedResourcePath, params object[] arguments)
{
return ExecuteScript<T>(embeddedResourcePath.GetScript(Assembly.GetCallingAssembly()), arguments);
}

/// <summary>
/// Executes predefined JS script.
/// </summary>
Expand All @@ -262,18 +280,6 @@ public void ExecuteScript(string script, params object[] arguments)
Driver.ExecuteJavaScript(script, arguments);
}

/// <summary>
/// Executes JS script from embedded resource file (*.js) and gets result value.
/// </summary>
/// <param name="embeddedResourcePath">Embedded resource path.</param>
/// <param name="arguments">Script arguments.</param>
/// <typeparam name="T">Type of return value.</typeparam>
/// <returns>Script execution result.</returns>
public T ExecuteScriptFromFile<T>(string embeddedResourcePath, params object[] arguments)
{
return ExecuteScript<T>(embeddedResourcePath.GetScript(Assembly.GetCallingAssembly()), arguments);
}

/// <summary>
/// Executes predefined JS script and gets result value.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Aquality.Selenium.Configurations;
using System;

namespace Aquality.Selenium.Browsers
{
Expand All @@ -7,12 +7,12 @@ namespace Aquality.Selenium.Browsers
/// </summary>
public abstract class BrowserFactory : IBrowserFactory
{
protected BrowserFactory(IConfiguration configuration)
protected BrowserFactory(IServiceProvider serviceProvider)
{
Configuration = configuration;
ServiceProvider = serviceProvider;
}

protected IConfiguration Configuration { get; }
protected IServiceProvider ServiceProvider { get; }

public abstract Browser Browser { get; }
}
Expand Down
94 changes: 71 additions & 23 deletions Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserManager.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
using Aquality.Selenium.Configurations;
using Aquality.Selenium.Elements;
using Aquality.Selenium.Elements.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Threading;
using Aquality.Selenium.Core.Localization;
using Aquality.Selenium.Core.Logging;
using System.Reflection;
using Aquality.Selenium.Core.Applications;
using Aquality.Selenium.Configurations;
using CoreElementFactory = Aquality.Selenium.Core.Elements.Interfaces.IElementFactory;
using CoreTimeoutConfiguration = Aquality.Selenium.Core.Configurations.ITimeoutConfiguration;
using ILoggerConfiguration = Aquality.Selenium.Core.Configurations.ILoggerConfiguration;

namespace Aquality.Selenium.Browsers
{
/// <summary>
/// Controls browser instance creation.
/// </summary>
public static class BrowserManager
public class BrowserManager : ApplicationManager<BrowserManager, Browser>
{
private static readonly ThreadLocal<Browser> BrowserContainer = new ThreadLocal<Browser>();
private static readonly ThreadLocal<IBrowserFactory> BrowserFactoryContainer = new ThreadLocal<IBrowserFactory>();

/// <summary>
Expand All @@ -19,54 +29,92 @@ public static Browser Browser
{
get
{
if (!BrowserContainer.IsValueCreated || BrowserContainer.Value.Driver.SessionId == null)
{
SetDefaultBrowser();
}
return BrowserContainer.Value;
return GetApplication(StartBrowserFunction, () => RegisterServices(services => Browser));
}
set
{
BrowserContainer.Value = value;
SetApplication(value);
}
}

private static void SetDefaultBrowser()
private static Func<IServiceProvider, Browser> StartBrowserFunction => services => BrowserFactory.Browser;

public static IServiceProvider ServiceProvider
{
if (!BrowserFactoryContainer.IsValueCreated)
get
{
SetDefaultFactory();
return GetServiceProvider(services => Browser, () => RegisterServices(services => Browser));
}
set
{
SetServiceProvider(value);
}
}

Browser = BrowserFactoryContainer.Value.Browser;
/// <summary>
/// Factory for application creation.
/// </summary>
public static IBrowserFactory BrowserFactory
{
get
{
if (!BrowserFactoryContainer.IsValueCreated)
{
SetDefaultFactory();
}
return BrowserFactoryContainer.Value;
}
set
{
BrowserFactoryContainer.Value = value;
}
}

private static IServiceCollection RegisterServices(Func<IServiceProvider, Browser> browserSupplier)
{
var services = new ServiceCollection();
var startup = new Startup();
var settingsFile = startup.GetSettings();
startup.ConfigureServices(services, browserSupplier, settingsFile);
services.AddTransient<IElementFactory, ElementFactory>();
services.AddTransient<CoreElementFactory, ElementFactory>();
services.AddSingleton<ITimeoutConfiguration>(serviceProvider => new TimeoutConfiguration(settingsFile));
services.AddSingleton<CoreTimeoutConfiguration>(serviceProvider => new TimeoutConfiguration(settingsFile));
services.AddSingleton<IBrowserProfile>(serviceProvider => new BrowserProfile(settingsFile));
services.AddSingleton(serviceProvider => new LocalizationManager(serviceProvider.GetRequiredService<ILoggerConfiguration>(), serviceProvider.GetRequiredService<Logger>(), Assembly.GetExecutingAssembly()));
services.AddTransient(serviceProvider => BrowserFactory);
return services;
}

/// <summary>
/// Sets default factory responsible for browser creation.
/// RemoteBrowserFactory if value set in configuration and LocalBrowserFactory otherwise.
/// </summary>
public static void SetDefaultFactory()
{
IConfiguration configuration = Configuration.Instance;
IBrowserFactory browserFactory;
if (configuration.BrowserProfile.IsRemote)
var appProfile = GetRequiredService<IBrowserProfile>();
IBrowserFactory applicationFactory;
if (appProfile.IsRemote)
{
browserFactory = new RemoteBrowserFactory(configuration);
applicationFactory = new RemoteBrowserFactory(ServiceProvider);
}
else
{
browserFactory = new LocalBrowserFactory(configuration);
applicationFactory = new LocalBrowserFactory(ServiceProvider);
}
SetFactory(browserFactory);

BrowserFactory = applicationFactory;
}

/// <summary>
/// Sets custom browser factory.
/// Resolves required service from <see cref="ServiceProvider"/>
/// </summary>
/// <param name="browserFactory">Custom implementation of <see cref="IBrowserFactory"/></param>
public static void SetFactory(IBrowserFactory browserFactory)
/// <typeparam name="T">type of required service</typeparam>
/// <exception cref="InvalidOperationException">Thrown if there is no service of the required type.</exception>
/// <returns></returns>
public static T GetRequiredService<T>()
{
BrowserFactoryContainer.Value = browserFactory;
return ServiceProvider.GetRequiredService<T>();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Aquality.Selenium.Logging;
using Aquality.Selenium.Core.Localization;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using System;
Expand All @@ -17,14 +17,14 @@ internal BrowserNavigation(RemoteWebDriver driver)
this.driver = driver;
}

private Logger Logger => Logger.Instance;
private LocalizationLogger Logger => BrowserManager.GetRequiredService<LocalizationLogger>();

/// <summary>
/// Navigates back.
/// </summary>
public void Back()
{
Logger.InfoLoc("loc.browser.back");
Logger.Info("loc.browser.back");
driver.Navigate().Back();
}

Expand All @@ -33,7 +33,7 @@ public void Back()
/// </summary>
public void Forward()
{
Logger.InfoLoc("loc.browser.forward");
Logger.Info("loc.browser.forward");
driver.Navigate().Forward();
}

Expand Down Expand Up @@ -62,13 +62,13 @@ public void GoToUrl(Uri url)
/// </summary>
public void Refresh()
{
Logger.InfoLoc("loc.browser.refresh");
Logger.Info("loc.browser.refresh");
driver.Navigate().Refresh();
}

private void InfoLocNavigate(string url)
{
Logger.InfoLoc("loc.browser.navigate", url);
Logger.Info("loc.browser.navigate", url);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Aquality.Selenium.Utilities;
using Aquality.Selenium.Core.Utilities;
using System.Reflection;

namespace Aquality.Selenium.Browsers
Expand Down
Loading

0 comments on commit 2fa3f91

Please sign in to comment.