package server import ( "net/http" "net/http/httptest" "os" "path/filepath" "strings" "testing" "time" ) func TestRenderCounter(t *testing.T) { html := renderCounter(7) if !strings.Contains(html, "Clicks:") { t.Fatalf("expected counter markup to include label") } if !strings.Contains(html, "> 7<") { t.Fatalf("expected counter value in markup, got %q", html) } } func TestRenderTime(t *testing.T) { now := time.Date(2024, time.August, 1, 12, 34, 56, 0, time.UTC) html := renderTime(now) expected := "2024-08-01 12:34:56" if !strings.Contains(html, expected) { t.Fatalf("expected formatted timestamp %s in markup", expected) } } func TestCounterEndpoint(t *testing.T) { srv := mustNewServer(t, nil) req := httptest.NewRequest(http.MethodPost, "/counter", nil) resp := httptest.NewRecorder() srv.Router().ServeHTTP(resp, req) if resp.Code != http.StatusOK { t.Fatalf("expected status 200, got %d", resp.Code) } body := resp.Body.String() if !strings.Contains(body, "> 1<") { t.Fatalf("expected counter to increment to 1, body: %q", body) } } func TestNotFound(t *testing.T) { srv := mustNewServer(t, nil) req := httptest.NewRequest(http.MethodGet, "/unknown", nil) resp := httptest.NewRecorder() srv.Router().ServeHTTP(resp, req) if resp.Code != http.StatusNotFound { t.Fatalf("expected 404, got %d", resp.Code) } if !strings.Contains(resp.Body.String(), "Route /unknown not found.") { t.Fatalf("expected not found message, got %q", resp.Body.String()) } } func TestStaticFileServing(t *testing.T) { srv := mustNewServer(t, nil) req := httptest.NewRequest(http.MethodGet, "/static/lib/htmx.2.0.7.min.js", nil) resp := httptest.NewRecorder() srv.Router().ServeHTTP(resp, req) if resp.Code != http.StatusOK { t.Fatalf("expected static asset to load, got status %d", resp.Code) } if resp.Body.Len() == 0 { t.Fatalf("expected static asset response body") } } func TestMediaServing(t *testing.T) { var demoName string srv := mustNewServer(t, func(dir string) { demoName = filepath.Join(dir, "demo.txt") if err := os.WriteFile(demoName, []byte("demo media file"), 0o644); err != nil { t.Fatalf("failed to seed media file: %v", err) } }) req := httptest.NewRequest(http.MethodGet, "/media/demo.txt", nil) resp := httptest.NewRecorder() srv.Router().ServeHTTP(resp, req) if resp.Code != http.StatusOK { t.Fatalf("expected public asset to load, got status %d", resp.Code) } body := resp.Body.String() if !strings.Contains(body, "demo media file") { t.Fatalf("unexpected asset body: %q", body) } } func TestNewRequiresMediaDir(t *testing.T) { if _, err := New(Config{}); err == nil { t.Fatalf("expected error when media dir is empty") } missing := filepath.Join(t.TempDir(), "missing") if _, err := New(Config{MediaDir: missing}); err == nil { t.Fatalf("expected error when media dir does not exist") } } func mustNewServer(t *testing.T, setup func(string)) *Server { t.Helper() mediaDir := t.TempDir() if setup != nil { setup(mediaDir) } srv, err := New(Config{MediaDir: mediaDir}) if err != nil { t.Fatalf("failed to create server: %v", err) } return srv }