package db import ( "context" "io" "log/slog" "os" "testing" ) // TestMigrateAgainstPostgres runs the embedded migrations against a real // Postgres indicated by MINSTREL_TEST_DATABASE_URL. Intended flow for local // development: `docker compose up -d postgres` then // `MINSTREL_TEST_DATABASE_URL=postgres://minstrel:minstrel@localhost:5432/minstrel?sslmode=disable go test ./...`. // Skipped in `-short` mode (which is what CI runs) and when the env var is unset. func TestMigrateAgainstPostgres(t *testing.T) { if testing.Short() { t.Skip("skipping migration test in -short mode") } dsn := os.Getenv("MINSTREL_TEST_DATABASE_URL") if dsn == "" { t.Skip("MINSTREL_TEST_DATABASE_URL not set; skipping") } logger := slog.New(slog.NewTextHandler(io.Discard, nil)) if err := Migrate(dsn, logger); err != nil { t.Fatalf("first Migrate: %v", err) } if err := Migrate(dsn, logger); err != nil { t.Fatalf("second Migrate (idempotency): %v", err) } pool, err := Open(context.Background(), dsn) if err != nil { t.Fatalf("Open: %v", err) } defer pool.Close() var count int if err := pool.QueryRow(context.Background(), `SELECT count(*) FROM schema_migrations`).Scan(&count); err != nil { t.Fatalf("query schema_migrations: %v", err) } if count == 0 { t.Fatal("schema_migrations empty after Migrate") } } func TestMigrationsFSListsFiles(t *testing.T) { entries, err := migrationsFS.ReadDir("migrations") if err != nil { t.Fatalf("read embedded dir: %v", err) } if len(entries) == 0 { t.Fatal("no migration files embedded") } }