using Xunit; using Npgsql; using Dapper; using KArtSell.Modules.IdentityAccess.ManageIdentityAndRoles.Features.RegisterIdentity; using System.Data; namespace KArtSell.IdentityAccess.IntegrationTests.ManageIdentityAndRoles; [Collection("Database")] public class RegisterIdentityIntegrationTests : IAsyncLifetime { private readonly string _connectionString; private NpgsqlDataSource _dataSource = null!; private RegisterIdentitySql _sql = null!; public RegisterIdentityIntegrationTests() { _connectionString = Environment.GetEnvironmentVariable("KARTSELL_POSTGRES") ?? "Host=127.0.0.1;Port=5432;Database=kartselldb;Username=postgres;Password=postgres"; } public async Task InitializeAsync() { _dataSource = new NpgsqlDataSourceBuilder(_connectionString).Build(); _sql = new RegisterIdentitySql(async () => await _dataSource.OpenConnectionAsync()); await CleanupAsync(); } public async Task DisposeAsync() { await CleanupAsync(); await _dataSource.DisposeAsync(); } private async Task CleanupAsync() { using var conn = await _dataSource.OpenConnectionAsync(); await conn.ExecuteAsync("DELETE FROM public.identity WHERE email LIKE 'test-integration-%'"); } [Fact] public async Task CreateIdentity_ValidRequest_InsertsAndReturnsId() { var email = "test-integration-001@example.com"; var displayName = "Test User 001"; var correlationId = Guid.NewGuid().ToString(); var identityId = Guid.NewGuid(); var conn = await _dataSource.OpenConnectionAsync() as NpgsqlConnection ?? throw new InvalidOperationException("Failed to open connection"); await using (conn) { await using var transaction = await conn.BeginTransactionAsync(IsolationLevel.ReadCommitted); var createdId = await _sql.CreateIdentityAsync(conn, transaction, identityId, email, displayName, correlationId, CancellationToken.None); await transaction.CommitAsync(); Assert.NotEqual(Guid.Empty, createdId); Assert.Equal(identityId, createdId); } } [Fact] public async Task CreateIdentity_DuplicateEmail_ReturnsEmpty() { var email = "test-integration-002@example.com"; var displayName = "Test User 002"; var correlationId = Guid.NewGuid().ToString(); var id1 = Guid.NewGuid(); var id2 = Guid.NewGuid(); var conn = await _dataSource.OpenConnectionAsync() as NpgsqlConnection ?? throw new InvalidOperationException("Failed to open connection"); await using (conn) { await using var transaction = await conn.BeginTransactionAsync(IsolationLevel.ReadCommitted); var created1 = await _sql.CreateIdentityAsync(conn, transaction, id1, email, displayName, correlationId, CancellationToken.None); await transaction.CommitAsync(); await using var transaction2 = await conn.BeginTransactionAsync(IsolationLevel.ReadCommitted); var created2 = await _sql.CreateIdentityAsync(conn, transaction2, id2, email, displayName, correlationId, CancellationToken.None); await transaction2.CommitAsync(); Assert.Equal(id1, created1); Assert.Equal(Guid.Empty, created2); } } [Fact] public async Task GetIdentity_AfterCreate_ReturnsCorrectData() { var email = "test-integration-003@example.com"; var displayName = "Test User 003"; var correlationId = Guid.NewGuid().ToString(); var identityId = Guid.NewGuid(); var conn = await _dataSource.OpenConnectionAsync() as NpgsqlConnection ?? throw new InvalidOperationException("Failed to open connection"); await using (conn) { await using var transaction = await conn.BeginTransactionAsync(IsolationLevel.ReadCommitted); await _sql.CreateIdentityAsync(conn, transaction, identityId, email, displayName, correlationId, CancellationToken.None); await transaction.CommitAsync(); var (id, returnedEmail, returnedDisplayName, state) = await _sql.GetIdentityAsync(identityId, CancellationToken.None); Assert.Equal(identityId, id); Assert.Equal(email, returnedEmail); Assert.Equal(displayName, returnedDisplayName); Assert.Equal("ACTIVE", state); } } [Fact] public async Task EmailExists_WithExistingEmail_ReturnsTrue() { var email = "test-integration-004@example.com"; var displayName = "Test User 004"; var correlationId = Guid.NewGuid().ToString(); var identityId = Guid.NewGuid(); var conn = await _dataSource.OpenConnectionAsync() as NpgsqlConnection ?? throw new InvalidOperationException("Failed to open connection"); await using (conn) { await using var transaction = await conn.BeginTransactionAsync(IsolationLevel.ReadCommitted); await _sql.CreateIdentityAsync(conn, transaction, identityId, email, displayName, correlationId, CancellationToken.None); await transaction.CommitAsync(); var exists = await _sql.EmailExistsAsync(email, CancellationToken.None); Assert.True(exists); } } [Fact] public async Task EmailExists_WithNonExistentEmail_ReturnsFalse() { var exists = await _sql.EmailExistsAsync("nonexistent-integration-001@example.com", CancellationToken.None); Assert.False(exists); } }