use std::collections::HashMap; use std::sync::Arc; use axum::body::Body; use axum::http::{Request, StatusCode}; use tower::util::ServiceExt; use doctate_server::config::{Config, User}; fn test_config() -> Arc { let data_path = std::env::temp_dir().join(format!( "doctate-web-test-{}-{}", std::process::id(), uuid::Uuid::new_v4() )); Arc::new(Config { server_port: 3000, data_path, log_level: "info".into(), log_path: "/tmp/doctate-test/logs".into(), log_max_days: 90, users: vec![User { slug: "dr_test".into(), api_key: "test-key".into(), web_password: "unused".into(), role: "doctor".into(), }], api_keys: HashMap::from([("test-key".into(), "dr_test".into())]), retention_audio_days: 30, retention_transcript_days: 30, retention_document_days: 0, whisper_url: "http://localhost:10300".into(), whisper_timeout_seconds: 120, ollama_url: "http://localhost:11434".into(), ollama_model: "gemma3:4b".into(), ollama_keep_alive: 0, llm_url: String::new(), llm_api_key: String::new(), llm_model: String::new(), llm_temperature: 0.0, session_timeout_hours: 8, }) } async fn body_to_string(response: axum::response::Response) -> String { let bytes = axum::body::to_bytes(response.into_body(), usize::MAX) .await .unwrap(); String::from_utf8(bytes.to_vec()).unwrap() } #[tokio::test] async fn web_index_empty() { let config = test_config(); let app = doctate_server::create_router(config); let response = app .oneshot( Request::builder() .uri("/web/") .body(Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::OK); let body = body_to_string(response).await; assert!(body.contains("No cases found")); } #[tokio::test] async fn web_index_shows_cases() { let config = test_config(); let data_path = config.data_path.clone(); // Pre-create cases on disk let case1 = "550e8400-e29b-41d4-a716-446655440000"; let case2 = "660e8400-e29b-41d4-a716-446655440000"; let open_case = data_path.join("dr_test/open").join(case1); std::fs::create_dir_all(&open_case).unwrap(); std::fs::write( open_case.join("2026-04-13T10-30-00Z.m4a"), b"fake audio 1", ) .unwrap(); let done_case = data_path.join("dr_test/done").join(case2); std::fs::create_dir_all(&done_case).unwrap(); std::fs::write( done_case.join("2026-04-12T09-00-00Z.m4a"), b"fake audio 2", ) .unwrap(); std::fs::write( done_case.join("2026-04-12T09-00-00Z.transcript.txt"), "Herzkatheter ohne Befund.", ) .unwrap(); let app = doctate_server::create_router(config); let response = app .oneshot( Request::builder() .uri("/web/") .body(Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::OK); let body = body_to_string(response).await; assert!(body.contains(case1)); assert!(body.contains(case2)); assert!(body.contains("dr_test")); assert!(body.contains("