diff --git a/tests/Trax.Effect.Tests.Data.Sqlite.Integration/IntegrationTests/SqliteContextProviderFactoryTests.cs b/tests/Trax.Effect.Tests.Data.Sqlite.Integration/IntegrationTests/SqliteContextProviderFactoryTests.cs new file mode 100644 index 0000000..fb66f87 --- /dev/null +++ b/tests/Trax.Effect.Tests.Data.Sqlite.Integration/IntegrationTests/SqliteContextProviderFactoryTests.cs @@ -0,0 +1,40 @@ +using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using Trax.Effect.Data.Services.IDataContextFactory; +using Trax.Effect.Data.Sqlite.Services.SqliteContextFactory; +using Trax.Effect.Tests.Data.Sqlite.Integration.Fixtures; + +namespace Trax.Effect.Tests.Data.Sqlite.Integration.IntegrationTests; + +[TestFixture] +public class SqliteContextProviderFactoryTests : TestSetup +{ + public override ServiceProvider ConfigureServices(IServiceCollection services) => + services.BuildServiceProvider(); + + [Test] + public void Create_IncrementsCount() + { + var factory = (SqliteContextProviderFactory) + Scope.ServiceProvider.GetRequiredService(); + var before = factory.Count; + + using var ctx1 = factory.Create(); + using var ctx2 = factory.Create(); + + factory.Count.Should().Be(before + 2); + } + + [Test] + public async Task CreateDbContextAsync_ReturnsContextAndIncrementsCount() + { + var factory = (SqliteContextProviderFactory) + Scope.ServiceProvider.GetRequiredService(); + var before = factory.Count; + + await using var ctx = await factory.CreateDbContextAsync(CancellationToken.None); + + ctx.Should().NotBeNull(); + factory.Count.Should().Be(before + 1); + } +} diff --git a/tests/Trax.Effect.Tests.Data.Sqlite.Integration/IntegrationTests/SqliteDatabaseMigratorTests.cs b/tests/Trax.Effect.Tests.Data.Sqlite.Integration/IntegrationTests/SqliteDatabaseMigratorTests.cs new file mode 100644 index 0000000..7601190 --- /dev/null +++ b/tests/Trax.Effect.Tests.Data.Sqlite.Integration/IntegrationTests/SqliteDatabaseMigratorTests.cs @@ -0,0 +1,62 @@ +using FluentAssertions; +using Trax.Effect.Data.Sqlite.Utils; + +namespace Trax.Effect.Tests.Data.Sqlite.Integration.IntegrationTests; + +[TestFixture] +public class SqliteDatabaseMigratorTests +{ + [Test] + public async Task Migrate_FreshTempDatabase_AppliesEmbeddedScripts() + { + var dbPath = Path.Combine(Path.GetTempPath(), $"trax_migrator_ok_{Guid.NewGuid():N}.db"); + var connectionString = $"Data Source={dbPath}"; + + try + { + await DatabaseMigrator.Migrate(connectionString); + + File.Exists(dbPath).Should().BeTrue(); + new FileInfo(dbPath).Length.Should().BeGreaterThan(0); + } + finally + { + if (File.Exists(dbPath)) + File.Delete(dbPath); + } + } + + [Test] + public async Task Migrate_InvalidConnectionString_Rethrows() + { + // A path under a non-writable directory triggers an SQLite IO failure during PerformUpgrade. + // DbUp captures the exception, sets Successful = false, and Migrator rethrows from the + // !Successful branch — the catch block then logs and rethrows again, covering lines 25, 27-32. + var invalidPath = "/proc/this-cannot-be-written/migrator-fail.db"; + var connectionString = $"Data Source={invalidPath}"; + + var act = async () => await DatabaseMigrator.Migrate(connectionString); + + await act.Should().ThrowAsync(); + } + + [Test] + public void CreateEngineWithEmbeddedScripts_ReturnsEngine() + { + var dbPath = Path.Combine( + Path.GetTempPath(), + $"trax_migrator_engine_{Guid.NewGuid():N}.db" + ); + try + { + var engine = DatabaseMigrator.CreateEngineWithEmbeddedScripts($"Data Source={dbPath}"); + + engine.Should().NotBeNull(); + } + finally + { + if (File.Exists(dbPath)) + File.Delete(dbPath); + } + } +} diff --git a/tests/Trax.Effect.Tests.Data.Sqlite.Integration/IntegrationTests/TransactionJunctionTests.cs b/tests/Trax.Effect.Tests.Data.Sqlite.Integration/IntegrationTests/TransactionJunctionTests.cs new file mode 100644 index 0000000..3f08594 --- /dev/null +++ b/tests/Trax.Effect.Tests.Data.Sqlite.Integration/IntegrationTests/TransactionJunctionTests.cs @@ -0,0 +1,56 @@ +using FluentAssertions; +using LanguageExt; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Trax.Effect.Data.Junctions.BeginTransaction; +using Trax.Effect.Data.Junctions.CommitTransaction; +using Trax.Effect.Data.Services.DataContext; +using Trax.Effect.Tests.Data.Sqlite.Integration.Fixtures; + +namespace Trax.Effect.Tests.Data.Sqlite.Integration.IntegrationTests; + +[TestFixture] +public class TransactionJunctionTests : TestSetup +{ + public override ServiceProvider ConfigureServices(IServiceCollection services) => + services.BuildServiceProvider(); + + [Test] + public async Task BeginTransaction_OpensTransactionOnDataContext() + { + var context = Scope.ServiceProvider.GetRequiredService(); + var junction = new BeginTransaction(context); + + var result = await junction.Run(Unit.Default); + + result.Should().Be(Unit.Default); + ((DbContext)context).Database.CurrentTransaction.Should().NotBeNull(); + + await context.CommitTransaction(); + } + + [Test] + public async Task CommitTransaction_AfterBegin_ClosesTransaction() + { + var context = Scope.ServiceProvider.GetRequiredService(); + await new BeginTransaction(context).Run(Unit.Default); + ((DbContext)context).Database.CurrentTransaction.Should().NotBeNull(); + + var commit = new CommitTransaction(context); + var result = await commit.Run(Unit.Default); + + result.Should().Be(Unit.Default); + ((DbContext)context).Database.CurrentTransaction.Should().BeNull(); + } + + [Test] + public async Task BeginThenCommit_ChainedThroughJunctions_LeavesNoOpenTransaction() + { + var context = Scope.ServiceProvider.GetRequiredService(); + + await new BeginTransaction(context).Run(Unit.Default); + await new CommitTransaction(context).Run(Unit.Default); + + ((DbContext)context).Database.CurrentTransaction.Should().BeNull(); + } +} diff --git a/tests/Trax.Effect.Tests.Integration/IntegrationTests/PostgresContextProviderFactoryTests.cs b/tests/Trax.Effect.Tests.Integration/IntegrationTests/PostgresContextProviderFactoryTests.cs new file mode 100644 index 0000000..1a967ae --- /dev/null +++ b/tests/Trax.Effect.Tests.Integration/IntegrationTests/PostgresContextProviderFactoryTests.cs @@ -0,0 +1,37 @@ +using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using Trax.Effect.Data.Postgres.Services.PostgresContextFactory; +using Trax.Effect.Data.Services.IDataContextFactory; +using Trax.Effect.Tests.Integration.Fixtures; + +namespace Trax.Effect.Tests.Integration.IntegrationTests; + +[TestFixture] +public class PostgresContextProviderFactoryTests : TestSetup +{ + [Test] + public void Create_IncrementsCount() + { + var factory = (PostgresContextProviderFactory) + Scope.ServiceProvider.GetRequiredService(); + var before = factory.Count; + + using var ctx1 = factory.Create(); + using var ctx2 = factory.Create(); + + factory.Count.Should().Be(before + 2); + } + + [Test] + public async Task CreateDbContextAsync_ReturnsContextAndIncrementsCount() + { + var factory = (PostgresContextProviderFactory) + Scope.ServiceProvider.GetRequiredService(); + var before = factory.Count; + + await using var ctx = await factory.CreateDbContextAsync(CancellationToken.None); + + ctx.Should().NotBeNull(); + factory.Count.Should().Be(before + 1); + } +}