test(10-01): add failing events create calendar tests

This commit is contained in:
Arthur Belleville 2026-05-16 00:24:33 +02:00
parent a15596cd09
commit 4fbd960621
No known key found for this signature in database

View file

@ -0,0 +1,184 @@
package web
import (
"context"
"net/http"
"net/http/httptest"
"net/url"
"os"
"strings"
"testing"
"backend/internal/auth"
"backend/internal/db/sqlc"
"github.com/jackc/pgx/v5/pgtype"
)
func newEventTestRouter(q *sqlc.Queries, store *auth.Store) http.Handler {
authDeps := AuthDeps{Queries: q, Store: store, Secure: false}
tabloDeps := TablosDeps{Queries: q}
taskDeps := TasksDeps{Queries: q}
etapeDeps := EtapesDeps{Queries: q}
eventDeps := EventsDeps{Queries: q}
router, err := NewRouter(stubPinger{}, os.DirFS("./static"), authDeps, tabloDeps, taskDeps, etapeDeps, eventDeps, FilesDeps{Queries: q}, testCSRFKey, "dev", "localhost")
if err != nil {
panic("newEventTestRouter: " + err.Error())
}
return router
}
func insertEventTestTablo(t *testing.T, ctx context.Context, q *sqlc.Queries, user sqlc.User, title string) sqlc.Tablo {
t.Helper()
tablo, err := q.InsertTablo(ctx, sqlc.InsertTabloParams{
UserID: user.ID,
Title: title,
Description: pgtype.Text{Valid: false},
Color: pgtype.Text{Valid: false},
})
if err != nil {
t.Fatalf("InsertTablo: %v", err)
}
return tablo
}
func sessionCookieForUser(t *testing.T, ctx context.Context, store *auth.Store, user sqlc.User) *http.Cookie {
t.Helper()
cookieVal, _, err := store.Create(ctx, user.ID)
if err != nil {
t.Fatalf("store.Create: %v", err)
}
return &http.Cookie{Name: auth.SessionCookieName, Value: cookieVal}
}
func TestEventsTabRendersMonthGrid(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, "eventsgrid@example.com", "correct-horse-12")
tablo := insertEventTestTablo(t, ctx, q, user, "Events Grid Tablo")
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 /tablos/{id}/events status = %d; want 200", rec.Code)
}
body := rec.Body.String()
for _, want := range []string{"Events", "May 2026", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "New event"} {
if !strings.Contains(body, want) {
t.Errorf("events calendar missing %q; body: %.800s", want, body)
}
}
}
func TestEventCreateRendersTitleInCalendar(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, "eventcreate@example.com", "correct-horse-12")
tablo := insertEventTestTablo(t, ctx, q, user, "Event Create Tablo")
sessionCookie := sessionCookieForUser(t, ctx, store, user)
csrfToken, csrfCookies := getCSRFToken(t, router, "/tablos/"+tablo.ID.String()+"/events?month=2026-05", []*http.Cookie{sessionCookie})
form := url.Values{
"title": {"Kickoff"},
"event_date": {"2026-05-20"},
"start_time": {"09:30"},
"end_time": {""},
"location": {"Office"},
"description": {"Planning"},
"_csrf": {csrfToken},
}
req := httptest.NewRequest(http.MethodPost, "/tablos/"+tablo.ID.String()+"/events?month=2026-05", strings.NewReader(form.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("HX-Request", "true")
for _, c := range csrfCookies {
req.AddCookie(c)
}
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("POST /tablos/{id}/events status = %d; want 200; body: %.500s", rec.Code, rec.Body.String())
}
if !strings.Contains(rec.Body.String(), "Kickoff") {
t.Fatalf("created event title missing from refreshed calendar; body: %.800s", rec.Body.String())
}
}
func TestEventCreateRejectsEndTimeBeforeOrEqualStart(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, "eventinvalid@example.com", "correct-horse-12")
tablo := insertEventTestTablo(t, ctx, q, user, "Event Invalid Tablo")
sessionCookie := sessionCookieForUser(t, ctx, store, user)
csrfToken, csrfCookies := getCSRFToken(t, router, "/tablos/"+tablo.ID.String()+"/events?month=2026-05", []*http.Cookie{sessionCookie})
form := url.Values{
"title": {"Invalid"},
"event_date": {"2026-05-20"},
"start_time": {"10:00"},
"end_time": {"10:00"},
"_csrf": {csrfToken},
}
req := httptest.NewRequest(http.MethodPost, "/tablos/"+tablo.ID.String()+"/events?month=2026-05", strings.NewReader(form.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("HX-Request", "true")
for _, c := range csrfCookies {
req.AddCookie(c)
}
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
if rec.Code != http.StatusUnprocessableEntity {
t.Fatalf("invalid event create status = %d; want 422", rec.Code)
}
if !strings.Contains(rec.Body.String(), "End time must be after the start time.") {
t.Fatalf("validation copy missing; body: %.800s", rec.Body.String())
}
}
func TestEventsTabOwnershipReturns404(t *testing.T) {
pool, cleanup := setupTestDB(t)
defer cleanup()
ctx := context.Background()
q := sqlc.New(pool)
store := auth.NewStore(q)
router := newEventTestRouter(q, store)
owner := preInsertUser(t, ctx, q, "eventsowner@example.com", "correct-horse-12")
nonOwner := preInsertUser(t, ctx, q, "eventsnonowner@example.com", "correct-horse-12")
tablo := insertEventTestTablo(t, ctx, q, owner, "Private Events Tablo")
nonOwnerCookie := sessionCookieForUser(t, ctx, store, nonOwner)
req := httptest.NewRequest(http.MethodGet, "/tablos/"+tablo.ID.String()+"/events?month=2026-05", nil)
req.AddCookie(nonOwnerCookie)
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
if rec.Code != http.StatusNotFound {
t.Fatalf("non-owner GET /tablos/{id}/events status = %d; want 404", rec.Code)
}
}