Skip to content

Commit ff674a7

Browse files
authored
added ISettingsFile (#20) +semver: feature
* repare a basic implementation of core functionality #1 Author: Alaksiej Mialeška <[email protected]> * replace GetText() with property. make constants internal * fix logging and settings resources. Add some tests * Fix ConditionalWait and tests * add general tests and some documentation. Enhanced Startup for flexibility * fix review comments in LoggerConfiguration and Element * removed internal access modifiers * Set up CI with Azure Pipelines [skip ci] * Update azure-pipelines.yml for Azure Pipelines * Update azure-pipelines.yml for Azure Pipelines * fix webDriverVersion for tests * fix WebDriverVersion dowloaded for tests at azure pipeline. closes #3 * Update azure-pipelines.yml for Azure Pipelines * fix webDriverVersion * fix yml file * Add tests for WinAppDriver and ElementFactory to resolve #5. Related to #6. Corrected Element's public interface * Update azure-pipelines.yml for Azure Pipelines use WinAppDriver task * Update azure-pipelines.yml for Azure Pipelines * replace calc application * Fixed ElementFactoryTests for new application * Feature/abstract application manager (#8) * Extract abstract ApplicationManager from WIndowsApp/ApplicationManager * reworked ApplicationManager for chrome app tests * Enhanced abstract ApplicationManager, add ability to provide custom dependencies. Create tests to ensure that ApplicationManager could have custom dependencies registered in container. * #11 added tests to check overriden settings * #15 added test for ovveriding config with env vars * #15 added fix for Azure * #15 added possibility to get Dictionary from JsonFile with overriden values with Env variables * #15 renamed some method * #15 removed Parallelizable for EnvConfigurationTests removed throw exception in IsValuePresent * #15 added debug test * #15 removed debug test * #15 added string.Empty * #9 moved JsonFile to an interface and renamed to JsonSettingsFile * #9 updated doc and tests with ISettingsFile * #9 fix GetSettings method * #9 fixed comments and sonar issues
1 parent 0b05407 commit ff674a7

File tree

15 files changed

+328
-92
lines changed

15 files changed

+328
-92
lines changed

Aquality.Selenium.Core/src/Aquality.Selenium.Core/Applications/Startup.cs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,49 +16,56 @@ namespace Aquality.Selenium.Core.Applications
1616
/// </summary>
1717
public class Startup
1818
{
19+
private ISettingsFile settingsFile;
20+
1921
/// <summary>
2022
/// Used to configure dependencies for services of the current library
2123
/// </summary>
2224
/// <param name="services">Collection of service descriptors</param>
2325
/// <param name="applicationProvider">function that provides an instance of <see cref="IApplication"/></param>
24-
/// <param name="settingsFile"><see cref="JsonFile"/> with settings for configuration of dependencies.
26+
/// <param name="settings">File with settings for configuration of dependencies.
2527
/// Pass the result of <see cref="GetSettings"/> if you need to get settings from the embedded resource of your project.</param>
26-
public void ConfigureServices(IServiceCollection services, Func<IServiceProvider, IApplication> applicationProvider, JsonFile settingsFile = null)
28+
public void ConfigureServices(IServiceCollection services, Func<IServiceProvider, IApplication> applicationProvider, ISettingsFile settings = null)
2729
{
28-
var settings = settingsFile ?? GetSettings();
30+
settingsFile = settings ?? GetSettings();
2931
services.AddScoped(applicationProvider);
3032

31-
services.AddSingleton<ITimeoutConfiguration>(new TimeoutConfiguration(settings));
33+
services.AddSingleton<ITimeoutConfiguration>(new TimeoutConfiguration(settingsFile));
3234
services.AddTransient<ConditionalWait>();
33-
services.AddSingleton<ILoggerConfiguration>(new LoggerConfiguration(settings));
35+
services.AddSingleton<ILoggerConfiguration>(new LoggerConfiguration(settingsFile));
3436
services.AddSingleton(Logger.Instance);
3537
services.AddSingleton<LocalizationManager>();
3638
services.AddSingleton<LocalizationLogger>();
37-
services.AddSingleton<IRetryConfiguration>(new RetryConfiguration(settings));
39+
services.AddSingleton<IRetryConfiguration>(new RetryConfiguration(settingsFile));
3840
services.AddSingleton<ElementActionRetrier>();
3941

4042
services.AddTransient<IElementFinder, ElementFinder>();
4143
services.AddTransient<IElementFactory, ElementFactory>();
4244
}
4345

4446
/// <summary>
45-
/// Provides a <see cref="JsonFile"/> with settings.
46-
/// If "profile" environment variable is defined, it will be used in the name : $"settings.{profile}.json";
47-
/// Otherwise, will use default name of settings file: "settings.json".
48-
/// Will look for the resource file (copied to binaries/Resources/ folder);
47+
/// Provides a <see cref="ISettingsFile"/> with settings.
48+
/// Value is set in <see cref="ConfigureServices"/>
49+
/// Otherwise, will use default JSON settings file with name: "settings.{profile}.json".
50+
/// Default settings will look for the resource file (copied to binaries/Resources/ folder);
4951
/// If not found, will look for embedded resource in the calling assembly of this method
5052
/// </summary>
51-
/// <returns>An instance of settings JsonFile</returns>
52-
public JsonFile GetSettings()
53+
/// <returns>An instance of settings</returns>
54+
public ISettingsFile GetSettings()
5355
{
54-
var profileNameFromEnvironment = EnvironmentConfiguration.GetVariable("profile");
55-
var settingsProfile = profileNameFromEnvironment == null ? "settings.json" : $"settings.{profileNameFromEnvironment}.json";
56-
Logger.Instance.Debug($"Get settings from: {settingsProfile}");
56+
if (settingsFile == null)
57+
{
58+
var profileNameFromEnvironment = EnvironmentConfiguration.GetVariable("profile");
59+
var settingsProfile = profileNameFromEnvironment == null ? "settings.json" : $"settings.{profileNameFromEnvironment}.json";
60+
Logger.Instance.Debug($"Get settings from: {settingsProfile}");
61+
62+
var jsonFile = FileReader.IsResourceFileExist(settingsProfile)
63+
? new JsonSettingsFile(settingsProfile)
64+
: new JsonSettingsFile($"Resources.{settingsProfile}", Assembly.GetCallingAssembly());
65+
return jsonFile;
66+
}
5767

58-
var jsonFile = FileReader.IsResourceFileExist(settingsProfile)
59-
? new JsonFile(settingsProfile)
60-
: new JsonFile($"Resources.{settingsProfile}", Assembly.GetCallingAssembly());
61-
return jsonFile;
68+
return settingsFile;
6269
}
6370
}
6471
}

Aquality.Selenium.Core/src/Aquality.Selenium.Core/Configurations/LoggerConfiguration.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ public class LoggerConfiguration : ILoggerConfiguration
1010
private const string DefaultLanguage = "en";
1111

1212
/// <summary>
13-
/// Instantiates class using JSON file with general settings.
13+
/// Instantiates class using <see cref="ISettingsFile"/> with general settings.
1414
/// </summary>
15-
/// <param name="settingsFile">JSON settings file.</param>
16-
public LoggerConfiguration(JsonFile settingsFile)
15+
/// <param name="settingsFile">Settings file</param>
16+
public LoggerConfiguration(ISettingsFile settingsFile)
1717
{
1818
Language = settingsFile.GetValueOrDefault(".logger.language", DefaultLanguage);
1919
}

Aquality.Selenium.Core/src/Aquality.Selenium.Core/Configurations/RetryConfiguration.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using Aquality.Selenium.Core.Utilities;
2-
using System;
1+
using System;
32

43
namespace Aquality.Selenium.Core.Configurations
54
{
@@ -8,13 +7,13 @@ namespace Aquality.Selenium.Core.Configurations
87
/// </summary>
98
public class RetryConfiguration : IRetryConfiguration
109
{
11-
private readonly JsonFile settingsFile;
10+
private readonly ISettingsFile settingsFile;
1211

1312
/// <summary>
14-
/// Instantiates class using JSON file with general settings.
13+
/// Instantiates class using <see cref="ISettingsFile"/> with general settings.
1514
/// </summary>
16-
/// <param name="settingsFile">JSON settings file.</param>
17-
public RetryConfiguration(JsonFile settingsFile)
15+
/// <param name="settingsFile">Settings file.</param>
16+
public RetryConfiguration(ISettingsFile settingsFile)
1817
{
1918
this.settingsFile = settingsFile;
2019

Aquality.Selenium.Core/src/Aquality.Selenium.Core/Configurations/TimeoutConfiguration.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using Aquality.Selenium.Core.Utilities;
2-
using System;
1+
using System;
32

43
namespace Aquality.Selenium.Core.Configurations
54
{
@@ -8,13 +7,13 @@ namespace Aquality.Selenium.Core.Configurations
87
/// </summary>
98
public class TimeoutConfiguration : ITimeoutConfiguration
109
{
11-
private readonly JsonFile settingsFile;
10+
private readonly ISettingsFile settingsFile;
1211

1312
/// <summary>
14-
/// Instantiates class using JSON file with general settings.
13+
/// Instantiates class using <see cref="ISettingsFile"/> with general settings.
1514
/// </summary>
16-
/// <param name="settingsFile">JSON settings file.</param>
17-
public TimeoutConfiguration(JsonFile settingsFile)
15+
/// <param name="settingsFile">Settings file.</param>
16+
public TimeoutConfiguration(ISettingsFile settingsFile)
1817
{
1918
this.settingsFile = settingsFile;
2019
Implicit = GetTimeoutFromSeconds(nameof(Implicit));

Aquality.Selenium.Core/src/Aquality.Selenium.Core/Localization/LocalizationManager.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ namespace Aquality.Selenium.Core.Localization
1111
public class LocalizationManager
1212
{
1313
private const string LangResource = "Resources.Localization.{0}.json";
14-
private readonly JsonFile localizationFile;
14+
private readonly JsonSettingsFile localizationFile;
1515
private readonly Logger logger;
1616

1717
public LocalizationManager(ILoggerConfiguration loggerConfiguration, Logger logger, Assembly assembly = null)
1818
{
1919
var language = loggerConfiguration.Language;
20-
localizationFile = new JsonFile(string.Format(LangResource, language.ToLower()), assembly ?? Assembly.GetExecutingAssembly());
20+
localizationFile = new JsonSettingsFile(string.Format(LangResource, language.ToLower()), assembly ?? Assembly.GetExecutingAssembly());
2121
this.logger = logger;
2222
}
2323

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System.Collections.Generic;
2+
3+
namespace Aquality.Selenium.Core.Configurations
4+
{
5+
/// <summary>
6+
/// Describes reader of settings file.
7+
/// </summary>
8+
public interface ISettingsFile
9+
{
10+
/// <summary>
11+
/// Gets value from settings file.
12+
/// </summary>
13+
/// <typeparam name="T">Type of the value.</typeparam>
14+
/// <param name="path">Path to the value. Depending on file format, it can be jsonPath, xpath etc.</param>
15+
/// <returns>Value</returns>
16+
T GetValue<T>(string path);
17+
18+
/// <summary>
19+
/// Gets list of values from settings file.
20+
/// </summary>
21+
/// <typeparam name="T">Type of the values.</typeparam>
22+
/// <param name="path">Path to the values. Depending on file format, it can be jsonPath, xpath etc.</param>
23+
/// <returns>List of values</returns>
24+
IReadOnlyList<T> GetValueList<T>(string path);
25+
26+
/// <summary>
27+
/// Gets dictionary of keys and values from settings file.
28+
/// </summary>
29+
/// <typeparam name="T">Type of the values.</typeparam>
30+
/// <param name="path">Path to the values. Depending on file format, it can be jsonPath, xpath etc.</param>
31+
/// <returns>Dictionary of keys and values</returns>
32+
IReadOnlyDictionary<string, T> GetValueDictionary<T>(string path);
33+
34+
/// <summary>
35+
/// Checks if value exists in settings.
36+
/// </summary>
37+
/// <param name="path">Path to the values. Depending on file format, it can be jsonPath, xpath etc.</param>
38+
/// <returns>True if exists, false otherwise.</returns>
39+
bool IsValuePresent(string path);
40+
}
41+
}

Aquality.Selenium.Core/src/Aquality.Selenium.Core/Utilities/JsonFileExtensions.cs

Lines changed: 0 additions & 22 deletions
This file was deleted.

Aquality.Selenium.Core/src/Aquality.Selenium.Core/Utilities/JsonFile.cs renamed to Aquality.Selenium.Core/src/Aquality.Selenium.Core/Utilities/JsonSettingsFile.cs

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.IO;
55
using System.Linq;
66
using System.Reflection;
7+
using Aquality.Selenium.Core.Configurations;
78
using Aquality.Selenium.Core.Logging;
89
using Newtonsoft.Json;
910
using Newtonsoft.Json.Linq;
@@ -15,7 +16,7 @@ namespace Aquality.Selenium.Core.Utilities
1516
/// Note that the value can be overriden via Environment variable with the same name
1617
/// (e.g. for json path ".timeouts.timeoutScript" you can set environment variable "timeouts.timeoutScript"
1718
/// </summary>
18-
public class JsonFile
19+
public class JsonSettingsFile : ISettingsFile
1920
{
2021
private readonly string fileContent;
2122
private readonly string resourceName;
@@ -26,7 +27,7 @@ public class JsonFile
2627
/// Inistantiates class using desired JSON fileinfo.
2728
/// </summary>
2829
/// <param name="fileInfo">JSON fileinfo.</param>
29-
public JsonFile(FileInfo fileInfo)
30+
public JsonSettingsFile(FileInfo fileInfo)
3031
{
3132
resourceName = fileInfo.Name;
3233
fileContent = FileReader.GetTextFromFile(fileInfo);
@@ -36,7 +37,7 @@ public JsonFile(FileInfo fileInfo)
3637
/// Inistantiates class using desired resource file info.
3738
/// </summary>
3839
/// <param name="resourceFileName"></param>
39-
public JsonFile(string resourceFileName)
40+
public JsonSettingsFile(string resourceFileName)
4041
{
4142
resourceName = resourceFileName;
4243
fileContent = FileReader.GetTextFromResource(resourceFileName);
@@ -47,7 +48,7 @@ public JsonFile(string resourceFileName)
4748
/// </summary>
4849
/// <param name="embededResourceName">Embeded resource name</param>
4950
/// <param name="assembly">Assembly which resource belongs to</param>
50-
public JsonFile(string embededResourceName, Assembly assembly)
51+
public JsonSettingsFile(string embededResourceName, Assembly assembly)
5152
{
5253
resourceName = embededResourceName;
5354
fileContent = FileReader.GetTextFromEmbeddedResource(embededResourceName, assembly);
@@ -58,20 +59,20 @@ public JsonFile(string embededResourceName, Assembly assembly)
5859
/// Note that the value can be overriden via Environment variable with the same name
5960
/// (e.g. for json path ".timeouts.timeoutScript" you can set environment variable "timeouts.timeoutScript")
6061
/// </summary>
61-
/// <param name="jsonPath">Relative JsonPath to the value.</param>
62+
/// <param name="path">Relative JsonPath to the value.</param>
6263
/// <typeparam name="T">Type of the value.</typeparam>
6364
/// <returns>Value from JSON/Environment by JsonPath.</returns>
6465
/// <exception cref="ArgumentException">Throws when there is no value found by jsonPath in desired JSON file.</exception>
65-
public T GetValue<T>(string jsonPath)
66+
public T GetValue<T>(string path)
6667
{
67-
var envValue = GetEnvironmentValue(jsonPath);
68+
var envValue = GetEnvironmentValue(path);
6869
if (envValue != null)
6970
{
7071
return ConvertEnvVar(() => (T) TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(envValue),
71-
envValue, jsonPath);
72+
envValue, path);
7273
}
7374

74-
var node = GetJsonNode(jsonPath);
75+
var node = GetJsonNode(path);
7576
return node.ToObject<T>();
7677
}
7778

@@ -80,38 +81,38 @@ public T GetValue<T>(string jsonPath)
8081
/// Note that the value can be overriden via Environment variable with the same name; values must be separated by ','
8182
/// (e.g. for json path ".driverSettings.chrome.startArguments" you can set environment variable "driverSettings.chrome.startArguments")
8283
/// </summary>
83-
/// <param name="jsonPath">Relative JsonPath to the values.</param>
84+
/// <param name="path">Relative JsonPath to the values.</param>
8485
/// <typeparam name="T">Type of the value.</typeparam>
8586
/// <returns>Value from JSON/Environment by JsonPath.</returns>
8687
/// <exception cref="ArgumentException">Throws when there are no values found by jsonPath in desired JSON file.</exception>
87-
public IList<T> GetValueList<T>(string jsonPath)
88+
public IReadOnlyList<T> GetValueList<T>(string path)
8889
{
89-
var envValue = GetEnvironmentValue(jsonPath);
90+
var envValue = GetEnvironmentValue(path);
9091
if (envValue != null)
9192
{
9293
return ConvertEnvVar(() =>
9394
{
9495
return envValue.Split(',').Select(value => (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(value.Trim())).ToList();
95-
}, envValue, jsonPath);
96+
}, envValue, path);
9697
}
9798

98-
var node = GetJsonNode(jsonPath);
99-
return node.ToObject<IList<T>>();
99+
var node = GetJsonNode(path);
100+
return node.ToObject<IReadOnlyList<T>>();
100101
}
101102

102103
/// <summary>
103104
/// Gets dictionary of values from JSON.
104105
/// Note that the value can be overriden via Environment variable with the same name;
105106
/// (e.g. for json path ".timeouts.timeoutImplicit" you can set environment variable ".timeouts.timeoutImplicit")
106107
/// </summary>
107-
/// <param name="jsonPath">Relative JsonPath to the values.</param>
108+
/// <param name="path">Relative JsonPath to the values.</param>
108109
/// <typeparam name="T">Type of the value.</typeparam>
109110
/// <returns>Value from JSON/Environment by JsonPath.</returns>
110111
/// <exception cref="ArgumentException">Throws when there are no values found by jsonPath in desired JSON file.</exception>
111-
public IReadOnlyDictionary<string, T> GetValueDictionary<T>(string jsonPath)
112+
public IReadOnlyDictionary<string, T> GetValueDictionary<T>(string path)
112113
{
113114
var dict = new Dictionary<string, T>();
114-
var node = GetJsonNode(jsonPath);;
115+
var node = GetJsonNode(path);
115116
foreach (var child in node.Children<JProperty>())
116117
{
117118
dict.Add(child.Name, GetValue<T>($".{child.Path}"));
@@ -123,11 +124,11 @@ public IReadOnlyDictionary<string, T> GetValueDictionary<T>(string jsonPath)
123124
/// <summary>
124125
/// Checks whether value present on JSON/Environment by JsonPath or not.
125126
/// </summary>
126-
/// <param name="jsonPath">Relative JsonPath to the object.</param>
127+
/// <param name="path">Relative JsonPath to the object.</param>
127128
/// <returns>True if present and false otherwise.</returns>
128-
public bool IsValuePresent(string jsonPath)
129+
public bool IsValuePresent(string path)
129130
{
130-
return GetEnvironmentValue(jsonPath) != null || JsonObject.SelectToken(jsonPath) != null;
131+
return GetEnvironmentValue(path) != null || JsonObject.SelectToken(path) != null;
131132
}
132133

133134
private static string GetEnvironmentValue(string jsonPath)

0 commit comments

Comments
 (0)