w4c-workflows-api/w4c-workflows-api.Tests/WorkflowsPostgresFixture.cs
2026-09-03 17:44:39 +03:00

67 lines
2.6 KiB
C#

using Microsoft.EntityFrameworkCore;
using Testcontainers.PostgreSql;
using w4c_workflows.Data;
using Xunit;
namespace w4c_workflows.Tests;
[CollectionDefinition("WorkflowsPostgres")]
public class WorkflowsPostgresCollection : ICollectionFixture<WorkflowsPostgresFixture>
{
}
/// <summary>
/// One Postgres 17 container per collection; applies the EF Core migration once
/// and hands out fresh (scoped-like) DbContext instances per test.
/// </summary>
public sealed class WorkflowsPostgresFixture : IAsyncLifetime
{
private PostgreSqlContainer? _container;
private string _connectionString = "";
public async Task InitializeAsync()
{
_container = new PostgreSqlBuilder()
.WithImage("postgres:17-alpine")
.WithDatabase("w4c_workflows_test")
.WithUsername("w4c")
.WithPassword("w4c_test_pw")
.Build();
await _container.StartAsync();
_connectionString = _container.GetConnectionString() + ";Timezone=UTC";
await using var context = CreateContext();
await context.Database.MigrateAsync();
// Mirror the production startup ordering (Program.cs): the add-on columns for
// W7 (ArchivedAt) and S8 (Server) are applied by idempotent raw SQL AFTER the
// EF migrations — no new EF migration is introduced (the project's house style).
await context.Database.ExecuteSqlRawAsync(
"ALTER TABLE workflows.\"Tasks\" ADD COLUMN IF NOT EXISTS \"ArchivedAt\" timestamptz NULL;");
await context.Database.ExecuteSqlRawAsync(
"ALTER TABLE workflows.\"Tasks\" ADD COLUMN IF NOT EXISTS \"Server\" text NULL;");
// Workflow repo scoping: the repo name column + per-tenant repo setting table.
await context.Database.ExecuteSqlRawAsync(
"ALTER TABLE workflows.\"Workflows\" ADD COLUMN IF NOT EXISTS \"Repo\" text NOT NULL DEFAULT 'workflows';");
await context.Database.ExecuteSqlRawAsync(
"CREATE TABLE IF NOT EXISTS workflows.\"WorkflowRepos\" (" +
"\"TenantId\" text NOT NULL, \"RepoName\" text NOT NULL, \"UpdatedAt\" timestamptz NULL, " +
"CONSTRAINT \"PK_WorkflowRepos\" PRIMARY KEY (\"TenantId\"));");
}
public async Task DisposeAsync()
{
if (_container is not null)
await _container.DisposeAsync();
}
public WorkflowsDbContext CreateContext()
{
var options = new DbContextOptionsBuilder<WorkflowsDbContext>()
.UseNpgsql(_connectionString)
.Options;
return new WorkflowsDbContext(options);
}
}