package infra import ( "testing" ) func TestMigrationDown(t *testing.T) { t.Run("revertir ultima migracion elimina registro y ejecuta down_sql", func(t *testing.T) { db := openMigrationTestDB(t) dir := t.TempDir() writeMigrationFile(t, dir, "001_create_users.sql", "-- +up\nCREATE TABLE users (id TEXT PRIMARY KEY);\n-- +down\nDROP TABLE IF EXISTS users;\n") writeMigrationFile(t, dir, "002_create_roles.sql", "-- +up\nCREATE TABLE roles (id TEXT PRIMARY KEY);\n-- +down\nDROP TABLE IF EXISTS roles;\n") if _, err := MigrationUp(db, dir); err != nil { t.Fatalf("up failed: %v", err) } reverted, err := MigrationDown(db, 1) if err != nil { t.Fatalf("down failed: %v", err) } if len(reverted) != 1 { t.Errorf("expected 1 reverted, got %d", len(reverted)) } if reverted[0].Version != 2 { t.Errorf("expected version 2 reverted, got %d", reverted[0].Version) } // roles table should be gone if err := db.QueryRow("SELECT COUNT(*) FROM roles").Err(); err == nil { t.Error("roles table should not exist after down") } // users table should still exist var count int if err := db.QueryRow("SELECT COUNT(*) FROM users").Scan(&count); err != nil { t.Errorf("users table should still exist: %v", err) } }) t.Run("revertir n migraciones revierte en orden descendente", func(t *testing.T) { db := openMigrationTestDB(t) dir := t.TempDir() writeMigrationFile(t, dir, "001_create_users.sql", "-- +up\nCREATE TABLE users (id TEXT PRIMARY KEY);\n-- +down\nDROP TABLE IF EXISTS users;\n") writeMigrationFile(t, dir, "002_create_roles.sql", "-- +up\nCREATE TABLE roles (id TEXT PRIMARY KEY);\n-- +down\nDROP TABLE IF EXISTS roles;\n") writeMigrationFile(t, dir, "003_create_logs.sql", "-- +up\nCREATE TABLE logs (id INTEGER PRIMARY KEY);\n-- +down\nDROP TABLE IF EXISTS logs;\n") if _, err := MigrationUp(db, dir); err != nil { t.Fatalf("up failed: %v", err) } reverted, err := MigrationDown(db, 2) if err != nil { t.Fatalf("down 2 failed: %v", err) } if len(reverted) != 2 { t.Errorf("expected 2 reverted, got %d", len(reverted)) } // Should be reverted in descending order: 3, 2 if reverted[0].Version != 3 || reverted[1].Version != 2 { t.Errorf("reverted order wrong: got %d, %d", reverted[0].Version, reverted[1].Version) } // users table should still exist (migration 1 not reverted) var count int if err := db.QueryRow("SELECT COUNT(*) FROM users").Scan(&count); err != nil { t.Errorf("users table should still exist: %v", err) } }) t.Run("n cero no revierte nada", func(t *testing.T) { db := openMigrationTestDB(t) dir := t.TempDir() writeMigrationFile(t, dir, "001_create_users.sql", "-- +up\nCREATE TABLE users (id TEXT PRIMARY KEY);\n-- +down\nDROP TABLE IF EXISTS users;\n") if _, err := MigrationUp(db, dir); err != nil { t.Fatalf("up failed: %v", err) } reverted, err := MigrationDown(db, 0) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(reverted) != 0 { t.Errorf("expected 0 reverted for n=0, got %d", len(reverted)) } }) t.Run("base de datos sin migraciones retorna slice vacio", func(t *testing.T) { db := openMigrationTestDB(t) dir := t.TempDir() // Apply to create _migrations table if _, err := MigrationUp(db, dir); err != nil { t.Fatalf("up failed: %v", err) } reverted, err := MigrationDown(db, 5) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(reverted) != 0 { t.Errorf("expected 0 reverted from empty DB, got %d", len(reverted)) } }) }