Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
*.swp
*.*~
project.lock.json
.DS_Store
*.pyc
nupkg/

# Visual Studio Code
.vscode

# Rider
.idea

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
msbuild.log
msbuild.err
msbuild.wrn

# Visual Studio 2015
.vs/

Log/
39 changes: 39 additions & 0 deletions Aquality.Selenium.Core/Aquality.Selenium.Core.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29009.5
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{613FE616-73B3-4C48-A84A-86C635363482}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aquality.Selenium.Core", "src\Aquality.Selenium.Core\Aquality.Selenium.Core.csproj", "{DCE7E884-9495-4B8B-BF82-2CB1AAEF8704}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{020FB8C3-77FD-48AE-BDD4-69B5186C0A2E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aquality.Selenium.Core.Tests", "tests\Aquality.Selenium.Core.Tests\Aquality.Selenium.Core.Tests.csproj", "{BE6E2E8F-597C-46C4-BC3B-259A74FBA5C7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DCE7E884-9495-4B8B-BF82-2CB1AAEF8704}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DCE7E884-9495-4B8B-BF82-2CB1AAEF8704}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DCE7E884-9495-4B8B-BF82-2CB1AAEF8704}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DCE7E884-9495-4B8B-BF82-2CB1AAEF8704}.Release|Any CPU.Build.0 = Release|Any CPU
{BE6E2E8F-597C-46C4-BC3B-259A74FBA5C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BE6E2E8F-597C-46C4-BC3B-259A74FBA5C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BE6E2E8F-597C-46C4-BC3B-259A74FBA5C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BE6E2E8F-597C-46C4-BC3B-259A74FBA5C7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{DCE7E884-9495-4B8B-BF82-2CB1AAEF8704} = {613FE616-73B3-4C48-A84A-86C635363482}
{BE6E2E8F-597C-46C4-BC3B-259A74FBA5C7} = {020FB8C3-77FD-48AE-BDD4-69B5186C0A2E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E4DEE5C3-7FA4-4D43-A57E-1E9EE245FE98}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Threading;

namespace Aquality.Selenium.Core.Applications
{
public abstract class ApplicationManager<TManager, TApplication>
where TManager : ApplicationManager<TManager, TApplication>
where TApplication : class, IApplication
{
private static readonly ThreadLocal<TApplication> AppContainer = new ThreadLocal<TApplication>();
private static readonly ThreadLocal<IServiceProvider> ServiceProviderContainer = new ThreadLocal<IServiceProvider>();

public static bool IsStarted => AppContainer.IsValueCreated && AppContainer.Value.Driver.SessionId != null;

protected static TApplication GetApplication(Func<IServiceProvider, TApplication> startApplicationFunction, IServiceCollection serviceCollection = null)
{
if (!IsStarted)
{
AppContainer.Value = startApplicationFunction(
GetServiceProvider(service => GetApplication(startApplicationFunction), serviceCollection));
}
return AppContainer.Value;
}

protected static IServiceProvider GetServiceProvider(Func<IServiceProvider, TApplication> applicationSupplier, IServiceCollection serviceCollection = null)
{
if (!ServiceProviderContainer.IsValueCreated)
{
var services = serviceCollection;
if (services == null)
{
services = new ServiceCollection();
new Startup().ConfigureServices(services, applicationSupplier);
}
ServiceProviderContainer.Value = services.BuildServiceProvider();
}
return ServiceProviderContainer.Value;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using OpenQA.Selenium.Remote;

namespace Aquality.Selenium.Core.Applications
{
/// <summary>
/// Interface of any application controlled by Selenium WebDriver API
/// </summary>
public interface IApplication
{
/// <summary>
/// Current instance of driver
/// </summary>
RemoteWebDriver Driver { get; }

/// <summary>
/// Sets implicit wait timeout to browser.
/// Method was extracted with purpose not to pass it to Driver if it is similar to previous value.
/// Simpliest implementation is: Driver.Manage().Timeouts().ImplicitlyWait = timeout
/// </summary>
/// <param name="timeout">timeout to set</param>
void SetImplicitWaitTimeout(TimeSpan timeout);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using Aquality.Selenium.Core.Configurations;
using Aquality.Selenium.Core.Elements;
using Aquality.Selenium.Core.Elements.Interfaces;
using Aquality.Selenium.Core.Localization;
using Aquality.Selenium.Core.Logging;
using Aquality.Selenium.Core.Utilities;
using Aquality.Selenium.Core.Waitings;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Reflection;

namespace Aquality.Selenium.Core.Applications
{
/// <summary>
/// Allows to resolve dependencies for all services in the Aquality.Selenium.Core library
/// </summary>
public class Startup
{
/// <summary>
/// Used to configure dependencies for services of the current library
/// </summary>
/// <param name="services">Collection of service descriptors</param>
/// <param name="applicationProvider">function that provides an instance of <see cref="IApplication"/></param>
/// <param name="settingsFile"><see cref="JsonFile"/> with settings for configuration of dependencies.
/// Pass the result of <see cref="GetSettings"/> if you need to get settings from the embedded resource of your project.</param>
public void ConfigureServices(IServiceCollection services, Func<IServiceProvider, IApplication> applicationProvider, JsonFile settingsFile = null)
{
var settings = settingsFile ?? GetSettings();
services.AddScoped(applicationProvider);

services.AddSingleton<ITimeoutConfiguration>(new TimeoutConfiguration(settings));
services.AddTransient<ConditionalWait>();
services.AddSingleton<ILoggerConfiguration>(new LoggerConfiguration(settings));
services.AddSingleton(Logger.Instance);
services.AddSingleton<LocalizationManager>();
services.AddSingleton<LocalizationLogger>();
services.AddSingleton<IRetryConfiguration>(new RetryConfiguration(settings));
services.AddSingleton<ElementActionRetrier>();

services.AddTransient<IElementFinder, ElementFinder>();
services.AddTransient<IElementFactory, ElementFactory>();
}

/// <summary>
/// Provides a <see cref="JsonFile"/> with settings.
/// If "profile" environment variable is defined, it will be used in the name : $"settings.{profile}.json";
/// Otherwise, will use default name of settings file: "settings.json".
/// Will look for the resource file (copied to binaries/Resources/ folder);
/// If not found, will look for embedded resource in the calling assembly of this method
/// </summary>
/// <returns>An instance of settings JsonFile</returns>
public JsonFile GetSettings()
{
var profileNameFromEnvironment = EnvironmentConfiguration.GetVariable("profile");
var settingsProfile = profileNameFromEnvironment == null ? "settings.json" : $"settings.{profileNameFromEnvironment}.json";
Logger.Instance.Debug($"Get settings from: {settingsProfile}");

var jsonFile = FileReader.IsResourceFileExist(settingsProfile)
? new JsonFile(settingsProfile)
: new JsonFile($"Resources.{settingsProfile}", Assembly.GetCallingAssembly());
return jsonFile;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>

<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<Authors>aquality automation committers</Authors>
<Company>aquality automation</Company>
<Description>Core functions for Selenium-based libraries for .NET</Description>
<PackageDescription>Core functions for Selenium-based libraries for .NET</PackageDescription>
<PackageLicenseExpression></PackageLicenseExpression>
<RepositoryUrl>https://github.com/aquality-automation/aquality-selenium-dotnet</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>selenium webdriver automation</PackageTags>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<Copyright>Copyright 2019 Aquality Automation</Copyright>
<IsPackable>true</IsPackable>
</PropertyGroup>

<ItemGroup>
<None Remove="Resources\Localization\be.json" />
<None Remove="Resources\Localization\en.json" />
<None Remove="Resources\Localization\ru.json" />
<None Remove="Resources\settings.json" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Resources\Localization\be.json" />
<EmbeddedResource Include="Resources\Localization\en.json" />
<EmbeddedResource Include="Resources\Localization\ru.json" />
<EmbeddedResource Include="Resources\settings.json" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\LICENSE">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.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" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Aquality.Selenium.Core.Configurations
{
/// <summary>
/// Describes logger configuration.
/// </summary>
public interface ILoggerConfiguration
{
/// <summary>
/// Gets language of framework.
/// </summary>
/// <value>Supported language.</value>
string Language { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;

namespace Aquality.Selenium.Core.Configurations
{
/// <summary>
/// Describes retry configuration.
/// </summary>
public interface IRetryConfiguration
{
/// <summary>
/// Gets the number of attempts during retry.
/// </summary>
/// <value>Number of retry attempts.</value>
int Number { get; }

/// <summary>
/// Gets the polling interval used in retry.
/// </summary>
/// <value>Polling interval for retry.</value>
TimeSpan PollingInterval { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;

namespace Aquality.Selenium.Core.Configurations
{
/// <summary>
/// Describes timeouts configuration.
/// </summary>
public interface ITimeoutConfiguration
{
/// <summary>
/// Gets WedDriver ImplicitWait timeout.
/// </summary>
TimeSpan Implicit { get; }

/// <summary>
/// Gets default ConditionalWait timeout.
/// </summary>
TimeSpan Condition { get; }

/// <summary>
/// Gets ConditionalWait polling interfal.
/// </summary>
TimeSpan PollingInterval { get; }

/// <summary>
/// Gets Command timeout.
/// </summary>
TimeSpan Command { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Aquality.Selenium.Core.Utilities;

namespace Aquality.Selenium.Core.Configurations
{
/// <summary>
/// Provides logger configuration
/// </summary>
public class LoggerConfiguration : ILoggerConfiguration
{
private const string defaultLanguage = "en";
private readonly JsonFile settingsFile;

/// <summary>
/// Instantiates class using JSON file with general settings.
/// </summary>
/// <param name="settingsFile">JSON settings file.</param>
public LoggerConfiguration(JsonFile settingsFile)
{
this.settingsFile = settingsFile;
}

public string Language => settingsFile.GetValueOrDefault(".logger.language", defaultLanguage);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Aquality.Selenium.Core.Utilities;
using System;

namespace Aquality.Selenium.Core.Configurations
{
/// <summary>
/// Provides retry configuration.
/// </summary>
public class RetryConfiguration : IRetryConfiguration
{
private readonly JsonFile settingsFile;

/// <summary>
/// Instantiates class using JSON file with general settings.
/// </summary>
/// <param name="settingsFile">JSON settings file.</param>
public RetryConfiguration(JsonFile settingsFile)
{
this.settingsFile = settingsFile;

Number = GetIntFromSettings(nameof(Number).ToLowerInvariant());
PollingInterval = TimeSpan.FromMilliseconds(GetIntFromSettings("pollingInterval"));
}

private int GetIntFromSettings(string name)
{
return settingsFile.GetValue<int>($".retry.{name}");
}

public int Number { get; }

public TimeSpan PollingInterval { get; }
}
}
Loading