//! Medication-endpoint integration tests. //! //! In-process against an isolated MongoDB test DB (see `common`). When Mongo is //! unreachable these skip gracefully. Verifies auth enforcement and an //! authenticated create -> list flow with the actual API contract. mod common; use serde_json::json; /// Skip when Mongo is unavailable (counts as a pass); CI provides Mongo. macro_rules! require_app { ($app:expr) => { match $app { Some(x) => x, None => { eprintln!("[integration] skipped (MongoDB unavailable)"); return; } } }; } #[tokio::test] async fn create_medication_requires_auth() { let (app, db_name) = require_app!(common::app_for_test().await); let (status, _) = common::send_json( &app, "POST", "/api/medications", Some( json!({ "name": "Test Med", "dosage": "10mg", "frequency": "daily", "route": "oral" }), ), None, ) .await; assert_eq!(status, 401); common::drop_test_db(&db_name).await; } #[tokio::test] async fn list_medications_requires_auth() { let (app, db_name) = require_app!(common::app_for_test().await); let (status, _) = common::send_json(&app, "GET", "/api/medications", None, None).await; assert_eq!(status, 401); common::drop_test_db(&db_name).await; } #[tokio::test] async fn get_medication_requires_auth() { let (app, db_name) = require_app!(common::app_for_test().await); let (status, _) = common::send_json( &app, "GET", "/api/medications/507f1f77bcf86cd799439011", None, None, ) .await; assert_eq!(status, 401); common::drop_test_db(&db_name).await; } #[tokio::test] async fn authenticated_user_can_create_and_list_medication() { let (app, db_name) = require_app!(common::app_for_test().await); let email = unique_email(); // Register and grab the access token. let (status, body) = common::send_json( &app, "POST", "/api/auth/register", Some(json!({ "email": email, "username": "tester", "password": "supersecret" })), None, ) .await; assert_eq!(status, 201); let token = body["token"].as_str().unwrap().to_string(); // Create a medication (name/dosage/frequency/route are all required). let (status, body) = common::send_json( &app, "POST", "/api/medications", Some(json!({ "name": "Ibuprofen", "dosage": "200mg", "frequency": "as needed", "route": "oral" })), Some(&token), ) .await; assert!( status == 200 || status == 201, "create should succeed, body: {body}" ); // List medications for the user — should include the one we just created. let (status, body) = common::send_json(&app, "GET", "/api/medications", None, Some(&token)).await; assert_eq!(status, 200, "list should succeed, body: {body}"); let empty = Vec::new(); let arr = body.as_array().unwrap_or(&empty); assert!( !arr.is_empty(), "list should contain the created medication" ); common::drop_test_db(&db_name).await; } fn unique_email() -> String { format!("test_{}@example.com", uuid::Uuid::new_v4()) }