use axum::body::Body;
use axum::http::{header, Request, StatusCode};
use cellos_server::{router, AppState};
use http_body_util::BodyExt;
use tower::ServiceExt;
const TOKEN: &str = "srv001-test-token";
fn state() -> AppState {
AppState::new(None, TOKEN)
}
fn version_request(auth: Option<&str>) -> Request<Body> {
let mut b = Request::builder().method("GET").uri("/v1/version");
if let Some(t) = auth {
b = b.header(header::AUTHORIZATION, format!("Bearer {t}"));
}
b.body(Body::empty()).expect("build request")
}
#[tokio::test]
async fn version_returns_documented_shape_with_auth() {
let app = router(state());
let resp = app
.oneshot(version_request(Some(TOKEN)))
.await
.expect("router response");
assert_eq!(resp.status(), StatusCode::OK);
let ct = resp
.headers()
.get(header::CONTENT_TYPE)
.and_then(|v| v.to_str().ok())
.unwrap_or_default()
.to_owned();
assert!(
ct.starts_with("application/json"),
"version response must be JSON, got {ct:?}",
);
let bytes = resp.into_body().collect().await.unwrap().to_bytes();
let body: serde_json::Value = serde_json::from_slice(&bytes).expect("body parses as JSON");
let server = body
.get("server")
.expect("response must contain a `server` object");
let api = body
.get("api")
.expect("response must contain an `api` object");
assert_eq!(
server.get("version").and_then(|v| v.as_str()),
Some(env!("CARGO_PKG_VERSION")),
"server.version must match the cellos-server crate version",
);
let profile = server
.get("buildProfile")
.and_then(|v| v.as_str())
.expect("server.buildProfile must be a string");
assert!(
profile == "release" || profile == "debug",
"buildProfile must be release or debug; got {profile:?}",
);
assert_eq!(api.get("version").and_then(|v| v.as_str()), Some("v1"));
match server.get("gitSha") {
None => {}
Some(serde_json::Value::String(s)) => {
assert!(!s.is_empty(), "gitSha if present must be non-empty");
}
other => panic!("gitSha must be a string or absent; got {other:?}"),
}
}
#[tokio::test]
async fn version_returns_unauthorized_without_bearer() {
let app = router(state());
let resp = app
.oneshot(version_request(None))
.await
.expect("router response");
assert_eq!(resp.status(), StatusCode::UNAUTHORIZED);
}
#[tokio::test]
async fn version_returns_unauthorized_with_wrong_token() {
let app = router(state());
let resp = app
.oneshot(version_request(Some("not-the-real-token")))
.await
.expect("router response");
assert_eq!(resp.status(), StatusCode::UNAUTHORIZED);
}