Files
summercms/modules/cabana/locale_order_test.go
Jakub Zych 837922cf43 test(cabana): relation subquery and locale order coverage
- TestListRelationSQL: DryRun matrix for belongsToMany (incl. custom pivot keys and self-reference), hasMany, hasOne and belongsTo search and sort, soft delete, 422 refusals, bound and LIKE-escaped search values, no outer JOIN next to ListExtendQuery and scope predicates
- TestListRelationSearchPostgres: exact total through two matching tags, string_agg sort order and hasMany search on Postgres
- TestEnabledLocalesDefaultFirst: default-locale ordering cases
2026-10-09 22:47:57 +02:00

136 lines
4.9 KiB
Go

package cabana
import (
"context"
"errors"
"slices"
"testing"
"git.golem15.com/golem15/summercms/modules/backpack"
"gorm.io/gorm"
)
// TestEnabledLocalesDefaultFirstSmoke pins D-03: the form schema lists the
// default locale first, so every ML control opens on the locale whose values
// live in the host columns, whatever order the writer keeps.
func TestEnabledLocalesDefaultFirstSmoke(t *testing.T) {
db, _ := openDryRunDB(t)
app := backpack.New(nil)
if err := app.Publish(db); err != nil {
t.Fatal(err)
}
if err := app.Publish[TranslationWriter](&recordingWriter{defaultLocale: "pl", enabled: []string{"en", "pl"}}); err != nil {
t.Fatal(err)
}
svc := &service{app: app}
if got := svc.enabledContentLocales(context.Background()); !slices.Equal(got, []string{"pl", "en"}) {
t.Fatalf("enabledContentLocales = %v, want [pl en]", got)
}
}
// failingDefaultWriter answers its enabled locales but fails DefaultLocale.
type failingDefaultWriter struct{ recordingWriter }
func (w *failingDefaultWriter) DefaultLocale(context.Context, *gorm.DB) (string, error) {
return "", errors.New("default locale unavailable")
}
// failingEnabledWriter fails EnabledLocales.
type failingEnabledWriter struct{ recordingWriter }
func (w *failingEnabledWriter) EnabledLocales(context.Context, *gorm.DB) ([]string, error) {
return nil, errors.New("enabled locales unavailable")
}
// TestEnabledLocalesDefaultFirst covers every ordering case of
// enabledContentLocales (D-03): the default moves to the front, the other
// codes keep the writer's order, and a missing or failing default leaves
// the writer's order alone.
func TestEnabledLocalesDefaultFirst(t *testing.T) {
cases := []struct {
name string
writer TranslationWriter
want []string
}{
{"default not first", &recordingWriter{defaultLocale: "pl", enabled: []string{"en", "pl"}}, []string{"pl", "en"}},
{"default already first", &recordingWriter{defaultLocale: "pl", enabled: []string{"pl", "en"}}, []string{"pl", "en"}},
{"default absent from the list", &recordingWriter{defaultLocale: "fr", enabled: []string{"en", "pl"}}, []string{"en", "pl"}},
{"empty default", &recordingWriter{defaultLocale: "", enabled: []string{"en", "pl"}}, []string{"en", "pl"}},
{"DefaultLocale error keeps the order", &failingDefaultWriter{recordingWriter{defaultLocale: "pl", enabled: []string{"en", "pl"}}}, []string{"en", "pl"}},
{"three locales keep their relative order", &recordingWriter{defaultLocale: "pl", enabled: []string{"en", "de", "pl"}}, []string{"pl", "en", "de"}},
{"default in the middle", &recordingWriter{defaultLocale: "de", enabled: []string{"en", "de", "pl"}}, []string{"de", "en", "pl"}},
{"single locale", &recordingWriter{defaultLocale: "pl", enabled: []string{"pl"}}, []string{"pl"}},
{"EnabledLocales error", &failingEnabledWriter{recordingWriter{defaultLocale: "pl"}}, nil},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
db, _ := openDryRunDB(t)
app := backpack.New(nil)
if err := app.Publish(db); err != nil {
t.Fatal(err)
}
if err := app.Publish[TranslationWriter](tc.writer); err != nil {
t.Fatal(err)
}
svc := &service{app: app}
got := svc.enabledContentLocales(context.Background())
if !slices.Equal(got, tc.want) {
t.Fatalf("enabledContentLocales = %v, want %v", got, tc.want)
}
})
}
t.Run("the writer's slice is not reordered in place", func(t *testing.T) {
db, _ := openDryRunDB(t)
app := backpack.New(nil)
if err := app.Publish(db); err != nil {
t.Fatal(err)
}
enabled := []string{"en", "de", "pl"}
if err := app.Publish[TranslationWriter](&sharedSliceWriter{defaultLocale: "pl", enabled: enabled}); err != nil {
t.Fatal(err)
}
svc := &service{app: app}
if got := svc.enabledContentLocales(context.Background()); !slices.Equal(got, []string{"pl", "en", "de"}) {
t.Fatalf("enabledContentLocales = %v", got)
}
if !slices.Equal(enabled, []string{"en", "de", "pl"}) {
t.Fatalf("writer slice changed to %v", enabled)
}
})
t.Run("no published writer", func(t *testing.T) {
db, _ := openDryRunDB(t)
app := backpack.New(nil)
if err := app.Publish(db); err != nil {
t.Fatal(err)
}
svc := &service{app: app}
if got := svc.enabledContentLocales(context.Background()); got != nil {
t.Fatalf("enabledContentLocales = %v, want nil", got)
}
})
t.Run("no app", func(t *testing.T) {
if got := (&service{}).enabledContentLocales(context.Background()); got != nil {
t.Fatalf("enabledContentLocales = %v, want nil", got)
}
})
}
// sharedSliceWriter returns its own enabled slice, not a copy, so a test can
// see whether the caller reorders it in place.
type sharedSliceWriter struct {
recordingWriter
defaultLocale string
enabled []string
}
func (w *sharedSliceWriter) DefaultLocale(context.Context, *gorm.DB) (string, error) {
return w.defaultLocale, nil
}
func (w *sharedSliceWriter) EnabledLocales(context.Context, *gorm.DB) ([]string, error) {
return w.enabled, nil
}