#[cfg(test)] mod tests { use crate::models::{CreateUser, UpdateUser, UserResponse}; use super::super::helpers::{create_test_app, create_test_user, login_user}; use axum::http::StatusCode; use serde_json::json; use tower::util::ServiceExt; #[tokio::test] async fn test_list_users() { let (app, _container) = create_test_app().await; let user = create_test_user(&app).await; let token = login_user(&app, &user.username, "password123").await; // Create another user let user2_data = json!({ "username": "testuser2", "email": "test2@example.com", "password": "password456" }); app.clone() .oneshot( axum::http::Request::builder() .method("POST") .uri("/api/auth/register") .header("Content-Type", "application/json") .body(axum::body::Body::from(serde_json::to_vec(&user2_data).unwrap())) .unwrap(), ) .await .unwrap(); let response = app .oneshot( axum::http::Request::builder() .method("GET") .uri("/api/users") .header("Authorization", format!("Bearer {}", token)) .body(axum::body::Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::OK); let body = axum::body::to_bytes(response.into_body(), usize::MAX) .await .unwrap(); let users: Vec = serde_json::from_slice(&body).unwrap(); assert_eq!(users.len(), 2); assert!(users.iter().any(|u| u.username == "testuser")); assert!(users.iter().any(|u| u.username == "testuser2")); } #[tokio::test] async fn test_get_user_by_id() { let (app, _container) = create_test_app().await; let user = create_test_user(&app).await; let token = login_user(&app, &user.username, "password123").await; let response = app .oneshot( axum::http::Request::builder() .method("GET") .uri(format!("/api/users/{}", user.id)) .header("Authorization", format!("Bearer {}", token)) .body(axum::body::Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::OK); let body = axum::body::to_bytes(response.into_body(), usize::MAX) .await .unwrap(); let fetched_user: UserResponse = serde_json::from_slice(&body).unwrap(); assert_eq!(fetched_user.id, user.id); assert_eq!(fetched_user.username, user.username); assert_eq!(fetched_user.email, user.email); } #[tokio::test] async fn test_create_user_via_api() { let (app, _container) = create_test_app().await; let admin = create_test_user(&app).await; let token = login_user(&app, &admin.username, "password123").await; let new_user_data = CreateUser { username: "newuser".to_string(), email: "new@example.com".to_string(), password: "newpassword".to_string(), role: Some(crate::models::UserRole::User), }; let response = app .oneshot( axum::http::Request::builder() .method("POST") .uri("/api/users") .header("Authorization", format!("Bearer {}", token)) .header("Content-Type", "application/json") .body(axum::body::Body::from(serde_json::to_vec(&new_user_data).unwrap())) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::OK); let body = axum::body::to_bytes(response.into_body(), usize::MAX) .await .unwrap(); let created_user: UserResponse = serde_json::from_slice(&body).unwrap(); assert_eq!(created_user.username, "newuser"); assert_eq!(created_user.email, "new@example.com"); } #[tokio::test] async fn test_update_user() { let (app, _container) = create_test_app().await; let user = create_test_user(&app).await; let token = login_user(&app, &user.username, "password123").await; let update_data = UpdateUser { username: Some("updateduser".to_string()), email: Some("updated@example.com".to_string()), password: None, }; let response = app .oneshot( axum::http::Request::builder() .method("PUT") .uri(format!("/api/users/{}", user.id)) .header("Authorization", format!("Bearer {}", token)) .header("Content-Type", "application/json") .body(axum::body::Body::from(serde_json::to_vec(&update_data).unwrap())) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::OK); let body = axum::body::to_bytes(response.into_body(), usize::MAX) .await .unwrap(); let updated_user: UserResponse = serde_json::from_slice(&body).unwrap(); assert_eq!(updated_user.username, "updateduser"); assert_eq!(updated_user.email, "updated@example.com"); } #[tokio::test] async fn test_update_user_password() { let (app, _container) = create_test_app().await; let user = create_test_user(&app).await; let token = login_user(&app, &user.username, "password123").await; let update_data = UpdateUser { username: None, email: None, password: Some("newpassword456".to_string()), }; let response = app .clone() .oneshot( axum::http::Request::builder() .method("PUT") .uri(format!("/api/users/{}", user.id)) .header("Authorization", format!("Bearer {}", token)) .header("Content-Type", "application/json") .body(axum::body::Body::from(serde_json::to_vec(&update_data).unwrap())) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::OK); // Verify new password works let new_token = login_user(&app, &user.username, "newpassword456").await; assert!(!new_token.is_empty()); } #[tokio::test] async fn test_delete_user() { let (app, _container) = create_test_app().await; let admin = create_test_user(&app).await; let token = login_user(&app, &admin.username, "password123").await; // Create another user to delete let user2_data = json!({ "username": "deleteuser", "email": "delete@example.com", "password": "password456" }); let response = app .clone() .oneshot( axum::http::Request::builder() .method("POST") .uri("/api/auth/register") .header("Content-Type", "application/json") .body(axum::body::Body::from(serde_json::to_vec(&user2_data).unwrap())) .unwrap(), ) .await .unwrap(); let body = axum::body::to_bytes(response.into_body(), usize::MAX) .await .unwrap(); let user2: UserResponse = serde_json::from_slice(&body).unwrap(); // Delete the user let response = app .clone() .oneshot( axum::http::Request::builder() .method("DELETE") .uri(format!("/api/users/{}", user2.id)) .header("Authorization", format!("Bearer {}", token)) .body(axum::body::Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::NO_CONTENT); // Verify user is deleted let response = app .oneshot( axum::http::Request::builder() .method("GET") .uri(format!("/api/users/{}", user2.id)) .header("Authorization", format!("Bearer {}", token)) .body(axum::body::Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::NOT_FOUND); } #[tokio::test] async fn test_cannot_delete_self() { let (app, _container) = create_test_app().await; let user = create_test_user(&app).await; let token = login_user(&app, &user.username, "password123").await; let response = app .oneshot( axum::http::Request::builder() .method("DELETE") .uri(format!("/api/users/{}", user.id)) .header("Authorization", format!("Bearer {}", token)) .body(axum::body::Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::FORBIDDEN); } #[tokio::test] async fn test_users_require_auth() { let (app, _container) = create_test_app().await; let response = app .oneshot( axum::http::Request::builder() .method("GET") .uri("/api/users") .body(axum::body::Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::UNAUTHORIZED); } }