//! Integration tests for the BFF shell. //! //! These drive the [`Router`] through `tower::ServiceExt::oneshot`, which //! exercises the real handler stack without binding a port or starting a //! server. use std::net::SocketAddr; use std::path::{Path, PathBuf}; use axum::body::Body; use axum::http::{Request, StatusCode}; use server::app::build_app; use server::config::ServerConfig; use server::state::AppState; use tower::ServiceExt as _; /// Path to the SPA build output owned by Wave 4, resolved independently of /// the test's working directory. fn dist_dir() -> PathBuf { Path::new(env!("CARGO_MANIFEST_DIR")) .join("..") .join("web") .join("dist") } /// A router built from an explicit config (no environment dependence). fn test_app() -> axum::Router { let config = ServerConfig::new(SocketAddr::from(([127, 0, 0, 1], 3001)), dist_dir()); build_app(AppState::new(config)) } #[tokio::test] async fn healthz_returns_200_without_binding_a_port() -> Result<(), Box> { let response = test_app() .oneshot(Request::builder().uri("/healthz").body(Body::empty())?) .await?; assert_eq!(response.status(), StatusCode::OK); let bytes = axum::body::to_bytes(response.into_body(), usize::MAX).await?; let body = std::str::from_utf8(&bytes)?; assert!(body.contains("ok"), "unexpected health body: {body:?}"); Ok(()) } #[tokio::test] async fn unknown_path_is_404_or_spa_fallback_when_dist_exists() -> Result<(), Box> { let response = test_app() .oneshot(Request::builder().uri("/nope").body(Body::empty())?) .await?; if dist_dir().join("index.html").is_file() { assert_eq!( response.status(), StatusCode::OK, "SPA fallback should serve index.html for an unknown path" ); } else { assert_eq!( response.status(), StatusCode::NOT_FOUND, "without a built dist, an unknown path must be 404" ); } Ok(()) }