Skip to main content

armature_testing/
test_app.rs

1// Test Application Builder
2
3use armature_core::{Application, Container, Module, Provider, Router};
4use std::sync::Arc;
5
6/// Test application for integration testing
7pub struct TestApp {
8    pub app: Application,
9    pub container: Arc<Container>,
10}
11
12impl TestApp {
13    /// Create a new test application
14    pub fn new(container: Container, router: Router) -> Self {
15        let container_arc = Arc::new(container);
16        let app = Application::new(Container::new(), router);
17        Self {
18            app,
19            container: container_arc,
20        }
21    }
22
23    /// Get a service from the container
24    pub fn get<T: Provider + Clone + 'static>(&self) -> Option<T> {
25        // This would need actual container implementation
26        None
27    }
28
29    /// Create a test client for making requests
30    ///
31    /// # Examples
32    ///
33    /// ```no_run
34    /// use armature_testing::TestAppBuilder;
35    /// use armature_core::HttpResponse;
36    ///
37    /// # tokio_test::block_on(async {
38    /// let app = TestAppBuilder::new()
39    ///     .with_route("/test", |_req| async {
40    ///         Ok(HttpResponse::ok().with_body(b"OK".to_vec()))
41    ///     })
42    ///     .build();
43    ///
44    /// let client = app.client();
45    /// let response = client.get("/test").await;
46    /// assert_eq!(response.status(), Some(200));
47    /// # });
48    /// ```
49    pub fn client(&self) -> crate::TestClient {
50        crate::TestClient::new(self.app.router.clone())
51    }
52}
53
54/// Builder for test applications.
55///
56/// Provides a fluent API for creating test applications with custom
57/// routes, services, and configuration.
58///
59/// # Examples
60///
61/// Basic test app:
62///
63/// ```no_run
64/// use armature_testing::TestAppBuilder;
65/// use armature_core::{HttpResponse, Error};
66///
67/// # tokio_test::block_on(async {
68/// let app = TestAppBuilder::new()
69///     .with_route("/test", |_req| async {
70///         Ok(HttpResponse::ok().with_body(b"test".to_vec()))
71///     })
72///     .build();
73///
74/// let client = app.client();
75/// let response = client.get("/test").await;
76/// assert_eq!(response.status(), Some(200));
77/// # });
78/// ```
79pub struct TestAppBuilder {
80    container: Container,
81    router: Router,
82}
83
84impl TestAppBuilder {
85    /// Create a new test app builder
86    pub fn new() -> Self {
87        Self {
88            container: Container::new(),
89            router: Router::new(),
90        }
91    }
92
93    /// Register a provider
94    pub fn register<T: Provider + Clone + 'static>(self, provider: T) -> Self {
95        self.container.register(provider);
96        self
97    }
98
99    /// Add a module
100    pub fn add_module<M: Module>(self, _module: M) -> Self {
101        // Module registration logic
102        self
103    }
104
105    /// Set custom container
106    pub fn with_container(self, container: Container) -> Self {
107        Self { container, ..self }
108    }
109
110    /// Set custom router
111    pub fn with_router(self, router: Router) -> Self {
112        Self { router, ..self }
113    }
114
115    /// Add a test route with a handler
116    ///
117    /// # Examples
118    ///
119    /// ```no_run
120    /// use armature_testing::TestAppBuilder;
121    /// use armature_core::HttpResponse;
122    ///
123    /// let app = TestAppBuilder::new()
124    ///     .with_route("/api/health", |_req| async {
125    ///         Ok(HttpResponse::ok().with_body(b"OK".to_vec()))
126    ///     })
127    ///     .build();
128    /// ```
129    pub fn with_route<F, Fut>(mut self, path: &str, handler: F) -> Self
130    where
131        F: Fn(armature_core::HttpRequest) -> Fut + Send + Sync + Clone + 'static,
132        Fut: std::future::Future<Output = Result<armature_core::HttpResponse, armature_core::Error>>
133            + Send
134            + 'static,
135    {
136        use armature_core::{HttpMethod, Route};
137        // Use the optimized Route::new which enables handler monomorphization
138        self.router
139            .add_route(Route::new(HttpMethod::GET, path, handler));
140        self
141    }
142
143    /// Build the test application
144    pub fn build(self) -> TestApp {
145        TestApp::new(self.container, self.router)
146    }
147}
148
149impl Default for TestAppBuilder {
150    fn default() -> Self {
151        Self::new()
152    }
153}
154
155#[cfg(test)]
156mod tests {
157    use super::*;
158
159    #[test]
160    fn test_builder_creation() {
161        let _builder = TestAppBuilder::new();
162    }
163
164    #[test]
165    fn test_app_creation() {
166        let builder = TestAppBuilder::new();
167        let _app = builder.build();
168    }
169}