use hyper::StatusCode;
#[allow(unused_imports)]
use miko::macros::{get, u_tag};
use serde_json::json;
#[get("/openapi-explicit-tag")]
#[u_tag("explicit")]
async fn openapi_explicit_tag() {}
#[path = "../examples/basic.rs"]
mod basic_example;
#[tokio::test]
async fn test_basic_integration() {
let mut app = basic_example::create_app().await;
let client = app.test_client();
client
.get("/")
.send()
.await
.assert_text("Hello, World! (macro defined route)");
client.get("/with_query?name=Alice&age=18")
.send()
.await
.assert_text("You can also use Query extractor!\n But #[query] is more convenient if you don't want to define a Query struct.\n Hello, Alice! You are 18 years old. (macro defined route)");
client.get("/with_path/foo/123")
.send()
.await
.assert_text("Hello from path parameters!\n #[path] and Path<T> has the same behavior.\n They will extract the value from the path and convert it to the specified type.\n But they are not named parameters, so the order matters.\n a: foo, b: 123 (macro defined route)");
let resp = client
.post("/json_req")
.json(&json!({"key": 1, "value": 99}))
.send()
.await;
resp.assert_ok();
let text = resp.text();
assert!(text.contains("Received JSON data"));
assert!(text.contains("\"key\": 1"));
client
.get("/sub/hello")
.send()
.await
.assert_text("Hello from sub route!");
client.get("/use_dep").send().await.assert_ok();
client
.get("/data")
.send()
.await
.assert_text("Service data has been changed.");
let err_resp = client.get("/custom_error").send().await;
err_resp.assert_status(StatusCode::BAD_GATEWAY);
let panic_resp = client.get("/panic").send().await;
panic_resp.assert_status(StatusCode::INTERNAL_SERVER_ERROR);
let layer_resp = client.get("/layer").send().await;
layer_resp.assert_header("X-Route-Layer", "Applied");
let nested_layer_resp = client.get("/layered/inner/test_inner").send().await;
nested_layer_resp.assert_header("X-Module-Layer", "Applied");
nested_layer_resp.assert_header("X-Inner-Layer", "Inner-Applied");
nested_layer_resp.assert_header("X-Route-INNER-Layer", "Inner-Applied");
client.get("/with_state").send().await.assert_text(
"App Name: Miko Demo App, App Version: 1.0.0 (macro defined route with state)",
);
client
.get("/no_macro/")
.send()
.await
.assert_text("Hello, World! (manually defined router)");
let openapi: serde_json::Value = client.get("/api-docs/openapi.json").send().await.json();
assert!(openapi.pointer("/paths/~1form/post").is_some());
let default_tag = openapi
.pointer("/paths/~1form/post/tags/0")
.and_then(serde_json::Value::as_str)
.expect("OpenAPI operation should have a default module tag");
assert!(default_tag.ends_with("basic_example"));
assert_eq!(
openapi.pointer("/paths/~1openapi-explicit-tag/get/tags/0"),
Some(&json!("explicit"))
);
assert!(openapi.pointer("/components/schemas/FormStruct").is_some());
}