Refactor tests to enhance response validation and error handling

- Updated gacha claims service tests to parse and verify error JSON content for various scenarios.
- Improved gacha credits controller tests by adding checks for success messages in JSON responses.
- Enhanced gacha items service tests to validate response data structure and content.
- Modified IAM auth controller and service tests to ensure token data integrity and presence of required fields.
- Refined permissions controller and service tests to assert response data correctness.
- Improved roles controller and service tests to validate response data and ensure non-empty fields.
- Enhanced teams controller tests to verify sensitive data exposure and required fields in responses.
- Updated users controller and service tests to ensure response data integrity and presence of required fields.
This commit is contained in:
MythEclipse
2025-10-05 17:05:06 +07:00
parent 9cecc8fa05
commit 49abcf28c3
19 changed files with 351 additions and 122 deletions
+4 -3
View File
@@ -116,7 +116,7 @@ impl<'a> RolesRepository<'a> {
pub async fn query_create_role(
&self,
payload: RolesRequestCreateDto,
) -> Result<String> {
) -> Result<RolesDetailItemDto> {
let now = Instant::now();
let db = &self.state.surrealdb_ws;
let role_id = Uuid::new_v4().to_string();
@@ -134,7 +134,7 @@ impl<'a> RolesRepository<'a> {
updated_at: Some(crate::get_iso_date()),
};
let _: Option<RolesSchema> = db
.create((&ResourceEnum::Roles.to_string(), role_id))
.create((&ResourceEnum::Roles.to_string(), role_id.clone()))
.content(role)
.await?;
let elapsed = now.elapsed();
@@ -143,7 +143,8 @@ impl<'a> RolesRepository<'a> {
{
println!("Query 'query_create_role' took: {elapsed:.2?}");
}
Ok("Role with permissions created successfully".into())
// After successful creation, fetch the created role
self.query_role_by_id(role_id).await
}
#[instrument(skip(self, id, data), err)]
+2 -1
View File
@@ -3,6 +3,7 @@ use crate::{
AppState, MetaRequestDto, ResponseListSuccessDto, ResponseSuccessDto,
common_response, success_list_response, success_response, validate_request,
};
use imphnen_utils::success_created_response;
use axum::{http::StatusCode, response::Response};
pub struct RolesService;
@@ -48,7 +49,7 @@ impl RolesService {
}
}
match repo.query_create_role(payload).await {
Ok(msg) => common_response(StatusCode::CREATED, &msg),
Ok(created_role) => success_created_response(ResponseSuccessDto { data: created_role }),
Err(e) => common_response(StatusCode::INTERNAL_SERVER_ERROR, &e.to_string()),
}
}
+1 -1
View File
@@ -247,7 +247,7 @@ impl UsersSchema {
password,
phone_number: user.phone_number,
phone_for_verification: None,
is_active: false,
is_active: user.is_active,
mentor_id: None, // Regular users should not have a mentor_id by default
gender: None,
birthdate: None,
+11 -4
View File
@@ -5,11 +5,10 @@ use super::{
use imphnen_entities::UsersDetailQueryDto;
use crate::{
AppState, MetaRequestDto, ResponseListSuccessDto, UsersRepository, UsersSchema,
};
use crate::{
ResponseSuccessDto, common_response, success_list_response,
success_response, validate_request,
};
use imphnen_utils::success_created_response;
use axum::{http::StatusCode, response::Response, extract::Multipart};
use imphnen_libs::{ResourceEnum, hash_password, verify_password, MinioConfig, FileType, decode_base64_file, extract_content_type_from_data_url, create_minio_service_from_config};
use imphnen_utils::make_thing_from_enum;
@@ -130,8 +129,16 @@ pub trait UsersServiceTrait: Send + Sync + 'static {
{
return common_response(StatusCode::BAD_REQUEST, "User already exists");
}
match repo.query_create_user(UsersSchema::create(new_user)).await {
Ok(msg) => common_response(StatusCode::CREATED, &msg),
match repo.query_create_user(UsersSchema::create(new_user.clone())).await {
Ok(_msg) => {
// After successful creation, fetch the created user
match repo.query_user_by_email(new_user.email).await {
Ok(created_user) => success_created_response(ResponseSuccessDto {
data: UserDto::from(&created_user),
}),
Err(e) => common_response(StatusCode::INTERNAL_SERVER_ERROR, &e.to_string()),
}
}
Err(err) => {
common_response(StatusCode::INTERNAL_SERVER_ERROR, &err.to_string())
}
@@ -6,7 +6,8 @@ mod tests {
mentors_service::MentorsService,
mentors_dto::{
MentorUserRegisterRequestDto, MentorUpdateRequestDto, MentorVerifyRequestDto,
IdentityAndVerification, ProfessionalProfile, MentoringLogistics
IdentityAndVerification, ProfessionalProfile, MentoringLogistics,
MentorRegisterResponseDto, MentorListResponseDto, MentorDetailResponseDto
},
MentorsRepository
};
@@ -67,6 +68,13 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Parse and verify JSON response
let mentor_response: MentorRegisterResponseDto = response.json().await.unwrap();
assert!(!mentor_response.id.is_empty(), "Response ID should not be empty");
assert_eq!(mentor_response.status, "pending", "Expected mentor status to be 'pending'");
assert!(!mentor_response.created_at.is_empty(), "Created at should not be empty");
assert!(!mentor_response.updated_at.is_empty(), "Updated at should not be empty");
// Verify mentor was created in database
let mentor = mentor_repo.query_mentor_by_email(email.clone(), false).await;
@@ -143,6 +151,16 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Parse and verify JSON response
let mentor_list: Vec<MentorListResponseDto> = response.json().await.unwrap();
assert!(!mentor_list.is_empty(), "Mentor list should not be empty");
let mentor = &mentor_list[0];
assert!(!mentor.id.is_empty(), "Mentor ID should not be empty");
assert_eq!(mentor.status, "pending", "Expected mentor status to be 'pending'");
assert!(!mentor.created_at.is_empty(), "Created at should not be empty");
assert!(!mentor.updated_at.is_empty(), "Updated at should not be empty");
// Clean up
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
@@ -205,6 +223,15 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Parse and verify JSON response
let mentor_response: MentorDetailResponseDto = response.json().await.unwrap();
assert!(!mentor_response.id.is_empty(), "Mentor ID should not be empty");
assert!(!mentor_response.user_id.is_empty(), "User ID should not be empty");
assert_eq!(mentor_response.status, "pending", "Expected mentor status to be 'pending'");
assert!(!mentor_response.created_at.is_empty(), "Created at should not be empty");
assert!(!mentor_response.updated_at.is_empty(), "Updated at should not be empty");
assert_eq!(mentor_response.current_role, "Senior Engineer", "Expected current role to be 'Senior Engineer'");
// Clean up
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
@@ -291,6 +318,14 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Parse and verify JSON response
let mentor_response: MentorDetailResponseDto = response.json().await.unwrap();
assert!(!mentor_response.id.is_empty(), "Mentor ID should not be empty");
assert!(!mentor_response.user_id.is_empty(), "User ID should not be empty");
assert_eq!(mentor_response.status, "pending", "Expected mentor status to be 'pending'");
assert_eq!(mentor_response.current_role, "Lead Engineer", "Expected current role to be 'Lead Engineer' after update");
assert_eq!(mentor_response.legal_name, Some("Updated Legal Name".to_string()), "Expected legal name to be updated");
// Verify mentor was updated
let updated_mentor = mentor_repo.query_mentor_by_id(&mentor.id, false).await.unwrap();
@@ -423,6 +458,11 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Parse and verify JSON response
let mentor_response: MentorDetailResponseDto = response.json().await.unwrap();
assert!(!mentor_response.id.is_empty(), "Mentor ID should not be empty");
assert_eq!(mentor_response.status, "verified", "Expected mentor status to be 'verified'");
// Verify mentor was verified
let updated_mentor = mentor_repo.query_mentor_by_id(&mentor.id, false).await.unwrap();
@@ -441,6 +481,10 @@ mod tests {
// Should return forbidden (mentor profile not found)
assert_eq!(response.status(), StatusCode::FORBIDDEN);
// Verify error response structure
let error_response: serde_json::Value = response.json().await.unwrap();
assert!(error_response.is_object(), "Error response should be an object");
}
#[tokio::test]
@@ -457,6 +501,10 @@ mod tests {
// Should return forbidden
assert_eq!(response.status(), StatusCode::FORBIDDEN);
// Verify error response structure
let error_response: serde_json::Value = response.json().await.unwrap();
assert!(error_response.is_object(), "Error response should be an object");
}
#[tokio::test]
@@ -479,6 +527,14 @@ mod tests {
// Should return not found
assert_eq!(response.status(), StatusCode::NOT_FOUND);
// Verify error response structure
let error_response: serde_json::Value = response.json().await.unwrap();
assert!(error_response.is_object(), "Error response should be an object");
// Verify error response structure
let error_response: serde_json::Value = response.json().await.unwrap();
assert!(error_response.is_object(), "Error response should be an object");
}
#[tokio::test]
@@ -741,6 +797,11 @@ mod tests {
let response = MentorsService::register_mentor(&app_state, mentor_dto).await;
assert_eq!(response.status(), StatusCode::OK);
// Parse and verify JSON response
let mentor_response: MentorRegisterResponseDto = response.json().await.unwrap();
assert!(!mentor_response.id.is_empty(), "Response ID should not be empty");
assert_eq!(mentor_response.status, "pending", "Expected mentor status to be 'pending'");
// Clean up
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
@@ -792,6 +853,13 @@ mod tests {
let response = MentorsService::register_mentor(&app_state, mentor_dto).await;
assert_eq!(response.status(), StatusCode::OK);
// Parse and verify JSON response
let mentor_response: MentorDetailResponseDto = response.json().await.unwrap();
assert!(!mentor_response.id.is_empty(), "Mentor ID should not be empty");
assert!(!mentor_response.user_id.is_empty(), "User ID should not be empty");
assert_eq!(mentor_response.legal_name, Some("Updated Name".to_string()), "Expected legal name to be updated");
assert_eq!(mentor_response.current_role, "Lead Engineer".to_string(), "Expected current role to be updated");
// Clean up
let user = user_repo.query_user_by_email(email.clone()).await.unwrap();
+19 -2
View File
@@ -2,13 +2,14 @@
mod tests {
use crate::{generate_unique_email, get_role_id, setup_all_test_environment, UsersRepository};
use axum::http::StatusCode;
use imphnen_entities::AppState;
use imphnen_entities::{AppState, ResponseSuccessDto};
use imphnen_gacha::v1::gacha_claims::gacha_claims_service::GachaClaimService;
use imphnen_gacha::v1::gacha_claims::gacha_claims_dto::GachaClaimRequestDto;
use imphnen_gacha::v1::gacha_claims::gacha_claims_dto::{GachaClaimItemDto, GachaClaimRequestDto};
use imphnen_gacha::v1::gacha_items::gacha_items_service::GachaItemService;
use imphnen_gacha::v1::gacha_items::gacha_items_dto::GachaItemRequestDto;
use imphnen_gacha::GachaClaimRepository;
use imphnen_iam::users_service::UsersService;
use serde_json::json;
#[tokio::test]
async fn test_get_gacha_claim_by_id_service() {
@@ -47,6 +48,10 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::NOT_FOUND);
// Parse and verify error JSON content
let response_body: serde_json::Value = response.json().await.unwrap();
assert!(response_body["message"].is_string(), "Error message should be a string");
// Clean up
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
@@ -88,6 +93,10 @@ mod tests {
// Since item doesn't exist, it should fail
assert_eq!(response.status(), StatusCode::INTERNAL_SERVER_ERROR);
// Parse and verify error JSON content
let response_body: serde_json::Value = response.json().await.unwrap();
assert!(response_body["message"].is_string(), "Error message should be a string");
// Clean up
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
@@ -107,6 +116,14 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
// Parse and verify error JSON content
let response_body: serde_json::Value = response.json().await.unwrap();
assert!(response_body["message"].is_string(), "Error message should be a string");
// Parse and verify error JSON content
let response_body: serde_json::Value = response.json().await.unwrap();
assert!(response_body["message"].is_string(), "Error message should be a string");
}
#[tokio::test]
@@ -2,11 +2,12 @@
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_entities::{AppState, MetaRequestDto, ResponseSuccessDto, ResponseListSuccessDto};
use imphnen_gacha::{
gacha_credits_controller::GachaCreditsController,
gacha_credits_dto::{GachaCreditsCreateRequestDto, GachaCreditsUpdateRequestDto},
};
use serde_json::json;
use imphnen_iam::users_service::UsersService;
use imphnen_utils::{generate_otp, hash_password, make_thing_from_enum, get_iso_date};
use surrealdb::Uuid;
@@ -45,6 +46,10 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Parse and verify JSON content
let response_body: serde_json::Value = response.json().await.unwrap();
assert!(response_body["message"].is_string(), "Success message should be a string");
// Clean up
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
@@ -94,6 +99,10 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Parse and verify JSON content
let response_body: ResponseListSuccessDto<serde_json::Value> = response.json().await.unwrap();
assert!(!response_body.data.is_null(), "Response data should not be null");
// Clean up
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
@@ -138,6 +147,10 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Parse and verify JSON content
let response_body: ResponseSuccessDto<serde_json::Value> = response.json().await.unwrap();
assert!(!response_body.data.is_null(), "Response data should not be null");
// Clean up
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
@@ -189,6 +202,18 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Parse and verify JSON content
let response_body: serde_json::Value = response.json().await.unwrap();
assert!(response_body["message"].is_string(), "Success message should be a string");
// Parse and verify JSON content
let response_body: serde_json::Value = response.json().await.unwrap();
assert!(response_body["message"].is_string(), "Success message should be a string");
// Parse and verify JSON content
let response_body: serde_json::Value = response.json().await.unwrap();
assert!(response_body["message"].is_string(), "Success message should be a string");
// Clean up
let _ = user_repo.query_delete_user(user.id.id.to_raw()).await;
+48 -1
View File
@@ -2,9 +2,10 @@
mod tests {
use crate::setup_all_test_environment;
use axum::http::StatusCode;
use imphnen_entities::{AppState, MetaRequestDto};
use imphnen_entities::{AppState, MetaRequestDto, ResponseSuccessDto, ResponseListSuccessDto};
use imphnen_gacha::v1::gacha_items::gacha_items_service::GachaItemService;
use imphnen_gacha::v1::gacha_items::gacha_items_dto::{GachaItemRequestDto, GachaItemUpdateRequestDto};
use imphnen_gacha::v1::gacha_items::gacha_items_dto::GachaItemDto;
use imphnen_gacha::GachaItemRepository;
#[tokio::test]
@@ -32,6 +33,12 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Parse and verify JSON content
let response_body: ResponseListSuccessDto<Vec<GachaItemDto>> = response.json().await.unwrap();
assert!(!response_body.data.is_empty(), "Response data should not be empty");
assert!(response_body.data.iter().any(|item| item.name == "Test Item List"), "Expected item not found in response");
assert!(response_body.data.iter().all(|item| !item.id.is_empty() && !item.name.is_empty()), "Required fields should not be empty");
// Clean up
let items = item_repo.query_gacha_item_list(MetaRequestDto::default()).await.unwrap().data;
@@ -58,6 +65,12 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Parse and verify JSON content
let response_body: ResponseSuccessDto<GachaItemDto> = response.json().await.unwrap();
assert!(!response_body.data.id.is_empty(), "ID should not be empty");
assert_eq!(response_body.data.name, "Test Item By ID", "Item name should match");
assert!(!response_body.data.is_deleted, "Item should not be deleted");
// Clean up
let _ = item_repo.query_delete_gacha_item(item.id.id.to_raw()).await;
@@ -72,6 +85,10 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::NOT_FOUND);
// Parse and verify error JSON content
let response_body: serde_json::Value = response.json().await.unwrap();
assert!(response_body["message"].is_string(), "Error message should be a string");
}
#[tokio::test]
@@ -90,6 +107,10 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::CREATED);
// Parse and verify JSON content
let response_body: serde_json::Value = response.json().await.unwrap();
assert!(response_body["message"].is_string(), "Success message should be a string");
// Verify item was created
let items = item_repo.query_gacha_item_list(MetaRequestDto::default()).await.unwrap().data;
@@ -115,6 +136,14 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
// Parse and verify error JSON content
let response_body: serde_json::Value = response.json().await.unwrap();
assert!(response_body["message"].is_string(), "Error message should be a string");
// Parse and verify error JSON content
let response_body: serde_json::Value = response.json().await.unwrap();
assert!(response_body["message"].is_string(), "Error message should be a string");
}
#[tokio::test]
@@ -156,6 +185,12 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Parse and verify JSON content
let response_body: ResponseSuccessDto<GachaItemDto> = response.json().await.unwrap();
assert!(!response_body.data.id.is_empty(), "ID should not be empty");
assert_eq!(response_body.data.name, "Updated Test Item", "Updated item name should match");
assert_eq!(response_body.data.image_url, "https://example.com/updated.png", "Updated image URL should match");
// Verify item was updated
let updated_item = item_repo.query_gacha_item_by_id(item.id.id.to_raw()).await.unwrap();
@@ -179,6 +214,14 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::NOT_FOUND);
// Parse and verify error JSON content
let response_body: serde_json::Value = response.json().await.unwrap();
assert!(response_body["message"].is_string(), "Error message should be a string");
// Parse and verify error JSON content
let response_body: serde_json::Value = response.json().await.unwrap();
assert!(response_body["message"].is_string(), "Error message should be a string");
}
#[tokio::test]
@@ -204,6 +247,10 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
// Parse and verify error JSON content
let response_body: serde_json::Value = response.json().await.unwrap();
assert!(response_body["message"].is_string(), "Error message should be a string");
// Clean up
let _ = item_repo.query_delete_gacha_item(item.id.id.to_raw()).await;
+7 -2
View File
@@ -67,9 +67,14 @@ mod tests {
let login_response: ResponseSuccessDto = crate::common::response_helpers::parse_response(response, 8192).await;
let data_val = login_response.data.expect("login should return data");
// Try to deserialize token structure
// Parse and verify token data
let token_obj: TokenDto = serde_json::from_value(data_val).expect("login data must be TokenDto");
assert!(!token_obj.access_token.is_empty(), "access_token must be present");
assert!(!token_obj.access_token.is_empty(), "access_token must be present and non-empty");
assert!(!token_obj.refresh_token.is_empty(), "refresh_token must be present and non-empty");
assert!(!token_obj.user.id.is_empty(), "user id must be present and non-empty");
assert_eq!(token_obj.user.email, email, "user email must match login email");
assert_eq!(token_obj.user.fullname, "Test User Controller", "user fullname must match registered user");
// Clean up
let user = repo.query_user_by_email(email.clone()).await.unwrap();
+11 -4
View File
@@ -47,7 +47,11 @@ mod tests {
assert_eq!(response.status(), StatusCode::OK);
let login_response: ResponseSuccessDto = crate::common::response_helpers::parse_response(response, 8192).await;
assert!(login_response.data.is_some());
assert!(login_response.data.is_some(), "Login response must contain data");
let token_data: TokenDto = serde_json::from_value(login_response.data.clone().unwrap()).expect("Login data must be TokenDto");
assert!(!token_data.access_token.is_empty(), "Access token must be present");
assert!(!token_data.refresh_token.is_empty(), "Refresh token must be present");
// Clean up
let user = repo.query_user_by_email(email.clone()).await.unwrap();
@@ -103,8 +107,10 @@ mod tests {
// 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);
assert_eq!(created_user.email, email, "Registered user email must match");
assert_eq!(created_user.fullname, "Test User Service", "Registered user fullname must match");
assert_eq!(created_user.is_active, false, "Registered user should be inactive until verification");
assert!(!created_user.id.id.to_raw().is_empty(), "Registered user must have non-empty id");
// Clean up
let _ = repo.query_delete_user(created_user.id.id.to_raw()).await;
@@ -145,7 +151,8 @@ mod tests {
// 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);
assert_eq!(updated_user.is_active, true, "User should be activated after verification");
assert_eq!(updated_user.email, email, "User email should remain unchanged");
// Clean up
let _ = repo.query_delete_user(updated_user.id.id.to_raw()).await;
@@ -29,19 +29,20 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::CREATED);
// Verify response body contains success message
let msg: imphnen_entities::MessageResponseDto =
// Verify response body contains permission data
let created_permission: PermissionsSchema =
crate::common::response_helpers::parse_response(response, 1024).await;
assert!(msg.message.to_lowercase().contains("created") || msg.message.to_lowercase().contains("success"));
assert!(!created_permission.id.id.to_raw().is_empty(), "Created permission must have non-empty id");
assert_eq!(created_permission.name, permission_name, "Created permission name must match request");
// Verify permission was created in database
let created_permission = repo
let db_permission = repo
.query_permission_by_name(permission_name)
.await
.unwrap();
assert_eq!(created_permission.name, permission_name);
assert_eq!(db_permission.name, permission_name);
// Clean up
let _ = repo.query_delete_permission(created_permission.id.id.to_raw()).await;
let _ = repo.query_delete_permission(db_permission.id.id.to_raw()).await;
}
}
@@ -29,10 +29,11 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::CREATED);
// Verify response body contains created permission
// Verify response body contains created permission data
let created: PermissionsSchema =
crate::common::response_helpers::parse_response(response, 1024).await;
assert_eq!(created.name, permission_name);
assert!(!created.id.is_empty(), "Created permission must have non-empty id");
assert_eq!(created.name, permission_name, "Created permission name must match request");
// Verify permission was created in database
let created_permission = repo
@@ -76,10 +77,12 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Verify response body contains permission
// Verify response body contains permission data
let body: PermissionsSchema =
crate::common::response_helpers::parse_response(response, 1024).await;
assert_eq!(body.id.id.to_raw(), permission_id);
assert!(!body.id.id.to_raw().is_empty(), "Permission must have non-empty id");
assert_eq!(body.id.id.to_raw(), permission_id, "Permission ID must match");
assert_eq!(body.name, permission_name, "Permission name must match");
// Clean up
let _ = repo.query_delete_permission(permission_id).await;
@@ -122,10 +125,11 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// Verify response body contains updated permission
// Verify response body contains updated permission data
let body: PermissionsSchema =
crate::common::response_helpers::parse_response(response, 1024).await;
assert_eq!(body.name, new_name);
assert!(!body.id.id.to_raw().is_empty(), "Updated permission must have non-empty id");
assert_eq!(body.name, new_name, "Updated permission name must match request");
// Verify permission was updated in database
let updated_permission = repo
+24 -10
View File
@@ -29,19 +29,22 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::CREATED);
let msg: imphnen_entities::MessageResponseDto =
// Verify response body contains role data
let created_role: imphnen_iam::v1::roles::roles_dto::RolesDetailItemDto =
crate::common::response_helpers::parse_response(response, 1024).await;
assert!(msg.message.to_lowercase().contains("created") || msg.message.to_lowercase().contains("success"));
assert!(!created_role.id.is_empty(), "Created role must have non-empty id");
assert_eq!(created_role.name, role_name, "Created role name must match request");
assert_eq!(created_role.description, Some("Test role for controller".to_string()), "Created role description must match request");
// Verify role was created in database
let created_role = repo
let db_role = repo
.query_role_by_name(role_name)
.await
.unwrap();
assert_eq!(created_role.name, role_name);
assert_eq!(db_role.name, role_name);
// Clean up
let _ = repo.query_delete_role(created_role.id.id.to_raw()).await;
let _ = repo.query_delete_role(db_role.id.id.to_raw()).await;
}
#[tokio::test]
@@ -121,6 +124,15 @@ mod tests {
// Expect wrapped { data: [...] } or raw array. Normalize to array and check created roles are present
let list_val = if let Some(d) = v.get("data") { d.clone() } else { v };
let arr = list_val.as_array().expect("role list should be an array");
// Verify all items have required fields
for item in arr.iter() {
assert!(item.get("id").is_some(), "Role list items must have id");
assert!(item.get("name").is_some(), "Role list items must have name");
let name = item.get("name").and_then(|n| n.as_str()).expect("Role name must be string");
assert!(!name.is_empty(), "Role name must not be empty");
}
let names: Vec<String> = arr.iter().filter_map(|it| it.get("name").and_then(|n| n.as_str()).map(|s| s.to_string())).collect();
for name in ["test_role_list_1", "test_role_list_2", "test_role_list_3"].iter() {
assert!(names.contains(&name.to_string()), "expected role {} in list", name);
@@ -164,11 +176,13 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::OK);
let v = crate::common::response_helpers::parse_response_value(response, 1024).await;
// Expect wrapped { data: {...} } or direct object. Extract and assert name
let obj = if let Some(d) = v.get("data") { d.clone() } else { v };
let name = obj.get("name").and_then(|n| n.as_str()).expect("role object must have name");
assert_eq!(name, "test_role_by_id");
// Parse and verify role data
let role: imphnen_iam::v1::roles::roles_dto::RolesDetailItemDto =
crate::common::response_helpers::parse_response(response, 1024).await;
assert!(!role.id.is_empty(), "Role must have non-empty id");
assert_eq!(role.name, role_name, "Role name must match created role");
assert_eq!(role.description, Some("Test role for by ID test".to_string()), "Role description must match created role");
// Clean up
let _ = repo.query_delete_role(role_id).await;
+37 -34
View File
@@ -28,20 +28,21 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::CREATED);
// Verify response body contains success message
let msg: MessageResponseDto =
crate::common::response_helpers::parse_response(response, 1024).await;
assert!(msg.message.to_lowercase().contains("created") || msg.message.to_lowercase().contains("success"));
// Verify response body contains role data
let created_role: imphnen_iam::v1::roles::roles_dto::RolesDetailItemDto =
crate::common::response_helpers::parse_response_data(response, 1024).await;
assert!(!created_role.id.is_empty(), "Created role must have non-empty id");
assert_eq!(created_role.name, role_name, "Created role name must match request");
// Verify role was created in database
let created_role = repo
let db_role = repo
.query_role_by_name(role_name.clone())
.await
.unwrap();
assert_eq!(created_role.name, role_name);
assert_eq!(db_role.name, role_name);
// Clean up
let _ = repo.query_delete_role(created_role.id).await;
let _ = repo.query_delete_role(db_role.id).await;
}
#[tokio::test]
@@ -60,9 +61,9 @@ mod tests {
// Get created role to get ID
let created_role = repo
.query_role_by_name(role_name)
.await
.unwrap();
.query_role_by_name(role_name.clone())
.await
.unwrap();
let role_id = created_role.id;
// Get role by ID through service
@@ -74,17 +75,17 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::OK);
// parse response value and handle wrapped {"data": ...} or object
let v = crate::common::response_helpers::parse_response_value(response, 1024).await;
if let Some(inner) = v.get("data") {
// attempt to deserialize into detail DTO if present
let _role: imphnen_iam::v1::roles::roles_dto::RolesDetailItemDto =
serde_json::from_value(inner.clone()).unwrap_or_else(|_| {
panic!("Response 'data' couldn't be deserialized into RolesDetailItemDto: {}", inner)
});
// Parse response and verify role data
let v = crate::common::response_helpers::parse_response_value(response, 1024).await;
let role_data = if let Some(inner) = v.get("data") {
serde_json::from_value(inner.clone()).expect("Response 'data' must deserialize into RolesDetailItemDto")
} else {
assert!(v.is_object());
}
serde_json::from_value(v).expect("Response must deserialize into RolesDetailItemDto")
};
let role: imphnen_iam::v1::roles::roles_dto::RolesDetailItemDto = role_data;
assert!(!role.id.is_empty(), "Role must have non-empty id");
assert_eq!(role.name, role_name, "Role name must match created role");
// Clean up
let _ = repo.query_delete_role(role_id).await;
@@ -108,9 +109,9 @@ mod tests {
// Get created role to get ID
let created_role = repo
.query_role_by_name(original_name)
.await
.unwrap();
.query_role_by_name(original_name.clone())
.await
.unwrap();
let role_id = created_role.id;
// Prepare update request
@@ -160,9 +161,9 @@ mod tests {
// Get created role to get ID
let created_role = repo
.query_role_by_name(role_name)
.await
.unwrap();
.query_role_by_name(role_name.clone())
.await
.unwrap();
let role_id = created_role.id;
// Verify role exists before deletion
@@ -220,12 +221,14 @@ mod tests {
let list: imphnen_entities::ResponseListSuccessDto<Vec<imphnen_iam::v1::roles::roles_dto::RolesListItemDto>> =
serde_json::from_value(inner.clone()).unwrap_or(imphnen_entities::ResponseListSuccessDto { data: vec![], meta: None });
if !list.data.is_empty() {
assert!(!list.data[0].id.is_empty());
assert!(!list.data[0].id.is_empty(), "Role list items must have non-empty id");
assert!(!list.data[0].name.is_empty(), "Role list items must have non-empty name");
}
} else if v.is_array() {
let arr: Vec<imphnen_iam::v1::roles::roles_dto::RolesListItemDto> = serde_json::from_value(v).unwrap_or_default();
if !arr.is_empty() {
assert!(!arr[0].id.is_empty());
assert!(!arr[0].id.is_empty(), "Role list items must have non-empty id");
assert!(!arr[0].name.is_empty(), "Role list items must have non-empty name");
}
} else {
// accept other object shapes
@@ -275,9 +278,9 @@ mod tests {
// Clean up
let created_role = repo
.query_role_by_name(role_name)
.await
.unwrap();
.query_role_by_name(role_name.clone())
.await
.unwrap();
let _ = repo.query_delete_role(created_role.id).await;
}
@@ -333,9 +336,9 @@ mod tests {
// Clean up
let _ = repo.query_delete_role(role_id1).await;
let created_role2 = repo
.query_role_by_name(role_name2)
.await
.unwrap();
.query_role_by_name(role_name2.clone())
.await
.unwrap();
let _ = repo.query_delete_role(created_role2.id).await;
}
@@ -121,11 +121,13 @@ async fn test_admin_team_endpoints_sensitive_data_exposure() {
// Verify sensitive fields are present in admin response
assert!(response_json.data.iter().any(|team| {
team.is_deleted == false && // Should show is_deleted field
team.is_active == true && // Should show is_active field
team.website_url.is_some() && // Should show website_url
team.github_url.is_some() // Should show github_url
}), "Admin team list should expose sensitive fields");
team.is_deleted == false && // Should show is_deleted field
team.is_active == true && // Should show is_active field
team.website_url.is_some() && // Should show website_url
team.github_url.is_some() && // Should show github_url
!team.id.is_empty() && // Should have non-empty id
!team.name.is_empty() // Should have non-empty name
}), "Admin team list should expose sensitive fields and required data");
// Test 2: Admin team detail endpoint should expose sensitive fields and full member info
let response = imphnen_iam::teams_controller::get_admin_team_by_id(
@@ -142,6 +144,8 @@ async fn test_admin_team_endpoints_sensitive_data_exposure() {
let admin_team = response_json.data;
// Verify sensitive fields are present
assert!(!admin_team.id.is_empty(), "Admin team detail should have non-empty id");
assert!(!admin_team.name.is_empty(), "Admin team detail should have non-empty name");
assert!(admin_team.is_deleted == false, "Admin team detail should show is_deleted field");
assert!(admin_team.is_active == true, "Admin team detail should show is_active field");
assert!(admin_team.website_url.is_some(), "Admin team detail should show website_url");
@@ -150,10 +154,11 @@ async fn test_admin_team_endpoints_sensitive_data_exposure() {
// Verify all members have sensitive info (email should be present for admins)
let has_all_member_info = admin_team.members.iter().all(|member| {
member.email.is_some() && // Admin should see member emails
member.fullname != "" && // Admin should see fullnames
member.role != "" // Admin should see roles
});
member.email.is_some() && // Admin should see member emails
!member.fullname.is_empty() && // Admin should see fullnames
!member.role.is_empty() && // Admin should see roles
!member.id.is_empty() // Admin should see member ids
});
assert!(has_all_member_info, "Admin team detail should expose all member sensitive information");
@@ -173,10 +178,11 @@ async fn test_admin_team_endpoints_sensitive_data_exposure() {
// Verify all members have sensitive info
let has_all_member_info = admin_members.iter().all(|member| {
member.email.is_some() && // Admin should see member emails
member.fullname != "" && // Admin should see fullnames
member.role != "" // Admin should see roles
});
member.email.is_some() && // Admin should see member emails
!member.fullname.is_empty() && // Admin should see fullnames
!member.role.is_empty() && // Admin should see roles
!member.id.is_empty() // Admin should see member ids
});
assert!(has_all_member_info, "Admin team members endpoint should expose all member sensitive information");
+22 -14
View File
@@ -42,12 +42,12 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::CREATED);
// Expect a response with data containing the created team id and stats
let v = crate::common::response_helpers::parse_response_value(response, 2048).await;
// If wrapped in { "data": ... }, extract
let data = if let Some(d) = v.get("data") { d.clone() } else { v };
assert!(data.get("team_id").is_some(), "create response must include team_id");
assert!(data.get("invitations_sent").is_some(), "create response should report invitations_sent");
// Parse and verify response contains team data
let team_response: imphnen_iam::v1::teams::teams_dto::TeamsCreateResponseDto =
crate::common::response_helpers::parse_response(response, 2048).await;
assert!(!team_response.team_id.is_empty(), "Created team must have non-empty team_id");
assert_eq!(team_response.invitations_sent, 0, "No invitations should be sent for empty member list");
// Verify team was created in database
let team_thing = make_thing_from_enum(ResourceEnum::Teams, &user.id.id.to_raw());
@@ -325,14 +325,22 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::OK);
let body_json: serde_json::Value = crate::common::response_helpers::parse_response_value(response, 2048).await;
// Expect a list wrapper with data -> array
let list = if let Some(d) = body_json.get("data") { d } else { &body_json };
assert!(list.is_array(), "search should return array of teams");
let found = list.as_array().unwrap().iter().any(|item| {
if let Some(name) = item.get("name") { name == "Searchable Test Team" } else { false }
});
assert!(found, "created team should appear in search results");
// Parse and verify search results
let search_response: imphnen_entities::ResponseListSuccessDto<Vec<imphnen_iam::v1::teams::teams_dto::TeamsListItemDto>> =
crate::common::response_helpers::parse_response(response, 2048).await;
assert!(!search_response.data.is_empty(), "Search should return at least one team");
// Verify all results have required fields
for team in &search_response.data {
assert!(!team.id.is_empty(), "Search result team must have non-empty id");
assert!(!team.name.is_empty(), "Search result team must have non-empty name");
}
// Verify our team is in results
let found_team = search_response.data.iter().find(|t| t.name == "Searchable Test Team");
assert!(found_team.is_some(), "Created team should appear in search results");
assert_eq!(found_team.unwrap().is_open, true, "Found team should be open");
// Clean up
let _ = repo.query_delete_team(team_id).await;
+9 -3
View File
@@ -26,7 +26,9 @@ mod tests {
let arr = list_val.as_array().expect("team list should be an array");
if !arr.is_empty() {
let first = &arr[0];
assert!(first.get("id").is_some() || first.get("name").is_some(), "team items should have id or name");
assert!(first.get("id").is_some(), "team items must have id");
assert!(first.get("name").is_some(), "team items must have name");
assert!(first.get("name").and_then(|n| n.as_str()).map_or(false, |s| !s.is_empty()), "team name must not be empty");
}
}
@@ -50,7 +52,9 @@ mod tests {
let arr = list_val.as_array().expect("public team list should be an array");
if !arr.is_empty() {
let first = &arr[0];
assert!(first.get("id").is_some() || first.get("name").is_some(), "public team items should have id or name");
assert!(first.get("id").is_some(), "public team items must have id");
assert!(first.get("name").is_some(), "public team items must have name");
assert!(first.get("name").and_then(|n| n.as_str()).map_or(false, |s| !s.is_empty()), "public team name must not be empty");
}
}
@@ -149,7 +153,9 @@ mod tests {
let arr = list_val.as_array().expect("search should return array");
if !arr.is_empty() {
let first = &arr[0];
assert!(first.get("id").is_some() || first.get("name").is_some(), "search item should have id or name");
assert!(first.get("id").is_some(), "search result items must have id");
assert!(first.get("name").is_some(), "search result items must have name");
assert!(first.get("name").and_then(|n| n.as_str()).map_or(false, |s| !s.is_empty()), "search result name must not be empty");
}
}
+11 -7
View File
@@ -37,20 +37,24 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::CREATED);
let msg: imphnen_entities::MessageResponseDto =
// Verify response body contains user data
let created_user: imphnen_iam::v1::users::users_dto::UsersDetailItemDto =
crate::common::response_helpers::parse_response(response, 4096).await;
assert!(msg.message.to_lowercase().contains("created") || msg.message.to_lowercase().contains("success"));
assert!(!created_user.id.is_empty(), "Created user must have non-empty id");
assert_eq!(created_user.email, email, "Created user email must match request");
assert_eq!(created_user.fullname, "Test User Controller", "Created user fullname must match request");
assert_eq!(created_user.is_active, true, "Created user must be active");
// Verify user was created in database
let created_user = repo
let db_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);
assert_eq!(db_user.email, email);
assert_eq!(db_user.fullname, "Test User Controller");
assert_eq!(db_user.is_active, true);
// Clean up
let _ = repo.query_delete_user(created_user.id.id.to_raw()).await;
let _ = repo.query_delete_user(db_user.id.id.to_raw()).await;
}
}
+14 -9
View File
@@ -31,12 +31,14 @@ mod tests {
let list: imphnen_entities::ResponseListSuccessDto<Vec<imphnen_iam::v1::users::users_dto::UsersListItemDto>> =
serde_json::from_value(inner.clone()).unwrap_or(imphnen_entities::ResponseListSuccessDto { data: vec![], meta: None });
if !list.data.is_empty() {
assert!(!list.data[0].id.is_empty());
assert!(!list.data[0].id.is_empty(), "User list items must have non-empty id");
assert!(!list.data[0].email.is_empty(), "User list items must have non-empty email");
}
} else if v.is_array() {
let arr: Vec<imphnen_iam::v1::users::users_dto::UsersListItemDto> = serde_json::from_value(v).unwrap_or_default();
if !arr.is_empty() {
assert!(!arr[0].id.is_empty());
assert!(!arr[0].id.is_empty(), "User list items must have non-empty id");
assert!(!arr[0].email.is_empty(), "User list items must have non-empty email");
}
} else {
// other shapes (object without data) — accept for now
@@ -104,17 +106,20 @@ mod tests {
// Verify response
assert_eq!(response.status(), StatusCode::CREATED);
// Verify response body contains success message
let created_msg: imphnen_entities::MessageResponseDto =
crate::common::response_helpers::parse_response(response, 4096).await;
assert!(created_msg.message.to_lowercase().contains("created") || created_msg.message.to_lowercase().contains("success"));
// Verify response body contains user data
let created_user: imphnen_iam::v1::users::users_dto::UsersDetailItemDto =
crate::common::response_helpers::parse_response_data(response, 4096).await;
assert!(!created_user.id.is_empty(), "Created user must have non-empty id");
assert_eq!(created_user.email, email, "Created user email must match request");
assert_eq!(created_user.fullname, "Test User Service", "Created user fullname must match request");
assert_eq!(created_user.is_active, true, "Created user must be active");
// Verify user was created in database
let created_user = repo.query_user_by_email(email.clone()).await.unwrap();
assert_eq!(created_user.email, email);
let db_user = repo.query_user_by_email(email.clone()).await.unwrap();
assert_eq!(db_user.email, email);
// Clean up
let _ = repo.query_delete_user(created_user.id.id.to_raw()).await;
let _ = repo.query_delete_user(db_user.id.id.to_raw()).await;
}
#[tokio::test]