ec36278c7b
Fase 1 del issue 0015. Tipos Go en functions/infra/migration.go con metadata en types/infra/. Funciones puras: MigrationParse (parsea filename NNN_name.sql + bloques -- +up/-- +down) y MigrationValidate (verifica secuencia, huecos, duplicados, bloques vacios). 16 tests, todos pasan. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
96 lines
2.9 KiB
Go
96 lines
2.9 KiB
Go
package infra
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestMigrationParse(t *testing.T) {
|
|
t.Run("archivo valido con up y down retorna Migration correcta", func(t *testing.T) {
|
|
content := "\n-- +up\nCREATE TABLE users (id TEXT PRIMARY KEY);\n\n-- +down\nDROP TABLE IF EXISTS users;\n"
|
|
m, err := MigrationParse("001_create_users.sql", content)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if m.Version != 1 {
|
|
t.Errorf("Version: got %d, want 1", m.Version)
|
|
}
|
|
if m.Name != "create_users" {
|
|
t.Errorf("Name: got %q, want %q", m.Name, "create_users")
|
|
}
|
|
if !strings.Contains(m.UpSQL, "CREATE TABLE users") {
|
|
t.Errorf("UpSQL missing CREATE TABLE: %q", m.UpSQL)
|
|
}
|
|
if !strings.Contains(m.DownSQL, "DROP TABLE") {
|
|
t.Errorf("DownSQL missing DROP TABLE: %q", m.DownSQL)
|
|
}
|
|
})
|
|
|
|
t.Run("archivo sin bloque down retorna DownSQL vacio sin error", func(t *testing.T) {
|
|
content := "-- +up\nCREATE TABLE logs (id INTEGER PRIMARY KEY);\n"
|
|
m, err := MigrationParse("002_create_logs.sql", content)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if m.Version != 2 {
|
|
t.Errorf("Version: got %d, want 2", m.Version)
|
|
}
|
|
if m.Name != "create_logs" {
|
|
t.Errorf("Name: got %q, want %q", m.Name, "create_logs")
|
|
}
|
|
if m.DownSQL != "" {
|
|
t.Errorf("DownSQL: got %q, want empty", m.DownSQL)
|
|
}
|
|
})
|
|
|
|
t.Run("filename sin separador underscore retorna error", func(t *testing.T) {
|
|
_, err := MigrationParse("001.sql", "-- +up\nCREATE TABLE x (id TEXT);\n")
|
|
if err == nil {
|
|
t.Fatal("expected error, got nil")
|
|
}
|
|
})
|
|
|
|
t.Run("version no numerica retorna error", func(t *testing.T) {
|
|
_, err := MigrationParse("abc_create_users.sql", "-- +up\nCREATE TABLE x (id TEXT);\n")
|
|
if err == nil {
|
|
t.Fatal("expected error, got nil")
|
|
}
|
|
})
|
|
|
|
t.Run("bloque up vacio retorna error", func(t *testing.T) {
|
|
content := "-- +up\n\n-- +down\nDROP TABLE users;\n"
|
|
_, err := MigrationParse("001_create_users.sql", content)
|
|
if err == nil {
|
|
t.Fatal("expected error for empty up block, got nil")
|
|
}
|
|
})
|
|
|
|
t.Run("version cero retorna error", func(t *testing.T) {
|
|
_, err := MigrationParse("000_something.sql", "-- +up\nCREATE TABLE x (id TEXT);\n")
|
|
if err == nil {
|
|
t.Fatal("expected error for version 0, got nil")
|
|
}
|
|
})
|
|
|
|
t.Run("nombre descriptivo vacio retorna error", func(t *testing.T) {
|
|
_, err := MigrationParse("001_.sql", "-- +up\nCREATE TABLE x (id TEXT);\n")
|
|
if err == nil {
|
|
t.Fatal("expected error for empty descriptive name, got nil")
|
|
}
|
|
})
|
|
|
|
t.Run("filename con path completo extrae nombre base", func(t *testing.T) {
|
|
content := "-- +up\nCREATE TABLE x (id TEXT PRIMARY KEY);\n-- +down\nDROP TABLE x;\n"
|
|
m, err := MigrationParse("apps/my_app/migrations/003_add_index.sql", content)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if m.Version != 3 {
|
|
t.Errorf("Version: got %d, want 3", m.Version)
|
|
}
|
|
if m.Name != "add_index" {
|
|
t.Errorf("Name: got %q, want %q", m.Name, "add_index")
|
|
}
|
|
})
|
|
}
|