use crate::common::TestServer; use serde_json::json; /// Helper: insert a finding directly via MongoDB for testing query endpoints. async fn insert_finding(server: &TestServer, repo_id: &str, title: &str, severity: &str) { // We insert via the agent's DB by posting to the internal test path. // Since there's no direct "create finding" API, we use MongoDB directly. let mongodb_uri = std::env::var("TEST_MONGODB_URI") .unwrap_or_else(|_| "mongodb://root:example@localhost:27017/?authSource=admin".into()); // Extract the database name from the server's unique DB // We'll use the agent's internal DB through the stats endpoint to verify let client = mongodb::Client::with_uri_str(&mongodb_uri).await.unwrap(); // Get the DB name from the test server by parsing the health response // For now, we use a direct insert approach let db = client.database(&server.db_name()); let now = mongodb::bson::DateTime::now(); db.collection::("findings") .insert_one(mongodb::bson::doc! { "repo_id": repo_id, "fingerprint": format!("fp-{title}-{severity}"), "scanner": "test-scanner", "scan_type": "sast", "title": title, "description": format!("Test finding: {title}"), "severity": severity, "status": "open", "created_at": now, "updated_at": now, }) .await .unwrap(); } #[tokio::test] async fn list_findings_empty() { let server = TestServer::start().await; let resp = server.get("/api/v1/findings").await; assert_eq!(resp.status(), 200); let body: serde_json::Value = resp.json().await.unwrap(); assert_eq!(body["data"].as_array().unwrap().len(), 0); assert_eq!(body["total"], 0); server.cleanup().await; } #[tokio::test] async fn list_findings_with_data() { let server = TestServer::start().await; insert_finding(&server, "repo1", "SQL Injection", "critical").await; insert_finding(&server, "repo1", "XSS", "high").await; insert_finding(&server, "repo2", "Info Leak", "low").await; let resp = server.get("/api/v1/findings").await; assert_eq!(resp.status(), 200); let body: serde_json::Value = resp.json().await.unwrap(); assert_eq!(body["total"], 3); // Filter by severity let resp = server.get("/api/v1/findings?severity=critical").await; let body: serde_json::Value = resp.json().await.unwrap(); assert_eq!(body["total"], 1); assert_eq!(body["data"][0]["title"], "SQL Injection"); // Filter by repo let resp = server.get("/api/v1/findings?repo_id=repo1").await; let body: serde_json::Value = resp.json().await.unwrap(); assert_eq!(body["total"], 2); server.cleanup().await; } #[tokio::test] async fn update_finding_status() { let server = TestServer::start().await; insert_finding(&server, "repo1", "Test Bug", "medium").await; // Get the finding ID let resp = server.get("/api/v1/findings").await; let body: serde_json::Value = resp.json().await.unwrap(); let finding_id = body["data"][0]["_id"]["$oid"].as_str().unwrap(); // Update status to resolved let resp = server .patch( &format!("/api/v1/findings/{finding_id}/status"), &json!({ "status": "resolved" }), ) .await; assert_eq!(resp.status(), 200); // Verify it's updated let resp = server.get(&format!("/api/v1/findings/{finding_id}")).await; assert_eq!(resp.status(), 200); let body: serde_json::Value = resp.json().await.unwrap(); assert_eq!(body["data"]["status"], "resolved"); server.cleanup().await; } #[tokio::test] async fn bulk_update_finding_status() { let server = TestServer::start().await; insert_finding(&server, "repo1", "Bug A", "high").await; insert_finding(&server, "repo1", "Bug B", "high").await; // Get both finding IDs let resp = server.get("/api/v1/findings").await; let body: serde_json::Value = resp.json().await.unwrap(); let ids: Vec = body["data"] .as_array() .unwrap() .iter() .map(|f| f["_id"]["$oid"].as_str().unwrap().to_string()) .collect(); // Bulk update let resp = server .patch( "/api/v1/findings/bulk-status", &json!({ "ids": ids, "status": "false_positive" }), ) .await; assert_eq!(resp.status(), 200); // Verify both are updated for id in &ids { let resp = server.get(&format!("/api/v1/findings/{id}")).await; let body: serde_json::Value = resp.json().await.unwrap(); assert_eq!(body["data"]["status"], "false_positive"); } server.cleanup().await; }