use axum::{ body::Body, http::{Request, StatusCode}, }; use http_body_util::BodyExt; use serde_json::Value; use tempfile::TempDir; use tower::ServiceExt; async fn test_app() -> (axum::Router, TempDir) { let temp_dir = TempDir::new().expect("temporary directory should be created"); let pool = task_pilot_backend::database::connect("sqlite::memory:") .await .expect("test database should initialize"); let app = task_pilot_backend::app(pool, temp_dir.path().join("logs")) .await .expect("test app should start"); (app, temp_dir) } #[tokio::test] async fn health_endpoint_returns_service_metadata() { let (app, _temp_dir) = test_app().await; let response = app .oneshot( Request::builder() .uri("/api/v1/health") .body(Body::empty()) .expect("request should build"), ) .await .expect("router should respond"); assert_eq!(response.status(), StatusCode::OK); let body = response .into_body() .collect() .await .expect("response body should be readable") .to_bytes(); let json: Value = serde_json::from_slice(&body).expect("response should be JSON"); assert_eq!(json["status"], "ok"); assert_eq!(json["service"], "task-pilot-backend"); assert_eq!(json["version"], env!("CARGO_PKG_VERSION")); } #[tokio::test] async fn openapi_endpoint_describes_health_api() { let (app, _temp_dir) = test_app().await; let response = app .oneshot( Request::builder() .uri("/api/v1/openapi.json") .body(Body::empty()) .expect("request should build"), ) .await .expect("router should respond"); assert_eq!(response.status(), StatusCode::OK); let body = response .into_body() .collect() .await .expect("response body should be readable") .to_bytes(); let json: Value = serde_json::from_slice(&body).expect("response should be JSON"); assert_eq!(json["info"]["title"], "TaskPilot API"); assert!(json["paths"]["/api/v1/health"]["get"].is_object()); }