package session import ( "net/http" "net/http/httptest" "testing" "time" ) func TestManager_CreateAndValidate(t *testing.T) { mgr, err := NewManager("test-signing-key-12345", false) if err != nil { t.Fatalf("NewManager() error = %v", err) } // Create a session w := httptest.NewRecorder() if err := mgr.CreateSession(w); err != nil { t.Fatalf("CreateSession() error = %v", err) } // Extract the cookie from response resp := w.Result() cookies := resp.Cookies() if len(cookies) == 0 { t.Fatal("CreateSession() did not set a cookie") } var sessionCookie *http.Cookie for _, c := range cookies { if c.Name == CookieName { sessionCookie = c break } } if sessionCookie == nil { t.Fatalf("CreateSession() did not set cookie named %q", CookieName) } // Validate the session req := httptest.NewRequest(http.MethodGet, "/", nil) req.AddCookie(sessionCookie) data, err := mgr.ValidateSession(req) if err != nil { t.Fatalf("ValidateSession() error = %v", err) } if !data.Authenticated { t.Error("ValidateSession() returned unauthenticated session") } if data.ExpiresAt.Before(time.Now()) { t.Error("ValidateSession() returned already-expired session") } } func TestManager_ValidateSession_NoCookie(t *testing.T) { mgr, _ := NewManager("test-signing-key-12345", false) req := httptest.NewRequest(http.MethodGet, "/", nil) _, err := mgr.ValidateSession(req) if err == nil { t.Error("ValidateSession() should fail with no cookie") } if err != ErrNoSession { t.Errorf("ValidateSession() error = %v, want %v", err, ErrNoSession) } } func TestManager_ValidateSession_TamperedCookie(t *testing.T) { mgr, _ := NewManager("test-signing-key-12345", false) req := httptest.NewRequest(http.MethodGet, "/", nil) req.AddCookie(&http.Cookie{ Name: CookieName, Value: "tampered-invalid-cookie-value", }) _, err := mgr.ValidateSession(req) if err == nil { t.Error("ValidateSession() should fail with tampered cookie") } if err != ErrInvalidSession { t.Errorf("ValidateSession() error = %v, want %v", err, ErrInvalidSession) } } func TestManager_ValidateSession_WrongKey(t *testing.T) { mgr1, _ := NewManager("signing-key-1", false) mgr2, _ := NewManager("signing-key-2", false) // Create session with mgr1 w := httptest.NewRecorder() _ = mgr1.CreateSession(w) resp := w.Result() var sessionCookie *http.Cookie for _, c := range resp.Cookies() { if c.Name == CookieName { sessionCookie = c break } } // Try to validate with mgr2 (different key) req := httptest.NewRequest(http.MethodGet, "/", nil) req.AddCookie(sessionCookie) _, err := mgr2.ValidateSession(req) if err == nil { t.Error("ValidateSession() should fail with different signing key") } } func TestManager_ClearSession(t *testing.T) { mgr, _ := NewManager("test-signing-key-12345", false) w := httptest.NewRecorder() mgr.ClearSession(w) resp := w.Result() cookies := resp.Cookies() var sessionCookie *http.Cookie for _, c := range cookies { if c.Name == CookieName { sessionCookie = c break } } if sessionCookie == nil { t.Fatal("ClearSession() did not set a cookie") } if sessionCookie.MaxAge != -1 { t.Errorf("ClearSession() cookie MaxAge = %d, want -1", sessionCookie.MaxAge) } } func TestManager_IsAuthenticated(t *testing.T) { mgr, _ := NewManager("test-signing-key-12345", false) // No session - should return false req := httptest.NewRequest(http.MethodGet, "/", nil) if mgr.IsAuthenticated(req) { t.Error("IsAuthenticated() should return false with no session") } // Create session w := httptest.NewRecorder() _ = mgr.CreateSession(w) resp := w.Result() var sessionCookie *http.Cookie for _, c := range resp.Cookies() { if c.Name == CookieName { sessionCookie = c break } } // With valid session - should return true req = httptest.NewRequest(http.MethodGet, "/", nil) req.AddCookie(sessionCookie) if !mgr.IsAuthenticated(req) { t.Error("IsAuthenticated() should return true with valid session") } } func TestManager_CookieAttributes(t *testing.T) { // Test with secure=true mgr, _ := NewManager("test-key", true) w := httptest.NewRecorder() _ = mgr.CreateSession(w) resp := w.Result() var sessionCookie *http.Cookie for _, c := range resp.Cookies() { if c.Name == CookieName { sessionCookie = c break } } if !sessionCookie.HttpOnly { t.Error("Cookie should have HttpOnly flag") } if !sessionCookie.Secure { t.Error("Cookie should have Secure flag when manager created with secure=true") } if sessionCookie.SameSite != http.SameSiteStrictMode { t.Errorf("Cookie SameSite = %v, want %v", sessionCookie.SameSite, http.SameSiteStrictMode) } }