From 1d760d5540a5080a4709ecfed57d03dc2201a895 Mon Sep 17 00:00:00 2001 From: Arthur Belleville Date: Sat, 16 May 2026 00:36:40 +0200 Subject: [PATCH] test(10-04): add final events regression coverage --- backend/internal/web/handlers_events_test.go | 130 +++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/backend/internal/web/handlers_events_test.go b/backend/internal/web/handlers_events_test.go index 511aac5..1aed581 100644 --- a/backend/internal/web/handlers_events_test.go +++ b/backend/internal/web/handlers_events_test.go @@ -632,3 +632,133 @@ func TestListUserEventsRangeReturnsOnlyOwnedTablos(t *testing.T) { t.Fatalf("row tablo color = %#v; want #123abc", row.TabloColor) } } + +func TestTabloDetailEventsTabFullPageFallback(t *testing.T) { + pool, cleanup := setupTestDB(t) + defer cleanup() + + ctx := context.Background() + q := sqlc.New(pool) + store := auth.NewStore(q) + router := newEventTestRouter(q, store) + + user := preInsertUser(t, ctx, q, "eventfullpage@example.com", "correct-horse-12") + tablo := insertEventTestTablo(t, ctx, q, user, "Events Full Page Tablo") + sessionCookie := sessionCookieForUser(t, ctx, store, user) + + req := httptest.NewRequest(http.MethodGet, "/tablos/"+tablo.ID.String()+"/events?month=2026-05", nil) + req.AddCookie(sessionCookie) + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + + if rec.Code != http.StatusOK { + t.Fatalf("GET full events page status = %d; want 200; body: %.500s", rec.Code, rec.Body.String()) + } + body := rec.Body.String() + for _, want := range []string{"Back to tablos", "Overview", "Tasks", "Files", "Events", "May 2026", `id="tab-content"`} { + if !strings.Contains(body, want) { + t.Errorf("full events page missing %q; body: %.800s", want, body) + } + } +} + +func TestEventContentIsEscaped(t *testing.T) { + pool, cleanup := setupTestDB(t) + defer cleanup() + + ctx := context.Background() + q := sqlc.New(pool) + store := auth.NewStore(q) + router := newEventTestRouter(q, store) + + user := preInsertUser(t, ctx, q, "eventescaped@example.com", "correct-horse-12") + tablo := insertEventTestTablo(t, ctx, q, user, "Escaped Event Tablo") + insertEventTestEvent(t, ctx, q, tablo.ID, "", "2026-05-20", "09:30", "", "", "") + sessionCookie := sessionCookieForUser(t, ctx, store, user) + + req := httptest.NewRequest(http.MethodGet, "/tablos/"+tablo.ID.String()+"/events?month=2026-05", nil) + req.Header.Set("HX-Request", "true") + req.AddCookie(sessionCookie) + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + + if rec.Code != http.StatusOK { + t.Fatalf("GET escaped event status = %d; want 200; body: %.500s", rec.Code, rec.Body.String()) + } + body := rec.Body.String() + if strings.Contains(body, "") { + t.Fatalf("event title rendered as raw script; body: %.800s", body) + } + if !strings.Contains(body, "<script>alert(1)</script>") { + t.Fatalf("escaped event title missing; body: %.800s", body) + } +} + +func TestEventWithoutEndTimeDisplaysOnlyStartTime(t *testing.T) { + pool, cleanup := setupTestDB(t) + defer cleanup() + + ctx := context.Background() + q := sqlc.New(pool) + store := auth.NewStore(q) + router := newEventTestRouter(q, store) + + user := preInsertUser(t, ctx, q, "eventnoend@example.com", "correct-horse-12") + tablo := insertEventTestTablo(t, ctx, q, user, "No End Event Tablo") + event := insertEventTestEvent(t, ctx, q, tablo.ID, "Open End", "2026-05-20", "09:30", "", "", "") + sessionCookie := sessionCookieForUser(t, ctx, store, user) + + req := httptest.NewRequest(http.MethodGet, "/tablos/"+tablo.ID.String()+"/events/"+event.ID.String()+"/edit?month=2026-05", nil) + req.Header.Set("HX-Request", "true") + req.AddCookie(sessionCookie) + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + + if rec.Code != http.StatusOK { + t.Fatalf("GET event edit status = %d; want 200; body: %.500s", rec.Code, rec.Body.String()) + } + body := rec.Body.String() + if !strings.Contains(body, `name="start_time" value="09:30"`) { + t.Fatalf("start time missing for event without end time; body: %.800s", body) + } + if strings.Contains(body, "09:30-") || strings.Contains(body, "09:30 –") { + t.Fatalf("event without end time rendered an inferred range; body: %.800s", body) + } +} + +func TestEventsOrderedByStartTimeThenTitle(t *testing.T) { + pool, cleanup := setupTestDB(t) + defer cleanup() + + ctx := context.Background() + q := sqlc.New(pool) + store := auth.NewStore(q) + router := newEventTestRouter(q, store) + + user := preInsertUser(t, ctx, q, "eventorder@example.com", "correct-horse-12") + tablo := insertEventTestTablo(t, ctx, q, user, "Ordered Events Tablo") + insertEventTestEvent(t, ctx, q, tablo.ID, "Beta", "2026-05-20", "10:00", "", "", "") + insertEventTestEvent(t, ctx, q, tablo.ID, "Gamma", "2026-05-20", "09:00", "", "", "") + insertEventTestEvent(t, ctx, q, tablo.ID, "Alpha", "2026-05-20", "09:00", "", "", "") + sessionCookie := sessionCookieForUser(t, ctx, store, user) + + req := httptest.NewRequest(http.MethodGet, "/tablos/"+tablo.ID.String()+"/events?month=2026-05", nil) + req.Header.Set("HX-Request", "true") + req.AddCookie(sessionCookie) + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + + if rec.Code != http.StatusOK { + t.Fatalf("GET ordered events status = %d; want 200; body: %.500s", rec.Code, rec.Body.String()) + } + body := rec.Body.String() + alpha := strings.Index(body, "Alpha") + gamma := strings.Index(body, "Gamma") + beta := strings.Index(body, "Beta") + if alpha == -1 || gamma == -1 || beta == -1 { + t.Fatalf("ordered event titles missing; Alpha=%d Gamma=%d Beta=%d body: %.800s", alpha, gamma, beta, body) + } + if !(alpha < gamma && gamma < beta) { + t.Fatalf("events not ordered by start time then title; Alpha=%d Gamma=%d Beta=%d body: %.800s", alpha, gamma, beta, body) + } +}