package server import ( "encoding/json" "net/http" "net/http/httptest" "net/url" "strings" "testing" "warpbox/lib/metastore" ) func TestAccountAlertsPageListsAndFiltersAlerts(t *testing.T) { app, user := setupAccountTestApp(t) router := setupAccountTestRouter(t, app) session := createAccountTestSession(t, app, user) createTestAlert(t, app, "601", metastore.AlertSeverityMedium, "thumbnail.generate.failed") createTestAlert(t, app, "701", metastore.AlertSeverityHigh, "storage.connector.health_failed") request := httptest.NewRequest(http.MethodGet, "/account/alerts?severity=high", nil) request.AddCookie(&http.Cookie{Name: accountSessionCookie, Value: session.Token}) response := httptest.NewRecorder() router.ServeHTTP(response, request) if response.Code != http.StatusOK { t.Fatalf("expected alerts page, got %d body=%s", response.Code, response.Body.String()) } body := response.Body.String() if !strings.Contains(body, "storage.connector.health_failed") { t.Fatal("expected high severity alert") } if strings.Contains(body, "thumbnail.generate.failed") { t.Fatal("did not expect medium severity alert in high filter") } } func TestAccountAlertAcknowledgeAndClose(t *testing.T) { app, user := setupAccountTestApp(t) router := setupAccountTestRouter(t, app) session := createAccountTestSession(t, app, user) alert := createTestAlert(t, app, "601", metastore.AlertSeverityMedium, "thumbnail.generate.failed") response := postAlertAction(router, session, "/account/alerts/"+alert.ID+"/acknowledge", nil) if response.Code != http.StatusSeeOther { t.Fatalf("expected acknowledge redirect, got %d", response.Code) } updated, ok, err := app.store.GetAlert(alert.ID) if err != nil || !ok { t.Fatalf("GetAlert returned ok=%v err=%v", ok, err) } if updated.Status != metastore.AlertStatusAcknowledged { t.Fatalf("expected acknowledged alert, got %s", updated.Status) } response = postAlertAction(router, session, "/account/alerts/"+alert.ID+"/close", nil) if response.Code != http.StatusSeeOther { t.Fatalf("expected close redirect, got %d", response.Code) } updated, ok, err = app.store.GetAlert(alert.ID) if err != nil || !ok { t.Fatalf("GetAlert returned ok=%v err=%v", ok, err) } if updated.Status != metastore.AlertStatusClosed { t.Fatalf("expected closed alert, got %s", updated.Status) } } func TestAccountAlertManagePermissionDenied(t *testing.T) { app, _ := setupAccountTestApp(t) regular, err := app.store.CreateUserWithPassword("regular-alerts", "regular-alerts@example.test", "secret", nil) if err != nil { t.Fatalf("CreateUserWithPassword returned error: %v", err) } router := setupAccountTestRouter(t, app) session := createAccountTestSession(t, app, regular) alert := createTestAlert(t, app, "601", metastore.AlertSeverityMedium, "thumbnail.generate.failed") response := postAlertAction(router, session, "/account/alerts/"+alert.ID+"/acknowledge", nil) if response.Code != http.StatusForbidden { t.Fatalf("expected permission denied, got %d", response.Code) } } func TestDashboardUsesRealAlertCount(t *testing.T) { app, user := setupAccountTestApp(t) router := setupAccountTestRouter(t, app) session := createAccountTestSession(t, app, user) createTestAlert(t, app, "601", metastore.AlertSeverityMedium, "thumbnail.generate.failed") request := httptest.NewRequest(http.MethodGet, "/account", nil) request.AddCookie(&http.Cookie{Name: accountSessionCookie, Value: session.Token}) response := httptest.NewRecorder() router.ServeHTTP(response, request) if response.Code != http.StatusOK { t.Fatalf("expected dashboard, got %d", response.Code) } if !strings.Contains(response.Body.String(), "1 alerts") { t.Fatal("expected dashboard alert chip/count") } if !strings.Contains(response.Body.String(), "Thumbnail alert") { t.Fatal("expected dashboard alert preview") } } func TestAccountAlertsExportJSON(t *testing.T) { app, user := setupAccountTestApp(t) router := setupAccountTestRouter(t, app) session := createAccountTestSession(t, app, user) createTestAlert(t, app, "601", metastore.AlertSeverityMedium, "thumbnail.generate.failed") request := httptest.NewRequest(http.MethodGet, "/account/alerts/export.json", nil) request.AddCookie(&http.Cookie{Name: accountSessionCookie, Value: session.Token}) response := httptest.NewRecorder() router.ServeHTTP(response, request) if response.Code != http.StatusOK { t.Fatalf("expected export success, got %d", response.Code) } var payload map[string]any if err := json.Unmarshal(response.Body.Bytes(), &payload); err != nil { t.Fatalf("Unmarshal returned error: %v", err) } if _, ok := payload["alerts"]; !ok { t.Fatal("expected alerts export shape") } } func createTestAlert(t *testing.T, app *App, code string, severity string, trace string) metastore.Alert { t.Helper() alert, err := app.store.CreateAlert(metastore.AlertInput{ Title: "Thumbnail alert", Description: "Alert test description.", Severity: severity, Code: code, Trace: trace, Metadata: json.RawMessage(`{"box":"box-1","file":"photo.jpg"}`), CreatedBy: "system", }) if err != nil { t.Fatalf("CreateAlert returned error: %v", err) } return alert } func postAlertAction(router http.Handler, session metastore.Session, path string, values url.Values) *httptest.ResponseRecorder { if values == nil { values = url.Values{} } values.Set("csrf_token", session.CSRFToken) request := httptest.NewRequest(http.MethodPost, path, strings.NewReader(values.Encode())) request.Header.Set("Content-Type", "application/x-www-form-urlencoded") request.AddCookie(&http.Cookie{Name: accountSessionCookie, Value: session.Token}) response := httptest.NewRecorder() router.ServeHTTP(response, request) return response }