use crate::common::TestServer; use serde_json::json; #[tokio::test] async fn stats_overview_reflects_inserted_data() { let server = TestServer::start().await; // Add a repo server .post( "/api/v1/repositories", &json!({ "name": "stats-repo", "git_url": "https://github.com/example/stats-repo.git", }), ) .await; // Insert findings directly let mongodb_uri = std::env::var("TEST_MONGODB_URI") .unwrap_or_else(|_| "mongodb://root:example@localhost:27017/?authSource=admin".into()); let client = mongodb::Client::with_uri_str(&mongodb_uri).await.unwrap(); let db = client.database(&server.db_name()); let now = mongodb::bson::DateTime::now(); for (title, severity) in [ ("Critical Bug", "critical"), ("High Bug", "high"), ("Medium Bug", "medium"), ("Low Bug", "low"), ] { db.collection::("findings") .insert_one(mongodb::bson::doc! { "repo_id": "test-repo-id", "fingerprint": format!("fp-{title}"), "scanner": "test", "scan_type": "sast", "title": title, "description": "desc", "severity": severity, "status": "open", "created_at": now, "updated_at": now, }) .await .unwrap(); } let resp = server.get("/api/v1/stats/overview").await; assert_eq!(resp.status(), 200); let body: serde_json::Value = resp.json().await.unwrap(); let data = &body["data"]; assert_eq!(data["repositories"], 1); assert_eq!(data["total_findings"], 4); assert_eq!(data["critical"], 1); assert_eq!(data["high"], 1); server.cleanup().await; } #[tokio::test] async fn stats_update_after_finding_status_change() { let server = TestServer::start().await; // Insert a finding let mongodb_uri = std::env::var("TEST_MONGODB_URI") .unwrap_or_else(|_| "mongodb://root:example@localhost:27017/?authSource=admin".into()); let client = mongodb::Client::with_uri_str(&mongodb_uri).await.unwrap(); let db = client.database(&server.db_name()); let now = mongodb::bson::DateTime::now(); let result = db .collection::("findings") .insert_one(mongodb::bson::doc! { "repo_id": "repo-1", "fingerprint": "fp-stats-test", "scanner": "test", "scan_type": "sast", "title": "Stats Test Finding", "description": "desc", "severity": "high", "status": "open", "created_at": now, "updated_at": now, }) .await .unwrap(); let finding_id = result.inserted_id.as_object_id().unwrap().to_hex(); // Stats should show 1 finding let resp = server.get("/api/v1/stats/overview").await; let body: serde_json::Value = resp.json().await.unwrap(); assert_eq!(body["data"]["total_findings"], 1); // Mark it as resolved server .patch( &format!("/api/v1/findings/{finding_id}/status"), &json!({ "status": "resolved" }), ) .await; // The finding still exists (status changed, not deleted) let resp = server.get("/api/v1/stats/overview").await; let body: serde_json::Value = resp.json().await.unwrap(); // total_findings counts all findings regardless of status assert_eq!(body["data"]["total_findings"], 1); server.cleanup().await; }