using EntKube.Provisioning.Domain; using EntKube.Provisioning.Features.Apps.CreateApp; using EntKube.Provisioning.Infrastructure; using EntKube.SharedKernel.Domain; using FluentAssertions; namespace EntKube.Provisioning.Tests.Features; public class CreateAppHandlerTests { private readonly CreateAppHandler handler; private readonly InMemoryAppRepository repository; public CreateAppHandlerTests() { repository = new InMemoryAppRepository(); handler = new CreateAppHandler(repository); } [Fact] public async Task HandleAsync_WithValidRequest_CreatesAppAndReturnsId() { // Arrange — A customer admin creates a new Deployment-type app. CreateAppRequest request = new( TenantId: Guid.NewGuid(), CustomerId: Guid.NewGuid(), Name: "Frontend Portal", Slug: "frontend-portal", Type: AppType.Deployment); // Act Result result = await handler.HandleAsync(request); // Assert — The app is created and its ID returned. result.IsSuccess.Should().BeTrue(); result.Value.Should().NotBe(Guid.Empty); App? stored = await repository.GetByIdAsync(result.Value!); stored.Should().NotBeNull(); stored!.Name.Should().Be("Frontend Portal"); stored.Type.Should().Be(AppType.Deployment); } [Fact] public async Task HandleAsync_WithDuplicateSlug_ReturnsFailure() { // Arrange — An app with the same slug already exists for this customer. Guid customerId = Guid.NewGuid(); CreateAppRequest first = new(Guid.NewGuid(), customerId, "App One", "my-app", AppType.Deployment); await handler.HandleAsync(first); CreateAppRequest duplicate = new(Guid.NewGuid(), customerId, "App Two", "my-app", AppType.HelmChart); // Act Result result = await handler.HandleAsync(duplicate); // Assert result.IsFailure.Should().BeTrue(); result.Error.Should().Contain("already exists"); } [Fact] public async Task HandleAsync_WithEmptyName_ReturnsFailure() { // Arrange & Act CreateAppRequest request = new(Guid.NewGuid(), Guid.NewGuid(), "", "slug", AppType.Deployment); Result result = await handler.HandleAsync(request); // Assert result.IsFailure.Should().BeTrue(); result.Error.Should().Contain("name"); } [Fact] public async Task HandleAsync_WithHelmChartType_CreatesHelmApp() { // Arrange — A customer wants to deploy a Helm chart-based app. CreateAppRequest request = new( TenantId: Guid.NewGuid(), CustomerId: Guid.NewGuid(), Name: "Redis Cache", Slug: "redis-cache", Type: AppType.HelmChart); // Act Result result = await handler.HandleAsync(request); // Assert result.IsSuccess.Should().BeTrue(); App? stored = await repository.GetByIdAsync(result.Value!); stored.Should().NotBeNull(); stored!.Type.Should().Be(AppType.HelmChart); } }