Files
fn_registry/functions/infra/migration_integration_test.go
T

115 lines
3.3 KiB
Go

package infra
import (
"os"
"path/filepath"
"testing"
)
// TestMigrationIntegration covers the full create -> up -> status -> down -> status cycle.
func TestMigrationIntegration(t *testing.T) {
t.Run("ciclo completo create up status down status", func(t *testing.T) {
db := openMigrationTestDB(t)
dir := t.TempDir()
// Step 1: Create migration files using MigrationCreate
path1, err := MigrationCreate(dir, "create_users")
if err != nil {
t.Fatalf("create 001 failed: %v", err)
}
path2, err := MigrationCreate(dir, "create_roles")
if err != nil {
t.Fatalf("create 002 failed: %v", err)
}
// Fill in actual SQL
sql1 := "-- 001_create_users.sql\n\n-- +up\nCREATE TABLE users (id TEXT PRIMARY KEY, name TEXT NOT NULL);\n\n-- +down\nDROP TABLE IF EXISTS users;\n"
if err := os.WriteFile(path1, []byte(sql1), 0o644); err != nil {
t.Fatalf("write sql1: %v", err)
}
sql2 := "-- 002_create_roles.sql\n\n-- +up\nCREATE TABLE roles (id TEXT PRIMARY KEY, label TEXT NOT NULL);\n\n-- +down\nDROP TABLE IF EXISTS roles;\n"
if err := os.WriteFile(path2, []byte(sql2), 0o644); err != nil {
t.Fatalf("write sql2: %v", err)
}
// Step 2: Parse and validate
content1, _ := os.ReadFile(filepath.Join(dir, "001_create_users.sql"))
content2, _ := os.ReadFile(filepath.Join(dir, "002_create_roles.sql"))
m1, err := MigrationParse("001_create_users.sql", string(content1))
if err != nil {
t.Fatalf("parse 001: %v", err)
}
m2, err := MigrationParse("002_create_roles.sql", string(content2))
if err != nil {
t.Fatalf("parse 002: %v", err)
}
validationErrs := MigrationValidate([]Migration{m1, m2})
if len(validationErrs) > 0 {
t.Fatalf("validate failed: %v", validationErrs)
}
// Step 3: Apply up
applied, err := MigrationUp(db, dir)
if err != nil {
t.Fatalf("up failed: %v", err)
}
if len(applied) != 2 {
t.Errorf("up: expected 2 applied, got %d", len(applied))
}
// Step 4: Check status — all applied
statuses, err := MigrationGetStatus(db, dir)
if err != nil {
t.Fatalf("status after up failed: %v", err)
}
if len(statuses) != 2 {
t.Errorf("status: expected 2, got %d", len(statuses))
}
for _, s := range statuses {
if !s.Applied {
t.Errorf("version %d should be applied", s.Version)
}
}
// Step 5: Revert the last migration
reverted, err := MigrationDown(db, 1)
if err != nil {
t.Fatalf("down failed: %v", err)
}
if len(reverted) != 1 || reverted[0].Version != 2 {
t.Errorf("down: expected version 2, got %v", reverted)
}
// Step 6: Check status — one applied, one pending
statuses2, err := MigrationGetStatus(db, dir)
if err != nil {
t.Fatalf("status after down failed: %v", err)
}
if len(statuses2) != 2 {
t.Errorf("status2: expected 2, got %d", len(statuses2))
}
// Version 1 should be applied, version 2 pending
for _, s := range statuses2 {
switch s.Version {
case 1:
if !s.Applied {
t.Errorf("version 1 should still be applied")
}
case 2:
if s.Applied {
t.Errorf("version 2 should be pending after down")
}
}
}
// Step 7: Re-apply — should apply version 2 again
applied2, err := MigrationUp(db, dir)
if err != nil {
t.Fatalf("second up failed: %v", err)
}
if len(applied2) != 1 || applied2[0].Version != 2 {
t.Errorf("second up: expected version 2, got %v", applied2)
}
})
}