#![allow(dead_code, private_interfaces)]
use axum::body::Body;
use axum::http::{Request, StatusCode};
use serde::{Deserialize, Serialize};
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions};
use tower::ServiceExt;
use umbral_openapi::OpenApiPlugin;
use umbral_rest::RestPlugin;
#[derive(Debug, sqlx::FromRow, Serialize, Deserialize, umbral::orm::Model)]
struct Note {
id: i64,
title: String,
}
async fn boot_prod() -> axum::Router {
unsafe {
std::env::set_var("UMBRAL_ENVIRONMENT", "Prod");
std::env::set_var(
"UMBRAL_SECRET_KEY",
"prod-gating-test-secret-key-0123456789abcdef",
);
}
let settings = umbral::Settings::from_env().expect("settings");
assert!(
matches!(settings.environment, umbral::Environment::Prod),
"test harness must run in Prod"
);
let tmp = tempfile::tempdir().expect("tempdir");
let path = tmp.path().join("openapi_prod.sqlite");
std::mem::forget(tmp);
let pool = SqlitePoolOptions::new()
.max_connections(2)
.connect_with(
SqliteConnectOptions::new()
.busy_timeout(std::time::Duration::from_secs(5))
.filename(&path)
.create_if_missing(true),
)
.await
.expect("pool");
umbral::App::builder()
.settings(settings)
.database("default", pool)
.model::<Note>()
.plugin(RestPlugin::default())
.plugin(OpenApiPlugin::default())
.build()
.expect("App::build")
.into_router()
}
async fn status(router: &axum::Router, uri: &str) -> StatusCode {
let req = Request::builder()
.uri(uri)
.header("host", "localhost")
.body(Body::empty())
.unwrap();
router.clone().oneshot(req).await.expect("oneshot").status()
}
#[tokio::test]
async fn openapi_not_mounted_in_prod_by_default() {
let router = boot_prod().await;
assert_eq!(
status(&router, "/openapi/openapi.json").await,
StatusCode::NOT_FOUND,
"the OpenAPI JSON spec must not be served in Prod without opt-in"
);
assert_eq!(
status(&router, "/openapi/").await,
StatusCode::NOT_FOUND,
"the Swagger UI must not be served in Prod without opt-in"
);
}