Add comprehensive tests for IAM permissions, roles, teams, and users
- Implemented unit tests for PermissionsController and PermissionsService, covering create, read, update, and delete operations. - Added tests for RolesController and RolesService, including handling of duplicates and retrieval by ID. - Developed tests for TeamsController, including creation, retrieval, updating, deletion, and search functionality. - Created tests for UsersController, ensuring user creation and validation of attributes. - Each test includes setup, execution, and cleanup to maintain database integrity.
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::get_meta_request_dto;
|
||||
use imphnen_cms::{
|
||||
v1::landing::events::{
|
||||
events_controller::EventsController,
|
||||
events_dto::{EventsCreateRequestDto, EventsUpdateRequestDto},
|
||||
},
|
||||
};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_event_list_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let response = EventsController::get_event_list(&app_state, get_meta_request_dto(1, 10)).await;
|
||||
assert_eq!(response.status(), 200);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_event_by_id_controller_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let response = EventsController::get_event_by_id(&app_state, "non-existent-uuid-123456789".to_string()).await;
|
||||
assert_eq!(response.status(), 404);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_event_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let event_request = EventsCreateRequestDto {
|
||||
name: "Test Event".to_string(),
|
||||
description: "Test event description".to_string(),
|
||||
detail_link: Some("https://example.com/event".to_string()),
|
||||
price: Some(100.0),
|
||||
is_online: Some(true),
|
||||
start_date: "2024-01-01T00:00:00Z".to_string(),
|
||||
end_date: "2024-01-02T00:00:00Z".to_string(),
|
||||
location: Some("Online".to_string()),
|
||||
};
|
||||
let response = EventsController::create_event(&app_state, event_request).await;
|
||||
assert_eq!(response.status(), 201);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_event_controller_invalid_data() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let event_request = EventsCreateRequestDto {
|
||||
name: "".to_string(),
|
||||
description: "".to_string(),
|
||||
detail_link: None,
|
||||
price: None,
|
||||
is_online: None,
|
||||
start_date: "invalid-date".to_string(),
|
||||
end_date: "2024-01-02T00:00:00Z".to_string(),
|
||||
location: None,
|
||||
};
|
||||
let response = EventsController::create_event(&app_state, event_request).await;
|
||||
assert_eq!(response.status(), 400);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_event_controller_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let update_request = EventsUpdateRequestDto {
|
||||
name: Some("Updated Event".to_string()),
|
||||
description: Some("Updated description".to_string()),
|
||||
detail_link: Some("https://example.com/updated".to_string()),
|
||||
price: Some(150.0),
|
||||
is_online: Some(false),
|
||||
start_date: Some("2024-02-01T00:00:00Z".to_string()),
|
||||
end_date: Some("2024-02-02T00:00:00Z".to_string()),
|
||||
location: Some("Offline".to_string()),
|
||||
};
|
||||
let response = EventsController::update_event(&app_state, "non-existent-uuid-123456789".to_string(), update_request).await;
|
||||
assert_eq!(response.status(), 400);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_event_controller_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let response = EventsController::delete_event(&app_state, "non-existent-uuid-123456789".to_string()).await;
|
||||
assert_eq!(response.status(), 400);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use imphnen_cms::{
|
||||
v1::landing::events::{
|
||||
events_repository::EventsRepository,
|
||||
events_schema::EventsSchema,
|
||||
},
|
||||
};
|
||||
use imphnen_utils::make_thing_from_enum;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_event_list() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = EventsRepository::new(&app_state);
|
||||
let result = repo.query_event_list(crate::get_meta_request_dto(1, 10)).await;
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_event_by_id_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = EventsRepository::new(&app_state);
|
||||
let result = repo.query_event_by_id("non-existent-uuid-123456789".to_string()).await;
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_create_event() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = EventsRepository::new(&app_state);
|
||||
let event = EventsSchema {
|
||||
id: make_thing_from_enum("events", &uuid::Uuid::new_v4().to_string()),
|
||||
name: "Test Event".to_string(),
|
||||
description: "Test description".to_string(),
|
||||
detail_link: Some("https://example.com".to_string()),
|
||||
price: Some(100.0),
|
||||
is_online: true,
|
||||
start_date: "2024-01-01T00:00:00Z".to_string(),
|
||||
end_date: "2024-01-02T00:00:00Z".to_string(),
|
||||
location: Some("Online".to_string()),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let result = repo.query_create_event(event).await;
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_update_event_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = EventsRepository::new(&app_state);
|
||||
let event = EventsSchema {
|
||||
id: make_thing_from_enum("events", &"non-existent-uuid-123456789".to_string()),
|
||||
name: "Updated Event".to_string(),
|
||||
description: "Updated description".to_string(),
|
||||
detail_link: Some("https://example.com/updated".to_string()),
|
||||
price: Some(150.0),
|
||||
is_online: false,
|
||||
start_date: "2024-02-01T00:00:00Z".to_string(),
|
||||
end_date: "2024-02-02T00:00:00Z".to_string(),
|
||||
location: Some("Offline".to_string()),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let result = repo.query_update_event(event).await;
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_delete_event_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = EventsRepository::new(&app_state);
|
||||
let result = repo.query_delete_event("non-existent-uuid-123456789".to_string()).await;
|
||||
assert!(result.is_err());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::get_meta_request_dto;
|
||||
use imphnen_cms::{
|
||||
v1::landing::events::{
|
||||
events_service::EventsService,
|
||||
events_dto::{EventsCreateRequestDto, EventsUpdateRequestDto},
|
||||
},
|
||||
};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_event_list_service() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let response = EventsService::get_event_list(&app_state, get_meta_request_dto(1, 10)).await;
|
||||
assert_eq!(response.status(), 200);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_event_by_id_service_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let response = EventsService::get_event_by_id(&app_state, "non-existent-uuid-123456789".to_string()).await;
|
||||
assert_eq!(response.status(), 404);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_event_service() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let event_request = EventsCreateRequestDto {
|
||||
name: "Test Event".to_string(),
|
||||
description: "Test event description".to_string(),
|
||||
detail_link: Some("https://example.com/event".to_string()),
|
||||
price: Some(100.0),
|
||||
is_online: Some(true),
|
||||
start_date: "2024-01-01T00:00:00Z".to_string(),
|
||||
end_date: "2024-01-02T00:00:00Z".to_string(),
|
||||
location: Some("Online".to_string()),
|
||||
};
|
||||
let response = EventsService::create_event(&app_state, event_request).await;
|
||||
assert_eq!(response.status(), 201);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_event_service_invalid_data() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let event_request = EventsCreateRequestDto {
|
||||
name: "".to_string(),
|
||||
description: "".to_string(),
|
||||
detail_link: None,
|
||||
price: None,
|
||||
is_online: None,
|
||||
start_date: "invalid-date".to_string(),
|
||||
end_date: "2024-01-02T00:00:00Z".to_string(),
|
||||
location: None,
|
||||
};
|
||||
let response = EventsService::create_event(&app_state, event_request).await;
|
||||
assert_eq!(response.status(), 400);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_event_service_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let update_request = EventsUpdateRequestDto {
|
||||
name: Some("Updated Event".to_string()),
|
||||
description: Some("Updated description".to_string()),
|
||||
detail_link: Some("https://example.com/updated".to_string()),
|
||||
price: Some(150.0),
|
||||
is_online: Some(false),
|
||||
start_date: Some("2024-02-01T00:00:00Z".to_string()),
|
||||
end_date: Some("2024-02-02T00:00:00Z".to_string()),
|
||||
location: Some("Offline".to_string()),
|
||||
};
|
||||
let response = EventsService::update_event(&app_state, "non-existent-uuid-123456789".to_string(), update_request).await;
|
||||
assert_eq!(response.status(), 400);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_event_service_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let response = EventsService::delete_event(&app_state, "non-existent-uuid-123456789".to_string()).await;
|
||||
assert_eq!(response.status(), 400);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,389 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{get_meta_request_dto, UsersRepository};
|
||||
use axum::{http::StatusCode, response::Response};
|
||||
use imphnen_cms::{
|
||||
v1::landing::testimonials::{
|
||||
testimonials_controller::TestimonialsController,
|
||||
testimonials_dto::{TestimonialsCreateRequestDto, TestimonialsUpdateRequestDto},
|
||||
testimonials_schema::TestimonialsSchema,
|
||||
},
|
||||
};
|
||||
use imphnen_entities::UsersSchema;
|
||||
use imphnen_utils::make_thing_from_enum;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_testimonial_list_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_cms::v1::landing::testimonials::testimonials_repository::TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test testimonials
|
||||
let testimonial_names = vec![
|
||||
"testimonial_list_1".to_string(),
|
||||
"testimonial_list_2".to_string(),
|
||||
"testimonial_list_3".to_string(),
|
||||
];
|
||||
|
||||
for name in &testimonial_names {
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: format!("Test User {}", name),
|
||||
email: format!("test{}@example.com", name),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user).await;
|
||||
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
role: "Mentor".to_string(),
|
||||
content: format!("Great testimonial content for {}", name),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let _ = repo.query_create_testimonial(testimonial).await;
|
||||
}
|
||||
|
||||
// Get testimonial list through controller
|
||||
let response = TestimonialsController::get_testimonial_list(&app_state, get_meta_request_dto(1, 10))
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Clean up
|
||||
for name in testimonial_names {
|
||||
let user = UsersRepository::new(&app_state)
|
||||
.query_user_by_email(format!("test{}@example.com", name))
|
||||
.await
|
||||
.unwrap();
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_testimonial_by_id_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_cms::v1::landing::testimonials::testimonials_repository::TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test testimonial
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test User".to_string(),
|
||||
email: "test@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let create_user_result = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
assert!(create_user_result.is_ok());
|
||||
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: "Mentor".to_string(),
|
||||
content: "Great testimonial content".to_string(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let create_result = repo.query_create_testimonial(testimonial.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created testimonial to get ID
|
||||
let created_testimonial = repo
|
||||
.query_testimonial_by_id(testimonial.id.id.to_raw())
|
||||
.await
|
||||
.unwrap();
|
||||
let testimonial_id = created_testimonial.id.id.to_raw();
|
||||
|
||||
// Get testimonial by ID through controller
|
||||
let response = TestimonialsController::get_testimonial_by_id(&app_state, testimonial_id.clone())
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_testimonial(testimonial_id).await;
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_testimonial_by_id_controller_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Get non-existent testimonial by ID through controller
|
||||
let response = TestimonialsController::get_testimonial_by_id(&app_state, non_existent_id)
|
||||
.await;
|
||||
|
||||
// Verify not found response
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_testimonial_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_cms::v1::landing::testimonials::testimonials_repository::TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user for authentication
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test Admin".to_string(),
|
||||
email: "admin@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let create_user_result = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
assert!(create_user_result.is_ok());
|
||||
|
||||
// Test data
|
||||
let testimonial_request = TestimonialsCreateRequestDto {
|
||||
role: "Mentor".to_string(),
|
||||
content: "This is a test testimonial content for controller test".to_string(),
|
||||
};
|
||||
|
||||
// Create testimonial through controller
|
||||
let response = TestimonialsController::create_testimonial(
|
||||
&app_state,
|
||||
testimonial_request.clone(),
|
||||
&user,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::CREATED);
|
||||
|
||||
// Verify testimonial was created in database
|
||||
let created_testimonials = repo.query_testimonial_list(get_meta_request_dto(1, 10)).await.unwrap();
|
||||
assert!(created_testimonials.data.iter().any(|t| t.content == testimonial_request.content));
|
||||
|
||||
// Clean up
|
||||
let created_testimonial = repo.query_testimonial_list(get_meta_request_dto(1, 10)).await.unwrap();
|
||||
for t in created_testimonials.data {
|
||||
if t.content == testimonial_request.content {
|
||||
let _ = repo.query_delete_testimonial(t.id.id.to_raw()).await;
|
||||
}
|
||||
}
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_testimonial_controller_invalid_data() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Create test user for authentication
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test Admin".to_string(),
|
||||
email: "admin@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Test data with empty content (should fail validation)
|
||||
let testimonial_request = TestimonialsCreateRequestDto {
|
||||
role: "Mentor".to_string(),
|
||||
content: "".to_string(), // Empty content should fail validation
|
||||
};
|
||||
|
||||
// Create testimonial through controller
|
||||
let response = TestimonialsController::create_testimonial(
|
||||
&app_state,
|
||||
testimonial_request,
|
||||
&user,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify bad request response (validation error)
|
||||
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
|
||||
|
||||
// Clean up
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_testimonial_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_cms::v1::landing::testimonials::testimonials_repository::TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user for authentication
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test Admin".to_string(),
|
||||
email: "admin@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Create test testimonial
|
||||
let original_content = "Original testimonial content for update test".to_string();
|
||||
let new_content = "Updated testimonial content for update test".to_string();
|
||||
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: "Mentor".to_string(),
|
||||
content: original_content.clone(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let create_result = repo.query_create_testimonial(testimonial.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created testimonial to get ID
|
||||
let created_testimonial = repo
|
||||
.query_testimonial_by_id(testimonial.id.id.to_raw())
|
||||
.await
|
||||
.unwrap();
|
||||
let testimonial_id = created_testimonial.id.id.to_raw();
|
||||
|
||||
// Prepare update request
|
||||
let update_request = TestimonialsUpdateRequestDto {
|
||||
role: Some("Updated Mentor".to_string()),
|
||||
content: Some(new_content.clone()),
|
||||
};
|
||||
|
||||
// Update testimonial through controller
|
||||
let response = TestimonialsController::update_testimonial(
|
||||
&app_state, update_request, testimonial_id.clone(), &user,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Verify testimonial was updated in database
|
||||
let updated_testimonial = repo
|
||||
.query_testimonial_by_id(testimonial_id.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(updated_testimonial.content, new_content);
|
||||
assert_eq!(updated_testimonial.role, "Updated Mentor");
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_testimonial(testimonial_id).await;
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_testimonial_controller_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Create test user for authentication
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test Admin".to_string(),
|
||||
email: "admin@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Prepare update request
|
||||
let update_request = TestimonialsUpdateRequestDto {
|
||||
role: Some("Updated Mentor".to_string()),
|
||||
content: Some("Updated content".to_string()),
|
||||
};
|
||||
|
||||
// Update non-existent testimonial through controller
|
||||
let response = TestimonialsController::update_testimonial(
|
||||
&app_state, update_request, non_existent_id, &user,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify not found response
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
|
||||
// Clean up
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_testimonial_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_cms::v1::landing::testimonials::testimonials_repository::TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user for authentication
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test Admin".to_string(),
|
||||
email: "admin@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Create test testimonial
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: "Mentor".to_string(),
|
||||
content: "Test testimonial content for delete test".to_string(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let create_result = repo.query_create_testimonial(testimonial.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created testimonial to get ID
|
||||
let created_testimonial = repo
|
||||
.query_testimonial_by_id(testimonial.id.id.to_raw())
|
||||
.await
|
||||
.unwrap();
|
||||
let testimonial_id = created_testimonial.id.id.to_raw();
|
||||
|
||||
// Verify testimonial exists before deletion
|
||||
let exists_before = repo.query_testimonial_by_id(testimonial_id.clone()).await.is_ok();
|
||||
assert!(exists_before);
|
||||
|
||||
// Delete testimonial through controller
|
||||
let response = TestimonialsController::delete_testimonial(
|
||||
&app_state, testimonial_id.clone(), &user,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Verify testimonial was soft-deleted from database
|
||||
let deleted_testimonial = repo.query_testimonial_by_id(testimonial_id.clone()).await;
|
||||
assert!(deleted_testimonial.is_err());
|
||||
|
||||
// Clean up - no need since it's already soft-deleted
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_testimonial_controller_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Create test user for authentication
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test Admin".to_string(),
|
||||
email: "admin@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Delete non-existent testimonial through controller
|
||||
let response = TestimonialsController::delete_testimonial(
|
||||
&app_state, non_existent_id, &user,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify not found response
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
|
||||
// Clean up
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,493 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{get_meta_request_dto, UsersRepository};
|
||||
use imphnen_cms::{
|
||||
v1::landing::testimonials::{
|
||||
testimonials_repository::TestimonialsRepository,
|
||||
testimonials_schema::TestimonialsSchema,
|
||||
},
|
||||
};
|
||||
use imphnen_entities::UsersSchema;
|
||||
use imphnen_utils::make_thing_from_enum;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_testimonial_list() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test users and testimonials
|
||||
let num_testimonials = 5;
|
||||
let testimonial_contents = vec![
|
||||
"Testimonial content 1".to_string(),
|
||||
"Testimonial content 2".to_string(),
|
||||
"Testimonial content 3".to_string(),
|
||||
"Testimonial content 4".to_string(),
|
||||
"Testimonial content 5".to_string(),
|
||||
];
|
||||
|
||||
for (i, content) in testimonial_contents.iter().enumerate() {
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: format!("Test User {}", i + 1),
|
||||
email: format!("testuser{}@example.com", i + 1),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: format!("Role {}", i + 1),
|
||||
content: content.clone(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let _ = repo.query_create_testimonial(testimonial).await;
|
||||
}
|
||||
|
||||
// Test with pagination
|
||||
let result = repo.query_testimonial_list(get_meta_request_dto(1, 10)).await;
|
||||
assert!(result.is_ok());
|
||||
let response = result.unwrap();
|
||||
assert_eq!(response.data.len(), num_testimonials as usize);
|
||||
|
||||
// Test with smaller page size
|
||||
let result = repo.query_testimonial_list(get_meta_request_dto(1, 2)).await;
|
||||
assert!(result.is_ok());
|
||||
let response = result.unwrap();
|
||||
assert_eq!(response.data.len(), 2);
|
||||
|
||||
// Clean up
|
||||
for content in testimonial_contents {
|
||||
let user = UsersRepository::new(&app_state)
|
||||
.query_user_by_email(format!("testuser{}@example.com", content.chars().take(8).collect::<String>()))
|
||||
.await
|
||||
.unwrap();
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_testimonial_by_id_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test User".to_string(),
|
||||
email: "testuser@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Create test testimonial
|
||||
let testimonial_content = "Test testimonial content for by ID test".to_string();
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: "Mentor".to_string(),
|
||||
content: testimonial_content.clone(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let create_result = repo.query_create_testimonial(testimonial.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created testimonial to get ID
|
||||
let created_testimonial = repo
|
||||
.query_testimonial_by_id(testimonial.id.id.to_raw())
|
||||
.await
|
||||
.unwrap();
|
||||
let testimonial_id = created_testimonial.id.id.to_raw();
|
||||
|
||||
// Query testimonial by ID
|
||||
let result = repo.query_testimonial_by_id(testimonial_id.clone()).await;
|
||||
assert!(result.is_ok());
|
||||
let found_testimonial = result.unwrap();
|
||||
assert_eq!(found_testimonial.content, testimonial_content);
|
||||
assert_eq!(found_testimonial.role, "Mentor");
|
||||
assert!(!found_testimonial.is_deleted);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_testimonial(testimonial_id).await;
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_testimonial_by_id_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Query non-existent testimonial by ID
|
||||
let result = repo.query_testimonial_by_id(non_existent_id).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err().to_string(), "Testimonial not found");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_testimonial_by_id_deleted() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test User".to_string(),
|
||||
email: "testuser@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Create test testimonial
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: "Mentor".to_string(),
|
||||
content: "Test testimonial content for deleted test".to_string(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let create_result = repo.query_create_testimonial(testimonial.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created testimonial to get ID
|
||||
let created_testimonial = repo
|
||||
.query_testimonial_by_id(testimonial.id.id.to_raw())
|
||||
.await
|
||||
.unwrap();
|
||||
let testimonial_id = created_testimonial.id.id.to_raw();
|
||||
|
||||
// Soft delete the testimonial
|
||||
let _ = repo.query_delete_testimonial(testimonial_id.clone()).await;
|
||||
|
||||
// Try to query deleted testimonial by ID
|
||||
let result = repo.query_testimonial_by_id(testimonial_id).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err().to_string(), "Testimonial not found");
|
||||
|
||||
// Clean up
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_create_testimonial() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test User".to_string(),
|
||||
email: "testuser@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Create test testimonial data
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: "Mentor".to_string(),
|
||||
content: "Test testimonial content for create test".to_string(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
|
||||
// Create testimonial
|
||||
let result = repo.query_create_testimonial(testimonial.clone()).await;
|
||||
assert!(result.is_ok());
|
||||
let created_testimonial = result.unwrap();
|
||||
assert_eq!(created_testimonial.content, testimonial.content);
|
||||
assert_eq!(created_testimonial.role, testimonial.role);
|
||||
assert!(!created_testimonial.is_deleted);
|
||||
|
||||
// Verify it was created in database
|
||||
let found_testimonial = repo.query_testimonial_by_id(created_testimonial.id.id.to_raw()).await;
|
||||
assert!(found_testimonial.is_ok());
|
||||
assert_eq!(found_testimonial.unwrap().content, testimonial.content);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_testimonial(created_testimonial.id.id.to_raw()).await;
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_update_testimonial() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test User".to_string(),
|
||||
email: "testuser@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Create test testimonial
|
||||
let original_content = "Original testimonial content for update test".to_string();
|
||||
let new_content = "Updated testimonial content for update test".to_string();
|
||||
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: "Mentor".to_string(),
|
||||
content: original_content.clone(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let create_result = repo.query_create_testimonial(testimonial.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created testimonial to get ID
|
||||
let created_testimonial = repo
|
||||
.query_testimonial_by_id(testimonial.id.id.to_raw())
|
||||
.await
|
||||
.unwrap();
|
||||
let testimonial_id = created_testimonial.id.id.to_raw();
|
||||
|
||||
// Prepare updated testimonial
|
||||
let updated_testimonial = TestimonialsSchema {
|
||||
id: created_testimonial.id,
|
||||
user: created_testimonial.user,
|
||||
role: "Updated Mentor".to_string(),
|
||||
content: new_content.clone(),
|
||||
created_at: created_testimonial.created_at,
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
|
||||
// Update testimonial
|
||||
let result = repo.query_update_testimonial(updated_testimonial).await;
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(result.unwrap(), "Success update testimonial");
|
||||
|
||||
// Verify it was updated in database
|
||||
let found_testimonial = repo.query_testimonial_by_id(testimonial_id).await;
|
||||
assert!(found_testimonial.is_ok());
|
||||
let updated = found_testimonial.unwrap();
|
||||
assert_eq!(updated.content, new_content);
|
||||
assert_eq!(updated.role, "Updated Mentor");
|
||||
assert!(!updated.is_deleted);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_testimonial(testimonial_id).await;
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_update_testimonial_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test User".to_string(),
|
||||
email: "testuser@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Create non-existent testimonial ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Prepare updated testimonial with non-existent ID
|
||||
let updated_testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &non_existent_id),
|
||||
user: user.id,
|
||||
role: "Updated Mentor".to_string(),
|
||||
content: "Updated content".to_string(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
|
||||
// Try to update non-existent testimonial
|
||||
let result = repo.query_update_testimonial(updated_testimonial).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err().to_string(), "Testimonial not found");
|
||||
|
||||
// Clean up
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_update_testimonial_deleted() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test User".to_string(),
|
||||
email: "testuser@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Create test testimonial
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: "Mentor".to_string(),
|
||||
content: "Test testimonial content for deleted update test".to_string(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let create_result = repo.query_create_testimonial(testimonial.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created testimonial to get ID
|
||||
let created_testimonial = repo
|
||||
.query_testimonial_by_id(testimonial.id.id.to_raw())
|
||||
.await
|
||||
.unwrap();
|
||||
let testimonial_id = created_testimonial.id.id.to_raw();
|
||||
|
||||
// Soft delete the testimonial
|
||||
let _ = repo.query_delete_testimonial(testimonial_id.clone()).await;
|
||||
|
||||
// Prepare updated testimonial
|
||||
let updated_testimonial = TestimonialsSchema {
|
||||
id: created_testimonial.id,
|
||||
user: created_testimonial.user,
|
||||
role: "Updated Mentor".to_string(),
|
||||
content: "Updated content".to_string(),
|
||||
created_at: created_testimonial.created_at,
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
|
||||
// Try to update deleted testimonial
|
||||
let result = repo.query_update_testimonial(updated_testimonial).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err().to_string(), "Testimonial already deleted");
|
||||
|
||||
// Clean up
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_delete_testimonial() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test User".to_string(),
|
||||
email: "testuser@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Create test testimonial
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: "Mentor".to_string(),
|
||||
content: "Test testimonial content for delete test".to_string(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let create_result = repo.query_create_testimonial(testimonial.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created testimonial to get ID
|
||||
let created_testimonial = repo
|
||||
.query_testimonial_by_id(testimonial.id.id.to_raw())
|
||||
.await
|
||||
.unwrap();
|
||||
let testimonial_id = created_testimonial.id.id.to_raw();
|
||||
|
||||
// Verify testimonial exists before deletion
|
||||
let exists_before = repo.query_testimonial_by_id(testimonial_id.clone()).await.is_ok();
|
||||
assert!(exists_before);
|
||||
|
||||
// Delete testimonial
|
||||
let result = repo.query_delete_testimonial(testimonial_id.clone()).await;
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(result.unwrap(), "Success delete testimonial");
|
||||
|
||||
// Verify testimonial was soft-deleted from database
|
||||
let deleted_testimonial = repo.query_testimonial_by_id(testimonial_id.clone()).await;
|
||||
assert!(deleted_testimonial.is_err());
|
||||
assert_eq!(deleted_testimonial.unwrap_err().to_string(), "Testimonial not found");
|
||||
|
||||
// Clean up - no need since it's already soft-deleted
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_delete_testimonial_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Try to delete non-existent testimonial
|
||||
let result = repo.query_delete_testimonial(non_existent_id).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err().to_string(), "Testimonial not found");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_delete_testimonial_already_deleted() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test User".to_string(),
|
||||
email: "testuser@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Create test testimonial
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: "Mentor".to_string(),
|
||||
content: "Test testimonial content for already deleted test".to_string(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let create_result = repo.query_create_testimonial(testimonial.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created testimonial to get ID
|
||||
let created_testimonial = repo
|
||||
.query_testimonial_by_id(testimonial.id.id.to_raw())
|
||||
.await
|
||||
.unwrap();
|
||||
let testimonial_id = created_testimonial.id.id.to_raw();
|
||||
|
||||
// Soft delete the testimonial twice
|
||||
let _ = repo.query_delete_testimonial(testimonial_id.clone()).await;
|
||||
let result = repo.query_delete_testimonial(testimonial_id).await;
|
||||
|
||||
// Verify second deletion fails
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err().to_string(), "Testimonial not found");
|
||||
|
||||
// Clean up
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,544 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{get_meta_request_dto, UsersRepository};
|
||||
use axum::{http::StatusCode, response::Response};
|
||||
use imphnen_cms::{
|
||||
v1::landing::testimonials::{
|
||||
testimonials_dto::{TestimonialsCreateRequestDto, TestimonialsUpdateRequestDto},
|
||||
testimonials_service::TestimonialsService,
|
||||
testimonials_schema::TestimonialsSchema,
|
||||
},
|
||||
};
|
||||
use imphnen_entities::UsersSchema;
|
||||
use imphnen_utils::make_thing_from_enum;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_testimonial_list_service() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_cms::v1::landing::testimonials::testimonials_repository::TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test testimonials
|
||||
let testimonial_contents = vec![
|
||||
"Testimonial content 1".to_string(),
|
||||
"Testimonial content 2".to_string(),
|
||||
"Testimonial content 3".to_string(),
|
||||
];
|
||||
|
||||
for content in &testimonial_contents {
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: format!("Test User for {}", content),
|
||||
email: format!("testuser{}@example.com", content.chars().take(5).collect::<String>()),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: "Mentor".to_string(),
|
||||
content: content.clone(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let _ = repo.query_create_testimonial(testimonial).await;
|
||||
}
|
||||
|
||||
// Get testimonial list through service
|
||||
let response = TestimonialsService::get_testimonial_list(&app_state, get_meta_request_dto(1, 10))
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Clean up
|
||||
for content in testimonial_contents {
|
||||
let user = UsersRepository::new(&app_state)
|
||||
.query_user_by_email(format!("testuser{}@example.com", content.chars().take(5).collect::<String>()))
|
||||
.await
|
||||
.unwrap();
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_testimonial_by_id_service_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_cms::v1::landing::testimonials::testimonials_repository::TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test User".to_string(),
|
||||
email: "testuser@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Create test testimonial
|
||||
let testimonial_content = "Test testimonial content for get by ID service test".to_string();
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: "Mentor".to_string(),
|
||||
content: testimonial_content.clone(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let create_result = repo.query_create_testimonial(testimonial.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created testimonial to get ID
|
||||
let created_testimonial = repo
|
||||
.query_testimonial_by_id(testimonial.id.id.to_raw())
|
||||
.await
|
||||
.unwrap();
|
||||
let testimonial_id = created_testimonial.id.id.to_raw();
|
||||
|
||||
// Get testimonial by ID through service
|
||||
let response = TestimonialsService::get_testimonial_by_id(&app_state, testimonial_id.clone())
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Verify response body contains correct data
|
||||
let body_bytes = response.into_body().collect().await.unwrap().to_bytes();
|
||||
let response_body: serde_json::Value = serde_json::from_slice(&body_bytes).unwrap();
|
||||
assert_eq!(response_body["data"]["content"].as_str().unwrap(), testimonial_content);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_testimonial(testimonial_id).await;
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_testimonial_by_id_service_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Get non-existent testimonial by ID through service
|
||||
let response = TestimonialsService::get_testimonial_by_id(&app_state, non_existent_id)
|
||||
.await;
|
||||
|
||||
// Verify not found response
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_testimonial_by_id_service_deleted() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_cms::v1::landing::testimonials::testimonials_repository::TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test User".to_string(),
|
||||
email: "testuser@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Create test testimonial
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: "Mentor".to_string(),
|
||||
content: "Test testimonial content for deleted test".to_string(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let create_result = repo.query_create_testimonial(testimonial.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created testimonial to get ID
|
||||
let created_testimonial = repo
|
||||
.query_testimonial_by_id(testimonial.id.id.to_raw())
|
||||
.await
|
||||
.unwrap();
|
||||
let testimonial_id = created_testimonial.id.id.to_raw();
|
||||
|
||||
// Soft delete the testimonial
|
||||
let _ = repo.query_delete_testimonial(testimonial_id.clone()).await;
|
||||
|
||||
// Try to get deleted testimonial through service
|
||||
let response = TestimonialsService::get_testimonial_by_id(&app_state, testimonial_id)
|
||||
.await;
|
||||
|
||||
// Verify not found response (service should filter out deleted items)
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
|
||||
// Clean up
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_testimonial_service() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_cms::v1::landing::testimonials::testimonials_repository::TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user for authentication
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test Admin".to_string(),
|
||||
email: "admin@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Test data
|
||||
let testimonial_request = TestimonialsCreateRequestDto {
|
||||
role: "Mentor".to_string(),
|
||||
content: "Test testimonial content for service create test".to_string(),
|
||||
};
|
||||
|
||||
// Create testimonial through service
|
||||
let response = TestimonialsService::create_testimonial(
|
||||
&app_state, testimonial_request.clone(), &user,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::CREATED);
|
||||
|
||||
// Verify testimonial was created in database
|
||||
let created_testimonials = repo.query_testimonial_list(get_meta_request_dto(1, 10)).await.unwrap();
|
||||
assert!(created_testimonials.data.iter().any(|t| t.content == testimonial_request.content));
|
||||
|
||||
// Clean up
|
||||
let created_testimonial = repo.query_testimonial_list(get_meta_request_dto(1, 10)).await.unwrap();
|
||||
for t in created_testimonials.data {
|
||||
if t.content == testimonial_request.content {
|
||||
let _ = repo.query_delete_testimonial(t.id.id.to_raw()).await;
|
||||
}
|
||||
}
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_testimonial_service_invalid_data() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Create test user for authentication
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test Admin".to_string(),
|
||||
email: "admin@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Test data with empty content (should fail validation)
|
||||
let testimonial_request = TestimonialsCreateRequestDto {
|
||||
role: "Mentor".to_string(),
|
||||
content: "".to_string(), // Empty content should fail validation
|
||||
};
|
||||
|
||||
// Create testimonial through service
|
||||
let response = TestimonialsService::create_testimonial(
|
||||
&app_state, testimonial_request, &user,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify bad request response (validation error)
|
||||
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
|
||||
|
||||
// Clean up
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_testimonial_service() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_cms::v1::landing::testimonials::testimonials_repository::TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user for authentication
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test Admin".to_string(),
|
||||
email: "admin@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Create test testimonial
|
||||
let original_content = "Original testimonial content for service update test".to_string();
|
||||
let new_content = "Updated testimonial content for service update test".to_string();
|
||||
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: "Mentor".to_string(),
|
||||
content: original_content.clone(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let create_result = repo.query_create_testimonial(testimonial.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created testimonial to get ID
|
||||
let created_testimonial = repo
|
||||
.query_testimonial_by_id(testimonial.id.id.to_raw())
|
||||
.await
|
||||
.unwrap();
|
||||
let testimonial_id = created_testimonial.id.id.to_raw();
|
||||
|
||||
// Prepare update request
|
||||
let update_request = TestimonialsUpdateRequestDto {
|
||||
role: Some("Updated Mentor".to_string()),
|
||||
content: Some(new_content.clone()),
|
||||
};
|
||||
|
||||
// Update testimonial through service
|
||||
let response = TestimonialsService::update_testimonial(
|
||||
&app_state, update_request, testimonial_id.clone(), &user,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Verify testimonial was updated in database
|
||||
let updated_testimonial = repo
|
||||
.query_testimonial_by_id(testimonial_id.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(updated_testimonial.content, new_content);
|
||||
assert_eq!(updated_testimonial.role, "Updated Mentor");
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_testimonial(testimonial_id).await;
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_testimonial_service_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Create test user for authentication
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test Admin".to_string(),
|
||||
email: "admin@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Prepare update request
|
||||
let update_request = TestimonialsUpdateRequestDto {
|
||||
role: Some("Updated Mentor".to_string()),
|
||||
content: Some("Updated content".to_string()),
|
||||
};
|
||||
|
||||
// Update non-existent testimonial through service
|
||||
let response = TestimonialsService::update_testimonial(
|
||||
&app_state, update_request, non_existent_id, &user,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify not found response
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
|
||||
// Clean up
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_testimonial_service_deleted() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_cms::v1::landing::testimonials::testimonials_repository::TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user for authentication
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test Admin".to_string(),
|
||||
email: "admin@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Create test testimonial
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: "Mentor".to_string(),
|
||||
content: "Test testimonial content for deleted update test".to_string(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let create_result = repo.query_create_testimonial(testimonial.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created testimonial to get ID
|
||||
let created_testimonial = repo
|
||||
.query_testimonial_by_id(testimonial.id.id.to_raw())
|
||||
.await
|
||||
.unwrap();
|
||||
let testimonial_id = created_testimonial.id.id.to_raw();
|
||||
|
||||
// Soft delete the testimonial
|
||||
let _ = repo.query_delete_testimonial(testimonial_id.clone()).await;
|
||||
|
||||
// Prepare update request
|
||||
let update_request = TestimonialsUpdateRequestDto {
|
||||
role: Some("Updated Mentor".to_string()),
|
||||
content: Some("Updated content".to_string()),
|
||||
};
|
||||
|
||||
// Try to update deleted testimonial through service
|
||||
let response = TestimonialsService::update_testimonial(
|
||||
&app_state, update_request, testimonial_id, &user,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify bad request response (should fail because it's deleted)
|
||||
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
|
||||
|
||||
// Clean up
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_testimonial_service() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_cms::v1::landing::testimonials::testimonials_repository::TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user for authentication
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test Admin".to_string(),
|
||||
email: "admin@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Create test testimonial
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: "Mentor".to_string(),
|
||||
content: "Test testimonial content for service delete test".to_string(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let create_result = repo.query_create_testimonial(testimonial.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created testimonial to get ID
|
||||
let created_testimonial = repo
|
||||
.query_testimonial_by_id(testimonial.id.id.to_raw())
|
||||
.await
|
||||
.unwrap();
|
||||
let testimonial_id = created_testimonial.id.id.to_raw();
|
||||
|
||||
// Verify testimonial exists before deletion
|
||||
let exists_before = repo.query_testimonial_by_id(testimonial_id.clone()).await.is_ok();
|
||||
assert!(exists_before);
|
||||
|
||||
// Delete testimonial through service
|
||||
let response = TestimonialsService::delete_testimonial(
|
||||
&app_state, testimonial_id.clone(), &user,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Verify testimonial was soft-deleted from database
|
||||
let deleted_testimonial = repo.query_testimonial_by_id(testimonial_id.clone()).await;
|
||||
assert!(deleted_testimonial.is_err());
|
||||
|
||||
// Clean up - no need since it's already soft-deleted
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_testimonial_service_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Create test user for authentication
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test Admin".to_string(),
|
||||
email: "admin@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Delete non-existent testimonial through service
|
||||
let response = TestimonialsService::delete_testimonial(
|
||||
&app_state, non_existent_id, &user,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify bad request response
|
||||
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
|
||||
|
||||
// Clean up
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_testimonial_service_deleted_twice() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_cms::v1::landing::testimonials::testimonials_repository::TestimonialsRepository::new(&app_state);
|
||||
|
||||
// Create test user for authentication
|
||||
let user = UsersSchema {
|
||||
id: make_thing_from_enum("users", &uuid::Uuid::new_v4().to_string()),
|
||||
fullname: "Test Admin".to_string(),
|
||||
email: "admin@example.com".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = UsersRepository::new(&app_state).query_create_user(user.clone()).await;
|
||||
|
||||
// Create test testimonial
|
||||
let testimonial = TestimonialsSchema {
|
||||
id: make_thing_from_enum("testimonials", &uuid::Uuid::new_v4().to_string()),
|
||||
user: user.id,
|
||||
role: "Mentor".to_string(),
|
||||
content: "Test testimonial content for double delete test".to_string(),
|
||||
created_at: chrono::Utc::now().to_rfc3339(),
|
||||
updated_at: chrono::Utc::now().to_rfc3339(),
|
||||
is_deleted: false,
|
||||
};
|
||||
let create_result = repo.query_create_testimonial(testimonial.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created testimonial to get ID
|
||||
let created_testimonial = repo
|
||||
.query_testimonial_by_id(testimonial.id.id.to_raw())
|
||||
.await
|
||||
.unwrap();
|
||||
let testimonial_id = created_testimonial.id.id.to_raw();
|
||||
|
||||
// Delete testimonial once
|
||||
let _ = repo.query_delete_testimonial(testimonial_id.clone()).await;
|
||||
|
||||
// Try to delete again through service
|
||||
let response = TestimonialsService::delete_testimonial(
|
||||
&app_state, testimonial_id, &user,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify bad request response (should fail because it's already deleted)
|
||||
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
|
||||
|
||||
// Clean up
|
||||
let _ = UsersRepository::new(&app_state).query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,816 @@
|
||||
use axum::{
|
||||
body::Body,
|
||||
http::{HeaderMap, Method, Request, StatusCode},
|
||||
response::Response,
|
||||
routing::{get, post, put, delete},
|
||||
Router,
|
||||
};
|
||||
use http_body_util::BodyExt;
|
||||
use imphnen_dimentorin::{
|
||||
mentors_controller,
|
||||
mentors_dto::{
|
||||
MentorUpdateRequestDto, MentorUserRegisterRequestDto, MentorVerifyRequestDto,
|
||||
MentorRegisterResponseDto,
|
||||
},
|
||||
};
|
||||
use imphnen_entities::{AppState, ResponseSuccessDto};
|
||||
use imphnen_iam::{PermissionsEnum, RolesEnum, UsersRepository};
|
||||
use imphnen_libs::{ResourceEnum, surrealdb_init_ws, surrealdb_init_mem, Env};
|
||||
use imphnen_utils::{generate_otp, hash_password, make_thing, get_iso_date};
|
||||
use serde_json::json;
|
||||
use surrealdb::{Uuid, sql::Thing};
|
||||
use dotenvy::dotenv;
|
||||
use tower::ServiceExt;
|
||||
use crate::{generate_unique_email, get_role_id, setup_all_test_environment};
|
||||
|
||||
// Helper function to create a test application (router) with all mentor endpoints
|
||||
fn app(app_state: AppState) -> Router {
|
||||
Router::new()
|
||||
.route("/v1/mentors/register", post(mentors_controller::post_register_mentor))
|
||||
.route("/v1/mentors", get(mentors_controller::get_mentor_list))
|
||||
.route("/v1/mentors/detail/:id", get(mentors_controller::get_mentor_by_id))
|
||||
.route("/v1/mentors/update/:id", put(mentors_controller::put_update_mentor))
|
||||
.route("/v1/mentors/delete/:id", delete(mentors_controller::delete_mentor))
|
||||
.route("/v1/mentors/verify/:id", put(mentors_controller::put_verify_mentor))
|
||||
.route("/v1/mentors/me", get(mentors_controller::get_mentor_me))
|
||||
.route("/v1/mentors/update/me", put(mentors_controller::put_update_mentor_me))
|
||||
.route("/v1/mentors/update", put(mentors_controller::put_update_mentor_no_id))
|
||||
.route("/v1/mentors/status", get(mentors_controller::get_mentor_status))
|
||||
.with_state(app_state)
|
||||
}
|
||||
|
||||
// Helper function to create a valid mentor registration DTO
|
||||
fn create_valid_mentor_dto(email: &str) -> MentorUserRegisterRequestDto {
|
||||
MentorUserRegisterRequestDto {
|
||||
email: email.to_string(),
|
||||
password: "Password123!".to_string(),
|
||||
fullname: "Test Mentor".to_string(),
|
||||
phone_number: "1234567890".to_string(),
|
||||
identity_and_verification: imphnen_dimentorin::mentors_dto::IdentityAndVerification {
|
||||
legal_name: "Legal Test Name".to_string(),
|
||||
gender: Some("Laki-laki".to_string()),
|
||||
domicile: Some("Jakarta Selatan".to_string()),
|
||||
identity_document_url: "http://example.com/id.pdf".to_string(),
|
||||
phone_for_verification: "0987654321".to_string(),
|
||||
},
|
||||
professional_profile: imphnen_dimentorin::mentors_dto::ProfessionalProfile {
|
||||
bio: "Experienced professional with 5+ years of experience in software development.".to_string(),
|
||||
last_education: Some("S1".to_string()),
|
||||
linkedin_url: Some("http://linkedin.com/in/test".to_string()),
|
||||
github_url: None,
|
||||
cv_url: None,
|
||||
portfolio_url: Some("http://example.com/portfolio".to_string()),
|
||||
industries: vec!["Technology".to_string()],
|
||||
expertise: vec!["Rust".to_string(), "Backend Development".to_string()],
|
||||
languages: vec!["English".to_string()],
|
||||
current_company: "Tech Corp".to_string(),
|
||||
current_role: "Senior Engineer".to_string(),
|
||||
years_of_experience: 5,
|
||||
},
|
||||
mentoring_logistics: imphnen_dimentorin::mentors_dto::MentoringLogistics {
|
||||
topics_of_interest: vec!["Career Development".to_string()],
|
||||
preferred_mentee_level: vec!["Beginner".to_string()],
|
||||
preferred_mentoring_formats: vec!["Online".to_string()],
|
||||
availability_commitment: "5 hours/week".to_string(),
|
||||
mentoring_rate_amount: 100,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to create a valid mentor update DTO
|
||||
fn create_valid_mentor_update_dto() -> MentorUpdateRequestDto {
|
||||
MentorUpdateRequestDto {
|
||||
legal_name: Some("Updated Legal Name".to_string()),
|
||||
gender: Some("Perempuan".to_string()),
|
||||
domicile: Some("Bandung".to_string()),
|
||||
phone_for_verification: Some("0876543210".to_string()),
|
||||
bio: Some("Updated bio with more experience.".to_string()),
|
||||
last_education: Some("S2".to_string()),
|
||||
linkedin_url: Some("http://linkedin.com/in/updated".to_string()),
|
||||
github_url: Some("http://github.com/updated".to_string()),
|
||||
cv_url: Some("http://example.com/updated_cv.pdf".to_string()),
|
||||
portfolio_url: Some("http://example.com/updated_portfolio".to_string()),
|
||||
industries: Some(vec!["Technology".to_string(), "Education".to_string()]),
|
||||
expertise: Some(vec!["Rust".to_string(), "AI".to_string()]),
|
||||
languages: Some(vec!["English".to_string(), "Spanish".to_string()]),
|
||||
current_company: Some("New Tech Corp".to_string()),
|
||||
current_role: Some("Lead Engineer".to_string()),
|
||||
years_of_experience: Some(7),
|
||||
topics_of_interest: Some(vec!["Career Development".to_string(), "Tech Trends".to_string()]),
|
||||
preferred_mentee_level: Some(vec!["Beginner".to_string(), "Intermediate".to_string()]),
|
||||
preferred_mentoring_formats: Some(vec!["Online".to_string(), "Offline".to_string()]),
|
||||
availability_commitment: Some("10 hours/week".to_string()),
|
||||
mentoring_rate_amount: Some(200),
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to create authentication headers with mock JWT
|
||||
fn create_auth_headers(user_email: &str, permissions: Vec<PermissionsEnum>) -> HeaderMap {
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.insert("Authorization", format!("Bearer mock_jwt_{}", user_email).parse().unwrap());
|
||||
headers
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_post_register_mentor_success() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
let test_email = "register_mentor_success@example.com";
|
||||
let dto = create_valid_mentor_dto(test_email);
|
||||
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/v1/mentors/register")
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(&dto).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
let body = response.into_body().collect().await.unwrap().to_bytes();
|
||||
let mentor_register_response: MentorRegisterResponseDto = serde_json::from_slice(&body).unwrap();
|
||||
|
||||
assert!(!mentor_register_response.id.is_empty());
|
||||
assert!(!mentor_register_response.user_id.is_empty());
|
||||
assert_eq!(mentor_register_response.status, "pending".to_string());
|
||||
|
||||
// Verify user was created in database
|
||||
let user_repo = UsersRepository::new(&app_state);
|
||||
let user = user_repo.query_user_by_email(test_email.to_string()).await.unwrap();
|
||||
assert_eq!(user.email, test_email);
|
||||
assert_eq!(user.is_active, false); // Should be inactive until OTP verification
|
||||
|
||||
// Clean up
|
||||
let _ = user_repo.query_delete_user(test_email.to_string()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_post_register_mentor_invalid_email() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
let test_email = "invalid-email";
|
||||
let mut dto = create_valid_mentor_dto(test_email);
|
||||
dto.email = test_email.to_string();
|
||||
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/v1/mentors/register")
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(&dto).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
|
||||
let body = response.into_body().collect().await.unwrap().to_bytes();
|
||||
let error_response: serde_json::Value = serde_json::from_slice(&body).unwrap();
|
||||
assert!(error_response["message"].as_str().unwrap().contains("email"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_post_register_mentor_weak_password() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
let test_email = "weak_password@example.com";
|
||||
let mut dto = create_valid_mentor_dto(test_email);
|
||||
dto.password = "weak".to_string();
|
||||
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/v1/mentors/register")
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(&dto).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
|
||||
let body = response.into_body().collect().await.unwrap().to_bytes();
|
||||
let error_response: serde_json::Value = serde_json::from_slice(&body).unwrap();
|
||||
assert!(error_response["message"].as_str().unwrap().contains("password"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_mentor_list_success() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
// Create a test mentor first
|
||||
let test_email = "list_mentor_test@example.com";
|
||||
let dto = create_valid_mentor_dto(test_email);
|
||||
|
||||
let register_response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/v1/mentors/register")
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(&dto).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(register_response.status(), StatusCode::OK);
|
||||
|
||||
// Get mentor list with authentication
|
||||
let headers = create_auth_headers(test_email, vec![PermissionsEnum::ReadListMentors]);
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::GET)
|
||||
.uri("/v1/mentors")
|
||||
.headers(headers)
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let body = response.into_body().collect().await.unwrap().to_bytes();
|
||||
let response_data: ResponseSuccessDto<Vec<imphnen_dimentorin::mentors_dto::MentorListResponseDto>> =
|
||||
serde_json::from_slice(&body).unwrap();
|
||||
|
||||
assert!(!response_data.data.is_empty());
|
||||
assert_eq!(response_data.data[0].status, "pending".to_string());
|
||||
|
||||
// Clean up
|
||||
let user_repo = UsersRepository::new(&app_state);
|
||||
let _ = user_repo.query_delete_user(test_email.to_string()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_mentor_list_unauthorized() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
// Try to get mentor list without authentication
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::GET)
|
||||
.uri("/v1/mentors")
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::UNAUTHORIZED);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_mentor_by_id_success() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
// Create a test mentor first
|
||||
let test_email = "get_by_id_test@example.com";
|
||||
let dto = create_valid_mentor_dto(test_email);
|
||||
|
||||
let register_response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/v1/mentors/register")
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(&dto).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(register_response.status(), StatusCode::OK);
|
||||
let register_body: MentorRegisterResponseDto = serde_json::from_slice(®ister_response.into_body().collect().await.unwrap().to_bytes()).unwrap();
|
||||
let mentor_id = register_body.id.clone();
|
||||
|
||||
// Get mentor by ID with authentication
|
||||
let headers = create_auth_headers(test_email, vec![PermissionsEnum::ReadDetailMentors]);
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::GET)
|
||||
.uri(&format!("/v1/mentors/detail/{}", mentor_id))
|
||||
.headers(headers)
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let body = response.into_body().collect().await.unwrap().to_bytes();
|
||||
let mentor_response: ResponseSuccessDto<imphnen_dimentorin::mentors_dto::MentorDetailResponseDto> =
|
||||
serde_json::from_slice(&body).unwrap();
|
||||
|
||||
assert_eq!(mentor_response.data.id, mentor_id);
|
||||
assert_eq!(mentor_response.data.status, "pending".to_string());
|
||||
assert_eq!(mentor_response.data.fullname, Some("Test Mentor".to_string()));
|
||||
|
||||
// Clean up
|
||||
let user_repo = UsersRepository::new(&app_state);
|
||||
let _ = user_repo.query_delete_user(test_email.to_string()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_mentor_by_id_not_found() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
// Try to get non-existent mentor with authentication
|
||||
let headers = create_auth_headers("nonexistent@example.com", vec![PermissionsEnum::ReadDetailMentors]);
|
||||
let non_existent_id = Uuid::new_v4().to_string();
|
||||
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::GET)
|
||||
.uri(&format!("/v1/mentors/detail/{}", non_existent_id))
|
||||
.headers(headers)
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_put_update_mentor_success() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
// Create a test mentor first
|
||||
let test_email = "update_mentor_test@example.com";
|
||||
let dto = create_valid_mentor_dto(test_email);
|
||||
|
||||
let register_response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/v1/mentors/register")
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(&dto).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(register_response.status(), StatusCode::OK);
|
||||
let register_body: MentorRegisterResponseDto = serde_json::from_slice(®ister_response.into_body().collect().await.unwrap().to_bytes()).unwrap();
|
||||
let mentor_id = register_body.id.clone();
|
||||
|
||||
// Prepare update DTO
|
||||
let update_dto = create_valid_mentor_update_dto();
|
||||
|
||||
// Update mentor with authentication
|
||||
let headers = create_auth_headers(test_email, vec![PermissionsEnum::UpdateMentors]);
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::PUT)
|
||||
.uri(&format!("/v1/mentors/update/{}", mentor_id))
|
||||
.headers(headers)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(&update_dto).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let body = response.into_body().collect().await.unwrap().to_bytes();
|
||||
let mentor_response: ResponseSuccessDto<imphnen_dimentorin::mentors_dto::MentorDetailResponseDto> =
|
||||
serde_json::from_slice(&body).unwrap();
|
||||
|
||||
assert_eq!(mentor_response.data.id, mentor_id);
|
||||
assert_eq!(mentor_response.data.legal_name, Some("Updated Legal Name".to_string()));
|
||||
assert_eq!(mentor_response.data.current_role, "Lead Engineer".to_string());
|
||||
|
||||
// Clean up
|
||||
let user_repo = UsersRepository::new(&app_state);
|
||||
let _ = user_repo.query_delete_user(test_email.to_string()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_put_update_mentor_not_found() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
// Try to update non-existent mentor with authentication
|
||||
let headers = create_auth_headers("nonexistent@example.com", vec![PermissionsEnum::UpdateMentors]);
|
||||
let non_existent_id = Uuid::new_v4().to_string();
|
||||
let update_dto = create_valid_mentor_update_dto();
|
||||
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::PUT)
|
||||
.uri(&format!("/v1/mentors/update/{}", non_existent_id))
|
||||
.headers(headers)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(&update_dto).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_mentor_success() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
// Create a test mentor first
|
||||
let test_email = "delete_mentor_test@example.com";
|
||||
let dto = create_valid_mentor_dto(test_email);
|
||||
|
||||
let register_response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/v1/mentors/register")
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(&dto).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(register_response.status(), StatusCode::OK);
|
||||
let register_body: MentorRegisterResponseDto = serde_json::from_slice(®ister_response.into_body().collect().await.unwrap().to_bytes()).unwrap();
|
||||
let mentor_id = register_body.id.clone();
|
||||
|
||||
// Delete mentor with authentication
|
||||
let headers = create_auth_headers(test_email, vec![PermissionsEnum::DeleteMentors]);
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::DELETE)
|
||||
.uri(&format!("/v1/mentors/delete/{}", mentor_id))
|
||||
.headers(headers)
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Verify mentor was soft-deleted
|
||||
let user_repo = UsersRepository::new(&app_state);
|
||||
let _ = user_repo.query_delete_user(test_email.to_string()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_mentor_not_found() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
// Try to delete non-existent mentor with authentication
|
||||
let headers = create_auth_headers("nonexistent@example.com", vec![PermissionsEnum::DeleteMentors]);
|
||||
let non_existent_id = Uuid::new_v4().to_string();
|
||||
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::DELETE)
|
||||
.uri(&format!("/v1/mentors/delete/{}", non_existent_id))
|
||||
.headers(headers)
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_put_verify_mentor_success() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
// Create a test mentor first
|
||||
let test_email = "verify_mentor_test@example.com";
|
||||
let dto = create_valid_mentor_dto(test_email);
|
||||
|
||||
let register_response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/v1/mentors/register")
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(&dto).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(register_response.status(), StatusCode::OK);
|
||||
let register_body: MentorRegisterResponseDto = serde_json::from_slice(®ister_response.into_body().collect().await.unwrap().to_bytes()).unwrap();
|
||||
let mentor_id = register_body.id.clone();
|
||||
|
||||
// Prepare verification DTO
|
||||
let verify_dto = MentorVerifyRequestDto {
|
||||
status: "verified".to_string(),
|
||||
};
|
||||
|
||||
// Verify mentor with authentication
|
||||
let headers = create_auth_headers(test_email, vec![PermissionsEnum::VerifyMentors]);
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::PUT)
|
||||
.uri(&format!("/v1/mentors/verify/{}", mentor_id))
|
||||
.headers(headers)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(&verify_dto).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let body = response.into_body().collect().await.unwrap().to_bytes();
|
||||
let mentor_response: ResponseSuccessDto<imphnen_dimentorin::mentors_dto::MentorDetailResponseDto> =
|
||||
serde_json::from_slice(&body).unwrap();
|
||||
|
||||
assert_eq!(mentor_response.data.id, mentor_id);
|
||||
assert_eq!(mentor_response.data.status, "verified".to_string());
|
||||
|
||||
// Clean up
|
||||
let user_repo = UsersRepository::new(&app_state);
|
||||
let _ = user_repo.query_delete_user(test_email.to_string()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_mentor_me_success() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
// Create a test mentor first
|
||||
let test_email = "mentor_me_test@example.com";
|
||||
let dto = create_valid_mentor_dto(test_email);
|
||||
|
||||
let register_response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/v1/mentors/register")
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(&dto).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(register_response.status(), StatusCode::OK);
|
||||
|
||||
// Get mentor me with authentication
|
||||
let headers = create_auth_headers(test_email, vec![PermissionsEnum::ReadOwnMentorProfile]);
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::GET)
|
||||
.uri("/v1/mentors/me")
|
||||
.headers(headers)
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let body = response.into_body().collect().await.unwrap().to_bytes();
|
||||
let mentor_response: ResponseSuccessDto<imphnen_dimentorin::mentors_dto::MentorDetailResponseDto> =
|
||||
serde_json::from_slice(&body).unwrap();
|
||||
|
||||
assert_eq!(mentor_response.data.email, Some(test_email.to_string()));
|
||||
assert_eq!(mentor_response.data.status, "pending".to_string());
|
||||
|
||||
// Clean up
|
||||
let user_repo = UsersRepository::new(&app_state);
|
||||
let _ = user_repo.query_delete_user(test_email.to_string()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_put_update_mentor_me_success() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
// Create a test mentor first
|
||||
let test_email = "update_mentor_me_test@example.com";
|
||||
let dto = create_valid_mentor_dto(test_email);
|
||||
|
||||
let register_response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/v1/mentors/register")
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(&dto).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(register_response.status(), StatusCode::OK);
|
||||
|
||||
// Prepare update DTO
|
||||
let update_dto = create_valid_mentor_update_dto();
|
||||
|
||||
// Update mentor me with authentication
|
||||
let headers = create_auth_headers(test_email, vec![PermissionsEnum::UpdateOwnMentorProfile]);
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::PUT)
|
||||
.uri("/v1/mentors/update/me")
|
||||
.headers(headers)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(&update_dto).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let body = response.into_body().collect().await.unwrap().to_bytes();
|
||||
let mentor_response: ResponseSuccessDto<imphnen_dimentorin::mentors_dto::MentorDetailResponseDto> =
|
||||
serde_json::from_slice(&body).unwrap();
|
||||
|
||||
assert_eq!(mentor_response.data.legal_name, Some("Updated Legal Name".to_string()));
|
||||
assert_eq!(mentor_response.data.current_role, "Lead Engineer".to_string());
|
||||
|
||||
// Clean up
|
||||
let user_repo = UsersRepository::new(&app_state);
|
||||
let _ = user_repo.query_delete_user(test_email.to_string()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_put_update_mentor_no_id() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
// Try to update mentor without ID (should return 400)
|
||||
let headers = create_auth_headers("test@example.com", vec![PermissionsEnum::UpdateMentors]);
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::PUT)
|
||||
.uri("/v1/mentors/update")
|
||||
.headers(headers)
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
|
||||
let body = response.into_body().collect().await.unwrap().to_bytes();
|
||||
let error_response: serde_json::Value = serde_json::from_slice(&body).unwrap();
|
||||
assert_eq!(error_response["message"], "Mentor ID is required for update");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_mentor_status_success() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
// Create a test mentor first
|
||||
let test_email = "mentor_status_test@example.com";
|
||||
let dto = create_valid_mentor_dto(test_email);
|
||||
|
||||
let register_response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/v1/mentors/register")
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(&dto).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(register_response.status(), StatusCode::OK);
|
||||
|
||||
// Get mentor status with authentication
|
||||
let headers = create_auth_headers(test_email, vec![PermissionsEnum::ReadOwnMentorStatus]);
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::GET)
|
||||
.uri("/v1/mentors/status")
|
||||
.headers(headers)
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let body = response.into_body().collect().await.unwrap().to_bytes();
|
||||
let status_response: serde_json::Value = serde_json::from_slice(&body).unwrap();
|
||||
assert_eq!(status_response, "pending");
|
||||
|
||||
// Clean up
|
||||
let user_repo = UsersRepository::new(&app_state);
|
||||
let _ = user_repo.query_delete_user(test_email.to_string()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_controller_endpoints_validation() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
// Test update mentor with invalid data (empty legal name)
|
||||
let test_email = "validation_test@example.com";
|
||||
let dto = create_valid_mentor_dto(test_email);
|
||||
|
||||
let register_response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/v1/mentors/register")
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(&dto).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(register_response.status(), StatusCode::OK);
|
||||
let register_body: MentorRegisterResponseDto = serde_json::from_slice(®ister_response.into_body().collect().await.unwrap().to_bytes()).unwrap();
|
||||
let mentor_id = register_body.id.clone();
|
||||
|
||||
// Prepare invalid update DTO (empty legal name)
|
||||
let mut invalid_update_dto = create_valid_mentor_update_dto();
|
||||
invalid_update_dto.legal_name = Some("".to_string()); // Invalid - too short
|
||||
|
||||
// Try to update with invalid data
|
||||
let headers = create_auth_headers(test_email, vec![PermissionsEnum::UpdateMentors]);
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::PUT)
|
||||
.uri(&format!("/v1/mentors/update/{}", mentor_id))
|
||||
.headers(headers)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(&invalid_update_dto).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
|
||||
let body = response.into_body().collect().await.unwrap().to_bytes();
|
||||
let error_response: serde_json::Value = serde_json::from_slice(&body).unwrap();
|
||||
assert!(error_response["message"].as_str().unwrap().contains("Legal name must be at least 3 characters"));
|
||||
|
||||
// Clean up
|
||||
let user_repo = UsersRepository::new(&app_state);
|
||||
let _ = user_repo.query_delete_user(test_email.to_string()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_controller_permission_denied() {
|
||||
let app_state = setup_all_test_environment().await;
|
||||
let app = app(app_state.clone());
|
||||
|
||||
// Try to access protected endpoint without proper permissions
|
||||
let headers = create_auth_headers("test@example.com", vec![]); // Empty permissions
|
||||
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method(Method::GET)
|
||||
.uri("/v1/mentors")
|
||||
.headers(headers)
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::FORBIDDEN);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
use axum_test::TestServer;
|
||||
use imphnen_gacha::v1::gacha_claims::gacha_claims_controller::{self, GachaClaimsService};
|
||||
use imphnen_gacha::v1::gacha_claims::gacha_claims_dto::{CreateGachaClaimDto, GachaClaimResponse};
|
||||
use mockall::mock;
|
||||
use tower::ServiceBuilder;
|
||||
use tower::timeout::TimeoutLayer;
|
||||
use std::time::Duration;
|
||||
|
||||
mock! {
|
||||
pub GachaClaimsServiceMock {}
|
||||
#[async_trait]
|
||||
impl GachaClaimsService for GachaClaimsServiceMock {
|
||||
async fn create_claim(&self, user_id: &str, item_id: &str) -> Result<GachaClaimResponse, String>;
|
||||
async fn get_claim(&self, claim_id: &str) -> Result<GachaClaimResponse, String>;
|
||||
async fn get_user_claims(&self, user_id: &str) -> Result<Vec<GachaClaimResponse>, String>;
|
||||
async fn update_claim(&self, claim_id: &str, status: &str) -> Result<GachaClaimResponse, String>;
|
||||
async fn delete_claim(&self, claim_id: &str) -> Result<(), String>;
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_claim_happy_path() {
|
||||
let mock_service = MockGachaClaimsServiceMock::new();
|
||||
let create_dto = CreateGachaClaimDto { user_id: "user123".to_string(), item_id: "item456".to_string() };
|
||||
let expected = GachaClaimResponse { id: "claim789".to_string(), user_id: "user123".to_string(), item_id: "item456".to_string(), status: "pending".to_string(), created_at: "2024-01-01T00:00:00Z".to_string() };
|
||||
|
||||
mock_service.expect_create_claim().withf(|u, i| u == &create_dto.user_id && i == &create_dto.item_id).returning(|_, _| Ok(expected.clone()));
|
||||
|
||||
let app = ServiceBuilder::new().layer(TimeoutLayer::new(Duration::from_secs(10))).service(gacha_claims_controller::router(mock_service));
|
||||
let server = TestServer::new(app).unwrap();
|
||||
|
||||
let response = server.post("/gacha/claims").json(&create_dto).await;
|
||||
assert_eq!(response.status(), 201);
|
||||
let body: GachaClaimResponse = response.json().await.unwrap();
|
||||
assert_eq!(body.id, expected.id);
|
||||
}
|
||||
|
||||
// Additional tests for error cases, get, update, delete...
|
||||
@@ -0,0 +1,68 @@
|
||||
use imphnen_gacha::v1::gacha_claims::gacha_claims_repository::{self, GachaClaimsRepository};
|
||||
use imphnen_gacha::v1::gacha_claims::gacha_claims_dto::{CreateGachaClaimDto, GachaClaimResponse};
|
||||
use surrealdb::engine::local::Mem;
|
||||
use surrealdb::Surreal;
|
||||
use surrealdb::opt::auth::Root;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_claims_repository_crud_operations() {
|
||||
// Setup in-memory SurrealDB for testing
|
||||
let db = Surreal::new::<Mem>(()).await.unwrap();
|
||||
db.signin(Root { username: "root", password: "root" }).await.unwrap();
|
||||
db.use_ns("test").use_db("test").await.unwrap();
|
||||
|
||||
let repo = gacha_claims_repository::GachaClaimsRepository::new(Arc::new(db));
|
||||
let create_dto = CreateGachaClaimDto { user_id: "user123".to_string(), item_id: "item456".to_string() };
|
||||
|
||||
// Test create
|
||||
let created = repo.create(&create_dto).await.unwrap();
|
||||
assert!(!created.id.is_empty());
|
||||
assert_eq!(created.user_id, "user123");
|
||||
assert_eq!(created.item_id, "item456");
|
||||
|
||||
// Test find by id
|
||||
let found = repo.find_by_id(&created.id).await.unwrap().unwrap();
|
||||
assert_eq!(found.id, created.id);
|
||||
|
||||
// Test find by user
|
||||
let user_claims = repo.find_by_user("user123").await.unwrap();
|
||||
assert_eq!(user_claims.len(), 1);
|
||||
assert_eq!(user_claims[0].id, created.id);
|
||||
|
||||
// Test update
|
||||
let updated = repo.update(&created.id, "approved").await.unwrap();
|
||||
assert_eq!(updated.status, "approved");
|
||||
|
||||
// Test delete
|
||||
let delete_result = repo.delete(&created.id).await;
|
||||
assert!(delete_result.is_ok());
|
||||
|
||||
// Verify deletion
|
||||
let deleted = repo.find_by_id(&created.id).await.unwrap();
|
||||
assert!(deleted.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_claims_repository_error_cases() {
|
||||
let db = Surreal::new::<Mem>(()).await.unwrap();
|
||||
db.signin(Root { username: "root", password: "root" }).await.unwrap();
|
||||
db.use_ns("test").use_db("test").await.unwrap();
|
||||
|
||||
let repo = gacha_claims_repository::GachaClaimsRepository::new(Arc::new(db));
|
||||
|
||||
// Test find by non-existent id
|
||||
let result = repo.find_by_id("non_existent_id").await;
|
||||
assert!(result.is_ok());
|
||||
assert!(result.unwrap().is_none());
|
||||
|
||||
// Test update non-existent claim
|
||||
let result = repo.update("non_existent_id", "approved").await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err(), "Claim not found");
|
||||
|
||||
// Test delete non-existent claim
|
||||
let result = repo.delete("non_existent_id").await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err(), "Claim not found");
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
use imphnen_gacha::v1::gacha_claims::gacha_claims_service::{self, GachaClaimsRepository};
|
||||
use imphnen_gacha::v1::gacha_claims::gacha_claims_dto::{CreateGachaClaimDto, GachaClaimResponse};
|
||||
use mockall::mock;
|
||||
use std::sync::Arc;
|
||||
|
||||
mock! {
|
||||
pub GachaClaimsRepositoryMock {}
|
||||
#[async_trait]
|
||||
impl GachaClaimsRepository for GachaClaimsRepositoryMock {
|
||||
async fn create(&self, claim: &CreateGachaClaimDto) -> Result<GachaClaimResponse, String>;
|
||||
async fn find_by_id(&self, claim_id: &str) -> Result<Option<GachaClaimResponse>, String>;
|
||||
async fn find_by_user(&self, user_id: &str) -> Result<Vec<GachaClaimResponse>, String>;
|
||||
async fn update(&self, claim_id: &str, status: &str) -> Result<GachaClaimResponse, String>;
|
||||
async fn delete(&self, claim_id: &str) -> Result<(), String>;
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_claim_happy_path() {
|
||||
let mock_repo = MockGachaClaimsRepositoryMock::new();
|
||||
let service = gacha_claims_service::GachaClaimsService::new(Arc::new(mock_repo));
|
||||
|
||||
let create_dto = CreateGachaClaimDto { user_id: "user123".to_string(), item_id: "item456".to_string() };
|
||||
let expected = GachaClaimResponse { id: "claim789".to_string(), user_id: "user123".to_string(), item_id: "item456".to_string(), status: "pending".to_string(), created_at: "2024-01-01T00:00:00Z".to_string() };
|
||||
|
||||
mock_repo.expect_create().withf(|c| c.user_id == create_dto.user_id && c.item_id == create_dto.item_id).returning(|_| Ok(expected.clone()));
|
||||
|
||||
let result = service.create_claim(&create_dto).await;
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(result.unwrap().id, expected.id);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_claim_error_case() {
|
||||
let mock_repo = MockGachaClaimsRepositoryMock::new();
|
||||
let service = gacha_claims_service::GachaClaimsService::new(Arc::new(mock_repo));
|
||||
|
||||
let create_dto = CreateGachaClaimDto { user_id: "user123".to_string(), item_id: "invalid_item".to_string() };
|
||||
let error_msg = "Item not found";
|
||||
|
||||
mock_repo.expect_create().withf(|c| c.item_id == "invalid_item").returning(|_| Err(error_msg.to_string()));
|
||||
|
||||
let result = service.create_claim(&create_dto).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err(), error_msg);
|
||||
}
|
||||
|
||||
// Additional tests for get, update, delete operations...
|
||||
@@ -0,0 +1,99 @@
|
||||
use imphnen_gacha::v1::gacha_credits::gacha_credits_repository::{self, GachaCreditsRepository};
|
||||
use surrealdb::engine::local::Mem;
|
||||
use surrealdb::Surreal;
|
||||
use surrealdb::opt::auth::Root;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_credits_repository_crud_operations() {
|
||||
// Setup in-memory SurrealDB for testing
|
||||
let db = Surreal::new::<Mem>(()).await.unwrap();
|
||||
db.signin(Root { username: "root", password: "root" }).await.unwrap();
|
||||
db.use_ns("test").use_db("test").await.unwrap();
|
||||
|
||||
let repo = gacha_credits_repository::GachaCreditsRepository::new(Arc::new(db));
|
||||
|
||||
// Test initial balance (should be 0 for new user)
|
||||
let initial_balance = repo.get_balance("user123").await.unwrap();
|
||||
assert_eq!(initial_balance, 0);
|
||||
|
||||
// Test add credits
|
||||
let add_result = repo.add_credits("user123", 100).await;
|
||||
assert!(add_result.is_ok());
|
||||
|
||||
// Verify balance after add
|
||||
let balance_after_add = repo.get_balance("user123").await.unwrap();
|
||||
assert_eq!(balance_after_add, 100);
|
||||
|
||||
// Test deduct credits
|
||||
let deduct_result = repo.deduct_credits("user123", 30).await;
|
||||
assert!(deduct_result.is_ok());
|
||||
|
||||
// Verify balance after deduct
|
||||
let balance_after_deduct = repo.get_balance("user123").await.unwrap();
|
||||
assert_eq!(balance_after_deduct, 70);
|
||||
|
||||
// Test add multiple times
|
||||
repo.add_credits("user123", 50).await.unwrap();
|
||||
let final_balance = repo.get_balance("user123").await.unwrap();
|
||||
assert_eq!(final_balance, 120);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_credits_repository_error_cases() {
|
||||
let db = Surreal::new::<Mem>(()).await.unwrap();
|
||||
db.signin(Root { username: "root", password: "root" }).await.unwrap();
|
||||
db.use_ns("test").use_db("test").await.unwrap();
|
||||
|
||||
let repo = gacha_credits_repository::GachaCreditsRepository::new(Arc::new(db));
|
||||
|
||||
// Test deduct more than available
|
||||
let deduct_result = repo.deduct_credits("user123", 50).await;
|
||||
assert!(deduct_result.is_err());
|
||||
assert_eq!(deduct_result.unwrap_err(), "Insufficient credits");
|
||||
|
||||
// Test add negative amount (should be invalid)
|
||||
let add_negative_result = repo.add_credits("user123", -10).await;
|
||||
assert!(add_negative_result.is_err());
|
||||
assert_eq!(add_negative_result.unwrap_err(), "Cannot add negative credits");
|
||||
|
||||
// Test deduct negative amount (should be invalid)
|
||||
let deduct_negative_result = repo.deduct_credits("user123", -5).await;
|
||||
assert!(deduct_negative_result.is_err());
|
||||
assert_eq!(deduct_negative_result.unwrap_err(), "Cannot deduct negative credits");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_credits_repository_edge_cases() {
|
||||
let db = Surreal::new::<Mem>(()).await.unwrap();
|
||||
db.signin(Root { username: "root", password: "root" }).await.unwrap();
|
||||
db.use_ns("test").use_db("test").await.unwrap();
|
||||
|
||||
let repo = gacha_credits_repository::GachaCreditsRepository::new(Arc::new(db));
|
||||
|
||||
// Test add zero credits
|
||||
let add_zero_result = repo.add_credits("user123", 0).await;
|
||||
assert!(add_zero_result.is_ok());
|
||||
|
||||
// Balance should still be 0
|
||||
let balance = repo.get_balance("user123").await.unwrap();
|
||||
assert_eq!(balance, 0);
|
||||
|
||||
// Test deduct zero credits
|
||||
let deduct_zero_result = repo.deduct_credits("user123", 0).await;
|
||||
assert!(deduct_zero_result.is_ok());
|
||||
|
||||
// Balance should still be 0
|
||||
let balance_after = repo.get_balance("user123").await.unwrap();
|
||||
assert_eq!(balance_after, 0);
|
||||
|
||||
// Test multiple users
|
||||
repo.add_credits("user456", 200).await.unwrap();
|
||||
repo.add_credits("user789", 150).await.unwrap();
|
||||
|
||||
let user456_balance = repo.get_balance("user456").await.unwrap();
|
||||
let user789_balance = repo.get_balance("user789").await.unwrap();
|
||||
|
||||
assert_eq!(user456_balance, 200);
|
||||
assert_eq!(user789_balance, 150);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
use axum_test::TestServer;
|
||||
use imphnen_gacha::v1::gacha_items::gacha_items_controller::{self, GachaItemsService};
|
||||
use imphnen_gacha::v1::gacha_items::gacha_items_dto::{CreateGachaItemDto, GachaItemResponse};
|
||||
use mockall::mock;
|
||||
use tower::ServiceBuilder;
|
||||
use tower::timeout::TimeoutLayer;
|
||||
use std::time::Duration;
|
||||
|
||||
mock! {
|
||||
pub GachaItemsServiceMock {}
|
||||
#[async_trait]
|
||||
impl GachaItemsService for GachaItemsServiceMock {
|
||||
async fn create_item(&self, item: &CreateGachaItemDto) -> Result<GachaItemResponse, String>;
|
||||
async fn get_item(&self, item_id: &str) -> Result<GachaItemResponse, String>;
|
||||
async fn get_all_items(&self) -> Result<Vec<GachaItemResponse>, String>;
|
||||
async fn update_item(&self, item_id: &str, item: &CreateGachaItemDto) -> Result<GachaItemResponse, String>;
|
||||
async fn delete_item(&self, item_id: &str) -> Result<(), String>;
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_item_happy_path() {
|
||||
let mock_service = MockGachaItemsServiceMock::new();
|
||||
let create_dto = CreateGachaItemDto { name: "Sword".to_string(), rarity: "rare".to_string(), image_url: "https://example.com/sword.png".to_string(), value: 100 };
|
||||
let expected = GachaItemResponse { id: "item123".to_string(), name: "Sword".to_string(), rarity: "rare".to_string(), image_url: "https://example.com/sword.png".to_string(), value: 100, created_at: "2024-01-01T00:00:00Z".to_string() };
|
||||
|
||||
mock_service.expect_create_item().withf(|i| i.name == create_dto.name && i.rarity == create_dto.rarity).returning(|_| Ok(expected.clone()));
|
||||
|
||||
let app = ServiceBuilder::new().layer(TimeoutLayer::new(Duration::from_secs(10))).service(gacha_items_controller::router(mock_service));
|
||||
let server = TestServer::new(app).unwrap();
|
||||
|
||||
let response = server.post("/gacha/items").json(&create_dto).await;
|
||||
assert_eq!(response.status(), 201);
|
||||
let body: GachaItemResponse = response.json().await.unwrap();
|
||||
assert_eq!(body.id, expected.id);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_all_items_happy_path() {
|
||||
let mock_service = MockGachaItemsServiceMock::new();
|
||||
let expected_items = vec![
|
||||
GachaItemResponse { id: "item123".to_string(), name: "Sword".to_string(), rarity: "rare".to_string(), image_url: "https://example.com/sword.png".to_string(), value: 100, created_at: "2024-01-01T00:00:00Z".to_string() },
|
||||
GachaItemResponse { id: "item456".to_string(), name: "Shield".to_string(), rarity: "common".to_string(), image_url: "https://example.com/shield.png".to_string(), value: 50, created_at: "2024-01-01T00:00:00Z".to_string() }
|
||||
];
|
||||
|
||||
mock_service.expect_get_all_items().returning(|| Ok(expected_items.clone()));
|
||||
|
||||
let app = ServiceBuilder::new().layer(TimeoutLayer::new(Duration::from_secs(10))).service(gacha_items_controller::router(mock_service));
|
||||
let server = TestServer::new(app).unwrap();
|
||||
|
||||
let response = server.get("/gacha/items").await;
|
||||
assert_eq!(response.status(), 200);
|
||||
let body: Vec<GachaItemResponse> = response.json().await.unwrap();
|
||||
assert_eq!(body.len(), 2);
|
||||
assert_eq!(body[0].id, "item123");
|
||||
assert_eq!(body[1].id, "item456");
|
||||
}
|
||||
|
||||
// Additional tests for error cases, get by id, update, delete...
|
||||
@@ -0,0 +1,92 @@
|
||||
use imphnen_gacha::v1::gacha_items::gacha_items_repository::{self, GachaItemsRepository};
|
||||
use imphnen_gacha::v1::gacha_items::gacha_items_dto::{CreateGachaItemDto, GachaItemResponse};
|
||||
use surrealdb::engine::local::Mem;
|
||||
use surrealdb::Surreal;
|
||||
use surrealdb::opt::auth::Root;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_items_repository_crud_operations() {
|
||||
// Setup in-memory SurrealDB for testing
|
||||
let db = Surreal::new::<Mem>(()).await.unwrap();
|
||||
db.signin(Root { username: "root", password: "root" }).await.unwrap();
|
||||
db.use_ns("test").use_db("test").await.unwrap();
|
||||
|
||||
let repo = gacha_items_repository::GachaItemsRepository::new(Arc::new(db));
|
||||
let create_dto = CreateGachaItemDto { name: "Sword".to_string(), rarity: "rare".to_string(), image_url: "https://example.com/sword.png".to_string(), value: 100 };
|
||||
|
||||
// Test create
|
||||
let created = repo.create(&create_dto).await.unwrap();
|
||||
assert!(!created.id.is_empty());
|
||||
assert_eq!(created.name, "Sword");
|
||||
assert_eq!(created.rarity, "rare");
|
||||
|
||||
// Test find by id
|
||||
let found = repo.find_by_id(&created.id).await.unwrap().unwrap();
|
||||
assert_eq!(found.id, created.id);
|
||||
|
||||
// Test find all
|
||||
let all_items = repo.find_all().await.unwrap();
|
||||
assert_eq!(all_items.len(), 1);
|
||||
assert_eq!(all_items[0].id, created.id);
|
||||
|
||||
// Test update
|
||||
let updated_dto = CreateGachaItemDto { name: "Magic Sword".to_string(), rarity: "epic".to_string(), image_url: "https://example.com/magic_sword.png".to_string(), value: 200 };
|
||||
let updated = repo.update(&created.id, &updated_dto).await.unwrap();
|
||||
assert_eq!(updated.name, "Magic Sword");
|
||||
assert_eq!(updated.rarity, "epic");
|
||||
assert_eq!(updated.value, 200);
|
||||
|
||||
// Test delete
|
||||
let delete_result = repo.delete(&created.id).await;
|
||||
assert!(delete_result.is_ok());
|
||||
|
||||
// Verify deletion
|
||||
let deleted = repo.find_by_id(&created.id).await.unwrap();
|
||||
assert!(deleted.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_items_repository_error_cases() {
|
||||
let db = Surreal::new::<Mem>(()).await.unwrap();
|
||||
db.signin(Root { username: "root", password: "root" }).await.unwrap();
|
||||
db.use_ns("test").use_db("test").await.unwrap();
|
||||
|
||||
let repo = gacha_items_repository::GachaItemsRepository::new(Arc::new(db));
|
||||
|
||||
// Test find by non-existent id
|
||||
let result = repo.find_by_id("non_existent_id").await;
|
||||
assert!(result.is_ok());
|
||||
assert!(result.unwrap().is_none());
|
||||
|
||||
// Test update non-existent item
|
||||
let update_dto = CreateGachaItemDto { name: "Test".to_string(), rarity: "common".to_string(), image_url: "https://example.com/test.png".to_string(), value: 10 };
|
||||
let result = repo.update("non_existent_id", &update_dto).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err(), "Item not found");
|
||||
|
||||
// Test delete non-existent item
|
||||
let result = repo.delete("non_existent_id").await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err(), "Item not found");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_items_repository_duplicate_name_error() {
|
||||
let db = Surreal::new::<Mem>(()).await.unwrap();
|
||||
db.signin(Root { username: "root", password: "root" }).await.unwrap();
|
||||
db.use_ns("test").use_db("test").await.unwrap();
|
||||
|
||||
let repo = gacha_items_repository::GachaItemsRepository::new(Arc::new(db));
|
||||
|
||||
// Create first item
|
||||
let create_dto1 = CreateGachaItemDto { name: "Sword".to_string(), rarity: "rare".to_string(), image_url: "https://example.com/sword.png".to_string(), value: 100 };
|
||||
repo.create(&create_dto1).await.unwrap();
|
||||
|
||||
// Try to create item with same name
|
||||
let create_dto2 = CreateGachaItemDto { name: "Sword".to_string(), rarity: "common".to_string(), image_url: "https://example.com/sword2.png".to_string(), value: 50 };
|
||||
let result = repo.create(&create_dto2).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err(), "Item with this name already exists");
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
use imphnen_gacha::v1::gacha_items::gacha_items_service::{self, GachaItemsRepository};
|
||||
use imphnen_gacha::v1::gacha_items::gacha_items_dto::{CreateGachaItemDto, GachaItemResponse};
|
||||
use mockall::mock;
|
||||
use std::sync::Arc;
|
||||
|
||||
mock! {
|
||||
pub GachaItemsRepositoryMock {}
|
||||
#[async_trait]
|
||||
impl GachaItemsRepository for GachaItemsRepositoryMock {
|
||||
async fn create(&self, item: &CreateGachaItemDto) -> Result<GachaItemResponse, String>;
|
||||
async fn find_by_id(&self, item_id: &str) -> Result<Option<GachaItemResponse>, String>;
|
||||
async fn find_all(&self) -> Result<Vec<GachaItemResponse>, String>;
|
||||
async fn update(&self, item_id: &str, item: &CreateGachaItemDto) -> Result<GachaItemResponse, String>;
|
||||
async fn delete(&self, item_id: &str) -> Result<(), String>;
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_item_happy_path() {
|
||||
let mock_repo = MockGachaItemsRepositoryMock::new();
|
||||
let service = gacha_items_service::GachaItemsService::new(Arc::new(mock_repo));
|
||||
|
||||
let create_dto = CreateGachaItemDto { name: "Sword".to_string(), rarity: "rare".to_string(), image_url: "https://example.com/sword.png".to_string(), value: 100 };
|
||||
let expected = GachaItemResponse { id: "item123".to_string(), name: "Sword".to_string(), rarity: "rare".to_string(), image_url: "https://example.com/sword.png".to_string(), value: 100, created_at: "2024-01-01T00:00:00Z".to_string() };
|
||||
|
||||
mock_repo.expect_create().withf(|i| i.name == create_dto.name && i.rarity == create_dto.rarity).returning(|_| Ok(expected.clone()));
|
||||
|
||||
let result = service.create_item(&create_dto).await;
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(result.unwrap().id, expected.id);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_item_duplicate_name_error() {
|
||||
let mock_repo = MockGachaItemsRepositoryMock::new();
|
||||
let service = gacha_items_service::GachaItemsService::new(Arc::new(mock_repo));
|
||||
|
||||
let create_dto = CreateGachaItemDto { name: "Sword".to_string(), rarity: "rare".to_string(), image_url: "https://example.com/sword.png".to_string(), value: 100 };
|
||||
let error_msg = "Item with this name already exists";
|
||||
|
||||
mock_repo.expect_create().withf(|i| i.name == "Sword").returning(|_| Err(error_msg.to_string()));
|
||||
|
||||
let result = service.create_item(&create_dto).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err(), error_msg);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_all_items_empty_case() {
|
||||
let mock_repo = MockGachaItemsRepositoryMock::new();
|
||||
let service = gacha_items_service::GachaItemsService::new(Arc::new(mock_repo));
|
||||
|
||||
mock_repo.expect_find_all().returning(|| Ok(Vec::new()));
|
||||
|
||||
let result = service.get_all_items().await;
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(result.unwrap().len(), 0);
|
||||
}
|
||||
|
||||
// Additional tests for get by id, update, delete operations...
|
||||
@@ -0,0 +1,60 @@
|
||||
use axum_test::TestServer;
|
||||
use imphnen_gacha::v1::gacha_rolls::gacha_rolls_controller::{self, GachaRollsService};
|
||||
use imphnen_gacha::v1::gacha_rolls::gacha_rolls_dto::{CreateGachaRollDto, GachaRollResponse};
|
||||
use mockall::mock;
|
||||
use tower::ServiceBuilder;
|
||||
use tower::timeout::TimeoutLayer;
|
||||
use std::time::Duration;
|
||||
|
||||
mock! {
|
||||
pub GachaRollsServiceMock {}
|
||||
#[async_trait]
|
||||
impl GachaRollsService for GachaRollsServiceMock {
|
||||
async fn create_roll(&self, user_id: &str, credits_used: i32) -> Result<GachaRollResponse, String>;
|
||||
async fn get_roll(&self, roll_id: &str) -> Result<GachaRollResponse, String>;
|
||||
async fn get_user_rolls(&self, user_id: &str) -> Result<Vec<GachaRollResponse>, String>;
|
||||
async fn get_all_rolls(&self) -> Result<Vec<GachaRollResponse>, String>;
|
||||
async fn update_roll(&self, roll_id: &str, status: &str) -> Result<GachaRollResponse, String>;
|
||||
async fn delete_roll(&self, roll_id: &str) -> Result<(), String>;
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_roll_happy_path() {
|
||||
let mock_service = MockGachaRollsServiceMock::new();
|
||||
let create_dto = CreateGachaRollDto { user_id: "user123".to_string(), credits_used: 10 };
|
||||
let expected = GachaRollResponse { id: "roll789".to_string(), user_id: "user123".to_string(), credits_used: 10, items_won: vec!["item456".to_string()], status: "completed".to_string(), created_at: "2024-01-01T00:00:00Z".to_string() };
|
||||
|
||||
mock_service.expect_create_roll().withf(|u, c| u == &create_dto.user_id && c == &create_dto.credits_used).returning(|_, _| Ok(expected.clone()));
|
||||
|
||||
let app = ServiceBuilder::new().layer(TimeoutLayer::new(Duration::from_secs(10))).service(gacha_rolls_controller::router(mock_service));
|
||||
let server = TestServer::new(app).unwrap();
|
||||
|
||||
let response = server.post("/gacha/rolls").json(&create_dto).await;
|
||||
assert_eq!(response.status(), 201);
|
||||
let body: GachaRollResponse = response.json().await.unwrap();
|
||||
assert_eq!(body.id, expected.id);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_user_rolls_happy_path() {
|
||||
let mock_service = MockGachaRollsServiceMock::new();
|
||||
let expected_rolls = vec![
|
||||
GachaRollResponse { id: "roll123".to_string(), user_id: "user123".to_string(), credits_used: 10, items_won: vec!["item456".to_string()], status: "completed".to_string(), created_at: "2024-01-01T00:00:00Z".to_string() },
|
||||
GachaRollResponse { id: "roll456".to_string(), user_id: "user123".to_string(), credits_used: 5, items_won: vec!["item789".to_string()], status: "completed".to_string(), created_at: "2024-01-02T00:00:00Z".to_string() }
|
||||
];
|
||||
|
||||
mock_service.expect_get_user_rolls().withf(|u| u == "user123").returning(|| Ok(expected_rolls.clone()));
|
||||
|
||||
let app = ServiceBuilder::new().layer(TimeoutLayer::new(Duration::from_secs(10))).service(gacha_rolls_controller::router(mock_service));
|
||||
let server = TestServer::new(app).unwrap();
|
||||
|
||||
let response = server.get("/gacha/rolls/user/user123").await;
|
||||
assert_eq!(response.status(), 200);
|
||||
let body: Vec<GachaRollResponse> = response.json().await.unwrap();
|
||||
assert_eq!(body.len(), 2);
|
||||
assert_eq!(body[0].id, "roll123");
|
||||
assert_eq!(body[1].id, "roll456");
|
||||
}
|
||||
|
||||
// Additional tests for error cases, get by id, update, delete, get all rolls...
|
||||
@@ -0,0 +1,101 @@
|
||||
use imphnen_gacha::v1::gacha_rolls::gacha_rolls_repository::{self, GachaRollsRepository};
|
||||
use imphnen_gacha::v1::gacha_rolls::gacha_rolls_dto::{CreateGachaRollDto, GachaRollResponse};
|
||||
use surrealdb::engine::local::Mem;
|
||||
use surrealdb::Surreal;
|
||||
use surrealdb::opt::auth::Root;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_rolls_repository_crud_operations() {
|
||||
// Setup in-memory SurrealDB for testing
|
||||
let db = Surreal::new::<Mem>(()).await.unwrap();
|
||||
db.signin(Root { username: "root", password: "root" }).await.unwrap();
|
||||
db.use_ns("test").use_db("test").await.unwrap();
|
||||
|
||||
let repo = gacha_rolls_repository::GachaRollsRepository::new(Arc::new(db));
|
||||
let create_dto = CreateGachaRollDto { user_id: "user123".to_string(), credits_used: 10 };
|
||||
|
||||
// Test create
|
||||
let created = repo.create(&create_dto).await.unwrap();
|
||||
assert!(!created.id.is_empty());
|
||||
assert_eq!(created.user_id, "user123");
|
||||
assert_eq!(created.credits_used, 10);
|
||||
assert_eq!(created.items_won.len(), 0); // Default empty array
|
||||
|
||||
// Test find by id
|
||||
let found = repo.find_by_id(&created.id).await.unwrap().unwrap();
|
||||
assert_eq!(found.id, created.id);
|
||||
assert_eq!(found.user_id, "user123");
|
||||
|
||||
// Test find by user
|
||||
let user_rolls = repo.find_by_user("user123").await.unwrap();
|
||||
assert_eq!(user_rolls.len(), 1);
|
||||
assert_eq!(user_rolls[0].id, created.id);
|
||||
|
||||
// Test find all
|
||||
let all_rolls = repo.find_all().await.unwrap();
|
||||
assert_eq!(all_rolls.len(), 1);
|
||||
assert_eq!(all_rolls[0].id, created.id);
|
||||
|
||||
// Test update status
|
||||
let updated = repo.update(&created.id, "completed").await.unwrap();
|
||||
assert_eq!(updated.status, "completed");
|
||||
assert_eq!(updated.id, created.id);
|
||||
|
||||
// Test delete
|
||||
let delete_result = repo.delete(&created.id).await;
|
||||
assert!(delete_result.is_ok());
|
||||
|
||||
// Verify deletion
|
||||
let deleted = repo.find_by_id(&created.id).await.unwrap();
|
||||
assert!(deleted.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_rolls_repository_error_cases() {
|
||||
let db = Surreal::new::<Mem>(()).await.unwrap();
|
||||
db.signin(Root { username: "root", password: "root" }).await.unwrap();
|
||||
db.use_ns("test").use_db("test").await.unwrap();
|
||||
|
||||
let repo = gacha_rolls_repository::GachaRollsRepository::new(Arc::new(db));
|
||||
|
||||
// Test find by non-existent id
|
||||
let result = repo.find_by_id("non_existent_id").await;
|
||||
assert!(result.is_ok());
|
||||
assert!(result.unwrap().is_none());
|
||||
|
||||
// Test update non-existent roll
|
||||
let result = repo.update("non_existent_id", "completed").await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err(), "Roll not found");
|
||||
|
||||
// Test delete non-existent roll
|
||||
let result = repo.delete("non_existent_id").await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err(), "Roll not found");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_rolls_repository_create_with_items() {
|
||||
let db = Surreal::new::<Mem>(()).await.unwrap();
|
||||
db.signin(Root { username: "root", password: "root" }).await.unwrap();
|
||||
db.use_ns("test").use_db("test").await.unwrap();
|
||||
|
||||
let repo = gacha_rolls_repository::GachaRollsRepository::new(Arc::new(db));
|
||||
|
||||
// Create a roll with pre-defined items_won
|
||||
let mut create_dto = CreateGachaRollDto { user_id: "user123".to_string(), credits_used: 15 };
|
||||
create_dto.items_won = Some(vec!["item456".to_string(), "item789".to_string()]);
|
||||
|
||||
let created = repo.create(&create_dto).await.unwrap();
|
||||
assert!(!created.id.is_empty());
|
||||
assert_eq!(created.items_won.len(), 2);
|
||||
assert_eq!(created.items_won[0], "item456");
|
||||
assert_eq!(created.items_won[1], "item789");
|
||||
|
||||
// Verify items are stored correctly
|
||||
let found = repo.find_by_id(&created.id).await.unwrap().unwrap();
|
||||
assert_eq!(found.items_won.len(), 2);
|
||||
assert_eq!(found.items_won[0], "item456");
|
||||
assert_eq!(found.items_won[1], "item789");
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
use imphnen_gacha::v1::gacha_rolls::gacha_rolls_service::{self, GachaRollsRepository, GachaCreditsRepository};
|
||||
use imphnen_gacha::v1::gacha_rolls::gacha_rolls_dto::{CreateGachaRollDto, GachaRollResponse};
|
||||
use mockall::mock;
|
||||
use std::sync::Arc;
|
||||
|
||||
mock! {
|
||||
pub GachaRollsRepositoryMock {}
|
||||
#[async_trait]
|
||||
impl GachaRollsRepository for GachaRollsRepositoryMock {
|
||||
async fn create(&self, roll: &CreateGachaRollDto) -> Result<GachaRollResponse, String>;
|
||||
async fn find_by_id(&self, roll_id: &str) -> Result<Option<GachaRollResponse>, String>;
|
||||
async fn find_by_user(&self, user_id: &str) -> Result<Vec<GachaRollResponse>, String>;
|
||||
async fn find_all(&self) -> Result<Vec<GachaRollResponse>, String>;
|
||||
async fn update(&self, roll_id: &str, status: &str) -> Result<GachaRollResponse, String>;
|
||||
async fn delete(&self, roll_id: &str) -> Result<(), String>;
|
||||
}
|
||||
}
|
||||
|
||||
mock! {
|
||||
pub GachaCreditsRepositoryMock {}
|
||||
#[async_trait]
|
||||
impl GachaCreditsRepository for GachaCreditsRepositoryMock {
|
||||
async fn deduct_credits(&self, user_id: &str, amount: i32) -> Result<(), String>;
|
||||
async fn add_credits(&self, user_id: &str, amount: i32) -> Result<(), String>;
|
||||
async fn get_balance(&self, user_id: &str) -> Result<i32, String>;
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_roll_happy_path() {
|
||||
let mock_roll_repo = MockGachaRollsRepositoryMock::new();
|
||||
let mock_credits_repo = MockGachaCreditsRepositoryMock::new();
|
||||
let service = gacha_rolls_service::GachaRollsService::new(Arc::new(mock_roll_repo), Arc::new(mock_credits_repo));
|
||||
|
||||
let create_dto = CreateGachaRollDto { user_id: "user123".to_string(), credits_used: 10 };
|
||||
let expected = GachaRollResponse { id: "roll789".to_string(), user_id: "user123".to_string(), credits_used: 10, items_won: vec!["item456".to_string()], status: "completed".to_string(), created_at: "2024-01-01T00:00:00Z".to_string() };
|
||||
|
||||
mock_credits_repo.expect_deduct_credits().withf(|u, a| u == "user123" && a == 10).returning(|_, _| Ok(()));
|
||||
mock_roll_repo.expect_create().withf(|r| r.user_id == create_dto.user_id && r.credits_used == create_dto.credits_used).returning(|_| Ok(expected.clone()));
|
||||
|
||||
let result = service.create_roll(&create_dto).await;
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(result.unwrap().id, expected.id);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_roll_insufficient_credits() {
|
||||
let mock_roll_repo = MockGachaRollsRepositoryMock::new();
|
||||
let mock_credits_repo = MockGachaCreditsRepositoryMock::new();
|
||||
let service = gacha_rolls_service::GachaRollsService::new(Arc::new(mock_roll_repo), Arc::new(mock_credits_repo));
|
||||
|
||||
let create_dto = CreateGachaRollDto { user_id: "user123".to_string(), credits_used: 100 };
|
||||
let error_msg = "Insufficient credits";
|
||||
|
||||
mock_credits_repo.expect_deduct_credits().withf(|u, a| u == "user123" && a == 100).returning(|_, _| Err(error_msg.to_string()));
|
||||
|
||||
let result = service.create_roll(&create_dto).await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err(), error_msg);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_user_rolls_empty_case() {
|
||||
let mock_roll_repo = MockGachaRollsRepositoryMock::new();
|
||||
let mock_credits_repo = MockGachaCreditsRepositoryMock::new();
|
||||
let service = gacha_rolls_service::GachaRollsService::new(Arc::new(mock_roll_repo), Arc::new(mock_credits_repo));
|
||||
|
||||
mock_roll_repo.expect_find_by_user().withf(|u| u == "user123").returning(|| Ok(Vec::new()));
|
||||
|
||||
let result = service.get_user_rolls("user123").await;
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(result.unwrap().len(), 0);
|
||||
}
|
||||
|
||||
// Additional tests for get by id, update, delete, get all rolls operations...
|
||||
@@ -0,0 +1,42 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{generate_unique_email, get_role_id, UsersRepository};
|
||||
use axum::{http::StatusCode, response::Response};
|
||||
use imphnen_iam::{
|
||||
PermissionsCreateRequestDto, PermissionsUpdateRequestDto, PermissionsSchema,
|
||||
ResourceEnum,
|
||||
};
|
||||
use imphnen_utils::{make_thing_from_enum, ResourceEnum as UtilsResourceEnum};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_permission_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::PermissionsRepository::new(&app_state);
|
||||
|
||||
// Test data
|
||||
let permission_name = "test_permission_controller".to_string();
|
||||
let permission_request = PermissionsCreateRequestDto {
|
||||
name: permission_name.clone(),
|
||||
};
|
||||
|
||||
// Create permission through controller
|
||||
let response = imphnen_iam::PermissionsController::create_permission(
|
||||
&app_state,
|
||||
permission_request.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::CREATED);
|
||||
|
||||
// Verify permission was created in database
|
||||
let created_permission = repo
|
||||
.query_permission_by_name(permission_name)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(created_permission.name, permission_name);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_permission(created_permission.id.id.to_raw()).await;
|
||||
}
|
||||
}
|
||||
@@ -1,145 +1,199 @@
|
||||
use crate::{
|
||||
get_iso_date, // Import the new setup function and get_iso_date
|
||||
permissions::{PermissionsRepository, PermissionsSchema},
|
||||
setup_all_test_environment,
|
||||
};
|
||||
use chrono::Utc;
|
||||
|
||||
fn create_dummy_permission(name: &str) -> PermissionsSchema {
|
||||
PermissionsSchema {
|
||||
name: name.to_string(),
|
||||
created_at: Some(get_iso_date()), // Ensure created_at is always set
|
||||
updated_at: Some(get_iso_date()), // Ensure updated_at is always set
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_permission_should_succeed() {
|
||||
let state = setup_all_test_environment().await; // Use the new setup function
|
||||
let repo = PermissionsRepository::new(&state);
|
||||
let permission = create_dummy_permission("Test Permission");
|
||||
let result = repo.query_create_permission(permission).await;
|
||||
assert!(result.is_ok(), "Create failed: {:?}", result.err());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_permission_list_should_return_data() {
|
||||
let state = setup_all_test_environment().await; // Use the new setup function
|
||||
let repo = PermissionsRepository::new(&state);
|
||||
|
||||
let _ = repo
|
||||
.query_create_permission(create_dummy_permission("View"))
|
||||
.await;
|
||||
let meta = crate::MetaRequestDto {
|
||||
page: Some(1),
|
||||
per_page: Some(10),
|
||||
search: None,
|
||||
sort_by: None,
|
||||
order: None,
|
||||
filter: None,
|
||||
filter_by: None,
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use imphnen_iam::{
|
||||
PermissionsSchema, ResourceEnum,
|
||||
};
|
||||
use imphnen_utils::{make_thing_from_enum};
|
||||
use surrealdb::Uuid;
|
||||
use imphnen_entities::MetaRequestDto;
|
||||
|
||||
let result = repo.query_permission_list(meta).await;
|
||||
assert!(result.is_ok(), "List failed: {:?}", result.err());
|
||||
assert!(!result.unwrap().data.is_empty(), "Data should not be empty");
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn test_query_create_permission() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::PermissionsRepository::new(&app_state);
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_permission_by_id_should_succeed() {
|
||||
let state = setup_all_test_environment().await; // Use the new setup function
|
||||
let repo = PermissionsRepository::new(&state);
|
||||
let permission = create_dummy_permission("Detail");
|
||||
let _ = repo.query_create_permission(permission.clone()).await;
|
||||
let id = permission.id.id.to_raw();
|
||||
let result = repo.query_permission_by_id(id).await;
|
||||
assert!(result.is_ok(), "Get by id failed: {:?}", result.err());
|
||||
}
|
||||
// Test data
|
||||
let permission_name = "test_permission_repo_create".to_string();
|
||||
let permission = PermissionsSchema {
|
||||
id: make_thing_from_enum(ResourceEnum::Permissions, &Uuid::new_v4().to_string()),
|
||||
name: permission_name.clone(),
|
||||
is_deleted: false,
|
||||
created_at: None,
|
||||
updated_at: None,
|
||||
};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_permission_should_succeed() {
|
||||
let state = setup_all_test_environment().await; // Use the new setup function
|
||||
let repo = PermissionsRepository::new(&state);
|
||||
let mut permission = create_dummy_permission("Update This");
|
||||
let _ = repo.query_create_permission(permission.clone()).await;
|
||||
permission.name = "Updated Name".into();
|
||||
permission.updated_at = Some(Utc::now().to_rfc3339());
|
||||
let result = repo.query_update_permission(permission).await;
|
||||
assert!(result.is_ok(), "Update failed: {:?}", result.err());
|
||||
}
|
||||
// Create permission
|
||||
let result = repo.query_create_permission(permission.clone()).await;
|
||||
assert!(result.is_ok(), "Failed to create permission: {:?}", result.err());
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_permission_should_succeed() {
|
||||
let state = setup_all_test_environment().await; // Use the new setup function
|
||||
let repo = PermissionsRepository::new(&state);
|
||||
let permission = create_dummy_permission("To Be Deleted");
|
||||
let _ = repo.query_create_permission(permission.clone()).await;
|
||||
let id = permission.id.id.to_raw();
|
||||
let result = repo.query_delete_permission(id).await;
|
||||
assert!(result.is_ok(), "Delete failed: {:?}", result.err());
|
||||
}
|
||||
// Verify permission was created
|
||||
let created_permission = repo
|
||||
.query_permission_by_name(permission_name.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(created_permission.name, permission_name);
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_permission_should_fail_if_already_deleted() {
|
||||
let state = setup_all_test_environment().await; // Use the new setup function
|
||||
let repo = PermissionsRepository::new(&state);
|
||||
let permission = create_dummy_permission("Delete Twice");
|
||||
let _ = repo.query_create_permission(permission.clone()).await;
|
||||
let id = permission.id.id.to_raw();
|
||||
let delete_result = repo.query_delete_permission(id.clone()).await;
|
||||
assert!(
|
||||
delete_result.is_ok(),
|
||||
"Initial delete failed: {:?}",
|
||||
delete_result.err()
|
||||
);
|
||||
let second_delete_result = repo.query_delete_permission(id).await;
|
||||
assert!(
|
||||
second_delete_result.is_err(),
|
||||
"Should fail on second delete"
|
||||
);
|
||||
if let Some(err) = second_delete_result.err() {
|
||||
assert!(
|
||||
err.to_string().contains("Permission not found"),
|
||||
"Expected 'Permission not found' error, got: {err}"
|
||||
);
|
||||
// Clean up
|
||||
let _ = repo.query_delete_permission(created_permission.id.id.to_raw()).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_permission_should_fail_if_deleted() {
|
||||
let state = setup_all_test_environment().await; // Use the new setup function
|
||||
let repo = PermissionsRepository::new(&state);
|
||||
let mut permission = create_dummy_permission("To Be Updated Then Deleted");
|
||||
let _ = repo.query_create_permission(permission.clone()).await;
|
||||
let id = permission.id.id.to_raw();
|
||||
let delete_result = repo.query_delete_permission(id.clone()).await;
|
||||
assert!(
|
||||
delete_result.is_ok(),
|
||||
"Initial delete failed: {:?}",
|
||||
delete_result.err()
|
||||
);
|
||||
permission.name = "Try Update".into();
|
||||
let result = repo.query_update_permission(permission).await;
|
||||
assert!(result.is_err(), "Update on deleted should fail");
|
||||
if let Some(err) = result.err() {
|
||||
assert!(
|
||||
err.to_string().contains("Permission not found"),
|
||||
"Expected 'Permission not found' error, got: {err}"
|
||||
);
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_permission_by_name() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::PermissionsRepository::new(&app_state);
|
||||
|
||||
// Test data
|
||||
let permission_name = "test_permission_repo_by_name".to_string();
|
||||
let permission = PermissionsSchema {
|
||||
id: make_thing_from_enum(ResourceEnum::Permissions, &Uuid::new_v4().to_string()),
|
||||
name: permission_name.clone(),
|
||||
is_deleted: false,
|
||||
created_at: None,
|
||||
updated_at: None,
|
||||
};
|
||||
|
||||
// Create permission
|
||||
let create_result = repo.query_create_permission(permission.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Query permission by name
|
||||
let result = repo.query_permission_by_name(permission_name.clone()).await;
|
||||
assert!(result.is_ok());
|
||||
let found_permission = result.unwrap();
|
||||
assert_eq!(found_permission.name, permission_name);
|
||||
|
||||
// Query non-existent permission
|
||||
let non_existent_result = repo.query_permission_by_name("non_existent".to_string()).await;
|
||||
assert!(non_existent_result.is_err());
|
||||
assert!(non_existent_result.err().unwrap().to_string().contains("not found"));
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_permission(found_permission.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_permission_list() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::PermissionsRepository::new(&app_state);
|
||||
|
||||
// Create test permissions
|
||||
let permission_names = vec![
|
||||
"test_permission_list_1".to_string(),
|
||||
"test_permission_list_2".to_string(),
|
||||
"test_permission_list_3".to_string(),
|
||||
];
|
||||
|
||||
for name in &permission_names {
|
||||
let permission = PermissionsSchema {
|
||||
id: make_thing_from_enum(ResourceEnum::Permissions, &Uuid::new_v4().to_string()),
|
||||
name: name.clone(),
|
||||
is_deleted: false,
|
||||
created_at: None,
|
||||
updated_at: None,
|
||||
};
|
||||
let _ = repo.query_create_permission(permission).await;
|
||||
}
|
||||
|
||||
// Query permission list
|
||||
let meta = MetaRequestDto {
|
||||
page: Some(1),
|
||||
per_page: Some(10),
|
||||
search: None,
|
||||
filter: None,
|
||||
sort_by: None,
|
||||
order: None,
|
||||
filter_by: None,
|
||||
};
|
||||
let result = repo.query_permission_list(meta).await;
|
||||
assert!(result.is_ok());
|
||||
let permission_list = result.unwrap();
|
||||
assert_eq!(permission_list.data.len(), 3);
|
||||
|
||||
// Clean up
|
||||
for name in permission_names {
|
||||
let permission = repo.query_permission_by_name(name).await.unwrap();
|
||||
let _ = repo.query_delete_permission(permission.id.id.to_raw()).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_update_permission() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::PermissionsRepository::new(&app_state);
|
||||
|
||||
// Test data
|
||||
let original_name = "test_permission_update_original".to_string();
|
||||
let new_name = "test_permission_update_updated".to_string();
|
||||
|
||||
let permission = PermissionsSchema {
|
||||
id: make_thing_from_enum(ResourceEnum::Permissions, &Uuid::new_v4().to_string()),
|
||||
name: original_name.clone(),
|
||||
is_deleted: false,
|
||||
created_at: None,
|
||||
updated_at: None,
|
||||
};
|
||||
|
||||
// Create permission
|
||||
let create_result = repo.query_create_permission(permission.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created permission
|
||||
let created_permission = repo.query_permission_by_name(original_name).await.unwrap();
|
||||
|
||||
// Update permission
|
||||
let updated_permission = PermissionsSchema {
|
||||
id: created_permission.id.clone(),
|
||||
name: new_name.clone(),
|
||||
is_deleted: created_permission.is_deleted,
|
||||
created_at: created_permission.created_at,
|
||||
updated_at: created_permission.updated_at,
|
||||
};
|
||||
|
||||
let update_result = repo.query_update_permission(updated_permission).await;
|
||||
assert!(update_result.is_ok());
|
||||
|
||||
// Verify permission was updated
|
||||
let result = repo.query_permission_by_name(new_name.clone()).await;
|
||||
assert!(result.is_ok());
|
||||
let found_permission = result.unwrap();
|
||||
assert_eq!(found_permission.name, new_name);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_permission(found_permission.id.id.to_raw()).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_permission_by_id_should_fail_if_not_found() {
|
||||
let state = setup_all_test_environment().await; // Use the new setup function
|
||||
let repo = PermissionsRepository::new(&state);
|
||||
let result = repo.query_permission_by_id("non-existent-id".into()).await;
|
||||
assert!(result.is_err(), "Expected error for not found id");
|
||||
if let Some(err) = result.err() {
|
||||
assert!(
|
||||
err.to_string().contains("Permission not found"),
|
||||
"Expected 'Permission not found' error, got: {err}"
|
||||
);
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_delete_permission() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::PermissionsRepository::new(&app_state);
|
||||
|
||||
// Test data
|
||||
let permission_name = "test_permission_delete".to_string();
|
||||
let permission = PermissionsSchema {
|
||||
id: make_thing_from_enum(ResourceEnum::Permissions, &Uuid::new_v4().to_string()),
|
||||
name: permission_name.clone(),
|
||||
is_deleted: false,
|
||||
created_at: None,
|
||||
updated_at: None,
|
||||
};
|
||||
|
||||
// Create permission
|
||||
let create_result = repo.query_create_permission(permission.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created permission
|
||||
let created_permission = repo.query_permission_by_name(permission_name).await.unwrap();
|
||||
|
||||
// Verify permission exists before deletion
|
||||
let exists_before = repo.query_permission_by_id(created_permission.id.id.to_raw()).await.is_ok();
|
||||
assert!(exists_before);
|
||||
|
||||
// Delete permission
|
||||
let delete_result = repo.query_delete_permission(created_permission.id.id.to_raw()).await;
|
||||
assert!(delete_result.is_ok());
|
||||
|
||||
// Verify permission was deleted
|
||||
let exists_after = repo.query_permission_by_id(created_permission.id.id.to_raw()).await.is_ok();
|
||||
assert!(!exists_after);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{generate_unique_email, get_role_id, UsersRepository};
|
||||
use axum::{http::StatusCode, response::Response};
|
||||
use imphnen_iam::{
|
||||
PermissionsCreateRequestDto, PermissionsUpdateRequestDto, PermissionsSchema,
|
||||
ResourceEnum,
|
||||
};
|
||||
use imphnen_utils::{make_thing_from_enum, ResourceEnum as UtilsResourceEnum};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_permission_service() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::PermissionsRepository::new(&app_state);
|
||||
|
||||
// Test data
|
||||
let permission_name = "test_permission_service".to_string();
|
||||
let permission_request = PermissionsCreateRequestDto {
|
||||
name: permission_name.clone(),
|
||||
};
|
||||
|
||||
// Create permission through service
|
||||
let response = imphnen_iam::PermissionsService::create_role(
|
||||
&app_state,
|
||||
permission_request.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::CREATED);
|
||||
|
||||
// Verify permission was created in database
|
||||
let created_permission = repo
|
||||
.query_permission_by_name(permission_name)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(created_permission.name, permission_name);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_permission(created_permission.id.id.to_raw()).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_permission_by_id_service() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::PermissionsRepository::new(&app_state);
|
||||
|
||||
// Create test permission
|
||||
let permission_name = "test_permission_by_id_service".to_string();
|
||||
let permission = PermissionsSchema {
|
||||
name: permission_name.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
let create_result = repo.query_create_permission(permission.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created permission to get ID
|
||||
let created_permission = repo
|
||||
.query_permission_by_name(permission_name)
|
||||
.await
|
||||
.unwrap();
|
||||
let permission_id = created_permission.id.id.to_raw();
|
||||
|
||||
// Get permission by ID through service
|
||||
let response = imphnen_iam::PermissionsService::get_permission_by_id(
|
||||
&app_state, permission_id.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_permission(permission_id).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_permission_service() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::PermissionsRepository::new(&app_state);
|
||||
|
||||
// Create test permission
|
||||
let original_name = "test_permission_update_original_service".to_string();
|
||||
let new_name = "test_permission_update_updated_service".to_string();
|
||||
|
||||
let permission = PermissionsSchema {
|
||||
name: original_name.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
let create_result = repo.query_create_permission(permission.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created permission to get ID
|
||||
let created_permission = repo
|
||||
.query_permission_by_name(original_name)
|
||||
.await
|
||||
.unwrap();
|
||||
let permission_id = created_permission.id.id.to_raw();
|
||||
|
||||
// Prepare update request
|
||||
let update_request = PermissionsUpdateRequestDto {
|
||||
name: Some(new_name.clone()),
|
||||
};
|
||||
|
||||
// Update permission through service
|
||||
let response = imphnen_iam::PermissionsService::update_permission(
|
||||
&app_state, update_request, permission_id.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Verify permission was updated in database
|
||||
let updated_permission = repo
|
||||
.query_permission_by_id(permission_id.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(updated_permission.name, new_name);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_permission(permission_id).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_permission_service() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::PermissionsRepository::new(&app_state);
|
||||
|
||||
// Create test permission
|
||||
let permission_name = "test_permission_delete_service".to_string();
|
||||
let permission = PermissionsSchema {
|
||||
name: permission_name.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
let create_result = repo.query_create_permission(permission.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created permission to get ID
|
||||
let created_permission = repo
|
||||
.query_permission_by_name(permission_name)
|
||||
.await
|
||||
.unwrap();
|
||||
let permission_id = created_permission.id.id.to_raw();
|
||||
|
||||
// Verify permission exists before deletion
|
||||
let exists_before = repo.query_permission_by_id(permission_id.clone()).await.is_ok();
|
||||
assert!(exists_before);
|
||||
|
||||
// Delete permission through service
|
||||
let response = imphnen_iam::PermissionsService::delete_permission(
|
||||
&app_state, permission_id.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Verify permission was deleted from database
|
||||
let exists_after = repo.query_permission_by_id(permission_id).await.is_ok();
|
||||
assert!(!exists_after);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_permission_by_id_service_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Get non-existent permission by ID through service
|
||||
let response = imphnen_iam::PermissionsService::get_permission_by_id(
|
||||
&app_state, non_existent_id,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify not found response
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_permission_service_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Prepare update request
|
||||
let update_request = PermissionsUpdateRequestDto {
|
||||
name: Some("new_name".to_string()),
|
||||
};
|
||||
|
||||
// Update non-existent permission through service
|
||||
let response = imphnen_iam::PermissionsService::update_permission(
|
||||
&app_state, update_request, non_existent_id,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify not found response
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_permission_service_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Delete non-existent permission through service
|
||||
let response = imphnen_iam::PermissionsService::delete_permission(
|
||||
&app_state, non_existent_id,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify not found response
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,301 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{generate_unique_email, get_role_id, UsersRepository};
|
||||
use axum::{http::StatusCode, response::Response};
|
||||
use imphnen_iam::{
|
||||
RolesCreateRequestDto, RolesUpdateRequestDto, RolesSchema, ResourceEnum,
|
||||
};
|
||||
use imphnen_utils::{make_thing_from_enum, ResourceEnum as UtilsResourceEnum};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_role_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::RolesRepository::new(&app_state);
|
||||
|
||||
// Test data
|
||||
let role_name = "test_role_controller".to_string();
|
||||
let role_request = RolesCreateRequestDto {
|
||||
name: role_name.clone(),
|
||||
description: Some("Test role for controller".to_string()),
|
||||
};
|
||||
|
||||
// Create role through controller
|
||||
let response = imphnen_iam::RolesController::create_role(
|
||||
&app_state,
|
||||
role_request.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::CREATED);
|
||||
|
||||
// Verify role was created in database
|
||||
let created_role = repo
|
||||
.query_role_by_name(role_name)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(created_role.name, role_name);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_role(created_role.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_role_controller_duplicate() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::RolesRepository::new(&app_state);
|
||||
|
||||
// Test data
|
||||
let role_name = "test_role_duplicate".to_string();
|
||||
let role_request = RolesCreateRequestDto {
|
||||
name: role_name.clone(),
|
||||
description: Some("Test role for duplicate check".to_string()),
|
||||
};
|
||||
|
||||
// Create role first time
|
||||
let response1 = imphnen_iam::RolesController::create_role(
|
||||
&app_state,
|
||||
role_request.clone(),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(response1.status(), StatusCode::CREATED);
|
||||
|
||||
// Try to create same role again
|
||||
let response2 = imphnen_iam::RolesController::create_role(
|
||||
&app_state,
|
||||
role_request,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify conflict response
|
||||
assert_eq!(response2.status(), StatusCode::CONFLICT);
|
||||
|
||||
// Clean up
|
||||
let created_role = repo
|
||||
.query_role_by_name(role_name)
|
||||
.await
|
||||
.unwrap();
|
||||
let _ = repo.query_delete_role(created_role.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_role_list_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::RolesRepository::new(&app_state);
|
||||
|
||||
// Create test roles
|
||||
let role_names = vec![
|
||||
"test_role_list_1".to_string(),
|
||||
"test_role_list_2".to_string(),
|
||||
"test_role_list_3".to_string(),
|
||||
];
|
||||
|
||||
for name in &role_names {
|
||||
let role = RolesSchema {
|
||||
name: name.clone(),
|
||||
description: Some(format!("Description for {}", name)),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = repo.query_create_role(role).await;
|
||||
}
|
||||
|
||||
// Get role list through controller
|
||||
let response = imphnen_iam::RolesController::get_role_list(
|
||||
&app_state,
|
||||
crate::get_meta_request_dto(1, 10),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Clean up
|
||||
for name in role_names {
|
||||
let role = repo.query_role_by_name(name).await.unwrap();
|
||||
let _ = repo.query_delete_role(role.id.id.to_raw()).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_role_by_id_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::RolesRepository::new(&app_state);
|
||||
|
||||
// Create test role
|
||||
let role_name = "test_role_by_id".to_string();
|
||||
let role = RolesSchema {
|
||||
name: role_name.clone(),
|
||||
description: Some("Test role for by ID test".to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
let create_result = repo.query_create_role(role.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created role to get ID
|
||||
let created_role = repo
|
||||
.query_role_by_name(role_name)
|
||||
.await
|
||||
.unwrap();
|
||||
let role_id = created_role.id.id.to_raw();
|
||||
|
||||
// Get role by ID through controller
|
||||
let response = imphnen_iam::RolesController::get_role_by_id(
|
||||
&app_state, role_id.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_role(role_id).await;
|
||||
}
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn test_get_role_by_id_controller_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Get non-existent role by ID through controller
|
||||
let response = imphnen_iam::RolesController::get_role_by_id(
|
||||
&app_state, non_existent_id,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify not found response
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_role_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::RolesRepository::new(&app_state);
|
||||
|
||||
// Create test role
|
||||
let original_name = "test_role_update_original_controller".to_string();
|
||||
let new_name = "test_role_update_updated_controller".to_string();
|
||||
|
||||
let role = RolesSchema {
|
||||
name: original_name.clone(),
|
||||
description: Some("Original description for controller test".to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
let create_result = repo.query_create_role(role.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created role to get ID
|
||||
let created_role = repo
|
||||
.query_role_by_name(original_name)
|
||||
.await
|
||||
.unwrap();
|
||||
let role_id = created_role.id.id.to_raw();
|
||||
|
||||
// Prepare update request
|
||||
let update_request = RolesUpdateRequestDto {
|
||||
name: Some(new_name.clone()),
|
||||
description: Some("Updated description for controller test".to_string()),
|
||||
};
|
||||
|
||||
// Update role through controller
|
||||
let response = imphnen_iam::RolesController::update_role(
|
||||
&app_state, update_request, role_id.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Verify role was updated in database
|
||||
let updated_role = repo
|
||||
.query_role_by_id(role_id.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(updated_role.name, new_name);
|
||||
assert_eq!(updated_role.description, Some("Updated description for controller test".to_string()));
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_role(role_id).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_role_controller_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Prepare update request
|
||||
let update_request = RolesUpdateRequestDto {
|
||||
name: Some("new_name".to_string()),
|
||||
description: Some("new description".to_string()),
|
||||
};
|
||||
|
||||
// Update non-existent role through controller
|
||||
let response = imphnen_iam::RolesController::update_role(
|
||||
&app_state, update_request, non_existent_id,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify not found response
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_role_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::RolesRepository::new(&app_state);
|
||||
|
||||
// Create test role
|
||||
let role_name = "test_role_delete_controller".to_string();
|
||||
let role = RolesSchema {
|
||||
name: role_name.clone(),
|
||||
description: Some("Test role for delete test in controller".to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
let create_result = repo.query_create_role(role.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created role to get ID
|
||||
let created_role = repo
|
||||
.query_role_by_name(role_name)
|
||||
.await
|
||||
.unwrap();
|
||||
let role_id = created_role.id.id.to_raw();
|
||||
|
||||
// Verify role exists before deletion
|
||||
let exists_before = repo.query_role_by_id(role_id.clone()).await.is_ok();
|
||||
assert!(exists_before);
|
||||
|
||||
// Delete role through controller
|
||||
let response = imphnen_iam::RolesController::delete_role(
|
||||
&app_state, role_id.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Verify role was deleted from database
|
||||
let exists_after = repo.query_role_by_id(role_id).await.is_ok();
|
||||
assert!(!exists_after);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_role_controller_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Delete non-existent role through controller
|
||||
let response = imphnen_iam::RolesController::delete_role(
|
||||
&app_state, non_existent_id,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify not found response
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
}
|
||||
@@ -1,315 +1,182 @@
|
||||
use crate::{
|
||||
get_iso_date, make_thing,
|
||||
permissions::{
|
||||
permissions_repository::PermissionsRepository,
|
||||
permissions_schema::PermissionsSchema,
|
||||
},
|
||||
roles::{
|
||||
roles_dto::{RolesRequestCreateDto, RolesRequestUpdateDto},
|
||||
roles_repository::RolesRepository,
|
||||
},
|
||||
setup_all_test_environment, ResourceEnum,
|
||||
};
|
||||
use surrealdb::Uuid;
|
||||
|
||||
fn generate_unique_name(prefix: &str) -> String {
|
||||
format!("{}_{}", prefix, Uuid::new_v4())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_create_role_should_succeed() {
|
||||
let state = setup_all_test_environment().await;
|
||||
let perm_repo = PermissionsRepository::new(&state);
|
||||
let role_repo = RolesRepository::new(&state);
|
||||
let perm_id = Uuid::new_v4().to_string();
|
||||
let permission = PermissionsSchema {
|
||||
id: make_thing(&ResourceEnum::Permissions.to_string(), &perm_id),
|
||||
name: generate_unique_name("read_quiz"),
|
||||
is_deleted: false,
|
||||
created_at: Some(get_iso_date()),
|
||||
updated_at: Some(get_iso_date()),
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use imphnen_iam::{
|
||||
RolesRequestCreateDto, RolesRequestUpdateDto, RolesDetailItemDto, ResourceEnum,
|
||||
};
|
||||
let perm_res = perm_repo.query_create_permission(permission).await;
|
||||
assert!(
|
||||
perm_res.is_ok(),
|
||||
"Failed to create permission: {:?}",
|
||||
perm_res.err()
|
||||
);
|
||||
let payload = RolesRequestCreateDto {
|
||||
name: generate_unique_name("user"),
|
||||
permissions: vec![perm_id.clone()],
|
||||
};
|
||||
let result = role_repo.query_create_role(payload).await;
|
||||
assert!(result.is_ok(), "Failed to create role: {:?}", result.err());
|
||||
}
|
||||
use imphnen_utils::{make_thing_from_enum};
|
||||
use imphnen_entities::MetaRequestDto;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_role_by_name_should_return_data() {
|
||||
let state = setup_all_test_environment().await;
|
||||
let role_repo = RolesRepository::new(&state);
|
||||
let name = generate_unique_name("viewer");
|
||||
let payload = RolesRequestCreateDto {
|
||||
name: name.clone(),
|
||||
permissions: vec![],
|
||||
};
|
||||
let create_res = role_repo.query_create_role(payload.clone()).await;
|
||||
assert!(
|
||||
create_res.is_ok(),
|
||||
"Failed to create role: {:?}",
|
||||
create_res.err()
|
||||
);
|
||||
let role = role_repo.query_role_by_name(name.clone()).await;
|
||||
assert!(role.is_ok(), "Failed to get role by name: {:?}", role.err());
|
||||
let role = role.unwrap();
|
||||
assert_eq!(role.name, name.clone());
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn test_query_create_role() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::RolesRepository::new(&app_state);
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_role_by_id_should_return_data() {
|
||||
let state = setup_all_test_environment().await;
|
||||
let role_repo = RolesRepository::new(&state);
|
||||
// Test data
|
||||
let role_name = "test_role_repo_create".to_string();
|
||||
let role = RolesRequestCreateDto {
|
||||
name: role_name.clone(),
|
||||
permissions: vec![],
|
||||
};
|
||||
|
||||
let name = generate_unique_name("tester");
|
||||
// Create role
|
||||
let result = repo.query_create_role(role.clone()).await;
|
||||
assert!(result.is_ok(), "Failed to create role: {:?}", result.err());
|
||||
|
||||
let payload = RolesRequestCreateDto {
|
||||
name: name.clone(),
|
||||
permissions: vec![],
|
||||
};
|
||||
// Verify role was created
|
||||
let created_role = repo
|
||||
.query_role_by_name(role_name.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(created_role.name, role_name);
|
||||
|
||||
let create_res = role_repo.query_create_role(payload.clone()).await;
|
||||
// Clean up
|
||||
let _ = repo.query_delete_role(created_role.id).await;
|
||||
}
|
||||
|
||||
assert!(
|
||||
create_res.is_ok(),
|
||||
"Failed to create role: {:?}",
|
||||
create_res.err()
|
||||
);
|
||||
#[tokio::test]
|
||||
async fn test_query_role_by_name() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::RolesRepository::new(&app_state);
|
||||
|
||||
let role = role_repo.query_role_by_name(name.clone()).await;
|
||||
// Test data
|
||||
let role_name = "test_role_repo_by_name".to_string();
|
||||
let role = RolesRequestCreateDto {
|
||||
name: role_name.clone(),
|
||||
permissions: vec![],
|
||||
};
|
||||
|
||||
assert!(role.is_ok(), "Failed to get role by name: {:?}", role.err());
|
||||
let role = role.unwrap();
|
||||
// Create role
|
||||
let create_result = repo.query_create_role(role.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
let result = role_repo.query_role_by_id(role.id.clone()).await;
|
||||
// Query role by name
|
||||
let result = repo.query_role_by_name(role_name.clone()).await;
|
||||
assert!(result.is_ok());
|
||||
let found_role = result.unwrap();
|
||||
assert_eq!(found_role.name, role_name);
|
||||
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Failed to get role by id: {:?}",
|
||||
result.err()
|
||||
);
|
||||
let result_role = result.unwrap();
|
||||
// Query non-existent role
|
||||
let non_existent_result = repo.query_role_by_name("non_existent".to_string()).await;
|
||||
assert!(non_existent_result.is_err());
|
||||
assert!(non_existent_result.err().unwrap().to_string().contains("not found"));
|
||||
|
||||
assert_eq!(result_role.name, name.clone());
|
||||
}
|
||||
// Clean up
|
||||
let _ = repo.query_delete_role(found_role.id).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_update_role_should_update_name_and_permissions() {
|
||||
let state = setup_all_test_environment().await;
|
||||
let repo = RolesRepository::new(&state);
|
||||
let perm_repo = PermissionsRepository::new(&state);
|
||||
let original_perm_id = Uuid::new_v4().to_string();
|
||||
let original_perm = PermissionsSchema {
|
||||
id: make_thing(&ResourceEnum::Permissions.to_string(), &original_perm_id),
|
||||
name: generate_unique_name("original_permission"),
|
||||
is_deleted: false,
|
||||
created_at: Some(crate::get_iso_date()),
|
||||
updated_at: Some(crate::get_iso_date()),
|
||||
};
|
||||
let perm_res = perm_repo.query_create_permission(original_perm).await;
|
||||
assert!(
|
||||
perm_res.is_ok(),
|
||||
"Failed to create original permission: {:?}",
|
||||
perm_res.err()
|
||||
);
|
||||
let role_upadate_name = generate_unique_name("role_for_update");
|
||||
let create_payload = RolesRequestCreateDto {
|
||||
name: role_upadate_name.clone(),
|
||||
permissions: vec![original_perm_id.clone()],
|
||||
};
|
||||
let create_res = repo.query_create_role(create_payload).await;
|
||||
assert!(
|
||||
create_res.is_ok(),
|
||||
"Failed to create role: {:?}",
|
||||
create_res.err()
|
||||
);
|
||||
let existing_role = repo.query_role_by_name(role_upadate_name.clone()).await;
|
||||
assert!(
|
||||
existing_role.is_ok(),
|
||||
"Failed to get role by name: {:?}",
|
||||
existing_role.err()
|
||||
);
|
||||
let existing_role = existing_role.unwrap();
|
||||
let existing_role_id = existing_role.id.clone();
|
||||
let new_perm_id = Uuid::new_v4().to_string();
|
||||
let new_perm = PermissionsSchema {
|
||||
id: make_thing(&ResourceEnum::Permissions.to_string(), &new_perm_id),
|
||||
name: "New Permission".into(),
|
||||
is_deleted: false,
|
||||
created_at: Some(crate::get_iso_date()),
|
||||
updated_at: Some(crate::get_iso_date()),
|
||||
};
|
||||
let new_role_name = generate_unique_name("updated_role_name");
|
||||
let perm_res = perm_repo.query_create_permission(new_perm).await;
|
||||
assert!(
|
||||
perm_res.is_ok(),
|
||||
"Failed to create new permission: {:?}",
|
||||
perm_res.err()
|
||||
);
|
||||
let update_payload = RolesRequestUpdateDto {
|
||||
name: Some(new_role_name.clone()),
|
||||
permissions: Some(vec![new_perm_id.clone()]),
|
||||
overwrite: None,
|
||||
};
|
||||
let update_result = repo
|
||||
.query_update_role(existing_role_id.clone(), update_payload)
|
||||
.await;
|
||||
assert!(
|
||||
update_result.is_ok(),
|
||||
"Failed to update role: {:?}",
|
||||
update_result.err()
|
||||
);
|
||||
let updated = repo.query_role_by_id(existing_role_id.clone()).await;
|
||||
assert!(
|
||||
updated.is_ok(),
|
||||
"Failed to get updated role: {:?}",
|
||||
updated.err()
|
||||
);
|
||||
assert_eq!(updated.unwrap().name, new_role_name.clone());
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn test_query_role_list() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::RolesRepository::new(&app_state);
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_delete_role_should_soft_delete() {
|
||||
let state = setup_all_test_environment().await;
|
||||
let role_repo = RolesRepository::new(&state);
|
||||
let name = generate_unique_name("temporary");
|
||||
let payload = RolesRequestCreateDto {
|
||||
name: name.clone(),
|
||||
permissions: vec![],
|
||||
};
|
||||
let create_res = role_repo.query_create_role(payload.clone()).await;
|
||||
assert!(
|
||||
create_res.is_ok(),
|
||||
"Failed to create role: {:?}",
|
||||
create_res.err()
|
||||
);
|
||||
let role = role_repo.query_role_by_name(name.clone()).await;
|
||||
assert!(role.is_ok(), "Failed to get role by name: {:?}", role.err());
|
||||
let role = role.unwrap();
|
||||
let result = role_repo.query_delete_role(role.id.clone()).await;
|
||||
assert!(result.is_ok(), "Failed to delete role: {:?}", result.err());
|
||||
let deleted = role_repo.query_role_by_id(role.id).await;
|
||||
assert!(
|
||||
deleted.is_err(),
|
||||
"Role should be deleted, but got: {deleted:?}"
|
||||
);
|
||||
if let Some(err) = deleted.err() {
|
||||
assert!(
|
||||
err.to_string().contains("Role not found"),
|
||||
"Expected 'Role not found' error, got: {err}"
|
||||
);
|
||||
// Create test roles
|
||||
let role_names = vec![
|
||||
"test_role_list_1".to_string(),
|
||||
"test_role_list_2".to_string(),
|
||||
"test_role_list_3".to_string(),
|
||||
];
|
||||
|
||||
for name in &role_names {
|
||||
let role = RolesRequestCreateDto {
|
||||
name: name.clone(),
|
||||
permissions: vec![],
|
||||
};
|
||||
let _ = repo.query_create_role(role).await;
|
||||
}
|
||||
|
||||
// Query role list
|
||||
let meta = MetaRequestDto {
|
||||
page: Some(1),
|
||||
per_page: Some(10),
|
||||
search: None,
|
||||
filter: None,
|
||||
sort_by: None,
|
||||
order: None,
|
||||
filter_by: None,
|
||||
};
|
||||
let result = repo.query_role_list(meta).await;
|
||||
assert!(result.is_ok());
|
||||
let role_list = result.unwrap();
|
||||
assert_eq!(role_list.data.len(), 3);
|
||||
|
||||
// Clean up
|
||||
for name in role_names {
|
||||
let role = repo.query_role_by_name(name).await.unwrap();
|
||||
let _ = repo.query_delete_role(role.id).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_update_role_should_fallback_to_existing_permissions_if_none_provided(
|
||||
) {
|
||||
let state = setup_all_test_environment().await;
|
||||
let repo = RolesRepository::new(&state);
|
||||
let perm_repo = PermissionsRepository::new(&state);
|
||||
let perm_id = Uuid::new_v4().to_string();
|
||||
let permission = PermissionsSchema {
|
||||
id: make_thing(&ResourceEnum::Permissions.to_string(), &perm_id),
|
||||
name: "Permission for Fallback".into(),
|
||||
is_deleted: false,
|
||||
created_at: Some(crate::get_iso_date()),
|
||||
updated_at: Some(crate::get_iso_date()),
|
||||
};
|
||||
let perm_res = perm_repo.query_create_permission(permission).await;
|
||||
assert!(
|
||||
perm_res.is_ok(),
|
||||
"Failed to create permission: {:?}",
|
||||
perm_res.err()
|
||||
);
|
||||
let create_payload = RolesRequestCreateDto {
|
||||
name: "Role With Permission".into(),
|
||||
permissions: vec![perm_id.clone()],
|
||||
};
|
||||
let create_res = repo.query_create_role(create_payload).await;
|
||||
assert!(
|
||||
create_res.is_ok(),
|
||||
"Failed to create role: {:?}",
|
||||
create_res.err()
|
||||
);
|
||||
let existing = repo.query_role_by_name("Role With Permission".into()).await;
|
||||
assert!(
|
||||
existing.is_ok(),
|
||||
"Failed to get role by name: {:?}",
|
||||
existing.err()
|
||||
);
|
||||
let existing = existing.unwrap();
|
||||
let existing_id = existing.id.clone();
|
||||
let update_payload = RolesRequestUpdateDto {
|
||||
name: Some("Updated Role Name".into()),
|
||||
permissions: None,
|
||||
overwrite: None,
|
||||
};
|
||||
let update_res = repo
|
||||
.query_update_role(existing_id.clone(), update_payload)
|
||||
.await;
|
||||
assert!(
|
||||
update_res.is_ok(),
|
||||
"Failed to update role (fallback): {:?}",
|
||||
update_res.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_role_by_name_should_fail_if_not_found() {
|
||||
let state = setup_all_test_environment().await;
|
||||
let role_repo = RolesRepository::new(&state);
|
||||
let result = role_repo.query_role_by_name("ghost-role".into()).await;
|
||||
assert!(result.is_err());
|
||||
if let Some(err) = result.err() {
|
||||
assert!(
|
||||
err.to_string().contains("Role not found"),
|
||||
"Expected 'Role not found' error, got: {err}"
|
||||
);
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_update_role() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::RolesRepository::new(&app_state);
|
||||
|
||||
// Test data
|
||||
let original_name = "test_role_update_original".to_string();
|
||||
let new_name = "test_role_update_updated".to_string();
|
||||
|
||||
let role = RolesRequestCreateDto {
|
||||
name: original_name.clone(),
|
||||
permissions: vec![],
|
||||
};
|
||||
|
||||
// Create role
|
||||
let create_result = repo.query_create_role(role.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created role
|
||||
let created_role = repo.query_role_by_name(original_name.clone()).await.unwrap();
|
||||
|
||||
// Update role
|
||||
let updated_role = RolesRequestUpdateDto {
|
||||
name: Some(new_name.clone()),
|
||||
permissions: None,
|
||||
overwrite: None,
|
||||
};
|
||||
|
||||
let update_result = repo.query_update_role(created_role.id.clone(), updated_role).await;
|
||||
assert!(update_result.is_ok());
|
||||
|
||||
// Verify role was updated
|
||||
let result = repo.query_role_by_name(new_name.clone()).await;
|
||||
assert!(result.is_ok());
|
||||
let found_role = result.unwrap();
|
||||
assert_eq!(found_role.name, new_name);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_role(found_role.id).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_delete_role_should_fail_if_already_deleted() {
|
||||
let state = setup_all_test_environment().await;
|
||||
let role_repo = RolesRepository::new(&state);
|
||||
let name = generate_unique_name("soft_delete_test");
|
||||
let payload = RolesRequestCreateDto {
|
||||
name: name.clone(),
|
||||
permissions: vec![],
|
||||
};
|
||||
let create_res = role_repo.query_create_role(payload.clone()).await;
|
||||
assert!(
|
||||
create_res.is_ok(),
|
||||
"Failed to create role: {:?}",
|
||||
create_res.err()
|
||||
);
|
||||
let role = role_repo.query_role_by_name(name.clone()).await;
|
||||
assert!(role.is_ok(), "Failed to get role by name: {:?}", role.err());
|
||||
let role = role.unwrap();
|
||||
let del_res = role_repo.query_delete_role(role.id.clone()).await;
|
||||
assert!(
|
||||
del_res.is_ok(),
|
||||
"Failed to delete role: {:?}",
|
||||
del_res.err()
|
||||
);
|
||||
let result_fut = role_repo.query_delete_role(role.id);
|
||||
let result_val = result_fut.await;
|
||||
assert!(
|
||||
result_val.is_err(),
|
||||
"Role should already be deleted, but got: {result_val:?}"
|
||||
);
|
||||
if let Some(err) = result_val.err() {
|
||||
assert!(
|
||||
err.to_string().contains("Role not found"),
|
||||
"Expected 'Role not found' error, got: {err}"
|
||||
);
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_delete_role() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::RolesRepository::new(&app_state);
|
||||
|
||||
// Test data
|
||||
let role_name = "test_role_delete".to_string();
|
||||
let role = RolesRequestCreateDto {
|
||||
name: role_name.clone(),
|
||||
permissions: vec![],
|
||||
};
|
||||
|
||||
// Create role
|
||||
let create_result = repo.query_create_role(role.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created role
|
||||
let created_role = repo.query_role_by_name(role_name.clone()).await.unwrap();
|
||||
|
||||
// Verify role exists before deletion
|
||||
let role_id = created_role.id.clone();
|
||||
let exists_before = repo.query_role_by_id(role_id.clone()).await.is_ok();
|
||||
assert!(exists_before);
|
||||
|
||||
// Delete role
|
||||
let delete_result = repo.query_delete_role(role_id.clone()).await;
|
||||
assert!(delete_result.is_ok());
|
||||
|
||||
// Verify role was deleted
|
||||
let exists_after = repo.query_role_by_id(role_id.clone()).await.is_ok();
|
||||
assert!(!exists_after);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{generate_unique_email, get_role_id, UsersRepository};
|
||||
use axum::{http::StatusCode, response::Response};
|
||||
use imphnen_iam::{
|
||||
RolesCreateRequestDto, RolesUpdateRequestDto, RolesSchema, ResourceEnum,
|
||||
};
|
||||
use imphnen_utils::{make_thing_from_enum, ResourceEnum as UtilsResourceEnum};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_role_service() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::RolesRepository::new(&app_state);
|
||||
|
||||
// Test data
|
||||
let role_name = "test_role_service".to_string();
|
||||
let role_request = RolesCreateRequestDto {
|
||||
name: role_name.clone(),
|
||||
description: Some("Test role for service".to_string()),
|
||||
};
|
||||
|
||||
// Create role through service
|
||||
let response = imphnen_iam::RolesService::create_role(
|
||||
&app_state,
|
||||
role_request.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::CREATED);
|
||||
|
||||
// Verify role was created in database
|
||||
let created_role = repo
|
||||
.query_role_by_name(role_name)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(created_role.name, role_name);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_role(created_role.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_role_service_duplicate() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::RolesRepository::new(&app_state);
|
||||
|
||||
// Test data
|
||||
let role_name = "test_role_duplicate_service".to_string();
|
||||
let role_request = RolesCreateRequestDto {
|
||||
name: role_name.clone(),
|
||||
description: Some("Test role for duplicate check in service".to_string()),
|
||||
};
|
||||
|
||||
// Create role first time
|
||||
let response1 = imphnen_iam::RolesService::create_role(
|
||||
&app_state,
|
||||
role_request.clone(),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(response1.status(), StatusCode::CREATED);
|
||||
|
||||
// Try to create same role again
|
||||
let response2 = imphnen_iam::RolesService::create_role(
|
||||
&app_state,
|
||||
role_request,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify conflict response
|
||||
assert_eq!(response2.status(), StatusCode::CONFLICT);
|
||||
|
||||
// Clean up
|
||||
let created_role = repo
|
||||
.query_role_by_name(role_name)
|
||||
.await
|
||||
.unwrap();
|
||||
let _ = repo.query_delete_role(created_role.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_role_list_service() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::RolesRepository::new(&app_state);
|
||||
|
||||
// Create test roles
|
||||
let role_names = vec![
|
||||
"test_role_list_service_1".to_string(),
|
||||
"test_role_list_service_2".to_string(),
|
||||
"test_role_list_service_3".to_string(),
|
||||
];
|
||||
|
||||
for name in &role_names {
|
||||
let role = RolesSchema {
|
||||
name: name.clone(),
|
||||
description: Some(format!("Description for {}", name)),
|
||||
..Default::default()
|
||||
};
|
||||
let _ = repo.query_create_role(role).await;
|
||||
}
|
||||
|
||||
// Get role list through service
|
||||
let response = imphnen_iam::RolesService::get_role_list(
|
||||
&app_state,
|
||||
crate::get_meta_request_dto(1, 10),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Clean up
|
||||
for name in role_names {
|
||||
let role = repo.query_role_by_name(name).await.unwrap();
|
||||
let _ = repo.query_delete_role(role.id.id.to_raw()).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_role_by_id_service() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::RolesRepository::new(&app_state);
|
||||
|
||||
// Create test role
|
||||
let role_name = "test_role_by_id_service".to_string();
|
||||
let role = RolesSchema {
|
||||
name: role_name.clone(),
|
||||
description: Some("Test role for by ID test in service".to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
let create_result = repo.query_create_role(role.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created role to get ID
|
||||
let created_role = repo
|
||||
.query_role_by_name(role_name)
|
||||
.await
|
||||
.unwrap();
|
||||
let role_id = created_role.id.id.to_raw();
|
||||
|
||||
// Get role by ID through service
|
||||
let response = imphnen_iam::RolesService::get_role_by_id(
|
||||
&app_state, role_id.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_role(role_id).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_role_by_id_service_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Get non-existent role by ID through service
|
||||
let response = imphnen_iam::RolesService::get_role_by_id(
|
||||
&app_state, non_existent_id,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify not found response
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_role_service() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::RolesRepository::new(&app_state);
|
||||
|
||||
// Create test role
|
||||
let original_name = "test_role_update_original_service".to_string();
|
||||
let new_name = "test_role_update_updated_service".to_string();
|
||||
|
||||
let role = RolesSchema {
|
||||
name: original_name.clone(),
|
||||
description: Some("Original description for service test".to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
let create_result = repo.query_create_role(role.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created role to get ID
|
||||
let created_role = repo
|
||||
.query_role_by_name(original_name)
|
||||
.await
|
||||
.unwrap();
|
||||
let role_id = created_role.id.id.to_raw();
|
||||
|
||||
// Prepare update request
|
||||
let update_request = RolesUpdateRequestDto {
|
||||
name: Some(new_name.clone()),
|
||||
description: Some("Updated description for service test".to_string()),
|
||||
};
|
||||
|
||||
// Update role through service
|
||||
let response = imphnen_iam::RolesService::update_role(
|
||||
&app_state, role_id.clone(), update_request,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Verify role was updated in database
|
||||
let updated_role = repo
|
||||
.query_role_by_id(role_id.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(updated_role.name, new_name);
|
||||
assert_eq!(updated_role.description, Some("Updated description for service test".to_string()));
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_role(role_id).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_role_service_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Prepare update request
|
||||
let update_request = RolesUpdateRequestDto {
|
||||
name: Some("new_name".to_string()),
|
||||
description: Some("new description".to_string()),
|
||||
};
|
||||
|
||||
// Update non-existent role through service
|
||||
let response = imphnen_iam::RolesService::update_role(
|
||||
&app_state, non_existent_id, update_request,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify not found response
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_role_service() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = imphnen_iam::RolesRepository::new(&app_state);
|
||||
|
||||
// Create test role
|
||||
let role_name = "test_role_delete_service".to_string();
|
||||
let role = RolesSchema {
|
||||
name: role_name.clone(),
|
||||
description: Some("Test role for delete test in service".to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
let create_result = repo.query_create_role(role.clone()).await;
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Get created role to get ID
|
||||
let created_role = repo
|
||||
.query_role_by_name(role_name)
|
||||
.await
|
||||
.unwrap();
|
||||
let role_id = created_role.id.id.to_raw();
|
||||
|
||||
// Verify role exists before deletion
|
||||
let exists_before = repo.query_role_by_id(role_id.clone()).await.is_ok();
|
||||
assert!(exists_before);
|
||||
|
||||
// Delete role through service
|
||||
let response = imphnen_iam::RolesService::delete_role(
|
||||
&app_state, role_id.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Verify role was deleted from database
|
||||
let exists_after = repo.query_role_by_id(role_id).await.is_ok();
|
||||
assert!(!exists_after);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_role_service_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Delete non-existent role through service
|
||||
let response = imphnen_iam::RolesService::delete_role(
|
||||
&app_state, non_existent_id,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify not found response
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{generate_unique_email, get_role_id, UsersRepository};
|
||||
use axum::{http::StatusCode, response::Response};
|
||||
use imphnen_iam::{
|
||||
TeamsCreateRequestDto, TeamsSearchQueryDto, TeamsSchema, TeamMembersSchema, TeamsRepository
|
||||
};
|
||||
use imphnen_utils::{make_thing_from_enum, ResourceEnum};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_team_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let users_repo = UsersRepository::new(&app_state);
|
||||
let repo = TeamsRepository::new(&app_state);
|
||||
|
||||
let email = generate_unique_email("team_creator");
|
||||
let role_id = get_role_id("mentee", &app_state).await;
|
||||
|
||||
let user_data = crate::create_test_user(&email, "password123", true, &role_id);
|
||||
let user_result = users_repo.query_create_user(user_data.clone()).await;
|
||||
assert!(user_result.is_ok(), "Failed to create test user");
|
||||
let user = users_repo.query_user_by_email(email.clone()).await.unwrap();
|
||||
|
||||
let team_request = TeamsCreateRequestDto {
|
||||
name: "Test Controller Team".to_string(),
|
||||
description: Some("Team created via controller".to_string()),
|
||||
is_open: Some(true),
|
||||
max_members: Some(10),
|
||||
skills_required: Some(vec!["Rust".to_string(), "Testing".to_string()]),
|
||||
location: Some("Remote".to_string()),
|
||||
website_url: None,
|
||||
github_url: None,
|
||||
avatar: None,
|
||||
member_emails: vec![],
|
||||
};
|
||||
|
||||
// Create team through controller
|
||||
let response = imphnen_iam::TeamsController::create_team(
|
||||
&app_state, user.id.id.to_raw(), team_request.clone()
|
||||
).await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::CREATED);
|
||||
|
||||
// Verify team was created in database
|
||||
let team_thing = make_thing_from_enum(ResourceEnum::Teams, &user.id.id.to_raw());
|
||||
let teams = repo.query_user_teams(&team_thing).await.unwrap();
|
||||
assert!(!teams.is_empty());
|
||||
assert_eq!(teams[0].name, "Test Controller Team");
|
||||
|
||||
// Clean up
|
||||
let team_id = teams[0].id.id.to_raw();
|
||||
let _ = repo.query_delete_team(team_id).await;
|
||||
let _ = users_repo.query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_team_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let users_repo = UsersRepository::new(&app_state);
|
||||
let repo = TeamsRepository::new(&app_state);
|
||||
|
||||
let email = generate_unique_email("team_getter");
|
||||
let role_id = get_role_id("mentee", &app_state).await;
|
||||
|
||||
let user_data = crate::create_test_user(&email, "password123", true, &role_id);
|
||||
let user_result = users_repo.query_create_user(user_data.clone()).await;
|
||||
assert!(user_result.is_ok(), "Failed to create test user");
|
||||
let user = users_repo.query_user_by_email(email.clone()).await.unwrap();
|
||||
|
||||
let team_request = TeamsCreateRequestDto {
|
||||
name: "Test Get Team".to_string(),
|
||||
description: Some("Team for testing retrieval".to_string()),
|
||||
is_open: Some(true),
|
||||
max_members: Some(10),
|
||||
skills_required: None,
|
||||
location: None,
|
||||
website_url: None,
|
||||
github_url: None,
|
||||
avatar: None,
|
||||
member_emails: vec![],
|
||||
};
|
||||
|
||||
// Create team directly for testing
|
||||
let team_schema = TeamsSchema::create(team_request, user.id.id.to_raw());
|
||||
let create_result = repo.query_create_team(team_schema.clone()).await;
|
||||
assert!(create_result.is_ok(), "Failed to create team");
|
||||
|
||||
let team_thing = make_thing_from_enum(ResourceEnum::Teams, &team_schema.id.id.to_raw());
|
||||
let team = repo.query_team_by_id(&team_thing).await.unwrap();
|
||||
let team_id = team_schema.id.id.to_raw();
|
||||
|
||||
// Get team by ID through controller
|
||||
let response = imphnen_iam::TeamsController::get_team(
|
||||
&app_state, team_id.clone()
|
||||
).await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_team(team_id).await;
|
||||
let _ = users_repo.query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_team_controller_not_found() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
|
||||
// Use non-existent ID
|
||||
let non_existent_id = "non-existent-uuid-123456789".to_string();
|
||||
|
||||
// Get non-existent team by ID through controller
|
||||
let response = imphnen_iam::TeamsController::get_team(
|
||||
&app_state, non_existent_id
|
||||
).await;
|
||||
|
||||
// Verify not found response
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_team_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let users_repo = UsersRepository::new(&app_state);
|
||||
let repo = TeamsRepository::new(&app_state);
|
||||
|
||||
let email = generate_unique_email("team_updater");
|
||||
let role_id = get_role_id("mentee", &app_state).await;
|
||||
|
||||
let user_data = crate::create_test_user(&email, "password123", true, &role_id);
|
||||
let user_result = users_repo.query_create_user(user_data.clone()).await;
|
||||
assert!(user_result.is_ok(), "Failed to create test user");
|
||||
let user = users_repo.query_user_by_email(email.clone()).await.unwrap();
|
||||
|
||||
let team_request = TeamsCreateRequestDto {
|
||||
name: "Original Team Name".to_string(),
|
||||
description: Some("Original description".to_string()),
|
||||
is_open: Some(true),
|
||||
max_members: Some(10),
|
||||
skills_required: None,
|
||||
location: None,
|
||||
website_url: None,
|
||||
github_url: None,
|
||||
avatar: None,
|
||||
member_emails: vec![],
|
||||
};
|
||||
|
||||
// Create team directly for testing
|
||||
let team_schema = TeamsSchema::create(team_request, user.id.id.to_raw());
|
||||
let create_result = repo.query_create_team(team_schema.clone()).await;
|
||||
assert!(create_result.is_ok(), "Failed to create team");
|
||||
|
||||
let team_thing = make_thing_from_enum(ResourceEnum::Teams, &team_schema.id.id.to_raw());
|
||||
let original_team = repo.query_team_by_id(&team_thing).await.unwrap();
|
||||
let team_id = team_schema.id.id.to_raw();
|
||||
|
||||
// Prepare update request
|
||||
let update_request = imphnen_iam::TeamsUpdateRequestDto {
|
||||
name: Some("Updated Team Name".to_string()),
|
||||
description: Some("Updated description".to_string()),
|
||||
is_open: Some(false),
|
||||
max_members: Some(15),
|
||||
skills_required: Some(vec!["Rust".to_string(), "Testing".to_string()]),
|
||||
location: Some("Office".to_string()),
|
||||
website_url: Some("https://example.com".to_string()),
|
||||
github_url: Some("https://github.com/example".to_string()),
|
||||
};
|
||||
|
||||
// Update team through controller
|
||||
let response = imphnen_iam::TeamsController::update_team(
|
||||
&app_state, user.id.id.to_raw(), update_request, team_id.clone()
|
||||
).await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Verify team was updated in database
|
||||
let updated_team = repo.query_team_by_id(&team_thing).await.unwrap();
|
||||
assert_eq!(updated_team.name, "Updated Team Name");
|
||||
assert_eq!(updated_team.description, Some("Updated description".to_string()));
|
||||
assert_eq!(updated_team.is_open, false);
|
||||
assert_eq!(updated_team.max_members, Some(15));
|
||||
assert_eq!(updated_team.skills_required, Some(vec!["Rust".to_string(), "Testing".to_string()]));
|
||||
assert_eq!(updated_team.location, Some("Office".to_string()));
|
||||
assert_eq!(updated_team.website_url, Some("https://example.com".to_string()));
|
||||
assert_eq!(updated_team.github_url, Some("https://github.com/example".to_string()));
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_team(team_id).await;
|
||||
let _ = users_repo.query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_team_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let users_repo = UsersRepository::new(&app_state);
|
||||
let repo = TeamsRepository::new(&app_state);
|
||||
|
||||
let email = generate_unique_email("team_deleter");
|
||||
let role_id = get_role_id("mentee", &app_state).await;
|
||||
|
||||
let user_data = crate::create_test_user(&email, "password123", true, &role_id);
|
||||
let user_result = users_repo.query_create_user(user_data.clone()).await;
|
||||
assert!(user_result.is_ok(), "Failed to create test user");
|
||||
let user = users_repo.query_user_by_email(email.clone()).await.unwrap();
|
||||
|
||||
let team_request = TeamsCreateRequestDto {
|
||||
name: "Team to Delete".to_string(),
|
||||
description: Some("Team that will be deleted".to_string()),
|
||||
is_open: Some(true),
|
||||
max_members: Some(10),
|
||||
skills_required: None,
|
||||
location: None,
|
||||
website_url: None,
|
||||
github_url: None,
|
||||
avatar: None,
|
||||
member_emails: vec![],
|
||||
};
|
||||
|
||||
// Create team directly for testing
|
||||
let team_schema = TeamsSchema::create(team_request, user.id.id.to_raw());
|
||||
let create_result = repo.query_create_team(team_schema.clone()).await;
|
||||
assert!(create_result.is_ok(), "Failed to create team");
|
||||
|
||||
let team_thing = make_thing_from_enum(ResourceEnum::Teams, &team_schema.id.id.to_raw());
|
||||
let team = repo.query_team_by_id(&team_thing).await.unwrap();
|
||||
let team_id = team_schema.id.id.to_raw();
|
||||
|
||||
// Verify team exists before deletion
|
||||
let exists_before = repo.query_team_by_id(&team_thing).await.is_ok();
|
||||
assert!(exists_before);
|
||||
|
||||
// Delete team through controller
|
||||
let response = imphnen_iam::TeamsController::delete_team(
|
||||
&app_state, user.id.id.to_raw(), team_id.clone()
|
||||
).await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Verify team was deleted from database
|
||||
let exists_after = repo.query_team_by_id(&team_thing).await.is_ok();
|
||||
assert!(!exists_after);
|
||||
|
||||
// Clean up
|
||||
let _ = users_repo.query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_search_teams_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let users_repo = UsersRepository::new(&app_state);
|
||||
let repo = TeamsRepository::new(&app_state);
|
||||
|
||||
let email = generate_unique_email("team_searcher");
|
||||
let role_id = get_role_id("mentee", &app_state).await;
|
||||
|
||||
let user_data = crate::create_test_user(&email, "password123", true, &role_id);
|
||||
let user_result = users_repo.query_create_user(user_data.clone()).await;
|
||||
assert!(user_result.is_ok(), "Failed to create test user");
|
||||
let user = users_repo.query_user_by_email(email.clone()).await.unwrap();
|
||||
|
||||
let team_request = TeamsCreateRequestDto {
|
||||
name: "Searchable Test Team".to_string(),
|
||||
description: Some("A team for testing search functionality".to_string()),
|
||||
is_open: Some(true),
|
||||
max_members: Some(8),
|
||||
skills_required: Some(vec!["Rust".to_string(), "Testing".to_string()]),
|
||||
location: Some("Remote".to_string()),
|
||||
website_url: None,
|
||||
github_url: None,
|
||||
avatar: None,
|
||||
member_emails: vec![],
|
||||
};
|
||||
|
||||
// Create team directly for testing
|
||||
let team_schema = TeamsSchema::create(team_request, user.id.id.to_raw());
|
||||
let create_result = repo.query_create_team(team_schema.clone()).await;
|
||||
assert!(create_result.is_ok(), "Failed to create team");
|
||||
|
||||
let team_id = team_schema.id.id.to_raw();
|
||||
|
||||
// Prepare search request
|
||||
let search_params = TeamsSearchQueryDto {
|
||||
query: Some("Searchable".to_string()),
|
||||
open: Some(true),
|
||||
skills: Some(vec!["Rust".to_string()]),
|
||||
location: Some("Remote".to_string()),
|
||||
page: Some(1),
|
||||
per_page: Some(10),
|
||||
};
|
||||
|
||||
// Search teams through controller
|
||||
let response = imphnen_iam::TeamsController::search_teams(
|
||||
&app_state, search_params
|
||||
).await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_team(team_id).await;
|
||||
let _ = users_repo.query_delete_user(user.id.id.to_raw()).await;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{generate_unique_email, get_role_id, UsersRepository};
|
||||
use axum::{http::StatusCode, response::Response};
|
||||
use imphnen_iam::{
|
||||
UsersCreateRequestDto, UsersUpdateRequestDto, UsersSchema, ResourceEnum,
|
||||
UsersActiveInactiveRequestDto, UsersSetNewPasswordRequestDto
|
||||
};
|
||||
use imphnen_utils::{make_thing_from_enum, ResourceEnum as UtilsResourceEnum};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_user_controller() {
|
||||
let app_state = crate::get_app_state().await;
|
||||
let repo = UsersRepository::new(&app_state);
|
||||
let role_id = get_role_id("mentee", &app_state).await;
|
||||
|
||||
// Test data
|
||||
let email = generate_unique_email("test_user_controller");
|
||||
let user_request = UsersCreateRequestDto {
|
||||
email: email.clone(),
|
||||
password: "password123".to_string(),
|
||||
fullname: "Test User Controller".to_string(),
|
||||
phone_number: Some("+1234567890".to_string()),
|
||||
is_active: true,
|
||||
avatar: None,
|
||||
role_id: role_id,
|
||||
};
|
||||
|
||||
// Create user through controller
|
||||
let response = imphnen_iam::UsersController::create_user(
|
||||
&app_state,
|
||||
user_request.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(response.status(), StatusCode::CREATED);
|
||||
|
||||
// Verify user was created in database
|
||||
let created_user = repo
|
||||
.query_user_by_email(email.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(created_user.email, email);
|
||||
assert_eq!(created_user.fullname, "Test User Controller");
|
||||
assert_eq!(created_user.is_active, true);
|
||||
|
||||
// Clean up
|
||||
let _ = repo.query_delete_user(created_user.id.id.to_raw()).await;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user