using Xunit; using StellaOps.TestKit; namespace StellaOps.TimelineIndexer.Tests; public sealed class TimelineSchemaTests { private static string FindMigrationPath() { var dir = AppContext.BaseDirectory; for (var i = 0; i < 12 && dir is not null; i++) { var candidate = Path.Combine(dir, "Db", "Migrations", "001_initial_schema.sql"); if (File.Exists(candidate)) { return candidate; } var infraCandidate = Path.Combine(dir, "StellaOps.TimelineIndexer.Infrastructure", "Db", "Migrations", "001_initial_schema.sql"); if (File.Exists(infraCandidate)) { return infraCandidate; } dir = Directory.GetParent(dir)?.FullName; } throw new FileNotFoundException("Expected migration file was not found after traversing upward.", "(Db/Migrations/001_initial_schema.sql)"); } private static string ReadMigrationSql() { var path = FindMigrationPath(); return File.ReadAllText(path); } [Trait("Category", TestCategories.Unit)] [Fact] public void MigrationFile_Exists() { var path = FindMigrationPath(); Assert.True(File.Exists(path), $"Migration script missing at {path}"); } [Trait("Category", TestCategories.Unit)] [Fact] public void Migration_EnablesRlsPolicies() { var sql = ReadMigrationSql(); Assert.Contains("timeline_app.require_current_tenant", sql, StringComparison.Ordinal); Assert.Contains("timeline_events_isolation", sql, StringComparison.Ordinal); Assert.Contains("timeline_event_details_isolation", sql, StringComparison.Ordinal); Assert.Contains("timeline_event_digests_isolation", sql, StringComparison.Ordinal); Assert.Contains("ENABLE ROW LEVEL SECURITY", sql, StringComparison.OrdinalIgnoreCase); } [Trait("Category", TestCategories.Unit)] [Fact] public void Migration_DefinesUniqueEventConstraint() { var sql = ReadMigrationSql(); Assert.Contains("UNIQUE (tenant_id, event_id)", sql, StringComparison.Ordinal); Assert.Contains("event_seq bigserial", sql, StringComparison.Ordinal); } }