Add comprehensive tests for Gacha Credits, Auth, and User services

- Implement tests for GachaCreditsService including creation, retrieval, updating, and deletion of gacha credits.
- Add tests for AuthController covering user login, registration, email verification, and error handling for invalid credentials.
- Enhance AuthService tests to include login, registration, email verification, OTP resend, password reset, and token refresh functionalities.
- Create tests for UsersService to validate user creation, retrieval, updating, deletion, and fetching by email.
- Ensure all tests utilize a consistent setup and teardown process for database interactions.
This commit is contained in:
MythEclipse
2025-09-25 22:53:26 +07:00
parent 0e48b6755f
commit f3d88e2ac9
8 changed files with 1912 additions and 212 deletions
@@ -0,0 +1,435 @@
#[cfg(test)]
mod tests {
use crate::{generate_unique_email, get_role_id, UsersRepository, setup_all_test_environment};
use axum::{http::StatusCode, response::Response};
use imphnen_dimentorin::{
mentors_service::MentorsService,
mentors_dto::{
MentorUserRegisterRequestDto, MentorUpdateRequestDto, MentorVerifyRequestDto,
IdentityAndVerification, ProfessionalProfile, MentoringLogistics
},
MentorsRepository
};
use imphnen_entities::{AppState, MetaRequestDto};
use imphnen_iam::{RolesEnum};
use imphnen_utils::{generate_otp, hash_password, make_thing_from_enum, get_iso_date};
use surrealdb::Uuid;
#[tokio::test]
async fn test_register_mentor_service() {
let app_state = setup_all_test_environment().await;
let user_repo = UsersRepository::new(&app_state);
let mentor_repo = MentorsRepository::new(&app_state);
let role_repo = imphnen_iam::RolesRepository::new(&app_state);
let auth_repo = imphnen_iam::AuthRepository::new(&app_state);
// Test data
let email = generate_unique_email("test_register_mentor");
let password = "Password123!".to_string();
let mentor_dto = MentorUserRegisterRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test Mentor Service".to_string(),
phone_number: "1234567890".to_string(),
identity_and_verification: 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: 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: 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,
},
};
// Register mentor
let response = MentorsService::register_mentor(&app_state, mentor_dto.clone()).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Verify mentor was created in database
let mentor = mentor_repo.query_mentor_by_email(email.clone(), false).await;
assert!(mentor.is_ok());
assert_eq!(mentor.unwrap().status, "pending".to_string());
// Verify user was updated in database
let user = user_repo.query_user_by_email(email.clone()).await;
assert!(user.is_ok());
assert_eq!(user.unwrap().is_active, false);
// Clean up
let user = user.unwrap();
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_get_mentor_list_service() {
let app_state = setup_all_test_environment().await;
let mentor_repo = MentorsRepository::new(&app_state);
let user_repo = UsersRepository::new(&app_state);
// Create test mentor first
let email = generate_unique_email("test_mentor_list");
let password = "Password123!".to_string();
let mentor_dto = MentorUserRegisterRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test Mentor List".to_string(),
phone_number: "1234567890".to_string(),
identity_and_verification: 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: 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: 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,
},
};
let _ = MentorsService::register_mentor(&app_state, mentor_dto).await;
// Get mentor list
let meta = MetaRequestDto {
limit: 10,
page: 1,
search: None,
sort: None,
filter: None,
};
let response = MentorsService::get_mentor_list(&app_state, meta).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Clean up
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_get_mentor_by_id_service() {
let app_state = setup_all_test_environment().await;
let mentor_repo = MentorsRepository::new(&app_state);
let user_repo = UsersRepository::new(&app_state);
// Create test mentor first
let email = generate_unique_email("test_mentor_by_id");
let password = "Password123!".to_string();
let mentor_dto = MentorUserRegisterRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test Mentor By ID".to_string(),
phone_number: "1234567890".to_string(),
identity_and_verification: 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: 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: 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,
},
};
let register_response = MentorsService::register_mentor(&app_state, mentor_dto).await;
assert_eq!(register_response.status(), StatusCode::OK);
let mentor = mentor_repo.query_mentor_by_email(email.clone(), false).await.unwrap();
let mentor_id = mentor.id.id.to_raw();
// Get mentor by ID
let response = MentorsService::get_mentor_by_id(&app_state, mentor_id).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Clean up
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_update_mentor_service() {
let app_state = setup_all_test_environment().await;
let mentor_repo = MentorsRepository::new(&app_state);
let user_repo = UsersRepository::new(&app_state);
// Create test mentor first
let email = generate_unique_email("test_update_mentor");
let password = "Password123!".to_string();
let mentor_dto = MentorUserRegisterRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test Mentor Update".to_string(),
phone_number: "1234567890".to_string(),
identity_and_verification: 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: 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: 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,
},
};
let _ = MentorsService::register_mentor(&app_state, mentor_dto).await;
let mentor = mentor_repo.query_mentor_by_email(email.clone(), false).await.unwrap();
let mentor_id = mentor.id.id.to_raw();
// Prepare update request
let update_dto = 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),
};
// Update mentor
let response = MentorsService::update_mentor(&app_state, mentor_id, update_dto).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Verify mentor was updated
let updated_mentor = mentor_repo.query_mentor_by_id(&mentor.id, false).await.unwrap();
assert_eq!(updated_mentor.legal_name, Some("Updated Legal Name".to_string()));
assert_eq!(updated_mentor.current_role, "Lead Engineer".to_string());
// Clean up
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_delete_mentor_service() {
let app_state = setup_all_test_environment().await;
let mentor_repo = MentorsRepository::new(&app_state);
let user_repo = UsersRepository::new(&app_state);
// Create test mentor first
let email = generate_unique_email("test_delete_mentor");
let password = "Password123!".to_string();
let mentor_dto = MentorUserRegisterRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test Mentor Delete".to_string(),
phone_number: "1234567890".to_string(),
identity_and_verification: 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: 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: 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,
},
};
let _ = MentorsService::register_mentor(&app_state, mentor_dto).await;
let mentor = mentor_repo.query_mentor_by_email(email.clone(), false).await.unwrap();
let mentor_id = mentor.id.id.to_raw();
// Delete mentor
let response = MentorsService::delete_mentor(&app_state, mentor_id).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Clean up
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_verify_mentor_service() {
let app_state = setup_all_test_environment().await;
let mentor_repo = MentorsRepository::new(&app_state);
let user_repo = UsersRepository::new(&app_state);
// Create test mentor first
let email = generate_unique_email("test_verify_mentor");
let password = "Password123!".to_string();
let mentor_dto = MentorUserRegisterRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test Mentor Verify".to_string(),
phone_number: "1234567890".to_string(),
identity_and_verification: 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: 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: 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,
},
};
let _ = MentorsService::register_mentor(&app_state, mentor_dto).await;
let mentor = mentor_repo.query_mentor_by_email(email.clone(), false).await.unwrap();
let mentor_id = mentor.id.id.to_raw();
// Prepare verification request
let verify_dto = MentorVerifyRequestDto {
status: "verified".to_string(),
};
// Verify mentor
let response = MentorsService::verify_mentor(&app_state, mentor_id, verify_dto).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Verify mentor was verified
let updated_mentor = mentor_repo.query_mentor_by_id(&mentor.id, false).await.unwrap();
assert_eq!(updated_mentor.status, "verified".to_string());
// Clean up
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
}
@@ -0,0 +1,240 @@
#[cfg(test)]
mod tests {
use crate::{generate_unique_email, get_role_id, setup_all_test_environment, UsersRepository};
use axum::{http::StatusCode, response::Response};
use imphnen_entities::{AppState, MetaRequestDto};
use imphnen_gacha::{
gacha_credits_controller::GachaCreditsController,
gacha_credits_dto::{GachaCreditsCreateRequestDto, GachaCreditsUpdateRequestDto},
};
use imphnen_iam::users_service::UsersService;
use imphnen_utils::{generate_otp, hash_password, make_thing_from_enum, get_iso_date};
use surrealdb::Uuid;
#[tokio::test]
async fn test_create_gacha_credits() {
let app_state = setup_all_test_environment().await;
let user_repo = UsersRepository::new(&app_state);
// Create test user first
let email = generate_unique_email("test_gacha_credits");
let password = "Password123!".to_string();
let user_dto = imphnen_iam::users_dto::UserCreateRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test Gacha Credits".to_string(),
phone_number: Some("1234567890".to_string()),
role_id: get_role_id(&app_state, "user").await.unwrap(),
};
let _ = UsersService::create_user(&app_state, user_dto).await;
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
// Test data
let gacha_credits_dto = GachaCreditsCreateRequestDto {
user_id: user.id.id.to_raw(),
amount: 100,
description: Some("Test Gacha Credits".to_string()),
transaction_id: Some("TXN-123456".to_string()),
status: "active".to_string(),
};
// Create gacha credits
let response = GachaCreditsController::create_gacha_credits(&app_state, gacha_credits_dto.clone()).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Clean up
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_get_gacha_credits_list() {
let app_state = setup_all_test_environment().await;
let user_repo = UsersRepository::new(&app_state);
// Create test user first
let email = generate_unique_email("test_gacha_credits_list");
let password = "Password123!".to_string();
let user_dto = imphnen_iam::users_dto::UserCreateRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test Gacha Credits List".to_string(),
phone_number: Some("1234567890".to_string()),
role_id: get_role_id(&app_state, "user").await.unwrap(),
};
let _ = UsersService::create_user(&app_state, user_dto).await;
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
// Create test gacha credits
let gacha_credits_dto = GachaCreditsCreateRequestDto {
user_id: user.id.id.to_raw(),
amount: 100,
description: Some("Test Gacha Credits List".to_string()),
transaction_id: Some("TXN-123456".to_string()),
status: "active".to_string(),
};
let _ = GachaCreditsController::create_gacha_credits(&app_state, gacha_credits_dto).await;
// Get gacha credits list
let meta = MetaRequestDto {
limit: 10,
page: 1,
search: None,
sort: None,
filter: None,
};
let response = GachaCreditsController::get_gacha_credits_list(&app_state, meta).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Clean up
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_get_gacha_credits_by_id() {
let app_state = setup_all_test_environment().await;
let user_repo = UsersRepository::new(&app_state);
let gacha_credits_repo = imphnen_gacha::GachaCreditsRepository::new(&app_state);
// Create test user first
let email = generate_unique_email("test_gacha_credits_by_id");
let password = "Password123!".to_string();
let user_dto = imphnen_iam::users_dto::UserCreateRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test Gacha Credits By ID".to_string(),
phone_number: Some("1234567890".to_string()),
role_id: get_role_id(&app_state, "user").await.unwrap(),
};
let _ = UsersService::create_user(&app_state, user_dto).await;
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
// Create test gacha credits
let gacha_credits_dto = GachaCreditsCreateRequestDto {
user_id: user.id.id.to_raw(),
amount: 100,
description: Some("Test Gacha Credits By ID".to_string()),
transaction_id: Some("TXN-123456".to_string()),
status: "active".to_string(),
};
let create_response = GachaCreditsController::create_gacha_credits(&app_state, gacha_credits_dto).await;
let gacha_credits = gacha_credits_repo.query_gacha_credits_by_user_id(user.id.id.to_raw(), false).await.unwrap();
let gacha_credits_id = gacha_credits.id.id.to_raw();
// Get gacha credits by ID
let response = GachaCreditsController::get_gacha_credits_by_id(&app_state, gacha_credits_id).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Clean up
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_update_gacha_credits() {
let app_state = setup_all_test_environment().await;
let user_repo = UsersRepository::new(&app_state);
let gacha_credits_repo = imphnen_gacha::GachaCreditsRepository::new(&app_state);
// Create test user first
let email = generate_unique_email("test_update_gacha_credits");
let password = "Password123!".to_string();
let user_dto = imphnen_iam::users_dto::UserCreateRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test Update Gacha Credits".to_string(),
phone_number: Some("1234567890".to_string()),
role_id: get_role_id(&app_state, "user").await.unwrap(),
};
let _ = UsersService::create_user(&app_state, user_dto).await;
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
// Create test gacha credits
let gacha_credits_dto = GachaCreditsCreateRequestDto {
user_id: user.id.id.to_raw(),
amount: 100,
description: Some("Test Update Gacha Credits".to_string()),
transaction_id: Some("TXN-123456".to_string()),
status: "active".to_string(),
};
let _ = GachaCreditsController::create_gacha_credits(&app_state, gacha_credits_dto).await;
let gacha_credits = gacha_credits_repo.query_gacha_credits_by_user_id(user.id.id.to_raw(), false).await.unwrap();
let gacha_credits_id = gacha_credits.id.id.to_raw();
// Prepare update request
let update_dto = GachaCreditsUpdateRequestDto {
amount: Some(200),
description: Some("Updated Test Gacha Credits".to_string()),
status: Some("used".to_string()),
};
// Update gacha credits
let response = GachaCreditsController::update_gacha_credits(&app_state, gacha_credits_id, update_dto).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Clean up
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_delete_gacha_credits() {
let app_state = setup_all_test_environment().await;
let user_repo = UsersRepository::new(&app_state);
let gacha_credits_repo = imphnen_gacha::GachaCreditsRepository::new(&app_state);
// Create test user first
let email = generate_unique_email("test_delete_gacha_credits");
let password = "Password123!".to_string();
let user_dto = imphnen_iam::users_dto::UserCreateRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test Delete Gacha Credits".to_string(),
phone_number: Some("1234567890".to_string()),
role_id: get_role_id(&app_state, "user").await.unwrap(),
};
let _ = UsersService::create_user(&app_state, user_dto).await;
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
// Create test gacha credits
let gacha_credits_dto = GachaCreditsCreateRequestDto {
user_id: user.id.id.to_raw(),
amount: 100,
description: Some("Test Delete Gacha Credits".to_string()),
transaction_id: Some("TXN-123456".to_string()),
status: "active".to_string(),
};
let _ = GachaCreditsController::create_gacha_credits(&app_state, gacha_credits_dto).await;
let gacha_credits = gacha_credits_repo.query_gacha_credits_by_user_id(user.id.id.to_raw(), false).await.unwrap();
let gacha_credits_id = gacha_credits.id.id.to_raw();
// Delete gacha credits
let response = GachaCreditsController::delete_gacha_credits(&app_state, gacha_credits_id).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Clean up
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
}
@@ -0,0 +1,258 @@
#[cfg(test)]
mod tests {
use crate::{generate_unique_email, get_role_id, setup_all_test_environment, UsersRepository};
use axum::{http::StatusCode, response::Response};
use imphnen_entities::{AppState, MetaRequestDto};
use imphnen_gacha::{
gacha_credits_service::GachaCreditsService,
gacha_credits_dto::{GachaCreditsCreateRequestDto, GachaCreditsUpdateRequestDto},
GachaCreditsRepository
};
use imphnen_iam::users_service::UsersService;
use imphnen_utils::{hash_password};
use surrealdb::Uuid;
#[tokio::test]
async fn test_create_gacha_credits_service() {
let app_state = setup_all_test_environment().await;
let user_repo = UsersRepository::new(&app_state);
let gacha_credits_repo = GachaCreditsRepository::new(&app_state);
// Create test user first
let email = generate_unique_email("test_create_gacha_credits_service");
let password = "Password123!".to_string();
let user_dto = imphnen_iam::users_dto::UserCreateRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test Gacha Credits Service".to_string(),
phone_number: Some("1234567890".to_string()),
role_id: get_role_id(&app_state, "user").await.unwrap(),
};
let _ = UsersService::create_user(&app_state, user_dto).await;
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
// Test data
let gacha_credits_dto = GachaCreditsCreateRequestDto {
user_id: user.id.id.to_raw(),
amount: 100,
description: Some("Test Gacha Credits Service".to_string()),
transaction_id: Some("TXN-123456".to_string()),
status: "active".to_string(),
};
// Create gacha credits via service
let response = GachaCreditsService::create_gacha_credits(&app_state, gacha_credits_dto.clone()).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Verify gacha credits was created in database
let gacha_credits = gacha_credits_repo.query_gacha_credits_by_user_id(user.id.id.to_raw(), false).await;
assert!(gacha_credits.is_ok());
assert_eq!(gacha_credits.unwrap().amount, 100);
assert_eq!(gacha_credits.unwrap().status, "active".to_string());
// Clean up
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_get_gacha_credits_list_service() {
let app_state = setup_all_test_environment().await;
let user_repo = UsersRepository::new(&app_state);
let gacha_credits_repo = GachaCreditsRepository::new(&app_state);
// Create test user first
let email = generate_unique_email("test_gacha_credits_list_service");
let password = "Password123!".to_string();
let user_dto = imphnen_iam::users_dto::UserCreateRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test Gacha Credits List Service".to_string(),
phone_number: Some("1234567890".to_string()),
role_id: get_role_id(&app_state, "user").await.unwrap(),
};
let _ = UsersService::create_user(&app_state, user_dto).await;
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
// Create test gacha credits
let gacha_credits_dto = GachaCreditsCreateRequestDto {
user_id: user.id.id.to_raw(),
amount: 100,
description: Some("Test Gacha Credits List Service".to_string()),
transaction_id: Some("TXN-123456".to_string()),
status: "active".to_string(),
};
let _ = GachaCreditsService::create_gacha_credits(&app_state, gacha_credits_dto).await;
// Get gacha credits list via service
let meta = MetaRequestDto {
limit: 10,
page: 1,
search: None,
sort: None,
filter: None,
};
let response = GachaCreditsService::get_gacha_credits_list(&app_state, meta).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Clean up
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_get_gacha_credits_by_id_service() {
let app_state = setup_all_test_environment().await;
let user_repo = UsersRepository::new(&app_state);
let gacha_credits_repo = GachaCreditsRepository::new(&app_state);
// Create test user first
let email = generate_unique_email("test_gacha_credits_by_id_service");
let password = "Password123!".to_string();
let user_dto = imphnen_iam::users_dto::UserCreateRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test Gacha Credits By ID Service".to_string(),
phone_number: Some("1234567890".to_string()),
role_id: get_role_id(&app_state, "user").await.unwrap(),
};
let _ = UsersService::create_user(&app_state, user_dto).await;
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
// Create test gacha credits
let gacha_credits_dto = GachaCreditsCreateRequestDto {
user_id: user.id.id.to_raw(),
amount: 100,
description: Some("Test Gacha Credits By ID Service".to_string()),
transaction_id: Some("TXN-123456".to_string()),
status: "active".to_string(),
};
let _ = GachaCreditsService::create_gacha_credits(&app_state, gacha_credits_dto).await;
let gacha_credits = gacha_credits_repo.query_gacha_credits_by_user_id(user.id.id.to_raw(), false).await.unwrap();
let gacha_credits_id = gacha_credits.id.id.to_raw();
// Get gacha credits by ID via service
let response = GachaCreditsService::get_gacha_credits_by_id(&app_state, gacha_credits_id).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Clean up
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_update_gacha_credits_service() {
let app_state = setup_all_test_environment().await;
let user_repo = UsersRepository::new(&app_state);
let gacha_credits_repo = GachaCreditsRepository::new(&app_state);
// Create test user first
let email = generate_unique_email("test_update_gacha_credits_service");
let password = "Password123!".to_string();
let user_dto = imphnen_iam::users_dto::UserCreateRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test Update Gacha Credits Service".to_string(),
phone_number: Some("1234567890".to_string()),
role_id: get_role_id(&app_state, "user").await.unwrap(),
};
let _ = UsersService::create_user(&app_state, user_dto).await;
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
// Create test gacha credits
let gacha_credits_dto = GachaCreditsCreateRequestDto {
user_id: user.id.id.to_raw(),
amount: 100,
description: Some("Test Update Gacha Credits Service".to_string()),
transaction_id: Some("TXN-123456".to_string()),
status: "active".to_string(),
};
let _ = GachaCreditsService::create_gacha_credits(&app_state, gacha_credits_dto).await;
let gacha_credits = gacha_credits_repo.query_gacha_credits_by_user_id(user.id.id.to_raw(), false).await.unwrap();
let gacha_credits_id = gacha_credits.id.id.to_raw();
// Prepare update request
let update_dto = GachaCreditsUpdateRequestDto {
amount: Some(200),
description: Some("Updated Test Gacha Credits Service".to_string()),
status: Some("used".to_string()),
};
// Update gacha credits via service
let response = GachaCreditsService::update_gacha_credits(&app_state, gacha_credits_id, update_dto).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Verify gacha credits was updated
let updated_gacha_credits = gacha_credits_repo.query_gacha_credits_by_id(&gacha_credits.id, false).await.unwrap();
assert_eq!(updated_gacha_credits.amount, 200);
assert_eq!(updated_gacha_credits.status, "used".to_string());
// Clean up
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_delete_gacha_credits_service() {
let app_state = setup_all_test_environment().await;
let user_repo = UsersRepository::new(&app_state);
let gacha_credits_repo = GachaCreditsRepository::new(&app_state);
// Create test user first
let email = generate_unique_email("test_delete_gacha_credits_service");
let password = "Password123!".to_string();
let user_dto = imphnen_iam::users_dto::UserCreateRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test Delete Gacha Credits Service".to_string(),
phone_number: Some("1234567890".to_string()),
role_id: get_role_id(&app_state, "user").await.unwrap(),
};
let _ = UsersService::create_user(&app_state, user_dto).await;
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
// Create test gacha credits
let gacha_credits_dto = GachaCreditsCreateRequestDto {
user_id: user.id.id.to_raw(),
amount: 100,
description: Some("Test Delete Gacha Credits Service".to_string()),
transaction_id: Some("TXN-123456".to_string()),
status: "active".to_string(),
};
let _ = GachaCreditsService::create_gacha_credits(&app_state, gacha_credits_dto).await;
let gacha_credits = gacha_credits_repo.query_gacha_credits_by_user_id(user.id.id.to_raw(), false).await.unwrap();
let gacha_credits_id = gacha_credits.id.id.to_raw();
// Delete gacha credits via service
let response = GachaCreditsService::delete_gacha_credits(&app_state, gacha_credits_id).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Verify gacha credits was deleted
let deleted_gacha_credits = gacha_credits_repo.query_gacha_credits_by_id(&gacha_credits.id, false).await;
assert!(deleted_gacha_credits.is_err());
// Clean up
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
}
+102
View File
@@ -0,0 +1,102 @@
#[cfg(test)]
mod tests {
use crate::{generate_unique_email, get_role_id, UsersRepository};
use axum::{http::StatusCode, response::Response};
use imphnen_iam::{
AuthLoginRequestDto, AuthLoginResponsetDto, AuthNewPasswordRequestDto,
AuthRefreshTokenRequestDto, AuthRegisterRequestDto, AuthResendOtpRequestDto,
AuthVerifyEmailRequestDto, MessageResponseDto, ResponseSuccessDto, TokenDto,
};
use imphnen_utils::{make_thing_from_enum, ResourceEnum as UtilsResourceEnum};
use uuid::Uuid;
#[tokio::test]
async fn test_post_login_controller() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let role_id = get_role_id("user", &app_state).await;
// Test data
let email = generate_unique_email("test_login_controller");
let password = "password123".to_string();
// Create test user first
let user_request = AuthRegisterRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test User Controller".to_string(),
phone_number: Some("+1234567890".to_string()),
};
let register_response = imphnen_iam::AuthController::mutation_register(
&app_state,
user_request,
)
.await;
assert_eq!(register_response.status(), StatusCode::CREATED);
// Wait for email verification (simulate OTP verification in test)
let verify_request = AuthVerifyEmailRequestDto {
email: email.clone(),
otp: "123456".to_string(), // Default test OTP
};
let verify_response = imphnen_iam::AuthController::mutation_verify_email(
&app_state,
verify_request,
)
.await;
assert_eq!(verify_response.status(), StatusCode::OK);
// Try to login
let login_request = AuthLoginRequestDto {
email: email.clone(),
password: password.clone(),
};
let response = imphnen_iam::AuthController::mutation_login(
&app_state,
login_request,
)
.await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
let login_response: ResponseSuccessDto = response.into_body().await.unwrap();
assert!(login_response.data.is_some());
// Clean up
let user = repo.query_user_by_email(email.clone()).await.unwrap();
let _ = repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_post_login_controller_invalid_credentials() {
let app_state = crate::get_app_state().await;
// Test data
let email = generate_unique_email("test_login_invalid");
let password = "wrongpassword".to_string();
// Try to login with non-existent user
let login_request = AuthLoginRequestDto {
email: email.clone(),
password: password.clone(),
};
let response = imphnen_iam::AuthController::mutation_login(
&app_state,
login_request,
)
.await;
// Verify response
assert_eq!(response.status(), StatusCode::UNAUTHORIZED);
let error_response: MessageResponseDto = response.into_body().await.unwrap();
assert!(error_response.message.contains("Email or password not correct"));
}
}
+440
View File
@@ -0,0 +1,440 @@
#[cfg(test)]
mod tests {
use crate::{generate_unique_email, get_role_id, UsersRepository};
use imphnen_iam::{
AuthLoginRequestDto, AuthLoginResponsetDto, AuthNewPasswordRequestDto,
AuthRefreshTokenRequestDto, AuthRegisterRequestDto, AuthResendOtpRequestDto,
AuthVerifyEmailRequestDto, MessageResponseDto, ResponseSuccessDto, TokenDto,
};
use imphnen_utils::{make_thing_from_enum, ResourceEnum as UtilsResourceEnum};
use axum::{http::StatusCode, response::Response};
use uuid::Uuid;
#[tokio::test]
async fn test_mutation_login_service() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let role_id = get_role_id("user", &app_state).await;
// Test data
let email = generate_unique_email("test_login_service");
let password = "password123".to_string();
// Create test user first
let user_schema = imphnen_iam::UsersSchema {
id: make_thing_from_enum(UtilsResourceEnum::Users, &Uuid::new_v4().to_string()),
email: email.clone(),
fullname: "Test User Service".to_string(),
password: imphnen_utils::hash_password(&password).unwrap(),
phone_number: Some("+1234567890".to_string()),
is_active: true,
role: role_id,
..Default::default()
};
let create_response = repo.query_create_user(user_schema).await;
assert!(create_response.is_ok());
// Try to login
let login_request = AuthLoginRequestDto {
email: email.clone(),
password: password.clone(),
};
let response = imphnen_iam::AuthService::mutation_login(login_request, &app_state).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
let login_response: ResponseSuccessDto = response.into_body().await.unwrap();
assert!(login_response.data.is_some());
// Clean up
let user = repo.query_user_by_email(email.clone()).await.unwrap();
let _ = repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_mutation_login_service_invalid_credentials() {
let app_state = crate::get_app_state().await;
// Test data
let email = generate_unique_email("test_login_invalid_service");
let password = "wrongpassword".to_string();
// Try to login with non-existent user
let login_request = AuthLoginRequestDto {
email: email.clone(),
password: password.clone(),
};
let response = imphnen_iam::AuthService::mutation_login(login_request, &app_state).await;
// Verify response
assert_eq!(response.status(), StatusCode::UNAUTHORIZED);
let error_response: MessageResponseDto = response.into_body().await.unwrap();
assert!(error_response.message.contains("Email or password not correct"));
}
#[tokio::test]
async fn test_mutation_register_service() {
let app_state = crate::get_app_state().await;
// Test data
let email = generate_unique_email("test_register_service");
let password = "password123".to_string();
let register_request = AuthRegisterRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test User Service".to_string(),
phone_number: Some("+1234567890".to_string()),
};
// Register user
let response = imphnen_iam::AuthService::mutation_register(register_request, &app_state).await;
// Verify response
assert_eq!(response.status(), StatusCode::CREATED);
let response_data: MessageResponseDto = response.into_body().await.unwrap();
assert_eq!(response_data.message, "User registered successfully, please check your email for OTP verification");
// Verify user was created in database (should be inactive until OTP verification)
let repo = UsersRepository::new(&app_state);
let created_user = repo.query_user_by_email(email.clone()).await.unwrap();
assert_eq!(created_user.email, email);
assert_eq!(created_user.is_active, false);
// Clean up
let _ = repo.query_delete_user(created_user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_mutation_verify_email_service() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
// Test data
let email = generate_unique_email("test_verify_email_service");
let password = "password123".to_string();
let register_request = AuthRegisterRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test User Service".to_string(),
phone_number: Some("+1234567890".to_string()),
};
// Register user first
let register_response = imphnen_iam::AuthService::mutation_register(register_request, &app_state).await;
assert_eq!(register_response.status(), StatusCode::CREATED);
// Verify email
let verify_request = AuthVerifyEmailRequestDto {
email: email.clone(),
otp: "123456".to_string(), // Default test OTP
};
let response = imphnen_iam::AuthService::mutation_verify_email(verify_request, &app_state).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
let response_data: MessageResponseDto = response.into_body().await.unwrap();
assert_eq!(response_data.message, "Email verified successfully");
// Verify user was activated in database
let updated_user = repo.query_user_by_email(email.clone()).await.unwrap();
assert_eq!(updated_user.is_active, true);
// Clean up
let _ = repo.query_delete_user(updated_user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_mutation_resend_otp_service() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
// Test data
let email = generate_unique_email("test_resend_otp_service");
let password = "password123".to_string();
let register_request = AuthRegisterRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test User Service".to_string(),
phone_number: Some("+1234567890".to_string()),
};
// Register user first
let register_response = imphnen_iam::AuthService::mutation_register(register_request, &app_state).await;
assert_eq!(register_response.status(), StatusCode::CREATED);
// Resend OTP
let resend_request = AuthResendOtpRequestDto {
email: email.clone(),
};
let response = imphnen_iam::AuthService::mutation_resend_otp(resend_request, &app_state).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
let response_data: MessageResponseDto = response.into_body().await.unwrap();
assert_eq!(response_data.message, "OTP resent successfully");
// Clean up
let user = repo.query_user_by_email(email.clone()).await.unwrap();
let _ = repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_mutation_forgot_password_service() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
// Test data
let email = generate_unique_email("test_forgot_password_service");
let password = "password123".to_string();
let register_request = AuthRegisterRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test User Service".to_string(),
phone_number: Some("+1234567890".to_string()),
};
// Register and verify user first
let register_response = imphnen_iam::AuthService::mutation_register(register_request, &app_state).await;
assert_eq!(register_response.status(), StatusCode::CREATED);
let verify_request = AuthVerifyEmailRequestDto {
email: email.clone(),
otp: "123456".to_string(),
};
let verify_response = imphnen_iam::AuthService::mutation_verify_email(verify_request, &app_state).await;
assert_eq!(verify_response.status(), StatusCode::OK);
// Forgot password
let forgot_request = AuthResendOtpRequestDto {
email: email.clone(),
};
let response = imphnen_iam::AuthService::mutation_forgot_password(forgot_request, &app_state).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
let response_data: MessageResponseDto = response.into_body().await.unwrap();
assert_eq!(
response_data.message,
"If your email is registered, you will receive a password reset link."
);
// Clean up
let user = repo.query_user_by_email(email.clone()).await.unwrap();
let _ = repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_mutation_new_password_service() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
// Test data
let email = generate_unique_email("test_new_password_service");
let old_password = "password123".to_string();
let new_password = "newpassword456".to_string();
// Register and verify user first
let register_request = AuthRegisterRequestDto {
email: email.clone(),
password: old_password.clone(),
fullname: "Test User Service".to_string(),
phone_number: Some("+1234567890".to_string()),
};
let register_response = imphnen_iam::AuthService::mutation_register(register_request, &app_state).await;
assert_eq!(register_response.status(), StatusCode::CREATED);
let verify_request = AuthVerifyEmailRequestDto {
email: email.clone(),
otp: "123456".to_string(),
};
let verify_response = imphnen_iam::AuthService::mutation_verify_email(verify_request, &app_state).await;
assert_eq!(verify_response.status(), StatusCode::OK);
// In a real test, we would extract the password reset token from the email, but for testing
// we'll simulate this by creating a reset token directly
let user = repo.query_user_by_email(email.clone()).await.unwrap();
let reset_token = imphnen_utils::encode_reset_password_token(user.email.clone(), user.id.id.to_raw()).unwrap();
// Set new password
let new_password_request = AuthNewPasswordRequestDto {
token: reset_token,
password: new_password.clone(),
};
let response = imphnen_iam::AuthService::mutation_new_password(new_password_request, &app_state).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
let response_data: MessageResponseDto = response.into_body().await.unwrap();
assert_eq!(response_data.message, "Password updated successfully");
// Verify password was updated in database
let updated_user = repo.query_user_by_email(email.clone()).await.unwrap();
let is_password_correct = imphnen_utils::verify_password(&new_password, &updated_user.password).unwrap();
assert!(is_password_correct);
// Clean up
let _ = repo.query_delete_user(updated_user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_mutation_refresh_token_service() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
// Test data
let email = generate_unique_email("test_refresh_token_service");
let password = "password123".to_string();
// Register and verify user first
let register_request = AuthRegisterRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test User Service".to_string(),
phone_number: Some("+1234567890".to_string()),
};
let register_response = imphnen_iam::AuthService::mutation_register(register_request, &app_state).await;
assert_eq!(register_response.status(), StatusCode::CREATED);
let verify_request = AuthVerifyEmailRequestDto {
email: email.clone(),
otp: "123456".to_string(),
};
let verify_response = imphnen_iam::AuthService::mutation_verify_email(verify_request, &app_state).await;
assert_eq!(verify_response.status(), StatusCode::OK);
// Login to get tokens
let login_request = AuthLoginRequestDto {
email: email.clone(),
password: password.clone(),
};
let login_response = imphnen_iam::AuthService::mutation_login(login_request, &app_state).await;
let login_response_data: ResponseSuccessDto = login_response.into_body().await.unwrap();
let refresh_token = login_response_data.data.as_ref().unwrap().token.refresh_token.clone();
// Refresh token
let refresh_request = AuthRefreshTokenRequestDto {
refresh_token: refresh_token,
};
let response = imphnen_iam::AuthService::mutation_refresh_token(refresh_request, &app_state).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
let response_data: ResponseSuccessDto = response.into_body().await.unwrap();
assert!(response_data.data.is_some());
let token_data = response_data.data.as_ref().unwrap();
assert!(token_data.access_token.is_some());
assert!(token_data.refresh_token.is_some());
// Clean up
let user = repo.query_user_by_email(email.clone()).await.unwrap();
let _ = repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_mutation_mentor_login_service() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let role_id = get_role_id("mentor", &app_state).await;
// Test data
let email = generate_unique_email("test_mentor_login_service");
let password = "password123".to_string();
// Create test mentor user first
let user_schema = imphnen_iam::UsersSchema {
id: make_thing_from_enum(UtilsResourceEnum::Users, &Uuid::new_v4().to_string()),
email: email.clone(),
fullname: "Test Mentor Service".to_string(),
password: imphnen_utils::hash_password(&password).unwrap(),
phone_number: Some("+1234567890".to_string()),
is_active: true,
role: role_id,
..Default::default()
};
let create_response = repo.query_create_user(user_schema).await;
assert!(create_response.is_ok());
// Try to login as mentor
let login_request = AuthLoginRequestDto {
email: email.clone(),
password: password.clone(),
};
let response = imphnen_iam::AuthService::mutation_mentor_login(login_request, &app_state).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
let login_response: ResponseSuccessDto = response.into_body().await.unwrap();
assert!(login_response.data.is_some());
// Clean up
let user = repo.query_user_by_email(email.clone()).await.unwrap();
let _ = repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_mutation_mentor_login_service_non_mentor() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let role_id = get_role_id("user", &app_state).await;
// Test data
let email = generate_unique_email("test_non_mentor_login_service");
let password = "password123".to_string();
// Create test user (not mentor) first
let user_schema = imphnen_iam::UsersSchema {
id: make_thing_from_enum(UtilsResourceEnum::Users, &Uuid::new_v4().to_string()),
email: email.clone(),
fullname: "Test User Service".to_string(),
password: imphnen_utils::hash_password(&password).unwrap(),
phone_number: Some("+1234567890".to_string()),
is_active: true,
role: role_id,
..Default::default()
};
let create_response = repo.query_create_user(user_schema).await;
assert!(create_response.is_ok());
// Try to login as mentor (should fail)
let login_request = AuthLoginRequestDto {
email: email.clone(),
password: password.clone(),
};
let response = imphnen_iam::AuthService::mutation_mentor_login(login_request, &app_state).await;
// Verify response
assert_eq!(response.status(), StatusCode::FORBIDDEN);
let error_response: MessageResponseDto = response.into_body().await.unwrap();
assert_eq!(error_response.message, "User does not have mentor privileges");
// Clean up
let user = repo.query_user_by_email(email.clone()).await.unwrap();
let _ = repo.query_delete_user(user.id.id.to_raw()).await;
}
}
+198 -212
View File
@@ -1,222 +1,208 @@
use crate::{create_test_user, mock_test::setup_all_test_environment};
use crate::{generate_unique_email, get_role_id, MetaRequestDto, UsersRepository}; // Import setup_all_test_environment from mock_test
#[cfg(test)]
mod tests {
use crate::{generate_unique_email, get_meta_request_dto, get_role_id, UsersRepository};
use imphnen_iam::{UsersSchema, ResourceEnum};
use imphnen_utils::{make_thing_from_enum, ResourceEnum as UtilsResourceEnum};
use uuid::Uuid;
#[tokio::test]
async fn test_create_and_get_user() {
let app_state = setup_all_test_environment().await; // Use centralized setup
let repo = UsersRepository::new(&app_state);
let email = generate_unique_email("testuser");
let user =
create_test_user(&email, "Test User", true, &get_role_id("user", &app_state).await);
let create_result = repo.query_create_user(user.clone()).await;
assert!(
create_result.is_ok(),
"Failed to create user: {:?}",
create_result.err()
);
let fetched = repo.query_user_by_email(email.clone()).await;
assert!(
fetched.is_ok(),
"Failed to fetch user by email: {:?}",
fetched.err()
);
assert_eq!(fetched.unwrap().email, email.clone());
}
#[tokio::test]
async fn test_query_create_user() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let role_id = get_role_id("user", &app_state).await;
#[tokio::test]
async fn test_query_user_list_with_pagination_and_filter() {
let app_state = setup_all_test_environment().await; // Use centralized setup
let repo = UsersRepository::new(&app_state);
for i in 0..10 {
let email = format!("user{i}@example.com");
let fullname = format!("User {i}");
let is_active = i % 2 == 0;
let user =
create_test_user(&email, &fullname, is_active, &get_role_id("user", &app_state).await);
let create_res = repo.query_create_user(user).await;
assert!(
create_res.is_ok(),
"Failed to create user: {:?}",
create_res.err()
);
// Test data
let email = generate_unique_email("test_create_user");
let user_schema = UsersSchema {
id: make_thing_from_enum(UtilsResourceEnum::Users, &Uuid::new_v4().to_string()),
email: email.clone(),
fullname: "Test User Create".to_string(),
password: "password123".to_string(),
phone_number: "+1234567890".to_string(),
is_active: true,
role: role_id,
..Default::default()
};
// Create user
let result = repo.query_create_user(user_schema.clone()).await;
assert!(result.is_ok());
// Verify user was created
let created_user_result = repo.query_user_by_email(email.clone()).await;
assert!(created_user_result.is_ok());
let created_user = created_user_result.as_ref().unwrap();
assert_eq!(created_user.email, email);
// Clean up
let user = created_user_result.unwrap();
let _ = repo.query_delete_user(user.id.id.to_raw()).await;
}
let meta = MetaRequestDto {
page: Some(1),
per_page: Some(5),
search: None,
sort_by: Some("email".into()),
order: Some("ASC".into()),
filter: Some("true".into()),
filter_by: Some("is_active".into()),
};
let result = repo.query_user_list(meta).await;
assert!(
result.is_ok(),
"Failed to query user list: {:?}",
result.err()
);
let result = result.unwrap();
assert!(result.data.len() <= 5);
assert!(result.data.iter().all(|u| u.is_active));
assert!(
result
.meta
.as_ref()
.map(|m| m.total.is_some())
.unwrap_or(false),
"Meta total should be Some"
);
}
#[tokio::test]
async fn test_query_user_list_basic() {
let app_state = setup_all_test_environment().await; // Use centralized setup
let repo = UsersRepository::new(&app_state);
for i in 0..10 {
let email = format!("basic{i}@example.com");
let user = create_test_user(
&email,
&format!("Basic User {i}"),
true,
&get_role_id("user", &app_state).await,
);
let create_res = repo.query_create_user(user).await;
assert!(
create_res.is_ok(),
"Failed to create user: {:?}",
create_res.err()
);
#[tokio::test]
async fn test_query_user_by_email() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let role_id = get_role_id("user", &app_state).await;
// Test data
let email = generate_unique_email("test_get_by_email");
let user_schema = UsersSchema {
id: make_thing_from_enum(UtilsResourceEnum::Users, &Uuid::new_v4().to_string()),
email: email.clone(),
fullname: "Test User Email".to_string(),
password: "password123".to_string(),
phone_number: "+1234567890".to_string(),
is_active: true,
role: role_id,
..Default::default()
};
// Create user first
let create_result = repo.query_create_user(user_schema.clone()).await;
assert!(create_result.is_ok());
// Get user by email
let result = repo.query_user_by_email(email.clone()).await;
assert!(result.is_ok());
let user = result.as_ref().unwrap();
assert_eq!(user.email, email);
// Clean up
let user = result.unwrap();
let _ = repo.query_delete_user(user.id.id.to_raw()).await;
}
let meta = MetaRequestDto {
page: Some(1),
per_page: Some(5),
search: None,
sort_by: None,
order: None,
filter: None,
filter_by: None,
};
let result = repo.query_user_list(meta).await;
assert!(
result.is_ok(),
"Failed to query user list: {:?}",
result.err()
);
let result = result.unwrap();
assert!(
result.meta.as_ref().and_then(|m| m.total).unwrap_or(0) >= 1,
"Meta total should be >= 1"
);
assert_eq!(
result.meta.as_ref().and_then(|m| m.page).unwrap_or(0),
1,
"Meta page should be 1"
);
assert_eq!(
result.meta.as_ref().and_then(|m| m.per_page).unwrap_or(0),
5,
"Meta per_page should be 5"
);
}
#[tokio::test]
async fn test_query_delete_user() {
let app_state = setup_all_test_environment().await; // Use centralized setup
let repo = UsersRepository::new(&app_state);
let email = &generate_unique_email("deleteuser");
let user =
create_test_user(email, "Delete User", true, &get_role_id("user", &app_state).await);
let create_res = repo.query_create_user(user.clone()).await;
assert!(
create_res.is_ok(),
"Failed to create user: {:?}",
create_res.err()
);
let user_detail = repo.query_user_by_email(email.to_string().clone()).await;
assert!(
user_detail.is_ok(),
"Failed to fetch user by email: {:?}",
user_detail.err()
);
let user_detail = user_detail.unwrap();
let delete_result = repo
.query_delete_user(user_detail.id.id.to_raw().clone())
.await;
assert!(
delete_result.is_ok(),
"Failed to delete user: {:?}",
delete_result.err()
);
let fetch_result = repo.query_user_by_email(user_detail.email.clone()).await;
assert!(
fetch_result.is_err(),
"User should be deleted, but got: {fetch_result:?}"
);
}
#[tokio::test]
async fn test_query_user_by_email_not_found() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
#[tokio::test]
async fn test_delete_non_existent_user_should_fail() {
let app_state = setup_all_test_environment().await; // Use centralized setup
let repo = UsersRepository::new(&app_state);
let result = repo.query_delete_user("lklklklk".to_string()).await;
assert!(result.is_err(), "Delete non-existent user should fail");
assert_eq!(
result.unwrap_err().to_string(),
"User not found in database"
);
}
// Try to get non-existent user
let result = repo.query_user_by_email("nonexistent@example.com".to_string()).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_delete_user_twice_should_fail_on_second_attempt() {
let app_state = setup_all_test_environment().await; // Use centralized setup
let repo = UsersRepository::new(&app_state);
let email = "twice@example.com";
let user =
create_test_user(email, "Delete Twice", true, &get_role_id("user", &app_state).await);
let create_res = repo.query_create_user(user.clone()).await;
assert!(
create_res.is_ok(),
"Failed to create user: {:?}",
create_res.err()
);
let first = repo.query_delete_user(user.id.id.to_raw()).await;
assert!(
first.is_ok(),
"First delete should succeed: {:?}",
first.err()
);
let second = repo.query_delete_user(user.id.id.to_raw()).await;
assert!(second.is_err(), "Second delete should fail");
assert_eq!(second.unwrap_err().to_string(), "User not found");
}
#[tokio::test]
async fn test_query_update_user() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let role_id = get_role_id("user", &app_state).await;
#[tokio::test]
async fn test_query_update_user_should_succeed() {
let state = setup_all_test_environment().await; // Use centralized setup
let repo = UsersRepository::new(&state);
let mut user = create_test_user(
"update@example.com",
"Old Name",
true,
&get_role_id("user", &state).await,
);
let create_res = repo.query_create_user(user.clone()).await;
assert!(
create_res.is_ok(),
"Failed to create user: {:?}",
create_res.err()
);
user.fullname = "Updated Name".into();
user.phone_number = "089876543210".into();
let result = repo.query_update_user(user.clone()).await;
assert!(result.is_ok(), "Update failed: {:?}", result.err());
let updated = repo.query_user_by_id(&user.id).await;
assert!(
updated.is_ok(),
"Failed to fetch updated user: {:?}",
updated.err()
);
let updated = updated.unwrap();
assert_eq!(updated.fullname, "Updated Name");
assert_eq!(updated.phone_number, "089876543210");
// Test data
let email = generate_unique_email("test_update_user");
let user_schema = UsersSchema {
id: make_thing_from_enum(UtilsResourceEnum::Users, &Uuid::new_v4().to_string()),
email: email.clone(),
fullname: "Original Name".to_string(),
password: "password123".to_string(),
phone_number: "+1234567890".to_string(),
is_active: true,
role: role_id,
..Default::default()
};
// Create user first
let create_result = repo.query_create_user(user_schema.clone()).await;
assert!(create_result.is_ok());
// Get user to update
let user = repo.query_user_by_email(email.clone()).await.unwrap();
// Update user
let updated_schema = UsersSchema {
id: user.id.clone(),
email: user.email.clone(),
fullname: "Updated Name".to_string(),
phone_number: "+9876543210".to_string(),
role: user.role.id.clone(),
..Default::default()
};
let result = repo.query_update_user(updated_schema).await;
assert!(result.is_ok());
// Verify user was updated
let retrieved_user = repo.query_user_by_email(email.clone()).await.unwrap();
assert_eq!(retrieved_user.fullname, "Updated Name");
assert_eq!(retrieved_user.phone_number, "+9876543210");
// Clean up
let _ = repo.query_delete_user(retrieved_user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_query_delete_user() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let role_id = get_role_id("user", &app_state).await;
// Test data
let email = generate_unique_email("test_delete_user");
let user_schema = UsersSchema {
id: make_thing_from_enum(UtilsResourceEnum::Users, &Uuid::new_v4().to_string()),
email: email.clone(),
fullname: "Test User Delete".to_string(),
password: "password123".to_string(),
phone_number: "+1234567890".to_string(),
is_active: true,
role: role_id,
..Default::default()
};
// Create user first
let create_result = repo.query_create_user(user_schema.clone()).await;
assert!(create_result.is_ok());
// Get user to delete
let user = repo.query_user_by_email(email.clone()).await.unwrap();
// Delete user
let result = repo.query_delete_user(user.id.id.to_raw()).await;
assert!(result.is_ok());
// Verify user was deleted
let deleted_user = repo.query_user_by_email(email.clone()).await;
assert!(deleted_user.is_err());
}
#[tokio::test]
async fn test_query_user_list() {
let app_state = crate::get_app_state().await;
let repo = UsersRepository::new(&app_state);
let role_id = get_role_id("user", &app_state).await;
// Create test users
let user_emails = vec![
generate_unique_email("user_list_1"),
generate_unique_email("user_list_2"),
generate_unique_email("user_list_3"),
];
for email in &user_emails {
let user_schema = UsersSchema {
id: make_thing_from_enum(UtilsResourceEnum::Users, &Uuid::new_v4().to_string()),
email: email.clone(),
fullname: format!("Test User {}", email),
password: "password123".to_string(),
phone_number: "+1234567890".to_string(),
is_active: true,
role: role_id.clone(),
..Default::default()
};
let _ = repo.query_create_user(user_schema).await;
}
// Get user list
let meta = crate::get_meta_request_dto(1, 10);
let result = repo.query_user_list(meta).await;
assert!(result.is_ok());
assert!(result.unwrap().data.len() >= 3);
// Clean up
for email in user_emails {
let user = repo.query_user_by_email(email).await.unwrap();
let _ = repo.query_delete_user(user.id.id.to_raw()).await;
}
}
}
+227
View File
@@ -0,0 +1,227 @@
#[cfg(test)]
mod tests {
use crate::{generate_unique_email, get_role_id, UsersRepository, setup_all_test_environment};
use axum::{http::StatusCode, response::Response};
use imphnen_entities::{AppState, MetaRequestDto};
use imphnen_iam::{
users_dto::{UserCreateRequestDto, UserUpdateRequestDto},
users_service::UsersService,
UsersRepository
};
use imphnen_utils::{hash_password, make_thing_from_enum};
use surrealdb::Uuid;
#[tokio::test]
async fn test_create_user_service() {
let app_state = setup_all_test_environment().await;
let user_repo = UsersRepository::new(&app_state);
let role_repo = imphnen_iam::RolesRepository::new(&app_state);
// Test data
let email = generate_unique_email("test_create_user");
let password = "Password123!".to_string();
let hashed_password = hash_password(&password).await.unwrap();
let user_dto = UserCreateRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test User Service".to_string(),
phone_number: Some("1234567890".to_string()),
role_id: get_role_id(&app_state, "user").await.unwrap(),
};
// Create user
let response = UsersService::create_user(&app_state, user_dto.clone()).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Verify user was created in database
let created_user = user_repo.query_user_by_email(email.clone()).await;
assert!(created_user.is_ok());
assert_eq!(created_user.unwrap().email, email);
assert_eq!(created_user.unwrap().fullname, "Test User Service".to_string());
// Clean up
let user = created_user.unwrap();
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_get_user_list_service() {
let app_state = setup_all_test_environment().await;
let user_repo = UsersRepository::new(&app_state);
// Create test user first
let email = generate_unique_email("test_user_list");
let password = "Password123!".to_string();
let user_dto = UserCreateRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test User List".to_string(),
phone_number: Some("1234567890".to_string()),
role_id: get_role_id(&app_state, "user").await.unwrap(),
};
let _ = UsersService::create_user(&app_state, user_dto).await;
// Get user list
let meta = MetaRequestDto {
limit: 10,
page: 1,
search: None,
sort: None,
filter: None,
};
let response = UsersService::get_user_list(&app_state, meta).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Clean up
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_get_user_by_id_service() {
let app_state = setup_all_test_environment().await;
let user_repo = UsersRepository::new(&app_state);
// Create test user first
let email = generate_unique_email("test_user_by_id");
let password = "Password123!".to_string();
let user_dto = UserCreateRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test User By ID".to_string(),
phone_number: Some("1234567890".to_string()),
role_id: get_role_id(&app_state, "user").await.unwrap(),
};
let _ = UsersService::create_user(&app_state, user_dto).await;
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
let user_id = user.id.id.to_raw();
// Get user by ID
let response = UsersService::get_user_by_id(&app_state, user_id).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Clean up
let _ = user_repo.query_delete_user(user_id).await;
}
#[tokio::test]
async fn test_update_user_service() {
let app_state = setup_all_test_environment().await;
let user_repo = UsersRepository::new(&app_state);
// Create test user first
let email = generate_unique_email("test_update_user");
let password = "Password123!".to_string();
let user_dto = UserCreateRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test User Update".to_string(),
phone_number: Some("1234567890".to_string()),
role_id: get_role_id(&app_state, "user").await.unwrap(),
};
let _ = UsersService::create_user(&app_state, user_dto).await;
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
let user_id = user.id.id.to_raw();
// Prepare update request
let update_dto = UserUpdateRequestDto {
fullname: Some("Updated Test User".to_string()),
phone_number: Some("0987654321".to_string()),
is_active: Some(true),
};
// Update user
let response = UsersService::update_user(&app_state, user_id, update_dto).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Verify user was updated
let updated_user = user_repo.query_user_by_id(&user.id, false).await.unwrap();
assert_eq!(updated_user.fullname, "Updated Test User".to_string());
assert_eq!(updated_user.phone_number, Some("0987654321".to_string()));
assert_eq!(updated_user.is_active, true);
// Clean up
let _ = user_repo.query_delete_user(user_id).await;
}
#[tokio::test]
async fn test_delete_user_service() {
let app_state = setup_all_test_environment().await;
let user_repo = UsersRepository::new(&app_state);
// Create test user first
let email = generate_unique_email("test_delete_user");
let password = "Password123!".to_string();
let user_dto = UserCreateRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test User Delete".to_string(),
phone_number: Some("1234567890".to_string()),
role_id: get_role_id(&app_state, "user").await.unwrap(),
};
let _ = UsersService::create_user(&app_state, user_dto).await;
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
let user_id = user.id.id.to_raw();
// Delete user
let response = UsersService::delete_user(&app_state, user_id).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Verify user was deleted
let deleted_user = user_repo.query_user_by_email(email.clone()).await;
assert!(deleted_user.is_err());
}
#[tokio::test]
async fn test_get_user_by_email_service() {
let app_state = setup_all_test_environment().await;
let user_repo = UsersRepository::new(&app_state);
// Create test user first
let email = generate_unique_email("test_user_by_email");
let password = "Password123!".to_string();
let user_dto = UserCreateRequestDto {
email: email.clone(),
password: password.clone(),
fullname: "Test User By Email".to_string(),
phone_number: Some("1234567890".to_string()),
role_id: get_role_id(&app_state, "user").await.unwrap(),
};
let _ = UsersService::create_user(&app_state, user_dto).await;
// Get user by email
let response = UsersService::get_user_by_email(&app_state, email.clone()).await;
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Clean up
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
}
}
+12
View File
@@ -99,3 +99,15 @@ pub async fn setup() {
.unwrap();
seed_users_for_test(&app_state.surrealdb_ws).await.unwrap();
}
pub fn get_meta_request_dto(page: u64, per_page: u64) -> imphnen_entities::MetaRequestDto {
imphnen_entities::MetaRequestDto {
page: Some(page),
per_page: Some(per_page),
search: None,
sort_by: None,
order: None,
filter: None,
filter_by: None,
}
}