using JdeScoping.ConfigManager.Core.Services; using JdeScoping.ConfigManager.Core.Services.SecureStore; namespace JdeScoping.ConfigManager.Core.Tests.Services; public class RuntimeConfigValidationServiceTests : IDisposable { private readonly string _testDirectory; private readonly ISecureStoreManager _secureStoreManager; private readonly RuntimeConfigValidationService _sut; public RuntimeConfigValidationServiceTests() { _testDirectory = Path.Combine(Path.GetTempPath(), $"RuntimeConfigValidationTests_{Guid.NewGuid():N}"); Directory.CreateDirectory(_testDirectory); _secureStoreManager = Substitute.For(); _sut = new RuntimeConfigValidationService(_secureStoreManager); } public void Dispose() { if (Directory.Exists(_testDirectory)) { Directory.Delete(_testDirectory, recursive: true); } } [Fact] public void ValidateRuntimeConfig_WithMissingAppSettings_ReturnsConfigurationError() { // Arrange - directory exists but no appsettings.json var configFolder = Path.Combine(_testDirectory, "missing"); Directory.CreateDirectory(configFolder); // Act var results = _sut.ValidateRuntimeConfig(configFolder); // Assert results.ShouldNotBeEmpty(); var configResult = results.FirstOrDefault(r => r.ValidatorName == "Configuration"); configResult.ShouldNotBeNull(); configResult.IsValid.ShouldBeFalse(); configResult.Errors.ShouldContain(e => e.Contains("appsettings.json not found")); } [Fact] public void ValidateRuntimeConfig_WhenSecureStoreNotOpen_AddsWarning() { // Arrange var configFolder = _testDirectory; var appSettingsPath = Path.Combine(configFolder, "appsettings.json"); File.WriteAllText(appSettingsPath, "{}"); _secureStoreManager.IsStoreOpen.Returns(false); // Act var results = _sut.ValidateRuntimeConfig(configFolder); // Assert var storeResult = results.FirstOrDefault(r => r.ValidatorName == "SecureStore"); storeResult.ShouldNotBeNull(); storeResult.Warnings.ShouldContain(w => w.Contains("No SecureStore is currently open")); } [Fact] public void ValidateRuntimeConfig_WhenSecureStoreIsOpen_NoSecureStoreWarning() { // Arrange var configFolder = _testDirectory; var appSettingsPath = Path.Combine(configFolder, "appsettings.json"); File.WriteAllText(appSettingsPath, "{}"); _secureStoreManager.IsStoreOpen.Returns(true); // Act var results = _sut.ValidateRuntimeConfig(configFolder); // Assert // There may be a SecureStore result from validators, but it should not have the // "No SecureStore is currently open" warning var storeResults = results.Where(r => r.ValidatorName == "SecureStore").ToList(); foreach (var storeResult in storeResults) { storeResult.Warnings.ShouldNotContain(w => w.Contains("No SecureStore is currently open")); } } [Fact] public void ValidateRuntimeConfig_WithValidAppSettings_RunsValidators() { // Arrange var configFolder = _testDirectory; var appSettingsPath = Path.Combine(configFolder, "appsettings.json"); var validConfig = """ { "ConnectionStrings": {}, "DataSync": { "Enabled": true } } """; File.WriteAllText(appSettingsPath, validConfig); _secureStoreManager.IsStoreOpen.Returns(true); // Act var results = _sut.ValidateRuntimeConfig(configFolder); // Assert // Should return results (empty or with validators) without throwing results.ShouldNotBeNull(); } [Fact] public void ValidateRuntimeConfig_WithNonExistentDirectory_ReturnsConfigurationError() { // Arrange var nonExistentFolder = Path.Combine(_testDirectory, "does-not-exist"); // Act var results = _sut.ValidateRuntimeConfig(nonExistentFolder); // Assert results.ShouldNotBeEmpty(); var configResult = results.FirstOrDefault(r => r.ValidatorName == "Configuration"); configResult.ShouldNotBeNull(); configResult.IsValid.ShouldBeFalse(); configResult.Errors.ShouldContain(e => e.Contains("not found")); } [Fact] public void ValidateRuntimeConfig_WithInvalidJson_ReturnsError() { // Arrange var configFolder = _testDirectory; var appSettingsPath = Path.Combine(configFolder, "appsettings.json"); File.WriteAllText(appSettingsPath, "{ invalid json }"); _secureStoreManager.IsStoreOpen.Returns(true); // Act & Assert // The service should either throw or return an error result for invalid JSON Should.Throw(() => _sut.ValidateRuntimeConfig(configFolder)); } [Fact] public void ValidateRuntimeConfig_ReturnsMultipleResults_WhenMultipleValidatorsRun() { // Arrange var configFolder = _testDirectory; var appSettingsPath = Path.Combine(configFolder, "appsettings.json"); var validConfig = """ { "ConnectionStrings": {}, "DataSync": { "Enabled": true }, "SecureStore": { "StorePath": "data/secrets.json", "KeyFilePath": "data/secrets.key" } } """; File.WriteAllText(appSettingsPath, validConfig); _secureStoreManager.IsStoreOpen.Returns(false); // Act var results = _sut.ValidateRuntimeConfig(configFolder); // Assert // Should have at least the SecureStore warning results.ShouldNotBeEmpty(); } }