Skip to content

Commit

Permalink
Feature/override setting with env vars (#16)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
knysh authored Sep 18, 2019
1 parent 4387a7f commit aa42f5e
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,17 @@ namespace Aquality.Selenium.Core.Configurations
/// </summary>
public class LoggerConfiguration : ILoggerConfiguration
{
private const string defaultLanguage = "en";
private readonly JsonFile settingsFile;
private const string DefaultLanguage = "en";

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

public string Language => settingsFile.GetValueOrDefault(".logger.language", defaultLanguage);
public string Language { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ public static string GetVariable(string key)
{
Environment.GetEnvironmentVariable(key),
Environment.GetEnvironmentVariable(key.ToLower()),
Environment.GetEnvironmentVariable(key.ToUpper())
Environment.GetEnvironmentVariable(key.ToUpper()),
//necessary for Azure
Environment.GetEnvironmentVariable(key.ToUpper().Replace('.', '_'))
};
return variables.FirstOrDefault(variable => variable != null);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using Aquality.Selenium.Core.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using Aquality.Selenium.Core.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Aquality.Selenium.Core.Utilities
{
Expand Down Expand Up @@ -67,23 +67,11 @@ public T GetValue<T>(string jsonPath)
var envValue = GetEnvironmentValue(jsonPath);
if (envValue != null)
{
Logger.Instance.Debug($"***** Using variable passed from environment {jsonPath.Substring(1)}={envValue}");
try
{
return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(envValue);
}
catch (ArgumentException ex)
{
var message = $"Value of '{jsonPath}' environment variable has incorrect format: {ex.Message}";
throw new ArgumentException(message);
}
return ConvertEnvVar(() => (T) TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(envValue),
envValue, jsonPath);
}

var node = GetJsonNode(jsonPath);
if (node == null)
{
throw new ArgumentException($"There is no value found by path '{jsonPath}' in JSON file '{resourceName}'");
}
return node.ToObject<T>();
}

Expand All @@ -101,24 +89,35 @@ public IList<T> GetValueList<T>(string jsonPath)
var envValue = GetEnvironmentValue(jsonPath);
if (envValue != null)
{
Logger.Instance.Debug($"***** Using variable passed from environment {jsonPath.Substring(1)}={envValue}");
try
return ConvertEnvVar(() =>
{
return envValue.Split(',').Select(value => (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(value.Trim())).ToList();
}
catch (ArgumentException ex)
{
var message = $"Value of '{jsonPath}' environment variable has incorrect format: {ex.Message}";
throw new ArgumentException(message);
}
}, envValue, jsonPath);
}

var node = GetJsonNode(jsonPath);
if (node == null)
return node.ToObject<IList<T>>();
}

/// <summary>
/// Gets dictionary of values from JSON.
/// Note that the value can be overriden via Environment variable with the same name;
/// (e.g. for json path ".timeouts.timeoutImplicit" you can set environment variable ".timeouts.timeoutImplicit")
/// </summary>
/// <param name="jsonPath">Relative JsonPath to the values.</param>
/// <typeparam name="T">Type of the value.</typeparam>
/// <returns>Value from JSON/Environment by JsonPath.</returns>
/// <exception cref="ArgumentException">Throws when there are no values found by jsonPath in desired JSON file.</exception>
public IReadOnlyDictionary<string, T> GetValueDictionary<T>(string jsonPath)
{
var dict = new Dictionary<string, T>();
var node = GetJsonNode(jsonPath);;
foreach (var child in node.Children<JProperty>())
{
throw new ArgumentException($"There are no values found by path '{jsonPath}' in JSON file '{resourceName}'");
dict.Add(child.Name, GetValue<T>($".{child.Path}"));
}
return node.ToObject<IList<T>>();

return dict;
}

/// <summary>
Expand All @@ -128,18 +127,37 @@ public IList<T> GetValueList<T>(string jsonPath)
/// <returns>True if present and false otherwise.</returns>
public bool IsValuePresent(string jsonPath)
{
return GetEnvironmentValue(jsonPath) != null || GetJsonNode(jsonPath) != null;
return GetEnvironmentValue(jsonPath) != null || JsonObject.SelectToken(jsonPath) != null;
}

private string GetEnvironmentValue(string jsonPath)
private static string GetEnvironmentValue(string jsonPath)
{
var key = jsonPath.Substring(1);
var key = jsonPath.Replace("['", ".").Replace("']", string.Empty).Substring(1);
return EnvironmentConfiguration.GetVariable(key);
}

private JToken GetJsonNode(string jsonPath)
{
return JsonObject.SelectToken(jsonPath);
var node = JsonObject.SelectToken(jsonPath);
if (node == null)
{
throw new ArgumentException($"There are no values found by path '{jsonPath}' in JSON file '{resourceName}'");
}
return node;
}

private static T ConvertEnvVar<T>(Func<T> convertMethod, string envValue, string jsonPath)
{
Logger.Instance.Debug($"***** Using variable passed from environment {jsonPath.Substring(1)}={envValue}");
try
{
return convertMethod();
}
catch (ArgumentException ex)
{
var message = $"Value of '{jsonPath}' environment variable has incorrect format: {ex.Message}";
throw new ArgumentException(message);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using Aquality.Selenium.Core.Configurations;
using NUnit.Framework;
using System;
using Microsoft.Extensions.DependencyInjection;

namespace Aquality.Selenium.Core.Tests.Configurations
{
[Parallelizable(ParallelScope.None)]
public class EnvConfigurationTests : TestWithoutApplication
{
private const string ProfileVariableName = "profile";
private const string ProfileName = "custom";

[SetUp]
public new void SetUp()
{
Environment.SetEnvironmentVariable(ProfileVariableName, ProfileName);
}

[TearDown]
public void CleanUp()
{
Environment.SetEnvironmentVariable(ProfileVariableName, null);
}

[Test]
public void Should_BePossible_ToOverrideTimeouts_WithEnvVariables()
{
const string testValue = "1000";
var expectedValueSec = TimeSpan.FromSeconds(1000);
var expectedValueMillis = TimeSpan.FromMilliseconds(1000);
const string messageTmp = "{0} timeout should be overridden with env variable";
Environment.SetEnvironmentVariable("timeouts.timeoutImplicit", testValue);
Environment.SetEnvironmentVariable("timeouts.timeoutCondition", testValue);
Environment.SetEnvironmentVariable("timeouts.timeoutPollingInterval", testValue);
Environment.SetEnvironmentVariable("timeouts.timeoutCommand", testValue);
base.SetUp();

var config = ServiceProvider.GetService<ITimeoutConfiguration>();
Assert.Multiple(() =>
{
Assert.AreEqual(expectedValueSec, config.Command, string.Format(messageTmp, "Command"));
Assert.AreEqual(expectedValueSec, config.Condition, string.Format(messageTmp, "Condition"));
Assert.AreEqual(expectedValueSec, config.Implicit, string.Format(messageTmp, "Implicit"));
Assert.AreEqual(expectedValueMillis, config.PollingInterval, string.Format(messageTmp, "PollingInterval"));
});
}

[Test]
public void Should_BePossible_ToOverrideRetryConfig_WithEnvVariables()
{
const string testValue = "1000";
var expectedInterval = TimeSpan.FromMilliseconds(1000);
const int expectedNumber = 1000;
const string messageTmp = "Retry value '{0}' should be overridden with env variable";
Environment.SetEnvironmentVariable("retry.number", testValue);
Environment.SetEnvironmentVariable("retry.pollingInterval", testValue);
base.SetUp();

var config = ServiceProvider.GetService<IRetryConfiguration>();
Assert.Multiple(() =>
{
Assert.AreEqual(expectedInterval, config.PollingInterval, string.Format(messageTmp, "PollingInterval"));
Assert.AreEqual(expectedNumber, config.Number, string.Format(messageTmp, "Number"));
});
}

[Test]
public void Should_BePossible_ToOverrideLoggerConfig_WithEnvVariables()
{
const string testValue = "testLang";
Environment.SetEnvironmentVariable("logger.language", testValue);
base.SetUp();

var config = ServiceProvider.GetService<ILoggerConfiguration>();
Assert.AreEqual(testValue, config.Language, "Logger language value should be overridden with env variable");
}
}
}

0 comments on commit aa42f5e

Please sign in to comment.