Files

119 lines
3.7 KiB
C#
Raw Permalink Normal View History

using Dapper;
using Microsoft.EntityFrameworkCore;
using Npgsql;
using Testcontainers.PostgreSql;
using WorkClub.Infrastructure.Data;
namespace WorkClub.Tests.Integration.Data;
public class MigrationTests : IAsyncLifetime
{
private PostgreSqlContainer? _container;
private string? _connectionString;
public async Task InitializeAsync()
{
_container = new PostgreSqlBuilder()
.WithImage("postgres:16-alpine")
.Build();
await _container.StartAsync();
_connectionString = _container.GetConnectionString();
}
public async Task DisposeAsync()
{
if (_container != null)
{
await _container.DisposeAsync();
}
}
[Fact]
public async Task Migration_AppliesSuccessfully_CreatesAllTables()
{
// Arrange
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseNpgsql(_connectionString)
.Options;
// Act
await using var context = new AppDbContext(options);
await context.Database.MigrateAsync();
// Assert - verify all expected tables exist
await using var connection = new NpgsqlConnection(_connectionString);
var tables = (await connection.QueryAsync<string>(
@"SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
ORDER BY table_name")).ToList();
Assert.Contains("clubs", tables);
Assert.Contains("members", tables);
Assert.Contains("work_items", tables);
Assert.Contains("shifts", tables);
Assert.Contains("shift_signups", tables);
}
[Fact]
public async Task Migration_CreatesCorrectIndexes()
{
// Arrange
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseNpgsql(_connectionString)
.Options;
// Act
await using var context = new AppDbContext(options);
await context.Database.MigrateAsync();
// Assert - verify critical indexes exist
await using var connection = new NpgsqlConnection(_connectionString);
var indexes = (await connection.QueryAsync<string>(
@"SELECT indexname
FROM pg_indexes
WHERE schemaname = 'public'
ORDER BY indexname")).ToList();
// TenantId indexes
Assert.Contains(indexes, i => i.Contains("tenant_id"));
// ClubId indexes
Assert.Contains(indexes, i => i.Contains("club_id"));
// Status indexes for WorkItem
Assert.Contains(indexes, i => i.Contains("status"));
}
[Fact]
public async Task Migration_CreatesExpectedSchema()
{
// Arrange
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseNpgsql(_connectionString)
.Options;
// Act
await using var context = new AppDbContext(options);
await context.Database.MigrateAsync();
// Assert - verify schema integrity (RLS and policies are applied via SeedDataService, not migrations)
await using var connection = new NpgsqlConnection(_connectionString);
// Verify tenant_id columns exist on all tables
var tenantColumns = (await connection.QueryAsync<string>(
@"SELECT table_name
FROM information_schema.columns
WHERE table_schema = 'public'
AND column_name = 'TenantId'
ORDER BY table_name")).ToList();
Assert.Contains("clubs", tenantColumns);
Assert.Contains("members", tenantColumns);
Assert.Contains("work_items", tenantColumns);
Assert.Contains("shifts", tenantColumns);
Assert.Contains("shift_signups", tenantColumns);
}
}