|
|
@@ -0,0 +1,102 @@
|
|
|
+// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
|
|
|
+// SPDX-License-Identifier: Apache-2.0
|
|
|
+
|
|
|
+package ui // import "miniflux.app/v2/internal/ui"
|
|
|
+
|
|
|
+import (
|
|
|
+ "net/http"
|
|
|
+ "net/http/httptest"
|
|
|
+ "testing"
|
|
|
+
|
|
|
+ "miniflux.app/v2/internal/config"
|
|
|
+)
|
|
|
+
|
|
|
+func configureTestOptions(t *testing.T, env map[string]string) {
|
|
|
+ t.Helper()
|
|
|
+
|
|
|
+ for key, value := range env {
|
|
|
+ t.Setenv(key, value)
|
|
|
+ }
|
|
|
+
|
|
|
+ parsedOptions, err := config.NewConfigParser().ParseEnvironmentVariables()
|
|
|
+ if err != nil {
|
|
|
+ t.Fatalf(`Unable to configure test options: %v`, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ previousOptions := config.Opts
|
|
|
+ config.Opts = parsedOptions
|
|
|
+ t.Cleanup(func() {
|
|
|
+ config.Opts = previousOptions
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+func TestSetPreferencesCookie(t *testing.T) {
|
|
|
+ scenarios := []struct {
|
|
|
+ name string
|
|
|
+ env map[string]string
|
|
|
+ wantPath string
|
|
|
+ wantSecure bool
|
|
|
+ }{
|
|
|
+ {"defaults", map[string]string{}, "/", false},
|
|
|
+ {"base path over HTTPS", map[string]string{"BASE_URL": "https://example.org/reader", "HTTPS": "1"}, "/reader", true},
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, scenario := range scenarios {
|
|
|
+ t.Run(scenario.name, func(t *testing.T) {
|
|
|
+ configureTestOptions(t, scenario.env)
|
|
|
+
|
|
|
+ w := httptest.NewRecorder()
|
|
|
+ setPreferencesCookie(w, "de_DE", "dark_serif")
|
|
|
+
|
|
|
+ cookies := w.Result().Cookies()
|
|
|
+ if len(cookies) != 1 {
|
|
|
+ t.Fatalf(`Expected one cookie, got %d`, len(cookies))
|
|
|
+ }
|
|
|
+
|
|
|
+ cookie := cookies[0]
|
|
|
+ if cookie.Name != preferencesCookieName || cookie.Value != "de_DE.dark_serif" {
|
|
|
+ t.Errorf(`Unexpected cookie: %s=%s`, cookie.Name, cookie.Value)
|
|
|
+ }
|
|
|
+ if cookie.Path != scenario.wantPath {
|
|
|
+ t.Errorf(`Unexpected path, got %q, want %q`, cookie.Path, scenario.wantPath)
|
|
|
+ }
|
|
|
+ if cookie.Secure != scenario.wantSecure {
|
|
|
+ t.Errorf(`Unexpected Secure attribute, got %v, want %v`, cookie.Secure, scenario.wantSecure)
|
|
|
+ }
|
|
|
+ if !cookie.HttpOnly || cookie.SameSite != http.SameSiteLaxMode {
|
|
|
+ t.Errorf(`Expected an HttpOnly cookie with SameSite=Lax`)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestPreferencesFromCookie(t *testing.T) {
|
|
|
+ scenarios := []struct {
|
|
|
+ name string
|
|
|
+ value string
|
|
|
+ wantLanguage string
|
|
|
+ wantTheme string
|
|
|
+ wantOK bool
|
|
|
+ }{
|
|
|
+ {"valid", "de_DE.dark_serif", "de_DE", "dark_serif", true},
|
|
|
+ {"unknown language", "xx_XX.dark_serif", "", "", false},
|
|
|
+ {"unknown theme", "de_DE.neon", "", "", false},
|
|
|
+ {"missing separator", "de_DE", "", "", false},
|
|
|
+ {"empty", "", "", "", false},
|
|
|
+ {"no cookie", "", "", "", false},
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, scenario := range scenarios {
|
|
|
+ t.Run(scenario.name, func(t *testing.T) {
|
|
|
+ r := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
|
+ if scenario.name != "no cookie" {
|
|
|
+ r.AddCookie(&http.Cookie{Name: preferencesCookieName, Value: scenario.value})
|
|
|
+ }
|
|
|
+
|
|
|
+ language, theme, ok := preferencesFromCookie(r)
|
|
|
+ if language != scenario.wantLanguage || theme != scenario.wantTheme || ok != scenario.wantOK {
|
|
|
+ t.Errorf(`Got (%q, %q, %v), want (%q, %q, %v)`, language, theme, ok, scenario.wantLanguage, scenario.wantTheme, scenario.wantOK)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|