use axum::{body::Body, http::Request}; use std::net::{SocketAddr, TcpListener}; use tokio::task::JoinHandle; use ztp::*; type NullHandle = JoinHandle<()>; async fn spawn_server() -> (SocketAddr, NullHandle) { let configuration = ztp::configuration::get_configuration().unwrap(); let listener = TcpListener::bind("127.0.0.1:0".parse::().unwrap()).unwrap(); let addr = listener.local_addr().unwrap(); let handle: NullHandle = tokio::spawn(async move { axum::Server::from_tcp(listener) .unwrap() .serve(app(&configuration).await.into_make_service()) .await .unwrap(); }); (addr, handle) } #[tokio::test] async fn test_for_hello_world() { let (addr, _server_handle) = spawn_server().await; let response = hyper::Client::new() .request( Request::builder() .uri(format!("http://{}/", addr)) .body(Body::empty()) .unwrap(), ) .await .unwrap(); let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); assert_eq!(&body[..], b"Hello, World!\n"); } #[tokio::test] async fn subscribe_returns_400_on_missing_data() { let (addr, _server_handle) = spawn_server().await; let test_cases = vec![ ("name=le%20guin", "missing the email"), ("email=ursula_le_guin%40gmail.com", "missing the name"), ("", "missing both name and email"), ]; for (invalid_body, error_message) in test_cases { let response = hyper::Client::new() .request( Request::builder() .method("POST") .header("content-type", "application/x-www-form-urlencoded") .uri(format!("http://{}/subscriptions", addr)) .body(Body::from(invalid_body)) .unwrap(), ) .await .expect("Failed to execute request."); assert_eq!( 400, response.status().as_u16(), // Additional customised error message on test failure "The API did not fail with 400 Bad Request when the payload was {}.", error_message ); } }