using System; using System.IO; using Migrato.Core; using Xunit; namespace Migrato.Tests; public class MigrationParserTests : IDisposable { private readonly string _tempDirectory = Directory.CreateTempSubdirectory("migrato-tests-").FullName; [Fact] public void Parse_ValidFile_ReturnsMigrationWithParsedSections() { var path = WriteFile( "20260101120000_create_users.sql", "-- +migrato Up\nCREATE TABLE users (id INTEGER PRIMARY KEY);\n\n-- +migrato Down\nDROP TABLE users;\n"); var migration = MigrationParser.Parse(path); Assert.Equal(20260101120000L, migration.Version); Assert.Equal("create_users", migration.Name); Assert.Equal("CREATE TABLE users (id INTEGER PRIMARY KEY);", migration.UpSql); Assert.Equal("DROP TABLE users;", migration.DownSql); Assert.Equal(path, migration.Source); } [Fact] public void Parse_MarkersAreCaseInsensitive() { var path = WriteFile( "20260101120000_case_insensitive.sql", "-- +MIGRATO up\nSELECT 1;\n-- +migrato DOWN\nSELECT 2;\n"); var migration = MigrationParser.Parse(path); Assert.Equal("SELECT 1;", migration.UpSql); Assert.Equal("SELECT 2;", migration.DownSql); } [Theory] [InlineData("not_a_migration.sql")] [InlineData("2026_bad_version.sql")] [InlineData("20260101120000.sql")] public void Parse_InvalidFileName_Throws(string fileName) { var path = WriteFile(fileName, "-- +migrato Up\nSELECT 1;\n-- +migrato Down\nSELECT 2;\n"); Assert.Throws(() => MigrationParser.Parse(path)); } [Fact] public void Parse_MissingUpMarker_Throws() { var path = WriteFile("20260101120000_missing_up.sql", "-- +migrato Down\nSELECT 2;\n"); Assert.Throws(() => MigrationParser.Parse(path)); } [Fact] public void Parse_MissingDownMarker_Throws() { var path = WriteFile("20260101120000_missing_down.sql", "-- +migrato Up\nSELECT 1;\n"); Assert.Throws(() => MigrationParser.Parse(path)); } [Fact] public void Parse_DownBeforeUp_Throws() { var path = WriteFile( "20260101120000_out_of_order.sql", "-- +migrato Down\nSELECT 2;\n-- +migrato Up\nSELECT 1;\n"); Assert.Throws(() => MigrationParser.Parse(path)); } [Fact] public void Parse_DuplicateMarker_Throws() { var path = WriteFile( "20260101120000_duplicate.sql", "-- +migrato Up\nSELECT 1;\n-- +migrato Up\nSELECT 2;\n-- +migrato Down\nSELECT 3;\n"); Assert.Throws(() => MigrationParser.Parse(path)); } private string WriteFile(string fileName, string content) { var path = Path.Combine(_tempDirectory, fileName); File.WriteAllText(path, content); return path; } public void Dispose() { Directory.Delete(_tempDirectory, recursive: true); } }