using EntKube.Provisioning.Domain; using EntKube.Provisioning.Features.Apps.ConfigureAppEnvironment; using EntKube.Provisioning.Infrastructure; using EntKube.SharedKernel.Domain; using FluentAssertions; namespace EntKube.Provisioning.Tests.Features; public class ConfigureAppEnvironmentHandlerTests { private readonly ConfigureAppEnvironmentHandler handler; private readonly InMemoryAppRepository repository; public ConfigureAppEnvironmentHandlerTests() { repository = new InMemoryAppRepository(); handler = new ConfigureAppEnvironmentHandler(repository); } [Fact] public async Task HandleAsync_DeploymentSpec_ConfiguresEnvironment() { // Arrange — An app with an environment that needs deployment config. App app = App.Create(Guid.NewGuid(), Guid.NewGuid(), "API", "api", AppType.Deployment); Guid environmentId = Guid.NewGuid(); app.AddEnvironment(environmentId, Guid.NewGuid(), "api-dev"); await repository.AddAsync(app); ConfigureDeploymentRequest request = new( AppId: app.Id, EnvironmentId: environmentId, Spec: new DeploymentSpec( Image: "registry.example.com/api", Tag: "v1.0.0", Replicas: 2, ContainerPort: 8080, ServicePort: 80, HostName: "api.dev.example.com", PathPrefix: "/", EnvironmentVariables: new Dictionary { ["ENV"] = "dev" }, Resources: new ResourceSpec("100m", "500m", "128Mi", "512Mi"))); // Act Result result = await handler.HandleDeploymentAsync(request); // Assert result.IsSuccess.Should().BeTrue(); App? updated = await repository.GetByIdAsync(app.Id); AppEnvironment env = updated!.Environments[0]; env.DeploymentSpec.Should().NotBeNull(); env.DeploymentSpec!.Image.Should().Be("registry.example.com/api"); env.SyncStatus.Should().Be(AppSyncStatus.Pending); } [Fact] public async Task HandleAsync_HelmSpec_ConfiguresEnvironment() { // Arrange — A Helm-type app with an environment that needs chart config. App app = App.Create(Guid.NewGuid(), Guid.NewGuid(), "Redis", "redis", AppType.HelmChart); Guid environmentId = Guid.NewGuid(); app.AddEnvironment(environmentId, Guid.NewGuid(), "redis-dev"); await repository.AddAsync(app); ConfigureHelmReleaseRequest request = new( AppId: app.Id, EnvironmentId: environmentId, Spec: new HelmReleaseSpec( RepoUrl: "https://charts.bitnami.com/bitnami", ChartName: "redis", ChartVersion: "18.6.1", ValuesYaml: "replica:\n replicaCount: 3")); // Act Result result = await handler.HandleHelmReleaseAsync(request); // Assert result.IsSuccess.Should().BeTrue(); App? updated = await repository.GetByIdAsync(app.Id); AppEnvironment env = updated!.Environments[0]; env.HelmReleaseSpec.Should().NotBeNull(); env.HelmReleaseSpec!.ChartName.Should().Be("redis"); } [Fact] public async Task HandleAsync_NonExistentApp_ReturnsFailure() { // Arrange & Act ConfigureDeploymentRequest request = new(Guid.NewGuid(), Guid.NewGuid(), new DeploymentSpec("img", "v1", 1, 80, 80, null, null, null, null)); Result result = await handler.HandleDeploymentAsync(request); // Assert result.IsFailure.Should().BeTrue(); result.Error.Should().Contain("not found"); } [Fact] public async Task HandleAsync_NonExistentEnvironment_ReturnsFailure() { // Arrange — App exists but the environment ID doesn't match. App app = App.Create(Guid.NewGuid(), Guid.NewGuid(), "API", "api", AppType.Deployment); await repository.AddAsync(app); ConfigureDeploymentRequest request = new(app.Id, Guid.NewGuid(), new DeploymentSpec("img", "v1", 1, 80, 80, null, null, null, null)); // Act Result result = await handler.HandleDeploymentAsync(request); // Assert result.IsFailure.Should().BeTrue(); result.Error.Should().Contain("not found"); } }