using Npgsql; using Testcontainers.PostgreSql; namespace ItWorx.KnowledgeHub.IntegrationTests.Infrastructure; /// /// One PostgreSQL Testcontainer for the whole assembly run (docs/22-testing-strategy.md /// — "One PostgreSQL Testcontainer per test collection/suite"). Individual test classes /// each get an isolated logical database on this shared server instance via /// , so tests never share mutable rows. /// public sealed class PostgresContainerFixture : IAsyncLifetime { private const string SharedNetworkAlias = "knowledge-hub-postgres"; private static readonly string? SharedNetworkName = Environment.GetEnvironmentVariable("TESTCONTAINERS_NETWORK"); // Pinned to the same PostgreSQL major/minor family as production // (docker-compose.yml / docs/23-deployment-unraid.md). private readonly PostgreSqlContainer _container = BuildContainer(); public string Host => UsesSharedNetwork ? SharedNetworkAlias : _container.Hostname; public int Port => UsesSharedNetwork ? 5432 : _container.GetMappedPublicPort(5432); public string AdminConnectionString => new NpgsqlConnectionStringBuilder(_container.GetConnectionString()) { Host = Host, Port = Port }.ConnectionString; public static string Username => "knowledge_hub"; public static string Password => "integration-test-only"; public Task InitializeAsync() => _container.StartAsync(); public Task DisposeAsync() => _container.DisposeAsync().AsTask(); private static bool UsesSharedNetwork => !string.IsNullOrWhiteSpace(SharedNetworkName); private static PostgreSqlContainer BuildContainer() { var builder = new PostgreSqlBuilder( "postgres:18.4-bookworm@sha256:882236b897e39051d2368c5ccc6cda944904723506b2dfc97f2a8f5bc9afa382") .WithDatabase("knowledge_hub_admin") .WithUsername("knowledge_hub") .WithPassword("integration-test-only"); if (UsesSharedNetwork) { builder = builder .WithNetwork(SharedNetworkName!) .WithNetworkAliases(SharedNetworkAlias); } return builder.Build(); } }