using FluentAssertions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using StellaOps.Microservice; using Xunit; namespace StellaOps.Microservice.Tests; /// /// Tests for MicroserviceYamlLoader. /// public class MicroserviceYamlLoaderTests : IDisposable { private readonly string _tempDirectory; private readonly ILogger _logger; public MicroserviceYamlLoaderTests() { _tempDirectory = Path.Combine(Path.GetTempPath(), $"MicroserviceYamlLoaderTests_{Guid.NewGuid()}"); Directory.CreateDirectory(_tempDirectory); _logger = NullLogger.Instance; } public void Dispose() { if (Directory.Exists(_tempDirectory)) { Directory.Delete(_tempDirectory, true); } } [Fact] public void Load_ReturnsNull_WhenConfigFilePathIsNull() { var options = new StellaMicroserviceOptions { ServiceName = "test", Version = "1.0.0", Region = "us", ConfigFilePath = null }; var loader = new MicroserviceYamlLoader(options, _logger); var result = loader.Load(); result.Should().BeNull(); } [Fact] public void Load_ReturnsNull_WhenConfigFilePathIsEmpty() { var options = new StellaMicroserviceOptions { ServiceName = "test", Version = "1.0.0", Region = "us", ConfigFilePath = "" }; var loader = new MicroserviceYamlLoader(options, _logger); var result = loader.Load(); result.Should().BeNull(); } [Fact] public void Load_ReturnsNull_WhenFileDoesNotExist() { var options = new StellaMicroserviceOptions { ServiceName = "test", Version = "1.0.0", Region = "us", ConfigFilePath = Path.Combine(_tempDirectory, "nonexistent.yaml") }; var loader = new MicroserviceYamlLoader(options, _logger); var result = loader.Load(); result.Should().BeNull(); } [Fact] public void Load_ParsesValidYaml() { var yamlContent = """ endpoints: - method: GET path: /api/test defaultTimeout: 30s supportsStreaming: true """; var filePath = Path.Combine(_tempDirectory, "config.yaml"); File.WriteAllText(filePath, yamlContent); var options = new StellaMicroserviceOptions { ServiceName = "test", Version = "1.0.0", Region = "us", ConfigFilePath = filePath }; var loader = new MicroserviceYamlLoader(options, _logger); var result = loader.Load(); result.Should().NotBeNull(); result!.Endpoints.Should().HaveCount(1); result.Endpoints[0].Method.Should().Be("GET"); result.Endpoints[0].Path.Should().Be("/api/test"); result.Endpoints[0].DefaultTimeout.Should().Be("30s"); result.Endpoints[0].SupportsStreaming.Should().BeTrue(); } [Fact] public void Load_ParsesMultipleEndpoints() { var yamlContent = """ endpoints: - method: GET path: /api/one defaultTimeout: 10s - method: POST path: /api/two defaultTimeout: 5m - method: DELETE path: /api/three defaultTimeout: 1h """; var filePath = Path.Combine(_tempDirectory, "config.yaml"); File.WriteAllText(filePath, yamlContent); var options = new StellaMicroserviceOptions { ServiceName = "test", Version = "1.0.0", Region = "us", ConfigFilePath = filePath }; var loader = new MicroserviceYamlLoader(options, _logger); var result = loader.Load(); result.Should().NotBeNull(); result!.Endpoints.Should().HaveCount(3); } [Fact] public void Load_ParsesClaimRequirements() { var yamlContent = """ endpoints: - method: DELETE path: /api/admin requiringClaims: - type: role value: admin - type: permission value: delete """; var filePath = Path.Combine(_tempDirectory, "config.yaml"); File.WriteAllText(filePath, yamlContent); var options = new StellaMicroserviceOptions { ServiceName = "test", Version = "1.0.0", Region = "us", ConfigFilePath = filePath }; var loader = new MicroserviceYamlLoader(options, _logger); var result = loader.Load(); result.Should().NotBeNull(); result!.Endpoints.Should().HaveCount(1); result.Endpoints[0].RequiringClaims.Should().HaveCount(2); result.Endpoints[0].RequiringClaims![0].Type.Should().Be("role"); result.Endpoints[0].RequiringClaims![0].Value.Should().Be("admin"); result.Endpoints[0].RequiringClaims![1].Type.Should().Be("permission"); result.Endpoints[0].RequiringClaims![1].Value.Should().Be("delete"); } [Fact] public void Load_HandlesEmptyEndpointsList() { var yamlContent = """ endpoints: [] """; var filePath = Path.Combine(_tempDirectory, "config.yaml"); File.WriteAllText(filePath, yamlContent); var options = new StellaMicroserviceOptions { ServiceName = "test", Version = "1.0.0", Region = "us", ConfigFilePath = filePath }; var loader = new MicroserviceYamlLoader(options, _logger); var result = loader.Load(); result.Should().NotBeNull(); result!.Endpoints.Should().BeEmpty(); } [Fact] public void Load_IgnoresUnknownProperties() { var yamlContent = """ unknownProperty: value endpoints: - method: GET path: /api/test unknownField: ignored """; var filePath = Path.Combine(_tempDirectory, "config.yaml"); File.WriteAllText(filePath, yamlContent); var options = new StellaMicroserviceOptions { ServiceName = "test", Version = "1.0.0", Region = "us", ConfigFilePath = filePath }; var loader = new MicroserviceYamlLoader(options, _logger); var result = loader.Load(); result.Should().NotBeNull(); result!.Endpoints.Should().HaveCount(1); } [Fact] public void Load_ThrowsOnInvalidYaml() { var yamlContent = """ endpoints: - method: GET path /api/test # missing colon """; var filePath = Path.Combine(_tempDirectory, "config.yaml"); File.WriteAllText(filePath, yamlContent); var options = new StellaMicroserviceOptions { ServiceName = "test", Version = "1.0.0", Region = "us", ConfigFilePath = filePath }; var loader = new MicroserviceYamlLoader(options, _logger); Action act = () => loader.Load(); act.Should().Throw(); } [Fact] public void Load_ResolvesRelativePath() { var yamlContent = """ endpoints: - method: GET path: /api/test """; var filePath = Path.Combine(_tempDirectory, "config.yaml"); File.WriteAllText(filePath, yamlContent); // Save current directory and change to temp directory var originalDirectory = Environment.CurrentDirectory; try { Environment.CurrentDirectory = _tempDirectory; var options = new StellaMicroserviceOptions { ServiceName = "test", Version = "1.0.0", Region = "us", ConfigFilePath = "config.yaml" // relative path }; var loader = new MicroserviceYamlLoader(options, _logger); var result = loader.Load(); result.Should().NotBeNull(); } finally { Environment.CurrentDirectory = originalDirectory; } } }