Skip to content

Commit

Permalink
feat: Add application configuration auto discovery from annotations
Browse files Browse the repository at this point in the history
Merge pull request #306 from DFE-Digital/feat/application-health
  • Loading branch information
killij authored Oct 25, 2023
2 parents 8d06226 + 316995f commit 82e76b1
Show file tree
Hide file tree
Showing 16 changed files with 649 additions and 228 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using NUnit.Framework;
using Childrens_Social_Care_CPD.Configuration;
using FluentAssertions;
using System.Linq;
using NSubstitute;

namespace Childrens_Social_Care_CPD_Tests.Configuration;

public partial class ConfigurationInformationTests
{
private IApplicationConfiguration _applicationConfiguration;

[SetUp]
public void Setup()
{
_applicationConfiguration = Substitute.For<IApplicationConfiguration>();
_applicationConfiguration.AzureEnvironment.Returns("dev");
}

[Test]
public void Required_Values_Are_Detected()
{
// arrange
_applicationConfiguration.AppVersion.Returns("foo");

// act
var sut = new ConfigurationInformation(_applicationConfiguration);
var actual = sut.ConfigurationInfo.Single(x => x.Name == "AppVersion");

// assert
actual.Required.Should().BeTrue();
actual.HasValue.Should().BeTrue();
}

[TestCase("")]
[TestCase(null)]
public void Missing_Values_Are_Detected(string value)
{
// arrange
_applicationConfiguration.AppVersion.Returns(value);

// act
var sut = new ConfigurationInformation(_applicationConfiguration);
var actual = sut.ConfigurationInfo.Single(x => x.Name == "AppVersion");

// assert
actual.Required.Should().BeTrue();
actual.HasValue.Should().BeFalse();
}

[Test]
public void Extraneous_Values_Are_Detected()
{
// arrange
_applicationConfiguration.ClarityProjectId.Returns("foo");

// act
var sut = new ConfigurationInformation(_applicationConfiguration);
var actual = sut.ConfigurationInfo.Single(x => x.Name == "ClarityProjectId");

// assert
actual.Required.Should().BeFalse();
actual.Extraneous.Should().BeTrue();
}

[Test]
public void Ignored_Values_Are_Detected()
{
// act
var sut = new ConfigurationInformation(_applicationConfiguration);
var actual = sut.ConfigurationInfo.SingleOrDefault(x => x.Name == "ContentfulPreviewHost");

// assert
actual.Should().BeNull();
}

[Test]
public void Sensitive_Values_Are_Obfuscated()
{
// arrange
var value = "sensitive value";
_applicationConfiguration.AzureEnvironment.Returns(ApplicationEnvironment.Production);
_applicationConfiguration.AppInsightsConnectionString.Returns(value);

// act
var sut = new ConfigurationInformation(_applicationConfiguration);
var actual = sut.ConfigurationInfo.Single(x => x.Name == "AppInsightsConnectionString");

// assert
actual.Value.Should().NotBe(value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
using NUnit.Framework;
using Childrens_Social_Care_CPD.Configuration;
using FluentAssertions;
using System.Linq;

namespace Childrens_Social_Care_CPD_Tests.Configuration;

public class RequiredForEnvironmentTests
{
private class TestConfiguration
{
public string PropertyHasNoRules { get; set; }

[RequiredForEnvironment("dev")]
public string PropertyHasSingleEnv { get; set; }

[RequiredForEnvironment("*")]
public string PropertyHasAllEnv { get; set; }

[RequiredForEnvironment("dev")]
[RequiredForEnvironment("test")]
[RequiredForEnvironment("prod")]
public string PropertyHasMultipleEnv { get; set; }

[RequiredForEnvironment("dev", Hidden = false)]
[RequiredForEnvironment("*")]
public string PropertyHasEnvironmentOverrideValue { get; set; }
}

[Test]
public void No_Rule_Property_Is_Ignored()
{
// arrange
var config = new TestConfiguration();

// act
var sut = config.RulesForEnvironment("dev");
var actual = sut.Where(x => x.Key.Name == "PropertyHasNoRules");

// assert
actual.Should().HaveCount(0);
}

[Test]
public void Single_Environment_Property_Returns_Rule_For_Correct_Environment()
{
// arrange
var config = new TestConfiguration();

// act
var sut = config.RulesForEnvironment("dev");
var actual = sut.SingleOrDefault(x => x.Key.Name == "PropertyHasSingleEnv");

// assert
actual.Value.Should().NotBeNull();
}

[Test]
public void Single_Environment_Property_Returns_No_Rule_For_Wrong_Environment()
{
// arrange
var config = new TestConfiguration();

// act
var sut = config.RulesForEnvironment(" ");
var actual = sut.SingleOrDefault(x => x.Key.Name == "PropertyHasSingleEnv");

// assert
actual.Value.Should().BeNull();
}

[Test]
public void Asterisk_Matches_Any_Environment()
{
// arrange
var config = new TestConfiguration();

// act
var sut = config.RulesForEnvironment("test");
var actual = sut.SingleOrDefault(x => x.Key.Name == "PropertyHasAllEnv");

// assert
actual.Value.Should().NotBeNull();
}

[TestCase("dev")]
[TestCase("test")]
[TestCase("prod")]
public void Multiple_Rules_For_Different_Environments_For_Same_Property_Return_Single_Rule(string env)
{
// arrange
var config = new TestConfiguration();

// act
var sut = config.RulesForEnvironment(env);
var actual = sut.SingleOrDefault(x => x.Key.Name == "PropertyHasMultipleEnv");

// assert
actual.Value.Should().NotBeNull();
}

[Test]
public void All_Environment_Matcher_Can_Be_Overidden()
{
// arrange
var config = new TestConfiguration();

// act
var sut = config.RulesForEnvironment("dev");
var actual = sut.SingleOrDefault(x => x.Key.Name == "PropertyHasEnvironmentOverrideValue");

// assert
actual.Value.Should().NotBeNull();
actual.Value.Environment.Should().Be("dev");
actual.Value.Hidden.Should().Be(false);
}

[Test]
public void Override_For_Non_Matching_Environment_Does_Not_Override_Catchall_Rule()
{
// arrange
var config = new TestConfiguration();

// act
var sut = config.RulesForEnvironment("text");
var actual = sut.SingleOrDefault(x => x.Key.Name == "PropertyHasEnvironmentOverrideValue");

// assert
actual.Value.Should().NotBeNull();
actual.Value.Environment.Should().Be("*");
actual.Value.Hidden.Should().Be(true);
}
}
107 changes: 4 additions & 103 deletions Childrens-Social-Care-CPD-Tests/ConfigurationHealthCheckTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Castle.Core.Logging;
using Childrens_Social_Care_CPD;
using Childrens_Social_Care_CPD;
using Childrens_Social_Care_CPD.Configuration;
using FluentAssertions;
using Microsoft.Extensions.Diagnostics.HealthChecks;
Expand All @@ -21,13 +20,13 @@ public void Setup()
{
_logger = Substitute.For<ILogger<ConfigurationHealthCheck>>();
_applicationConfiguration = Substitute.For<IApplicationConfiguration>();
_applicationConfiguration.ReturnsForAll("foo");
}

[Test]
public async Task Passes_When_All_Values_Set_And_Cookies_Are_Secured()
{
// arrange
_applicationConfiguration.ReturnsForAll("foo");
var sut = new ConfigurationHealthCheck(_logger, _applicationConfiguration);

// act
Expand All @@ -41,6 +40,7 @@ public async Task Passes_When_All_Values_Set_And_Cookies_Are_Secured()
public async Task Fails_When_Disable_Cookies_Is_True()
{
// arrange
_applicationConfiguration.ReturnsForAll("foo");
_applicationConfiguration.DisableSecureCookies.Returns(true);
var sut = new ConfigurationHealthCheck(_logger, _applicationConfiguration);

Expand All @@ -52,108 +52,9 @@ public async Task Fails_When_Disable_Cookies_Is_True()
}

[Test]
public async Task Fails_When_AppInsightsConnectionString_Is_Not_Set()
{
// arrange
_applicationConfiguration.AppInsightsConnectionString.Returns(string.Empty);
var sut = new ConfigurationHealthCheck(_logger, _applicationConfiguration);

// act
var result = await sut.CheckHealthAsync(null, default);

// assert
result.Status.Should().Be(HealthStatus.Unhealthy);
}

[Test]
public async Task Fails_When_AppVersion_Is_Not_Set()
{
// arrange
_applicationConfiguration.AppVersion.Returns(string.Empty);
var sut = new ConfigurationHealthCheck(_logger, _applicationConfiguration);

// act
var result = await sut.CheckHealthAsync(null, default);

// assert
result.Status.Should().Be(HealthStatus.Unhealthy);
}

[Test]
public async Task Fails_When_AzureEnvironment_Is_Not_Set()
{
// arrange
_applicationConfiguration.AzureEnvironment.Returns(string.Empty);
var sut = new ConfigurationHealthCheck(_logger, _applicationConfiguration);

// act
var result = await sut.CheckHealthAsync(null, default);

// assert
result.Status.Should().Be(HealthStatus.Unhealthy);
}

[Test]
public async Task Fails_When_ClarityProjectId_Is_Not_Set()
{
// arrange
_applicationConfiguration.ClarityProjectId.Returns(string.Empty);
var sut = new ConfigurationHealthCheck(_logger, _applicationConfiguration);

// act
var result = await sut.CheckHealthAsync(null, default);

// assert
result.Status.Should().Be(HealthStatus.Unhealthy);
}

[Test]
public async Task Fails_When_ContentfulDeliveryApiKey_Is_Not_Set()
{
// arrange
_applicationConfiguration.ContentfulDeliveryApiKey.Returns(string.Empty);
var sut = new ConfigurationHealthCheck(_logger, _applicationConfiguration);

// act
var result = await sut.CheckHealthAsync(null, default);

// assert
result.Status.Should().Be(HealthStatus.Unhealthy);
}

[Test]
public async Task Fails_When_ContentfulEnvironment_Is_Not_Set()
{
// arrange
_applicationConfiguration.ContentfulEnvironment.Returns(string.Empty);
var sut = new ConfigurationHealthCheck(_logger, _applicationConfiguration);

// act
var result = await sut.CheckHealthAsync(null, default);

// assert
result.Status.Should().Be(HealthStatus.Unhealthy);
}

[Test]
public async Task Fails_When_ContentfulSpaceId_Is_Not_Set()
{
// arrange
_applicationConfiguration.ContentfulSpaceId.Returns(string.Empty);
var sut = new ConfigurationHealthCheck(_logger, _applicationConfiguration);

// act
var result = await sut.CheckHealthAsync(null, default);

// assert
result.Status.Should().Be(HealthStatus.Unhealthy);
}

[Test]
public async Task Fails_When_GoogleTagManagerKey_Is_Not_Set()
public async Task Fails_When_Required_Value_Is_Missing()
{
// arrange
_applicationConfiguration.GoogleTagManagerKey.Returns(string.Empty);
var sut = new ConfigurationHealthCheck(_logger, _applicationConfiguration);

// act
Expand Down
Loading

0 comments on commit 82e76b1

Please sign in to comment.