package classes import ( "context" "strings" "testing" "git.golem15.com/golem15/sm-user-plugin/models" "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/compass" "git.golem15.com/golem15/summercms/modules/towel" ) func TestMailTemplate(t *testing.T) { base := "golem15.user::mail.reactivate" for _, tc := range []struct { locale, want string }{ {"pl", base}, {"", base}, {"en", base + "-en"}, {"en-GB", base + "-en"}, {"en-GB,en;q=0.9", base + "-en"}, {"de", base}, {"pl-PL,en;q=0.5", base}, } { if got := MailTemplate(base, tc.locale); got != tc.want { t.Errorf("MailTemplate(%q) = %s, want %s", tc.locale, got, tc.want) } } } func TestNormalizeMailLocale(t *testing.T) { for _, tc := range []struct { raw, want string }{ {"en", "en"}, {"pl", "pl"}, {"EN", "en"}, {"en-GB", "en"}, {"en_US", "en"}, {"pl-PL", "pl"}, {" en-gb ; q=0.9 ", "en"}, {"en-GB,en;q=0.9", "en"}, {"pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7", "pl"}, {"de-DE,de;q=0.9,en;q=0.8", "en"}, {"de-DE,en;q=0.5,pl;q=0.7", "pl"}, {"en;q=0.5,pl;q=0.5", "en"}, {"en;q=0,pl", "pl"}, {"en;q=0", ""}, {"en;q=abc,pl;q=0.1", "pl"}, {"en;q=1.5", ""}, {"english", ""}, {"de", ""}, {"*", ""}, {"", ""}, {" ", ""}, } { if got := NormalizeMailLocale(tc.raw); got != tc.want { t.Errorf("NormalizeMailLocale(%q) = %q, want %q", tc.raw, got, tc.want) } } } func TestResolveMailLocale(t *testing.T) { str := func(s string) *string { return &s } header := "en-GB,en;q=0.9" for _, tc := range []struct { name string saved *string nilUser bool request string want string }{ {"saved region form wins", str("en-GB"), false, "pl", "en"}, {"saved upper case", str("PL"), false, "", "pl"}, {"unsupported saved falls through", str("de"), false, header, "en"}, {"nil user, raw header", nil, true, header, "en"}, {"nil user, no request locale", nil, true, "", ""}, {"empty saved, unsupported request", str(""), false, "fr", ""}, } { ctx := context.Background() if tc.request != "" { ctx = towel.WithLocale(ctx, tc.request) } var user *models.User if !tc.nilUser { user = &models.User{PreferredLocale: tc.saved} } if got := ResolveMailLocale(ctx, user); got != tc.want { t.Errorf("%s: got %q, want %q", tc.name, got, tc.want) } } } func mailTestApp(t *testing.T, environ ...string) *backpack.App { t.Helper() cfg, err := compass.Open(compass.Options{Dir: t.TempDir(), Env: "development", Environ: append([]string{"SUMMER_ENV=development"}, environ...)}) if err != nil { t.Fatal(err) } return backpack.New(cfg) } func TestMailFallbackLocale(t *testing.T) { if got, err := MailFallbackLocale(nil); got != "pl" || err != nil { t.Errorf("nil app: %q %v", got, err) } if got, err := MailFallbackLocale(&backpack.App{}); got != "pl" || err != nil { t.Errorf("nil config: %q %v", got, err) } if got, err := MailFallbackLocale(mailTestApp(t)); got != "pl" || err != nil { t.Errorf("no key: %q %v", got, err) } for _, tc := range []struct { value, want string bad bool }{ {"", "pl", false}, {" ", "pl", false}, {"en", "en", false}, {"EN-gb", "en", false}, {"pl", "pl", false}, {"de", "pl", true}, } { app := mailTestApp(t) if err := app.Config.Set("golem15.user.mail.fallback_locale", tc.value); err != nil { t.Fatal(err) } got, err := MailFallbackLocale(app) if got != tc.want { t.Errorf("%q: got %q, want %q", tc.value, got, tc.want) } if tc.bad { if err == nil || !strings.Contains(err.Error(), "golem15.user.mail.fallback_locale") || !strings.Contains(err.Error(), `"de"`) { t.Errorf("%q: error %v", tc.value, err) } } else if err != nil { t.Errorf("%q: unexpected error %v", tc.value, err) } } app := mailTestApp(t, "SUMMER_GOLEM15__USER__MAIL__FALLBACK_LOCALE=en") if got, err := MailFallbackLocale(app); got != "en" || err != nil { t.Errorf("env override: %q %v", got, err) } } func TestResolveMailLocaleFor(t *testing.T) { const restore = "golem15.user::mail.restore" user := &models.User{} headerCtx := towel.WithLocale(context.Background(), "en-GB,en;q=0.9") // The reported bug: raw Accept-Language, no preferred_locale, default config. if got := MailTemplate(restore, ResolveMailLocaleFor(headerCtx, mailTestApp(t), user)); got != restore+"-en" { t.Errorf("raw header: %s", got) } if got := MailTemplate(restore, ResolveMailLocaleFor(context.Background(), mailTestApp(t), user)); got != restore { t.Errorf("default fallback: %s", got) } if got := ResolveMailLocaleFor(context.Background(), nil, nil); got != "pl" { t.Errorf("nil app and user: %q", got) } set := mailTestApp(t) if err := set.Config.Set("golem15.user.mail.fallback_locale", "en"); err != nil { t.Fatal(err) } if got := MailTemplate(restore, ResolveMailLocaleFor(context.Background(), set, user)); got != restore+"-en" { t.Errorf("fallback en via Set: %s", got) } env := mailTestApp(t, "SUMMER_GOLEM15__USER__MAIL__FALLBACK_LOCALE=en") if got := MailTemplate(restore, ResolveMailLocaleFor(context.Background(), env, user)); got != restore+"-en" { t.Errorf("fallback en via env: %s", got) } // The user and the request still come first. if got := ResolveMailLocaleFor(towel.WithLocale(context.Background(), "pl-PL,en;q=0.5"), set, user); got != "pl" { t.Errorf("Polish-first browser on an en fallback: %q", got) } bad := mailTestApp(t) if err := bad.Config.Set("golem15.user.mail.fallback_locale", "de"); err != nil { t.Fatal(err) } if got := ResolveMailLocaleFor(context.Background(), bad, user); got != "pl" { t.Errorf("invalid fallback: %q", got) } }