using EntKube.Provisioning.Domain; using EntKube.Provisioning.Features.Apps.AddAppEnvironment; using EntKube.Provisioning.Features.Apps.Reconcile; using EntKube.Provisioning.Infrastructure; using EntKube.SharedKernel.Domain; using FluentAssertions; using Moq; namespace EntKube.Provisioning.Tests.Features; public class AddAppEnvironmentHandlerTests { private readonly AddAppEnvironmentHandler handler; private readonly InMemoryAppRepository repository; private readonly Mock applyClientMock; public AddAppEnvironmentHandlerTests() { repository = new InMemoryAppRepository(); applyClientMock = new Mock(); handler = new AddAppEnvironmentHandler(repository, applyClientMock.Object); } [Fact] public async Task HandleAsync_WithValidRequest_AddsEnvironmentToApp() { // Arrange — An app exists and the admin wants to add it to the dev environment. App app = App.Create(Guid.NewGuid(), Guid.NewGuid(), "API", "api", AppType.Deployment); await repository.AddAsync(app); Guid environmentId = Guid.NewGuid(); Guid clusterId = Guid.NewGuid(); AddAppEnvironmentRequest request = new( AppId: app.Id, EnvironmentId: environmentId, ClusterId: clusterId, Namespace: "api-dev"); // Act Result result = await handler.HandleAsync(request); // Assert — The environment is added and its ID returned. result.IsSuccess.Should().BeTrue(); result.Value.Should().NotBe(Guid.Empty); App? updated = await repository.GetByIdAsync(app.Id); updated!.Environments.Should().HaveCount(1); updated.Environments[0].EnvironmentId.Should().Be(environmentId); updated.Environments[0].ClusterId.Should().Be(clusterId); updated.Environments[0].Namespace.Should().Be("api-dev"); // Verify that a namespace manifest was applied to the cluster. applyClientMock.Verify( c => c.ApplyManifestAsync(clusterId, It.Is(y => y.Contains("kind: Namespace") && y.Contains("name: api-dev")), It.IsAny()), Times.Once); } [Fact] public async Task HandleAsync_WithNonExistentApp_ReturnsFailure() { // Arrange & Act AddAppEnvironmentRequest request = new(Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), "ns"); Result result = await handler.HandleAsync(request); // Assert result.IsFailure.Should().BeTrue(); result.Error.Should().Contain("not found"); } [Fact] public async Task HandleAsync_WithDuplicateEnvironment_ReturnsFailure() { // Arrange — The app is already deployed to this environment. 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); AddAppEnvironmentRequest request = new(app.Id, environmentId, Guid.NewGuid(), "api-dev-2"); // Act Result result = await handler.HandleAsync(request); // Assert result.IsFailure.Should().BeTrue(); result.Error.Should().Contain("already"); } }