Skip to main content

logdive_api/
router.rs

1//! Axum router construction.
2//!
3//! Extracted from `main.rs` so integration tests can build the same router
4//! the binary uses without duplicating route definitions. The router is
5//! pure data — no I/O happens here; `AppState` carries the configuration
6//! and all I/O is deferred into the handler layer.
7
8use axum::{Router, routing::get};
9
10use crate::handlers::{query_handler, stats_handler};
11use crate::state::AppState;
12
13/// Build the application router with all endpoints wired up.
14///
15/// Caller supplies a fully-constructed [`AppState`]. The returned router
16/// is ready to be handed to `axum::serve` in the binary, or to
17/// `tower::ServiceExt::oneshot` in tests.
18pub fn build_router(state: AppState) -> Router {
19    Router::new()
20        .route("/query", get(query_handler))
21        .route("/stats", get(stats_handler))
22        .with_state(state)
23}
24
25// ---------------------------------------------------------------------------
26// Tests
27// ---------------------------------------------------------------------------
28//
29// The router itself is a thin composition layer; meaningful coverage of its
30// behavior lives in the end-to-end integration tests (milestone 8 Unit D),
31// which exercise actual HTTP requests against a real temporary database.
32// A compile-time smoke test here guards against basic regressions in the
33// wiring without duplicating the integration test surface.
34
35#[cfg(test)]
36mod tests {
37    use super::*;
38    use std::path::PathBuf;
39
40    #[test]
41    fn build_router_produces_a_router_from_a_valid_state() {
42        let state = AppState::new(PathBuf::from("/tmp/does-not-need-to-exist-yet.db"));
43        let _router: Router = build_router(state);
44        // If this compiles and runs, the type plumbing between AppState,
45        // the handlers, and axum::Router is sound. Real behavior is
46        // validated by the integration test suite.
47    }
48}