Files
summercms/lagoon/migrations_test.go
Jakub Zych 8e3bf266d8 feat(03-03): add typed path params and per-plugin rollback
Compile regex and enum constraints at route registration so malformed and unknown IDs share a 404, and named rollback errors isolate one plugin's history.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 20:19:59 +02:00

126 lines
3.1 KiB
Go

package lagoon
import (
"bytes"
"errors"
"io"
"os"
"strings"
"testing"
"git.golem15.com/golem15/summercms/backpack"
"git.golem15.com/golem15/summercms/bonfire"
"git.golem15.com/golem15/summercms/party"
"gorm.io/gorm"
)
func TestHistoryTableName(t *testing.T) {
got, err := HistoryTableName("golem15.user")
if err != nil {
t.Fatal(err)
}
if got != "summer_migrations_golem15_user" {
t.Fatalf("got %q", got)
}
got, err = HistoryTableName("golem15.fonoteka")
if err != nil {
t.Fatal(err)
}
if got != "summer_migrations_golem15_fonoteka" {
t.Fatalf("got %q", got)
}
if _, err := HistoryTableName("golem15.user;drop"); err == nil {
t.Fatal("want invalid plugin id error")
}
if _, err := HistoryTableName(""); err == nil {
t.Fatal("want empty plugin id error")
}
}
func TestCheckLocaleMessage(t *testing.T) {
if err := checkLocale("i", "pl-PL"); err != nil {
t.Fatal(err)
}
err := checkLocale("c", "en_US")
if err == nil {
t.Fatal("want locale error")
}
msg := err.Error()
for _, want := range []string{"ICU", "pl-PL", "CREATE DATABASE", "LOCALE_PROVIDER icu", "en_US"} {
if !strings.Contains(msg, want) {
t.Fatalf("missing %q in %s", want, msg)
}
}
}
func TestRuntimeCommandsRegisterBareAndColonNames(t *testing.T) {
cmds := RuntimeCommands(nil, nil)
names := map[string]bool{}
for _, c := range cmds {
names[c.Name] = true
}
for _, want := range []string{"migrate", "migrate:rollback", "migrate:status"} {
if !names[want] {
t.Fatalf("missing %s", want)
}
}
root, err := bonfire.NewRoot("app", cmds, io.Discard)
if err != nil {
t.Fatal(err)
}
root.SetArgs([]string{"migrate", "--help"})
if err := root.Execute(); err != nil {
t.Fatal(err)
}
}
func TestNoAutoMigrate(t *testing.T) {
entries, err := os.ReadDir(".")
if err != nil {
t.Fatal(err)
}
for _, entry := range entries {
if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") || strings.HasSuffix(entry.Name(), "_test.go") {
continue
}
body, err := os.ReadFile(entry.Name())
if err != nil {
t.Fatal(err)
}
if bytes.Contains(body, []byte("AutoMigrate")) {
t.Fatalf("%s must not call AutoMigrate", entry.Name())
}
}
}
func TestOpenRequiresDSN(t *testing.T) {
_, _, err := Open(t.Context(), " ")
if err == nil || !strings.Contains(err.Error(), "database.dsn") {
t.Fatalf("got %v", err)
}
}
type stubPlugin struct{ id string }
func (s stubPlugin) ID() string { return s.id }
func (s stubPlugin) Requires() []string { return nil }
func (s stubPlugin) Register(*backpack.App) error { return nil }
func (s stubPlugin) Boot(*backpack.App) error { return nil }
func TestRollbackUnknownPluginIsNamedError(t *testing.T) {
err := RollbackLast(&gorm.DB{}, []party.Plugin{stubPlugin{id: "golem15.user"}}, "golem15.missing")
if !errors.Is(err, ErrUnknownPlugin) {
t.Fatalf("got %v", err)
}
if !strings.Contains(err.Error(), "golem15.missing") {
t.Fatalf("error should name plugin: %v", err)
}
}
func TestRollbackMissingPluginIsNamedError(t *testing.T) {
err := RollbackLast(&gorm.DB{}, nil, "")
if !errors.Is(err, ErrNoMigrations) {
t.Fatalf("got %v", err)
}
}