Skip to content

Commit

Permalink
override default container (#154)
Browse files Browse the repository at this point in the history
* added possibility to override default container with services
added unit tests

* set ParallelScope.None for CustomConfigurationTests

* fixed parallel run for Custom Configuration

* removed cast Startup to BrowserStartup

* added dot

* removed reduntant empty line

* updated registration of BrowserFactory
  • Loading branch information
knysh authored Dec 12, 2019
1 parent 81fe09f commit 2e4b09c
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Aquality.Selenium.Core" Version="0.2.2" />
<PackageReference Include="Aquality.Selenium.Core" Version="0.2.5" />
<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
69 changes: 25 additions & 44 deletions Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserManager.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
using Aquality.Selenium.Elements;
using Aquality.Selenium.Elements.Interfaces;
using Microsoft.Extensions.DependencyInjection;
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
{
Expand All @@ -19,6 +11,7 @@ namespace Aquality.Selenium.Browsers
/// </summary>
public class BrowserManager : ApplicationManager<Browser>
{
private static readonly ThreadLocal<BrowserStartup> BrowserStartupContainer = new ThreadLocal<BrowserStartup>(() => new BrowserStartup());
private static readonly ThreadLocal<IBrowserFactory> BrowserFactoryContainer = new ThreadLocal<IBrowserFactory>();

/// <summary>
Expand All @@ -27,27 +20,28 @@ public class BrowserManager : ApplicationManager<Browser>
/// <value>Instance of desired browser.</value>
public static Browser Browser
{
get
{
return GetApplication(StartBrowserFunction, () => RegisterServices(services => Browser));
}
set
{
SetApplication(value);
}
get => GetApplication(StartBrowserFunction, ConfigureServices);
set => SetApplication(value);
}

private static Func<IServiceProvider, Browser> StartBrowserFunction => services => BrowserFactory.Browser;

public static IServiceProvider ServiceProvider
{
get
{
return GetServiceProvider(services => Browser, () => RegisterServices(services => Browser));
}
set
get => GetServiceProvider(services => Browser, ConfigureServices);
set => SetServiceProvider(value);
}

/// <summary>
/// Method which allow user to override or add custom services.
/// </summary>
/// <param name="startup"><see cref="BrowserStartup"/>> object with custom or overriden services.</param>
public static void SetStartup(BrowserStartup startup)
{
if (startup != null)
{
SetServiceProvider(value);
BrowserStartupContainer.Value = startup;
SetServiceProvider(ConfigureServices().BuildServiceProvider());
}
}

Expand All @@ -62,30 +56,12 @@ public static IBrowserFactory BrowserFactory
{
SetDefaultFactory();
}

return BrowserFactoryContainer.Value;
}
set
{
BrowserFactoryContainer.Value = 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.
Expand All @@ -109,12 +85,17 @@ public static void SetDefaultFactory()
/// <summary>
/// Resolves required service from <see cref="ServiceProvider"/>
/// </summary>
/// <typeparam name="T">type of required service</typeparam>
/// <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>()
{
return ServiceProvider.GetRequiredService<T>();
}

private static IServiceCollection ConfigureServices()
{
return BrowserStartupContainer.Value.ConfigureServices(new ServiceCollection(), services => Browser);
}
}
}
36 changes: 36 additions & 0 deletions Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserStartup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using Aquality.Selenium.Elements;
using Aquality.Selenium.Elements.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using System;
using Aquality.Selenium.Core.Localization;
using Aquality.Selenium.Core.Logging;
using System.Reflection;
using Aquality.Selenium.Core.Applications;
using Aquality.Selenium.Configurations;
using Aquality.Selenium.Core.Configurations;
using CoreElementFactory = Aquality.Selenium.Core.Elements.Interfaces.IElementFactory;
using CoreTimeoutConfiguration = Aquality.Selenium.Core.Configurations.ITimeoutConfiguration;
using ILoggerConfiguration = Aquality.Selenium.Core.Configurations.ILoggerConfiguration;
using ITimeoutConfiguration = Aquality.Selenium.Configurations.ITimeoutConfiguration;
using TimeoutConfiguration = Aquality.Selenium.Configurations.TimeoutConfiguration;

namespace Aquality.Selenium.Browsers
{
public class BrowserStartup : Startup
{
public override IServiceCollection ConfigureServices(IServiceCollection services, Func<IServiceProvider, IApplication> applicationProvider,
ISettingsFile settings = null)
{
settings = settings ?? GetSettings();
base.ConfigureServices(services, applicationProvider, settings);
services.AddTransient<IElementFactory, ElementFactory>();
services.AddTransient<CoreElementFactory, ElementFactory>();
services.AddSingleton<ITimeoutConfiguration>(serviceProvider => new TimeoutConfiguration(settings));
services.AddSingleton<CoreTimeoutConfiguration>(serviceProvider => new TimeoutConfiguration(settings));
services.AddSingleton<IBrowserProfile>(serviceProvider => new BrowserProfile(settings));
services.AddSingleton(serviceProvider => new LocalizationManager(serviceProvider.GetRequiredService<ILoggerConfiguration>(), serviceProvider.GetRequiredService<Logger>(), Assembly.GetExecutingAssembly()));
services.AddTransient(serviceProvider => BrowserManager.BrowserFactory);
return services;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Aquality.Selenium.Tests.Integration
[TestFixture]
[Parallelizable(ParallelScope.All)]
internal class UITest
{
{
[TearDown]
public void CleanUp()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using System;
using Aquality.Selenium.Browsers;
using Aquality.Selenium.Core.Applications;
using Aquality.Selenium.Core.Configurations;
using Microsoft.Extensions.DependencyInjection;
using NUnit.Framework;

namespace Aquality.Selenium.Tests.Unit.Configuration
{
[TestFixture]
[Parallelizable(ParallelScope.All)]
internal class CustomConfigurationTests
{
private const string SpecialLoggerLanguage = "SpecialLoggerLanguage";
private const string SpecialCustomValue = "SpecialCustomValue";
private static readonly TimeSpan DefaultCommandTimeout = TimeSpan.FromSeconds(60);

[SetUp]
public static void Before()
{
BrowserManager.SetStartup(new CustomStartup());
}

[Test]
public void Should_BeAbleOverrideDependencies_AndGetCustomService()
{
Assert.AreEqual(SpecialLoggerLanguage, BrowserManager.GetRequiredService<ILoggerConfiguration>().Language, "Configuration value should be overriden.");
}

[Test]
public void Should_BeAbleAdd_CustomService()
{
Assert.AreEqual(SpecialCustomValue, BrowserManager.GetRequiredService<ICustomService>().CustomValue, "Custom service should have value");
}

[Test]
public void Should_BeAbleGet_DefaultService()
{
Assert.AreEqual(DefaultCommandTimeout, BrowserManager.GetRequiredService<ITimeoutConfiguration>().Command, "Default service value should have default value");
}

[TearDown]
public static void After()
{
BrowserManager.SetStartup(new BrowserStartup());
}

private class CustomLoggerConfiguration : ILoggerConfiguration
{
public string Language { get; } = SpecialLoggerLanguage;
}

private interface ICustomService
{
string CustomValue { get; }
}

private class CustomService : ICustomService
{
public string CustomValue { get; } = SpecialCustomValue;
}

private class CustomStartup : BrowserStartup
{
public override IServiceCollection ConfigureServices(IServiceCollection services, Func<IServiceProvider, IApplication> applicationProvider, ISettingsFile settings = null)
{
settings = GetSettings();
base.ConfigureServices(services, applicationProvider, settings);
services.AddSingleton<ILoggerConfiguration>(new CustomLoggerConfiguration());
services.AddTransient<ICustomService, CustomService>();
return services;
}
}
}
}

0 comments on commit 2e4b09c

Please sign in to comment.