package config import ( "os" "strings" "testing" ) func TestLoadDefaultsLegacyInstallationToEmbeddedShell(t *testing.T) { for _, profile := range []string{"local", "server"} { t.Run(profile, func(t *testing.T) { path, _, _, _ := writeInstallation(t, profile) installation, err := Load(path) if err != nil { t.Fatal(err) } if got, want := installation.Shell, (Shell{Mode: "embedded", DefaultLocale: "en", Adapter: "omics-portal"}); got != want { t.Fatalf("Shell = %#v, want %#v", got, want) } }) } } func TestLoadResolvesExplicitShell(t *testing.T) { for _, test := range []struct { name, yaml string want Shell }{ {"empty mapping", "shell: {}\n", Shell{Mode: "embedded", DefaultLocale: "en", Adapter: "omics-portal"}}, {"embedded Italian", "shell:\n mode: embedded\n defaultLocale: it\n", Shell{Mode: "embedded", DefaultLocale: "it", Adapter: "omics-portal"}}, {"full defaults", "shell:\n mode: full\n", Shell{Mode: "full", DefaultLocale: "en"}}, {"full ignores known adapter", "shell:\n mode: full\n defaultLocale: it\n adapter: omics-portal\n", Shell{Mode: "full", DefaultLocale: "it"}}, } { t.Run(test.name, func(t *testing.T) { path, _, _, _ := writeInstallation(t, "local") appendShellDescriptor(t, path, test.yaml) installation, err := Load(path) if err != nil { t.Fatal(err) } if installation.Shell != test.want { t.Fatalf("Shell = %#v, want %#v", installation.Shell, test.want) } }) } } func TestLoadRejectsInvalidShell(t *testing.T) { for _, test := range []struct{ name, yaml, errorPart string }{ {"unknown mode", "shell:\n mode: fullscreen\n", "shell.mode"}, {"mode whitespace", "shell:\n mode: ' full '\n", "shell.mode"}, {"malformed locale separator", "shell:\n defaultLocale: en_US\n", "shell.defaultLocale"}, {"malformed locale", "shell:\n defaultLocale: 'en;alert(1)'\n", "shell.defaultLocale"}, {"unknown adapter", "shell:\n adapter: other-portal\n", "shell.adapter"}, {"unknown adapter in full", "shell:\n mode: full\n adapter: other-portal\n", "shell.adapter"}, {"wrong shape", "shell: []\n", "cannot unmarshal"}, {"wrong field type", "shell:\n mode: [full]\n", "cannot unmarshal"}, {"unknown field", "shell:\n theme: light\n", "field theme not found"}, } { t.Run(test.name, func(t *testing.T) { path, _, _, _ := writeInstallation(t, "local") appendShellDescriptor(t, path, test.yaml) if _, err := Load(path); err == nil || !strings.Contains(err.Error(), test.errorPart) { t.Fatalf("Load() error = %v, want %q", err, test.errorPart) } }) } } func TestLoadPreservesWellFormedShellLocalesWithoutCatalogLookup(t *testing.T) { for _, locale := range []string{ "fr", "de-DE", "en-US", "sr-Latn-RS", "es-419", "zh-cmn-Hans-CN", "sl-rozaj-biske", "de-CH-1901", "en-US-u-ca-gregory", "en-a-foo-b-bar-x-private", "x-clinical", "en-x-a-a", "qaa-Qaaa-QM", "zzzz", "abcde", "EN-us", "en-GB-oed", "i-klingon", "sgn-BE-FR", "zh-min-nan", } { t.Run(locale, func(t *testing.T) { path, _, _, _ := writeInstallation(t, "local") appendShellDescriptor(t, path, "shell:\n mode: full\n defaultLocale: "+locale+"\n") installation, err := Load(path) if err != nil || installation.Shell.DefaultLocale != locale { t.Fatalf("Load() locale = %q, %v; want preserved %q", installation.Shell.DefaultLocale, err, locale) } }) } } func TestLoadRejectsMalformedShellLocales(t *testing.T) { for _, locale := range []string{ "en_US", "en--US", "-en", "en-", "e", "123", "en-1234a5678", "en-12", "en-US-Latn", "en-u", "en-x", "x", "a-foo", "i-unknown", "en-äbc", "en-Kaaa", "en US", " en", "en;alert(1)", "sl-rozaj-ROZAJ", "en-a-foo-A-bar", } { t.Run(locale, func(t *testing.T) { path, _, _, _ := writeInstallation(t, "local") appendShellDescriptor(t, path, "shell:\n defaultLocale: '"+locale+"'\n") if _, err := Load(path); err == nil || !strings.Contains(err.Error(), "shell.defaultLocale") { t.Fatalf("Load() error = %v; want invalid locale %q rejected", err, locale) } }) } } func appendShellDescriptor(t *testing.T, path, shell string) { t.Helper() contents, err := os.ReadFile(path) if err != nil { t.Fatal(err) } if err := os.WriteFile(path, append(contents, []byte(shell)...), 0o600); err != nil { t.Fatal(err) } }