116 lines
3.9 KiB
Rust
116 lines
3.9 KiB
Rust
//! Test Server Management
|
|
//!
|
|
//! Manages isolated test server instance for UX testing
|
|
|
|
use actix_web::{web, App, HttpServer, middleware::Logger};
|
|
use std::sync::Arc;
|
|
use tokio::sync::Mutex;
|
|
use std::time::Duration;
|
|
|
|
/// Test server instance
|
|
pub struct TestServer {
|
|
port: u16,
|
|
server_handle: Option<actix_web::dev::ServerHandle>,
|
|
}
|
|
|
|
impl TestServer {
|
|
/// Start a new test server instance
|
|
pub async fn start(port: u16) -> Result<Self, Box<dyn std::error::Error>> {
|
|
// Set environment variables for test mode
|
|
std::env::set_var("TEST_MODE", "true");
|
|
std::env::set_var("TEST_PORT", port.to_string());
|
|
std::env::set_var("TEST_DATA_DIR", "user_data_test");
|
|
|
|
// Import the main app configuration
|
|
let config = threefold_marketplace::config::get_config();
|
|
|
|
log::info!("Starting test server on port {}", port);
|
|
|
|
// Create test server with the same configuration as main app
|
|
let server = HttpServer::new(move || {
|
|
// Initialize Tera templates
|
|
let mut tera = match tera::Tera::new(&format!("{}/**/*.html", config.templates.dir)) {
|
|
Ok(t) => t,
|
|
Err(e) => {
|
|
eprintln!("Tera initialization error: {}", e);
|
|
std::process::exit(1);
|
|
}
|
|
};
|
|
|
|
// Register custom Tera functions
|
|
threefold_marketplace::utils::register_tera_functions(&mut tera);
|
|
|
|
App::new()
|
|
.wrap(Logger::default())
|
|
.wrap(threefold_marketplace::middleware::RequestTimer)
|
|
.wrap(threefold_marketplace::middleware::SecurityHeaders)
|
|
.service(actix_files::Files::new("/static", "./src/static"))
|
|
.app_data(web::Data::new(tera))
|
|
.configure(threefold_marketplace::routes::configure_routes)
|
|
})
|
|
.workers(1) // Single worker for testing
|
|
.bind(format!("127.0.0.1:{}", port))?;
|
|
|
|
let server_handle = server.handle();
|
|
|
|
// Start server in background
|
|
tokio::spawn(async move {
|
|
if let Err(e) = server.run().await {
|
|
eprintln!("Test server error: {}", e);
|
|
}
|
|
});
|
|
|
|
// Wait for server to start
|
|
tokio::time::sleep(Duration::from_millis(500)).await;
|
|
|
|
// Verify server is running
|
|
let client = reqwest::Client::new();
|
|
let health_check_url = format!("http://127.0.0.1:{}/", port);
|
|
|
|
for attempt in 1..=10 {
|
|
match client.get(&health_check_url).send().await {
|
|
Ok(response) if response.status().is_success() => {
|
|
log::info!("Test server started successfully on port {}", port);
|
|
return Ok(Self {
|
|
port,
|
|
server_handle: Some(server_handle),
|
|
});
|
|
}
|
|
Ok(_) | Err(_) => {
|
|
if attempt == 10 {
|
|
return Err("Failed to start test server after 10 attempts".into());
|
|
}
|
|
tokio::time::sleep(Duration::from_millis(500)).await;
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(Self {
|
|
port,
|
|
server_handle: Some(server_handle),
|
|
})
|
|
}
|
|
|
|
/// Get the server URL
|
|
pub fn url(&self) -> String {
|
|
format!("http://127.0.0.1:{}", self.port)
|
|
}
|
|
|
|
/// Stop the test server
|
|
pub async fn stop(&mut self) -> Result<(), Box<dyn std::error::Error>> {
|
|
if let Some(handle) = self.server_handle.take() {
|
|
handle.stop(true).await;
|
|
log::info!("Test server stopped");
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl Drop for TestServer {
|
|
fn drop(&mut self) {
|
|
if let Some(handle) = self.server_handle.take() {
|
|
// Best effort cleanup
|
|
let _ = handle.stop(false);
|
|
}
|
|
}
|
|
} |