using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using StackExchange.Redis; public class GatewayApiFixture : WebApplicationFactory, IAsyncLifetime { // Prefer CI/env overrides; fall back to ward-gateway compose profile ports. public static string TestConnectionString { get; } = Environment.GetEnvironmentVariable("ConnectionStrings__GatewayDb") ?? "Host=localhost;Port=5437;Database=vigilcare_ward_test;Username=postgres;Password=password"; public static string RedisConnection { get; } = Environment.GetEnvironmentVariable("Gateway__Redis__ConnectionString") ?? Environment.GetEnvironmentVariable("Redis__ConnectionString") ?? "localhost:6383,defaultDatabase=2,allowAdmin=true"; protected override void ConfigureWebHost(IWebHostBuilder builder) { builder.UseEnvironment("Testing"); builder.ConfigureAppConfiguration((_, config) => { config.AddInMemoryCollection(new Dictionary { ["ConnectionStrings:GatewayDb"] = TestConnectionString, ["Redis:ConnectionString"] = RedisConnection, ["RabbitMq:Host"] = Environment.GetEnvironmentVariable("Gateway__RabbitMq__Host") ?? Environment.GetEnvironmentVariable("RabbitMq__Host") ?? "localhost", ["RabbitMq:Port"] = Environment.GetEnvironmentVariable("Gateway__RabbitMq__Port") ?? Environment.GetEnvironmentVariable("RabbitMq__Port") ?? "5675", ["RabbitMq:Username"] = Environment.GetEnvironmentVariable("RabbitMq__Username") ?? "guest", ["RabbitMq:Password"] = Environment.GetEnvironmentVariable("RabbitMq__Password") ?? "guest", ["RabbitMq:PagingAckTimeoutMs"] = "5000", ["CentralApi:BaseUrl"] = "http://127.0.0.1:1", ["Gateway:GatewayId"] = "22222222-2222-2222-2222-222222222222", ["Gateway:SiteId"] = "11111111-1111-1111-1111-111111111111", ["Gateway:Department"] = "ICU", ["Gateway:EncounterSyncIntervalMinutes"] = "60", ["Gateway:CentralReachabilityIntervalSeconds"] = "1", ["Gateway:HeartbeatIntervalSeconds"] = "1", ["Gateway:SyncBatchSize"] = "500", ["Gateway:AutoMigrate"] = "false", ["ApiKey:Gateway"] = "dev-gateway-key-change-in-production", ["Jwt:SigningKey"] = "dev-signing-key-minimum-32-bytes-long!!", ["Jwt:Issuer"] = "vigilcare-gateway", ["Jwt:Audience"] = "vigilcare-dashboard", }); }); builder.ConfigureServices(services => { services.AddAuthentication(options => { options.DefaultAuthenticateScheme = TestingAuthHandler.SchemeName; options.DefaultChallengeScheme = TestingAuthHandler.SchemeName; }) .AddScheme( TestingAuthHandler.SchemeName, _ => { }); }); } public async Task InitializeAsync() { var options = new DbContextOptionsBuilder() .UseNpgsql(TestConnectionString) .Options; await using (var migrateDb = new GatewayDbContext(options)) { await migrateDb.Database.MigrateAsync(); await GatewayDbResetHelper.ResetAsync(migrateDb); } using var scope = Services.CreateScope(); var redis = scope.ServiceProvider.GetRequiredService(); var server = redis.GetServer(redis.GetEndPoints().First()); // Flush only the gateway test DB index — do not FlushAll (would wipe API test DB 1). var dbIndex = 2; var cfg = RedisConnection.Split(',').FirstOrDefault(p => p.StartsWith("defaultDatabase=", StringComparison.OrdinalIgnoreCase)); if (cfg is not null && int.TryParse(cfg.Split('=')[1], out var parsed)) dbIndex = parsed; await server.FlushDatabaseAsync(dbIndex); } protected override void ConfigureClient(HttpClient client) { base.ConfigureClient(client); client.AsNurse(); } public new async Task DisposeAsync() => await base.DisposeAsync(); }