use std::path::Path; use axum::{Router, routing::get}; use axum_test::{TestServer, TestServerConfig, Transport}; use hurl::report::html::{Testcase, write_report}; use hurl::runner::{self, RunnerOptions, Value, VariableSet}; use hurl::util::logger::LoggerOptionsBuilder; use hurl_core::input::Input; use tower_http::trace::TraceLayer; async fn create_app() -> Router { use backend::database::{DatabaseConfig, create_pool}; use backend::services; // Use in-memory SQLite for tests let config = DatabaseConfig { database_url: "sqlite::memory:".to_string(), }; let pool = create_pool(&config) .await .expect("Failed to create test database pool"); // Run migrations on in-memory database sqlx::migrate!("./migrations") .run(&pool) .await .expect("Failed to run migrations"); Router::new() .route("/health", get(health)) .nest("/api/tasks", services::create_task_router()) .with_state(pool) } async fn health() -> &'static str { "Ok" } async fn run_hurl_test(hurl_file_path: &str) { let app = create_app().await; let config = TestServerConfig { transport: Some(Transport::HttpRandomPort), ..TestServerConfig::default() }; let server = TestServer::new_with_config(app, config).unwrap(); let address = server.server_address().unwrap(); let host = address.as_str().strip_suffix("/").unwrap(); let content = std::fs::read_to_string(hurl_file_path).unwrap(); let mut variables = VariableSet::new(); variables.insert("host".to_string(), Value::String(host.to_string())); let runner_opts = RunnerOptions::default(); let logger_opts = LoggerOptionsBuilder::new().build(); let result = runner::run(&content, None, &runner_opts, &variables, &logger_opts).unwrap(); let input = Input::new(hurl_file_path); let test_case = Testcase::from(&result, &input); test_case .write_html(&content, &result.entries, Path::new("reports/store"), &[]) .expect("Failed to write html files"); write_report(Path::new("reports/"), &vec![test_case]).expect("Failed to write report"); assert!(result.success, "Hurl test failed for {}", hurl_file_path); } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_tasks_api() { run_hurl_test("./tests/api/tasks.hurl").await; } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_list_tasks_api() { run_hurl_test("./tests/api/list_tasks.hurl").await; } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_update_tasks_api() { run_hurl_test("./tests/api/update_tasks.hurl").await; } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_delete_tasks_api() { run_hurl_test("./tests/api/delete_tasks.hurl").await; } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_projects_api() { run_hurl_test("./tests/api/projects.hurl").await; }