diff --git a/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj b/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj index 7896e84d..82d6cad0 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj +++ b/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj @@ -59,7 +59,7 @@ - + diff --git a/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserManager.cs b/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserManager.cs index a7b6a4fb..fa554f85 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserManager.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserManager.cs @@ -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 { @@ -19,6 +11,7 @@ namespace Aquality.Selenium.Browsers /// public class BrowserManager : ApplicationManager { + private static readonly ThreadLocal BrowserStartupContainer = new ThreadLocal(() => new BrowserStartup()); private static readonly ThreadLocal BrowserFactoryContainer = new ThreadLocal(); /// @@ -27,27 +20,28 @@ public class BrowserManager : ApplicationManager /// Instance of desired browser. public static Browser Browser { - get - { - return GetApplication(StartBrowserFunction, () => RegisterServices(services => Browser)); - } - set - { - SetApplication(value); - } + get => GetApplication(StartBrowserFunction, ConfigureServices); + set => SetApplication(value); } private static Func 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); + } + + /// + /// Method which allow user to override or add custom services. + /// + /// > object with custom or overriden services. + public static void SetStartup(BrowserStartup startup) + { + if (startup != null) { - SetServiceProvider(value); + BrowserStartupContainer.Value = startup; + SetServiceProvider(ConfigureServices().BuildServiceProvider()); } } @@ -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 browserSupplier) - { - var services = new ServiceCollection(); - var startup = new Startup(); - var settingsFile = startup.GetSettings(); - startup.ConfigureServices(services, browserSupplier, settingsFile); - services.AddTransient(); - services.AddTransient(); - services.AddSingleton(serviceProvider => new TimeoutConfiguration(settingsFile)); - services.AddSingleton(serviceProvider => new TimeoutConfiguration(settingsFile)); - services.AddSingleton(serviceProvider => new BrowserProfile(settingsFile)); - services.AddSingleton(serviceProvider => new LocalizationManager(serviceProvider.GetRequiredService(), serviceProvider.GetRequiredService(), Assembly.GetExecutingAssembly())); - services.AddTransient(serviceProvider => BrowserFactory); - return services; - } - /// /// Sets default factory responsible for browser creation. /// RemoteBrowserFactory if value set in configuration and LocalBrowserFactory otherwise. @@ -109,12 +85,17 @@ public static void SetDefaultFactory() /// /// Resolves required service from /// - /// type of required service + /// type of required service. /// Thrown if there is no service of the required type. /// public static T GetRequiredService() { return ServiceProvider.GetRequiredService(); } + + private static IServiceCollection ConfigureServices() + { + return BrowserStartupContainer.Value.ConfigureServices(new ServiceCollection(), services => Browser); + } } } diff --git a/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserStartup.cs b/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserStartup.cs new file mode 100644 index 00000000..81565aae --- /dev/null +++ b/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserStartup.cs @@ -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 applicationProvider, + ISettingsFile settings = null) + { + settings = settings ?? GetSettings(); + base.ConfigureServices(services, applicationProvider, settings); + services.AddTransient(); + services.AddTransient(); + services.AddSingleton(serviceProvider => new TimeoutConfiguration(settings)); + services.AddSingleton(serviceProvider => new TimeoutConfiguration(settings)); + services.AddSingleton(serviceProvider => new BrowserProfile(settings)); + services.AddSingleton(serviceProvider => new LocalizationManager(serviceProvider.GetRequiredService(), serviceProvider.GetRequiredService(), Assembly.GetExecutingAssembly())); + services.AddTransient(serviceProvider => BrowserManager.BrowserFactory); + return services; + } + } +} diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/UITest.cs b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/UITest.cs index db4d7800..d4d5788a 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/UITest.cs +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/UITest.cs @@ -7,7 +7,7 @@ namespace Aquality.Selenium.Tests.Integration [TestFixture] [Parallelizable(ParallelScope.All)] internal class UITest - { + { [TearDown] public void CleanUp() { diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Unit/Configuration/CustomConfigurationTests.cs b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Unit/Configuration/CustomConfigurationTests.cs new file mode 100644 index 00000000..6272f361 --- /dev/null +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Unit/Configuration/CustomConfigurationTests.cs @@ -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().Language, "Configuration value should be overriden."); + } + + [Test] + public void Should_BeAbleAdd_CustomService() + { + Assert.AreEqual(SpecialCustomValue, BrowserManager.GetRequiredService().CustomValue, "Custom service should have value"); + } + + [Test] + public void Should_BeAbleGet_DefaultService() + { + Assert.AreEqual(DefaultCommandTimeout, BrowserManager.GetRequiredService().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 applicationProvider, ISettingsFile settings = null) + { + settings = GetSettings(); + base.ConfigureServices(services, applicationProvider, settings); + services.AddSingleton(new CustomLoggerConfiguration()); + services.AddTransient(); + return services; + } + } + } +}