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;
}
}
}