using Xunit; using Npgsql; using Testcontainers.PostgreSql; namespace Kbx.Tests.Scenarios; /// /// Host repository reference fixture. Requires Testcontainers.PostgreSql and Npgsql. /// The container is disposable; never point this fixture at a production connection string. /// public sealed class KbxScenarioPostgresFixture : IAsyncLifetime { private readonly PostgreSqlContainer _postgres = new PostgreSqlBuilder() .WithImage("postgres:17-alpine") .WithDatabase("kbx_scenario_test") .WithUsername("kbx") .WithPassword("kbx-test-only") .Build(); public string ConnectionString => _postgres.GetConnectionString(); public async Task InitializeAsync() { await _postgres.StartAsync(); // Host: run DbUp migrations in filename order, then bootstrap/reset/seed SQL. } public Task DisposeAsync() => _postgres.DisposeAsync().AsTask(); public static async Task AssertTestGuardAsync(string connectionString, CancellationToken ct = default) { await using var connection = new NpgsqlConnection(connectionString); await connection.OpenAsync(ct); await using var command = new NpgsqlCommand( "select exists(select 1 from kbx_test.environment_guard where marker='KBX_SCENARIO_TEST_ONLY')", connection); if (await command.ExecuteScalarAsync(ct) is not true) throw new InvalidOperationException("KBX scenario database guard is missing."); } }