// SPDX-License-Identifier: AGPL-3.0-or-later package render import ( "context" "net/http" "net/http/httptest" "strings" "testing" "kode.naiv.no/olemd/favoritter/internal/config" ) func testRenderer(t *testing.T) *Renderer { t.Helper() cfg := &config.Config{ SiteName: "Test Site", BasePath: "/test", } r, err := New(cfg) if err != nil { t.Fatalf("create renderer: %v", err) } return r } func TestRenderPage(t *testing.T) { r := testRenderer(t) req := httptest.NewRequest("GET", "/", nil) rr := httptest.NewRecorder() r.Page(rr, req, "login", PageData{ Title: "Logg inn", }) if rr.Code != http.StatusOK { t.Errorf("render page: got %d, want 200", rr.Code) } body := rr.Body.String() if !strings.Contains(body, "Logg inn") { t.Error("page should contain title") } ct := rr.Header().Get("Content-Type") if !strings.Contains(ct, "text/html") { t.Errorf("content-type = %q, want text/html", ct) } } func TestRenderPageWithData(t *testing.T) { r := testRenderer(t) req := httptest.NewRequest("GET", "/", nil) rr := httptest.NewRecorder() r.Page(rr, req, "login", PageData{ Title: "Test Page", SiteName: "My Site", BasePath: "/base", }) body := rr.Body.String() if !strings.Contains(body, "Test Page") { t.Error("should contain title in output") } } func TestRenderMissingTemplate(t *testing.T) { r := testRenderer(t) req := httptest.NewRequest("GET", "/", nil) rr := httptest.NewRecorder() r.Page(rr, req, "nonexistent_template_xyz", PageData{}) if rr.Code != http.StatusInternalServerError { t.Errorf("missing template: got %d, want 500", rr.Code) } } func TestRenderErrorPage(t *testing.T) { r := testRenderer(t) req := httptest.NewRequest("GET", "/", nil) rr := httptest.NewRecorder() r.Error(rr, req, http.StatusNotFound, "Ikke funnet") if rr.Code != http.StatusNotFound { t.Errorf("error page: got %d, want 404", rr.Code) } body := rr.Body.String() if !strings.Contains(body, "Ikke funnet") { t.Error("error page should contain message") } } func TestRenderPopulatesCommonData(t *testing.T) { cfg := &config.Config{ SiteName: "Favoritter", BasePath: "/app", ExternalURL: "https://example.com", } r, err := New(cfg) if err != nil { t.Fatalf("create renderer: %v", err) } req := httptest.NewRequest("GET", "/", nil) // Add a CSRF token to the context. type contextKey string ctx := context.WithValue(req.Context(), contextKey("csrf_token"), "test-token") req = req.WithContext(ctx) rr := httptest.NewRecorder() r.Page(rr, req, "login", PageData{Title: "Test"}) // BasePath and SiteName should be populated from config. body := rr.Body.String() if !strings.Contains(body, "/app") { t.Error("should contain basePath from config") } } func TestTemplateFuncs(t *testing.T) { cfg := &config.Config{BasePath: "/test", ExternalURL: "https://example.com"} r, _ := New(cfg) funcs := r.templateFuncs() // Test truncate function. truncate := funcs["truncate"].(func(int, string) string) if got := truncate(5, "Hello, world!"); got != "Hello..." { t.Errorf("truncate(5, long) = %q, want Hello...", got) } if got := truncate(20, "Short"); got != "Short" { t.Errorf("truncate(20, short) = %q, want Short", got) } // Test with Norwegian characters (Ærlig = 5 runes: Æ r l i g). if got := truncate(3, "Ærlig"); got != "Ærl..." { t.Errorf("truncate(3, Ærlig) = %q, want Ærl...", got) } // Test add/subtract. add := funcs["add"].(func(int, int) int) if add(2, 3) != 5 { t.Error("add(2,3) should be 5") } sub := funcs["subtract"].(func(int, int) int) if sub(5, 3) != 2 { t.Error("subtract(5,3) should be 2") } // Test basePath function. bp := funcs["basePath"].(func() string) if bp() != "/test" { t.Errorf("basePath() = %q", bp()) } }