use std::net::SocketAddr; use api::AppState; use db::Db; use server::serve; use tokio::net::TcpListener; #[tokio::test] async fn serves_health_live_over_tcp() { let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set for this test"); let db = Db::connect(&database_url, 2) .await .expect("connect to database"); let state = AppState { db, app_name: "Test".to_string(), cookie_secure: false, search: None, default_language: "sv".into(), default_timezone: "Europe/Stockholm".into(), }; let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); let addr: SocketAddr = listener.local_addr().unwrap(); let handle = tokio::spawn(async move { serve(listener, state).await }); let url = format!("http://{addr}/health/live"); let response = reqwest::get(&url).await; // If the request failed and the server task already ended, it errored — surface that // (a clear server error) instead of the opaque reqwest failure. if response.is_err() && handle.is_finished() { match handle.await { Ok(Err(err)) => panic!("server failed: {err:?}"), other => panic!("server task ended unexpectedly: {other:?}"), } } let body: serde_json::Value = response .expect("request succeeds") .json() .await .expect("json body"); assert_eq!(body["status"], "ok"); handle.abort(); }