using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using ColaFlow.Modules.Identity.Infrastructure.Persistence; using ColaFlow.Modules.ProjectManagement.Infrastructure.Persistence; namespace ColaFlow.Modules.Identity.IntegrationTests.Infrastructure; /// /// Custom WebApplicationFactory for ColaFlow Integration Tests /// Supports both In-Memory and Real PostgreSQL databases /// public class ColaFlowWebApplicationFactory : WebApplicationFactory { private readonly bool _useInMemoryDatabase; private readonly string? _testDatabaseName; public ColaFlowWebApplicationFactory(bool useInMemoryDatabase = true, string? testDatabaseName = null) { _useInMemoryDatabase = useInMemoryDatabase; _testDatabaseName = testDatabaseName ?? $"TestDb_{Guid.NewGuid()}"; } protected override void ConfigureWebHost(IWebHostBuilder builder) { // Set environment to Testing - this prevents PostgreSQL DbContext registration in modules builder.UseEnvironment("Testing"); // Configure test-specific settings builder.ConfigureAppConfiguration((context, config) => { // Clear existing connection strings to prevent PostgreSQL registration config.Sources.Clear(); // Add minimal config for testing config.AddInMemoryCollection(new Dictionary { ["ConnectionStrings:DefaultConnection"] = "", ["ConnectionStrings:PMDatabase"] = "", ["Jwt:SecretKey"] = "test-secret-key-for-integration-tests-minimum-32-characters", ["Jwt:Issuer"] = "ColaFlow.Test", ["Jwt:Audience"] = "ColaFlow.Test", ["Jwt:AccessTokenExpirationMinutes"] = "15", ["Jwt:RefreshTokenExpirationDays"] = "7" }); }); builder.ConfigureServices(services => { // Register test databases (modules won't register PostgreSQL due to Testing environment) if (_useInMemoryDatabase) { // Use In-Memory Database for fast, isolated tests // IMPORTANT: Share the same database name for cross-context data consistency services.AddDbContext(options => { options.UseInMemoryDatabase(_testDatabaseName!); options.EnableSensitiveDataLogging(); }); services.AddDbContext(options => { options.UseInMemoryDatabase(_testDatabaseName!); options.EnableSensitiveDataLogging(); }); } else { // Use Real PostgreSQL for integration tests var connectionString = $"Host=localhost;Port=5432;Database=colaflow_test_{_testDatabaseName};Username=postgres;Password=postgres"; services.AddDbContext(options => { options.UseNpgsql(connectionString); options.EnableSensitiveDataLogging(); }); services.AddDbContext(options => { options.UseNpgsql(connectionString); options.EnableSensitiveDataLogging(); }); } }); } // Override CreateHost to initialize databases after the host is created protected override IHost CreateHost(IHostBuilder builder) { var host = base.CreateHost(builder); // Initialize databases after host is created using var scope = host.Services.CreateScope(); var services = scope.ServiceProvider; try { // Initialize Identity database var identityDb = services.GetRequiredService(); if (_useInMemoryDatabase) { identityDb.Database.EnsureCreated(); } else { identityDb.Database.Migrate(); } // Initialize ProjectManagement database var pmDb = services.GetRequiredService(); if (_useInMemoryDatabase) { pmDb.Database.EnsureCreated(); } else { pmDb.Database.Migrate(); } } catch (Exception ex) { Console.WriteLine($"Error initializing test database: {ex.Message}"); throw; } return host; } }