package handlers import ( "html/template" "net/http" "net/http/httptest" "testing" "custom-start-page/internal/auth" ) // MockSessionStore is a mock implementation of SessionStore for testing type MockSessionStore struct { userID string shouldError bool } func (m *MockSessionStore) CreateSession(w http.ResponseWriter, r *http.Request, userID string) error { m.userID = userID return nil } func (m *MockSessionStore) GetUserID(r *http.Request) (string, error) { if m.shouldError { return "", http.ErrNoCookie } return m.userID, nil } func (m *MockSessionStore) DestroySession(w http.ResponseWriter, r *http.Request) error { m.userID = "" return nil } func (m *MockSessionStore) ValidateSession(r *http.Request) bool { return m.userID != "" } // createMockTemplate creates a simple mock template for testing func createMockTemplate() *template.Template { tmpl := template.New("login.html") template.Must(tmpl.Parse(`{{if .Error}}
{{.Error}}
{{end}}Login`)) return tmpl } // TestHandleLogin_UnauthenticatedUser tests that unauthenticated users see the login page func TestHandleLogin_UnauthenticatedUser(t *testing.T) { // Setup mockSessionStore := &MockSessionStore{shouldError: true} oauthService := auth.NewOAuthService("test-client-id", "test-secret", "http://localhost/callback", auth.NewMemoryStateStore()) userService := auth.NewUserService(nil) // nil repo for this test mockTemplate := createMockTemplate() handler := NewAuthHandlerWithTemplates(oauthService, userService, mockSessionStore, mockTemplate) // Create request req := httptest.NewRequest(http.MethodGet, "/login", nil) w := httptest.NewRecorder() // Execute handler.HandleLogin(w, req) // Assert if w.Code != http.StatusOK { t.Errorf("Expected status 200, got %d", w.Code) } // Check that response contains login page elements body := w.Body.String() if body == "" { t.Error("Expected non-empty response body") } } // TestHandleLogin_AuthenticatedUser tests that authenticated users are redirected to dashboard func TestHandleLogin_AuthenticatedUser(t *testing.T) { // Setup mockSessionStore := &MockSessionStore{userID: "test-user-123"} oauthService := auth.NewOAuthService("test-client-id", "test-secret", "http://localhost/callback", auth.NewMemoryStateStore()) userService := auth.NewUserService(nil) mockTemplate := createMockTemplate() handler := NewAuthHandlerWithTemplates(oauthService, userService, mockSessionStore, mockTemplate) // Create request req := httptest.NewRequest(http.MethodGet, "/login", nil) w := httptest.NewRecorder() // Execute handler.HandleLogin(w, req) // Assert if w.Code != http.StatusTemporaryRedirect { t.Errorf("Expected status 307, got %d", w.Code) } location := w.Header().Get("Location") if location != "/dashboard" { t.Errorf("Expected redirect to /dashboard, got %s", location) } } // TestHandleLogin_WithError tests that error messages are displayed func TestHandleLogin_WithError(t *testing.T) { // Setup mockSessionStore := &MockSessionStore{shouldError: true} oauthService := auth.NewOAuthService("test-client-id", "test-secret", "http://localhost/callback", auth.NewMemoryStateStore()) userService := auth.NewUserService(nil) mockTemplate := createMockTemplate() handler := NewAuthHandlerWithTemplates(oauthService, userService, mockSessionStore, mockTemplate) // Create request with error parameter req := httptest.NewRequest(http.MethodGet, "/login?error=oauth_failed", nil) w := httptest.NewRecorder() // Execute handler.HandleLogin(w, req) // Assert if w.Code != http.StatusOK { t.Errorf("Expected status 200, got %d", w.Code) } // Check that response contains error message body := w.Body.String() if body == "" { t.Error("Expected non-empty response body") } } // TestHandleLogout tests that logout destroys session and redirects to login func TestHandleLogout(t *testing.T) { // Setup mockSessionStore := &MockSessionStore{userID: "test-user-123"} oauthService := auth.NewOAuthService("test-client-id", "test-secret", "http://localhost/callback", auth.NewMemoryStateStore()) userService := auth.NewUserService(nil) mockTemplate := createMockTemplate() handler := NewAuthHandlerWithTemplates(oauthService, userService, mockSessionStore, mockTemplate) // Create request req := httptest.NewRequest(http.MethodPost, "/logout", nil) w := httptest.NewRecorder() // Execute handler.HandleLogout(w, req) // Assert if w.Code != http.StatusTemporaryRedirect { t.Errorf("Expected status 307, got %d", w.Code) } location := w.Header().Get("Location") if location != "/login" { t.Errorf("Expected redirect to /login, got %s", location) } // Verify session was destroyed if mockSessionStore.userID != "" { t.Error("Expected session to be destroyed") } }