diff --git a/imphnen-hackathon/src/v1/hackathon/hackathon_schema.rs b/imphnen-hackathon/src/v1/hackathon/hackathon_schema.rs index ccb7c33..764a1e0 100644 --- a/imphnen-hackathon/src/v1/hackathon/hackathon_schema.rs +++ b/imphnen-hackathon/src/v1/hackathon/hackathon_schema.rs @@ -93,7 +93,7 @@ pub struct Winner { pub team_name: Option, } -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, utoipa::ToSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, utoipa::ToSchema, strum::Display)] pub enum HackathonStatus { Draft, RegistrationOpen, @@ -104,7 +104,7 @@ pub enum HackathonStatus { Cancelled, } -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, utoipa::ToSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, utoipa::ToSchema, strum::Display)] pub enum HackathonEventType { Workshop, Keynote, @@ -114,7 +114,7 @@ pub enum HackathonEventType { Other, } -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, utoipa::ToSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, utoipa::ToSchema, strum::Display)] pub enum HackathonPhase { Registration, Ideation, @@ -124,7 +124,7 @@ pub enum HackathonPhase { Awards, } -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, utoipa::ToSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, utoipa::ToSchema, strum::Display)] pub enum SubmissionStatus { Draft, Submitted, diff --git a/imphnen-iam/src/v1/users/users_schema.rs b/imphnen-iam/src/v1/users/users_schema.rs index f58dbac..3bb0216 100644 --- a/imphnen-iam/src/v1/users/users_schema.rs +++ b/imphnen-iam/src/v1/users/users_schema.rs @@ -242,30 +242,30 @@ impl UsersSchema { &Uuid::new_v4().to_string(), ), fullname: user.fullname, - legal_name: None, + legal_name: Some("".to_string()), email: user.email, password, - phone_number: user.phone_number, - phone_for_verification: None, + phone_number: user.phone_number.clone(), + phone_for_verification: Some(user.phone_number.clone()), is_active: user.is_active, mentor_id: None, // Regular users should not have a mentor_id by default - gender: None, - birthdate: None, - domicile: None, - bio: None, - last_education: None, - linkedin_url: None, - github_url: None, - cv_url: None, - portfolio_url: None, - website_url: None, - twitter_url: None, - location: None, - skills: None, - experience: None, - education: None, - career_status: None, - avatar: user.avatar, + gender: Some("".to_string()), + birthdate: Some("".to_string()), + domicile: Some("".to_string()), + bio: Some("".to_string()), + last_education: Some("".to_string()), + linkedin_url: Some("".to_string()), + github_url: Some("".to_string()), + cv_url: Some("".to_string()), + portfolio_url: Some("".to_string()), + website_url: Some("".to_string()), + twitter_url: Some("".to_string()), + location: Some("".to_string()), + skills: Some(vec![]), + experience: Some(vec![]), + education: Some(vec![]), + career_status: Some("".to_string()), + avatar: user.avatar.or(Some("https://via.placeholder.com/150".to_string())), is_deleted: false, role: make_thing_from_enum(ResourceEnum::Roles, &user.role_id), created_at: get_iso_date(), diff --git a/tests/src/dimentorin/mentors/mentors_service_test.rs b/tests/src/dimentorin/mentors/mentors_service_test.rs index 6f33411..2eac06f 100644 --- a/tests/src/dimentorin/mentors/mentors_service_test.rs +++ b/tests/src/dimentorin/mentors/mentors_service_test.rs @@ -72,6 +72,9 @@ mod tests { // 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!(!mentor_response.user_id.is_empty(), "User ID should not be empty"); + assert!(mentor_response.email.is_some(), "Email should be present"); + assert!(!mentor_response.email.unwrap().is_empty(), "Email 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"); @@ -158,6 +161,10 @@ mod tests { let mentor = &mentor_list[0]; assert!(!mentor.id.is_empty(), "Mentor ID should not be empty"); + assert!(mentor.fullname.is_some(), "Fullname should be present"); + assert!(!mentor.fullname.unwrap().is_empty(), "Fullname should not be empty"); + assert!(mentor.email.is_some(), "Email should be present"); + assert!(!mentor.email.unwrap().is_empty(), "Email 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"); @@ -226,12 +233,65 @@ mod tests { // Parse and verify JSON response let mentor_response: MentorDetailResponseDto = response.json().await.unwrap(); + + // Core required fields 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!(mentor_response.fullname.is_some(), "Fullname should be present"); + assert!(!mentor_response.fullname.unwrap().is_empty(), "Fullname should not be empty"); + assert!(mentor_response.email.is_some(), "Email should be present"); + assert!(!mentor_response.email.unwrap().is_empty(), "Email should not be empty"); + assert!(mentor_response.legal_name.is_some(), "Legal name should be present"); + assert!(!mentor_response.legal_name.unwrap().is_empty(), "Legal name should not be empty"); + assert!(mentor_response.phone_for_verification.is_some(), "Phone for verification should be present"); + assert!(!mentor_response.phone_for_verification.unwrap().is_empty(), "Phone for verification should not be empty"); + assert!(mentor_response.bio.is_some(), "Bio should be present"); + assert!(!mentor_response.bio.unwrap().is_empty(), "Bio should not be empty"); + + // Professional profile fields + assert!(!mentor_response.current_company.is_empty(), "Current company should not be empty"); + assert!(!mentor_response.current_role.is_empty(), "Current role should not be empty"); + assert!(mentor_response.years_of_experience >= 2, "Years of experience should be at least 2"); + assert!(!mentor_response.industries.is_empty(), "Industries should not be empty"); + assert!(!mentor_response.expertise.is_empty(), "Expertise should not be empty"); + assert!(!mentor_response.languages.is_empty(), "Languages should not be empty"); + assert!(!mentor_response.topics_of_interest.is_empty(), "Topics of interest should not be empty"); + assert!(!mentor_response.preferred_mentee_level.is_empty(), "Preferred mentee level should not be empty"); + assert!(!mentor_response.preferred_mentoring_formats.is_empty(), "Preferred mentoring formats should not be empty"); + assert!(!mentor_response.availability_commitment.is_empty(), "Availability commitment should not be empty"); + + // Mentoring rate validation + assert!(mentor_response.mentoring_rate.amount > 0, "Mentoring rate amount should be greater than 0"); + assert!(!mentor_response.mentoring_rate.currency.is_empty(), "Mentoring rate currency should not be empty"); + assert!(!mentor_response.mentoring_rate.per_duration.is_empty(), "Mentoring rate per duration should not be empty"); + + // Status and timestamps 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'"); + + // Optional fields (check if present, then validate) + if let Some(gender) = &mentor_response.gender { + assert!(!gender.is_empty(), "Gender should not be empty if present"); + } + if let Some(domicile) = &mentor_response.domicile { + assert!(!domicile.is_empty(), "Domicile should not be empty if present"); + } + if let Some(last_education) = &mentor_response.last_education { + assert!(!last_education.is_empty(), "Last education should not be empty if present"); + } + if let Some(linkedin_url) = &mentor_response.linkedin_url { + assert!(linkedin_url.starts_with("http"), "LinkedIn URL should be valid"); + } + if let Some(github_url) = &mentor_response.github_url { + assert!(github_url.starts_with("http"), "GitHub URL should be valid"); + } + if let Some(cv_url) = &mentor_response.cv_url { + assert!(cv_url.starts_with("http"), "CV URL should be valid"); + } + if let Some(portfolio_url) = &mentor_response.portfolio_url { + assert!(portfolio_url.starts_with("http"), "Portfolio URL should be valid"); + } // Clean up let user = user_repo.query_user_by_email(email.clone()).await.unwrap(); @@ -321,11 +381,70 @@ mod tests { // Parse and verify JSON response let mentor_response: MentorDetailResponseDto = response.json().await.unwrap(); + + // Core required fields 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.fullname.is_some(), "Fullname should be present"); + assert!(!mentor_response.fullname.unwrap().is_empty(), "Fullname should not be empty"); + assert!(mentor_response.email.is_some(), "Email should be present"); + assert!(!mentor_response.email.unwrap().is_empty(), "Email should not be empty"); + assert!(mentor_response.legal_name.is_some(), "Legal name should be present"); + assert!(!mentor_response.legal_name.unwrap().is_empty(), "Legal name should not be empty"); + assert!(mentor_response.phone_for_verification.is_some(), "Phone for verification should be present"); + assert!(!mentor_response.phone_for_verification.unwrap().is_empty(), "Phone for verification should not be empty"); + assert!(mentor_response.bio.is_some(), "Bio should be present"); + assert!(!mentor_response.bio.unwrap().is_empty(), "Bio should not be empty"); + + // Professional profile fields + assert!(!mentor_response.current_company.is_empty(), "Current company should not be empty"); + assert!(!mentor_response.current_role.is_empty(), "Current role should not be empty"); assert_eq!(mentor_response.current_role, "Lead Engineer", "Expected current role to be 'Lead Engineer' after update"); + assert!(mentor_response.years_of_experience >= 2, "Years of experience should be at least 2"); + assert!(!mentor_response.industries.is_empty(), "Industries should not be empty"); + assert!(!mentor_response.expertise.is_empty(), "Expertise should not be empty"); + assert!(!mentor_response.languages.is_empty(), "Languages should not be empty"); + assert!(!mentor_response.topics_of_interest.is_empty(), "Topics of interest should not be empty"); + assert!(!mentor_response.preferred_mentee_level.is_empty(), "Preferred mentee level should not be empty"); + assert!(!mentor_response.preferred_mentoring_formats.is_empty(), "Preferred mentoring formats should not be empty"); + assert!(!mentor_response.availability_commitment.is_empty(), "Availability commitment should not be empty"); + + // Mentoring rate validation + assert!(mentor_response.mentoring_rate.amount > 0, "Mentoring rate amount should be greater than 0"); + assert!(!mentor_response.mentoring_rate.currency.is_empty(), "Mentoring rate currency should not be empty"); + assert!(!mentor_response.mentoring_rate.per_duration.is_empty(), "Mentoring rate per duration should not be empty"); + + // Status and timestamps + 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"); + + // Updated fields validation assert_eq!(mentor_response.legal_name, Some("Updated Legal 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"); + + // Optional fields (check if present, then validate) + if let Some(gender) = &mentor_response.gender { + assert!(!gender.is_empty(), "Gender should not be empty if present"); + } + if let Some(domicile) = &mentor_response.domicile { + assert!(!domicile.is_empty(), "Domicile should not be empty if present"); + } + if let Some(last_education) = &mentor_response.last_education { + assert!(!last_education.is_empty(), "Last education should not be empty if present"); + } + if let Some(linkedin_url) = &mentor_response.linkedin_url { + assert!(linkedin_url.starts_with("http"), "LinkedIn URL should be valid"); + } + if let Some(github_url) = &mentor_response.github_url { + assert!(github_url.starts_with("http"), "GitHub URL should be valid"); + } + if let Some(cv_url) = &mentor_response.cv_url { + assert!(cv_url.starts_with("http"), "CV URL should be valid"); + } + if let Some(portfolio_url) = &mentor_response.portfolio_url { + assert!(portfolio_url.starts_with("http"), "Portfolio URL should be valid"); + } // Verify mentor was updated let updated_mentor = mentor_repo.query_mentor_by_id(&mentor.id, false).await.unwrap(); @@ -461,8 +580,65 @@ mod tests { // Parse and verify JSON response let mentor_response: MentorDetailResponseDto = response.json().await.unwrap(); + + // Core required fields 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!(mentor_response.fullname.is_some(), "Fullname should be present"); + assert!(!mentor_response.fullname.unwrap().is_empty(), "Fullname should not be empty"); + assert!(mentor_response.email.is_some(), "Email should be present"); + assert!(!mentor_response.email.unwrap().is_empty(), "Email should not be empty"); + assert!(mentor_response.legal_name.is_some(), "Legal name should be present"); + assert!(!mentor_response.legal_name.unwrap().is_empty(), "Legal name should not be empty"); + assert!(mentor_response.phone_for_verification.is_some(), "Phone for verification should be present"); + assert!(!mentor_response.phone_for_verification.unwrap().is_empty(), "Phone for verification should not be empty"); + assert!(mentor_response.bio.is_some(), "Bio should be present"); + assert!(!mentor_response.bio.unwrap().is_empty(), "Bio should not be empty"); + + // Professional profile fields + assert!(!mentor_response.current_company.is_empty(), "Current company should not be empty"); + assert!(!mentor_response.current_role.is_empty(), "Current role should not be empty"); + assert!(mentor_response.years_of_experience >= 2, "Years of experience should be at least 2"); + assert!(!mentor_response.industries.is_empty(), "Industries should not be empty"); + assert!(!mentor_response.expertise.is_empty(), "Expertise should not be empty"); + assert!(!mentor_response.languages.is_empty(), "Languages should not be empty"); + assert!(!mentor_response.topics_of_interest.is_empty(), "Topics of interest should not be empty"); + assert!(!mentor_response.preferred_mentee_level.is_empty(), "Preferred mentee level should not be empty"); + assert!(!mentor_response.preferred_mentoring_formats.is_empty(), "Preferred mentoring formats should not be empty"); + assert!(!mentor_response.availability_commitment.is_empty(), "Availability commitment should not be empty"); + + // Mentoring rate validation + assert!(mentor_response.mentoring_rate.amount > 0, "Mentoring rate amount should be greater than 0"); + assert!(!mentor_response.mentoring_rate.currency.is_empty(), "Mentoring rate currency should not be empty"); + assert!(!mentor_response.mentoring_rate.per_duration.is_empty(), "Mentoring rate per duration should not be empty"); + + // Status and timestamps assert_eq!(mentor_response.status, "verified", "Expected mentor status to be 'verified'"); + 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"); + + // Optional fields (check if present, then validate) + if let Some(gender) = &mentor_response.gender { + assert!(!gender.is_empty(), "Gender should not be empty if present"); + } + if let Some(domicile) = &mentor_response.domicile { + assert!(!domicile.is_empty(), "Domicile should not be empty if present"); + } + if let Some(last_education) = &mentor_response.last_education { + assert!(!last_education.is_empty(), "Last education should not be empty if present"); + } + if let Some(linkedin_url) = &mentor_response.linkedin_url { + assert!(linkedin_url.starts_with("http"), "LinkedIn URL should be valid"); + } + if let Some(github_url) = &mentor_response.github_url { + assert!(github_url.starts_with("http"), "GitHub URL should be valid"); + } + if let Some(cv_url) = &mentor_response.cv_url { + assert!(cv_url.starts_with("http"), "CV URL should be valid"); + } + if let Some(portfolio_url) = &mentor_response.portfolio_url { + assert!(portfolio_url.starts_with("http"), "Portfolio URL should be valid"); + } // Verify mentor was verified let updated_mentor = mentor_repo.query_mentor_by_id(&mentor.id, false).await.unwrap(); diff --git a/tests/src/gacha/gacha_claims_controller_test.rs b/tests/src/gacha/gacha_claims_controller_test.rs index c0fd291..0c247d3 100644 --- a/tests/src/gacha/gacha_claims_controller_test.rs +++ b/tests/src/gacha/gacha_claims_controller_test.rs @@ -32,6 +32,13 @@ async fn test_create_claim_happy_path() { let response = server.post("/gacha/claims").json(&create_dto).await; assert_eq!(response.status(), 201); let body: GachaClaimResponse = response.json().await.unwrap(); + + // Verify all fields in response are not empty + assert!(!body.id.is_empty(), "GachaClaimResponse.id should not be empty"); + assert!(!body.user_id.is_empty(), "GachaClaimResponse.user_id should not be empty"); + assert!(!body.item_id.is_empty(), "GachaClaimResponse.item_id should not be empty"); + assert!(!body.status.is_empty(), "GachaClaimResponse.status should not be empty"); + assert!(!body.created_at.is_empty(), "GachaClaimResponse.created_at should not be empty"); assert_eq!(body.id, expected.id); } diff --git a/tests/src/gacha/gacha_claims_service_test.rs b/tests/src/gacha/gacha_claims_service_test.rs index d0d24bd..8fff191 100644 --- a/tests/src/gacha/gacha_claims_service_test.rs +++ b/tests/src/gacha/gacha_claims_service_test.rs @@ -52,6 +52,7 @@ mod tests { // 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"); + assert!(!response_body["message"].as_str().unwrap().is_empty(), "Error message should not be empty"); // Clean up let _ = user_repo.query_delete_user(user.id.id.to_raw()).await; @@ -97,6 +98,7 @@ mod tests { // 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"); + assert!(!response_body["message"].as_str().unwrap().is_empty(), "Error message should not be empty"); // Clean up let _ = user_repo.query_delete_user(user.id.id.to_raw()).await; @@ -120,6 +122,7 @@ mod tests { // 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"); + assert!(!response_body["message"].as_str().unwrap().is_empty(), "Error message should not be empty"); // Parse and verify error JSON content let response_body: serde_json::Value = response.json().await.unwrap(); diff --git a/tests/src/gacha/gacha_credits_controller_test.rs b/tests/src/gacha/gacha_credits_controller_test.rs index 3e7cc68..b88db60 100644 --- a/tests/src/gacha/gacha_credits_controller_test.rs +++ b/tests/src/gacha/gacha_credits_controller_test.rs @@ -103,6 +103,17 @@ mod tests { // Parse and verify JSON content let response_body: ResponseListSuccessDto = response.json().await.unwrap(); assert!(!response_body.data.is_null(), "Response data should not be null"); + + // Verify all fields in response are not empty + let credits_array = response_body.data.as_array().unwrap(); + for credit in credits_array { + assert!(credit["id"].is_string() && !credit["id"].as_str().unwrap().is_empty(), "Response credit.id should not be empty"); + assert!(credit["user"].is_object(), "Response credit.user should be an object"); + assert!(credit["available_rolls"].is_i64(), "Response credit.available_rolls should be present"); + assert!(credit["is_deleted"].is_bool(), "Response credit.is_deleted should be present"); + assert!(credit["created_at"].is_string(), "Response credit.created_at should be present"); + assert!(credit["updated_at"].is_string(), "Response credit.updated_at should be present"); + } // Clean up let _ = user_repo.query_delete_user(user.id.id.to_raw()).await; @@ -151,6 +162,15 @@ mod tests { // Parse and verify JSON content let response_body: ResponseSuccessDto = response.json().await.unwrap(); assert!(!response_body.data.is_null(), "Response data should not be null"); + + // Verify all fields in response are not empty + let credit = response_body.data.as_object().unwrap(); + assert!(credit["id"].is_string() && !credit["id"].as_str().unwrap().is_empty(), "Response credit.id should not be empty"); + assert!(credit["user"].is_object(), "Response credit.user should be an object"); + assert!(credit["available_rolls"].is_i64(), "Response credit.available_rolls should be present"); + assert!(credit["is_deleted"].is_bool(), "Response credit.is_deleted should be present"); + assert!(credit["created_at"].is_string(), "Response credit.created_at should be present"); + assert!(credit["updated_at"].is_string(), "Response credit.updated_at should be present"); // Clean up let _ = user_repo.query_delete_user(user.id.id.to_raw()).await; diff --git a/tests/src/gacha/gacha_items_controller_test.rs b/tests/src/gacha/gacha_items_controller_test.rs index 18a4f0c..12bb4cb 100644 --- a/tests/src/gacha/gacha_items_controller_test.rs +++ b/tests/src/gacha/gacha_items_controller_test.rs @@ -32,6 +32,14 @@ async fn test_create_item_happy_path() { let response = server.post("/gacha/items").json(&create_dto).await; assert_eq!(response.status(), 201); let body: GachaItemResponse = response.json().await.unwrap(); + + // Verify all fields in response are not empty + assert!(!body.id.is_empty(), "GachaItemResponse.id should not be empty"); + assert!(!body.name.is_empty(), "GachaItemResponse.name should not be empty"); + assert!(!body.rarity.is_empty(), "GachaItemResponse.rarity should not be empty"); + assert!(!body.image_url.is_empty(), "GachaItemResponse.image_url should not be empty"); + assert!(body.value > 0, "GachaItemResponse.value should be positive"); + assert!(!body.created_at.is_empty(), "GachaItemResponse.created_at should not be empty"); assert_eq!(body.id, expected.id); } @@ -52,6 +60,16 @@ async fn test_get_all_items_happy_path() { assert_eq!(response.status(), 200); let body: Vec = response.json().await.unwrap(); assert_eq!(body.len(), 2); + + // Verify all fields in all responses are not empty + for item in &body { + assert!(!item.id.is_empty(), "GachaItemResponse.id should not be empty"); + assert!(!item.name.is_empty(), "GachaItemResponse.name should not be empty"); + assert!(!item.rarity.is_empty(), "GachaItemResponse.rarity should not be empty"); + assert!(!item.image_url.is_empty(), "GachaItemResponse.image_url should not be empty"); + assert!(item.value > 0, "GachaItemResponse.value should be positive"); + assert!(!item.created_at.is_empty(), "GachaItemResponse.created_at should not be empty"); + } assert_eq!(body[0].id, "item123"); assert_eq!(body[1].id, "item456"); } diff --git a/tests/src/gacha/gacha_items_service_test.rs b/tests/src/gacha/gacha_items_service_test.rs index f02f52d..f45d793 100644 --- a/tests/src/gacha/gacha_items_service_test.rs +++ b/tests/src/gacha/gacha_items_service_test.rs @@ -38,7 +38,15 @@ mod tests { let response_body: ResponseListSuccessDto> = 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"); + + // Verify all fields in GachaItemDto are not empty + for item in &response_body.data { + assert!(!item.id.is_empty(), "GachaItemDto.id should not be empty"); + assert!(!item.name.is_empty(), "GachaItemDto.name should not be empty"); + assert!(!item.is_deleted.to_string().is_empty(), "GachaItemDto.is_deleted should not be empty"); + assert!(item.created_at.is_some(), "GachaItemDto.created_at should be present"); + assert!(item.updated_at.is_some(), "GachaItemDto.updated_at should be present"); + } // Clean up let items = item_repo.query_gacha_item_list(MetaRequestDto::default()).await.unwrap().data; @@ -68,9 +76,13 @@ mod tests { // Parse and verify JSON content let response_body: ResponseSuccessDto = 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"); + + // Verify all fields in GachaItemDto are not empty + assert!(!response_body.data.id.is_empty(), "GachaItemDto.id should not be empty"); + assert_eq!(response_body.data.name, "Test Item By ID", "GachaItemDto.name should match"); + assert!(!response_body.data.is_deleted.to_string().is_empty(), "GachaItemDto.is_deleted should not be empty"); + assert!(response_body.data.created_at.is_some(), "GachaItemDto.created_at should be present"); + assert!(response_body.data.updated_at.is_some(), "GachaItemDto.updated_at should be present"); // Clean up let _ = item_repo.query_delete_gacha_item(item.id.id.to_raw()).await; @@ -188,9 +200,14 @@ mod tests { // Parse and verify JSON content let response_body: ResponseSuccessDto = 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 all fields in GachaItemDto are not empty + assert!(!response_body.data.id.is_empty(), "GachaItemDto.id should not be empty"); + assert_eq!(response_body.data.name, "Updated Test Item", "GachaItemDto.name should match"); + assert_eq!(response_body.data.image_url, "https://example.com/updated.png", "GachaItemDto.image_url should match"); + assert!(!response_body.data.is_deleted.to_string().is_empty(), "GachaItemDto.is_deleted should not be empty"); + assert!(response_body.data.created_at.is_some(), "GachaItemDto.created_at should be present"); + assert!(response_body.data.updated_at.is_some(), "GachaItemDto.updated_at should be present"); // Verify item was updated let updated_item = item_repo.query_gacha_item_by_id(item.id.id.to_raw()).await.unwrap(); diff --git a/tests/src/hackathon/hackathon_controller_test.rs b/tests/src/hackathon/hackathon_controller_test.rs index e790890..d679acc 100644 --- a/tests/src/hackathon/hackathon_controller_test.rs +++ b/tests/src/hackathon/hackathon_controller_test.rs @@ -68,9 +68,17 @@ mod tests { let hackathon: imphnen_hackathon::v1::hackathon::hackathon_dto::HackathonDto = crate::common::response_helpers::parse_response_data(response, 4096).await; - // Basic field asserts to ensure response contains expected values + // Assert all required fields are present and not empty + assert!(!hackathon.id.is_empty(), "Hackathon ID should not be empty"); assert_eq!(hackathon.name, "Controller Test Hackathon"); assert_eq!(hackathon.description, "Testing controller endpoints"); + assert!(!hackathon.start_date.to_rfc3339().is_empty(), "Start date should not be empty"); + assert!(!hackathon.end_date.to_rfc3339().is_empty(), "End date should not be empty"); + assert!(!hackathon.registration_deadline.to_rfc3339().is_empty(), "Registration deadline should not be empty"); + assert!(hackathon.max_participants.is_some(), "Max participants should be present"); + assert!(!hackathon.status.to_string().is_empty(), "Status should not be empty"); + assert!(hackathon.organizers.len() > 0, "Organizers list should not be empty"); + assert_eq!(hackathon.is_deleted, false, "Hackathon should not be marked as deleted"); } #[tokio::test] @@ -165,9 +173,19 @@ mod tests { let list: Vec = crate::common::response_helpers::parse_response_data(response, 4096).await; - // if non-empty, ensure items have required fields + // if non-empty, ensure items have all required fields if !list.is_empty() { - assert!(!list[0].id.is_empty()); + let hackathon = &list[0]; + assert!(!hackathon.id.is_empty(), "Hackathon ID should not be empty"); + assert!(!hackathon.name.is_empty(), "Hackathon name should not be empty"); + assert!(!hackathon.description.is_empty(), "Hackathon description should not be empty"); + assert!(!hackathon.start_date.to_rfc3339().is_empty(), "Start date should not be empty"); + assert!(!hackathon.end_date.to_rfc3339().is_empty(), "End date should not be empty"); + assert!(!hackathon.registration_deadline.to_rfc3339().is_empty(), "Registration deadline should not be empty"); + assert!(hackathon.max_participants.is_some(), "Max participants should be present"); + assert!(!hackathon.status.to_string().is_empty(), "Status should not be empty"); + assert!(hackathon.organizers.len() > 0, "Organizers list should not be empty"); + assert_eq!(hackathon.is_deleted, false, "Hackathon should not be marked as deleted"); } } @@ -262,7 +280,15 @@ mod tests { // parse created event and assert fields let event: imphnen_hackathon::v1::hackathon::hackathon_dto::HackathonEventDto = crate::common::response_helpers::parse_response_data(response, 2048).await; + // Assert all required fields are present and not empty + assert!(!event.id.is_empty(), "Event ID should not be empty"); + assert!(!event.hackathon_id.is_empty(), "Hackathon ID should not be empty"); assert_eq!(event.title, "Controller Event Test"); + assert!(!event.start_time.to_rfc3339().is_empty(), "Start time should not be empty"); + assert!(!event.end_time.to_rfc3339().is_empty(), "End time should not be empty"); + assert!(!event.event_type.to_string().is_empty(), "Event type should not be empty"); + assert_eq!(event.is_mandatory, false, "Is mandatory should be false by default"); + assert_eq!(event.is_deleted, false, "Event should not be marked as deleted"); } else { assert!(status == StatusCode::NOT_FOUND || status == StatusCode::BAD_REQUEST); } @@ -342,8 +368,24 @@ mod tests { .unwrap(); let response = router.oneshot(request).await.unwrap(); - // This will likely fail due to invalid hackathon ID, but tests the endpoint structure - assert!(response.status() == StatusCode::CREATED || response.status() == StatusCode::NOT_FOUND || response.status() == StatusCode::BAD_REQUEST); + let status = response.status(); + if status == StatusCode::CREATED { + // Parse created timeline and assert all fields are present + let timeline: imphnen_hackathon::v1::hackathon::hackathon_dto::HackathonTimelineDto = + crate::common::response_helpers::parse_response_data(response, 2048).await; + + // Assert all required fields are present and not empty + assert!(!timeline.id.is_empty(), "Timeline ID should not be empty"); + assert!(!timeline.hackathon_id.is_empty(), "Hackathon ID should not be empty"); + assert!(!timeline.phase.to_string().is_empty(), "Phase should not be empty"); + assert!(!timeline.title.is_empty(), "Timeline title should not be empty"); + assert!(!timeline.start_date.to_rfc3339().is_empty(), "Start date should not be empty"); + assert!(!timeline.end_date.to_rfc3339().is_empty(), "End date should not be empty"); + assert!(timeline.order > 0, "Order should be positive"); + assert_eq!(timeline.is_deleted, false, "Timeline should not be marked as deleted"); + } else { + assert!(status == StatusCode::NOT_FOUND || status == StatusCode::BAD_REQUEST); + } } #[tokio::test] @@ -424,7 +466,16 @@ mod tests { if status == StatusCode::CREATED { let submission: imphnen_hackathon::v1::hackathon::hackathon_dto::HackathonSubmissionDto = crate::common::response_helpers::parse_response_data(response, 2048).await; + // Assert all required fields are present and not empty + assert!(!submission.id.is_empty(), "Submission ID should not be empty"); + assert!(!submission.hackathon_id.is_empty(), "Hackathon ID should not be empty"); + assert!(!submission.team_id.is_empty(), "Team ID should not be empty"); assert_eq!(submission.project_name, "Controller Submission Test"); + assert!(!submission.description.is_empty(), "Description should not be empty"); + assert!(submission.technologies.len() > 0, "Technologies list should not be empty"); + assert!(!submission.submission_status.to_string().is_empty(), "Submission status should not be empty"); + assert!(!submission.submitted_at.to_rfc3339().is_empty(), "Submitted at should not be empty"); + assert_eq!(submission.is_deleted, false, "Submission should not be marked as deleted"); } else { assert!(status == StatusCode::NOT_FOUND || status == StatusCode::BAD_REQUEST); } @@ -446,7 +497,16 @@ mod tests { let list: Vec = crate::common::response_helpers::parse_response_data(response, 4096).await; if !list.is_empty() { - assert!(!list[0].id.is_empty()); + let submission = &list[0]; + assert!(!submission.id.is_empty(), "Submission ID should not be empty"); + assert!(!submission.hackathon_id.is_empty(), "Hackathon ID should not be empty"); + assert!(!submission.team_id.is_empty(), "Team ID should not be empty"); + assert!(!submission.project_name.is_empty(), "Project name should not be empty"); + assert!(!submission.description.is_empty(), "Description should not be empty"); + assert!(submission.technologies.len() > 0, "Technologies list should not be empty"); + assert!(!submission.submission_status.to_string().is_empty(), "Submission status should not be empty"); + assert!(!submission.submitted_at.to_rfc3339().is_empty(), "Submitted at should not be empty"); + assert_eq!(submission.is_deleted, false, "Submission should not be marked as deleted"); } } else { assert_eq!(status, StatusCode::NOT_FOUND); diff --git a/tests/src/iam/auth/auth_controller_test.rs b/tests/src/iam/auth/auth_controller_test.rs index d6c2af7..e07b40d 100644 --- a/tests/src/iam/auth/auth_controller_test.rs +++ b/tests/src/iam/auth/auth_controller_test.rs @@ -75,6 +75,10 @@ mod tests { 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"); + assert!(!token_obj.user.status.is_empty(), "user status must be present and non-empty"); + assert_eq!(token_obj.user.phone_number, Some("+1234567890".to_string()), "user phone_number must match registered phone number"); + assert!(!token_obj.user.created_at.is_empty(), "user created_at must be present and non-empty"); + assert!(!token_obj.user.updated_at.is_empty(), "user updated_at must be present and non-empty"); // Clean up let user = repo.query_user_by_email(email.clone()).await.unwrap(); diff --git a/tests/src/iam/auth/auth_service_test.rs b/tests/src/iam/auth/auth_service_test.rs index 6c75ecc..1313d7d 100644 --- a/tests/src/iam/auth/auth_service_test.rs +++ b/tests/src/iam/auth/auth_service_test.rs @@ -50,8 +50,19 @@ mod tests { 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"); + + // Validate ALL fields in TokenDto response assert!(!token_data.access_token.is_empty(), "Access token must be present"); assert!(!token_data.refresh_token.is_empty(), "Refresh token must be present"); + assert!(token_data.token_type.is_some(), "Token type must be present"); + assert!(token_data.expires_in.is_some(), "Token expires_in must be present"); + assert!(token_data.not_before.is_some(), "Token not_before must be present"); + assert!(token_data.issued_at.is_some(), "Token issued_at must be present"); + assert!(token_data.jwt_id.is_some(), "Token jwt_id must be present"); + assert!(token_data.subject.is_some(), "Token subject must be present"); + assert!(token_data.audience.is_some(), "Token audience must be present"); + assert!(token_data.issuer.is_some(), "Token issuer must be present"); + assert!(token_data.refresh_expires_in.is_some(), "Token refresh_expires_in must be present"); // Clean up let user = repo.query_user_by_email(email.clone()).await.unwrap(); @@ -107,10 +118,22 @@ 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(); + + // Validate ALL required fields in UsersSchema response 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"); + assert!(!created_user.phone_number.unwrap().is_empty(), "Registered user must have non-empty phone_number"); + assert!(!created_user.role.id.id.to_raw().is_empty(), "Registered user must have non-empty role id"); + assert!(!created_user.role.name.is_empty(), "Registered user must have non-empty role name"); + assert!(created_user.created_at.is_some(), "Registered user must have created_at timestamp"); + assert!(created_user.updated_at.is_some(), "Registered user must have updated_at timestamp"); + assert!(created_user.is_deleted == false, "Registered user should not be deleted"); + assert!(created_user.avatar.is_some(), "Registered user must have avatar field"); + assert!(created_user.bio.is_some(), "Registered user must have bio field"); + assert!(created_user.gender.is_some(), "Registered user must have gender field"); + assert!(created_user.birthdate.is_some(), "Registered user must have birthdate field"); // Clean up let _ = repo.query_delete_user(created_user.id.id.to_raw()).await; @@ -349,8 +372,19 @@ mod tests { let response_data: ResponseSuccessDto = crate::common::response_helpers::parse_response(response, 8192).await; 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()); + + // Validate ALL fields in TokenDto response + assert!(token_data.access_token.is_some(), "Refresh token response must have access_token"); + assert!(token_data.refresh_token.is_some(), "Refresh token response must have refresh_token"); + assert!(token_data.token_type.is_some(), "Refresh token response must have token_type"); + assert!(token_data.expires_in.is_some(), "Refresh token response must have expires_in"); + assert!(token_data.not_before.is_some(), "Refresh token response must have not_before"); + assert!(token_data.issued_at.is_some(), "Refresh token response must have issued_at"); + assert!(token_data.jwt_id.is_some(), "Refresh token response must have jwt_id"); + assert!(token_data.subject.is_some(), "Refresh token response must have subject"); + assert!(token_data.audience.is_some(), "Refresh token response must have audience"); + assert!(token_data.issuer.is_some(), "Refresh token response must have issuer"); + assert!(token_data.refresh_expires_in.is_some(), "Refresh token response must have refresh_expires_in"); // Clean up let user = repo.query_user_by_email(email.clone()).await.unwrap(); diff --git a/tests/src/iam/permissions/permissions_controller_test.rs b/tests/src/iam/permissions/permissions_controller_test.rs index 5146983..7c59eda 100644 --- a/tests/src/iam/permissions/permissions_controller_test.rs +++ b/tests/src/iam/permissions/permissions_controller_test.rs @@ -32,8 +32,14 @@ mod tests { // Verify response body contains permission data let created_permission: PermissionsSchema = crate::common::response_helpers::parse_response(response, 1024).await; + + // Validate all required fields in PermissionsSchema 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"); + assert!(created_permission.created_at.is_some(), "Created permission must have created_at timestamp"); + assert!(created_permission.updated_at.is_some(), "Created permission must have updated_at timestamp"); + assert!(created_permission.is_active == true, "Created permission should be active by default"); + assert!(created_permission.is_deleted == false, "Created permission should not be deleted by default"); // Verify permission was created in database let db_permission = repo diff --git a/tests/src/iam/permissions/permissions_service_test.rs b/tests/src/iam/permissions/permissions_service_test.rs index c91bfd3..d57b816 100644 --- a/tests/src/iam/permissions/permissions_service_test.rs +++ b/tests/src/iam/permissions/permissions_service_test.rs @@ -32,8 +32,14 @@ mod tests { // Verify response body contains created permission data let created: PermissionsSchema = crate::common::response_helpers::parse_response(response, 1024).await; + + // Validate all required fields in PermissionsSchema assert!(!created.id.is_empty(), "Created permission must have non-empty id"); assert_eq!(created.name, permission_name, "Created permission name must match request"); + assert!(created.created_at.is_some(), "Created permission must have created_at timestamp"); + assert!(created.updated_at.is_some(), "Created permission must have updated_at timestamp"); + assert!(created.is_active == true, "Created permission should be active by default"); + assert!(created.is_deleted == false, "Created permission should not be deleted by default"); // Verify permission was created in database let created_permission = repo @@ -80,9 +86,15 @@ mod tests { // Verify response body contains permission data let body: PermissionsSchema = crate::common::response_helpers::parse_response(response, 1024).await; + + // Validate all required fields in PermissionsSchema 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"); + assert!(body.created_at.is_some(), "Permission must have created_at timestamp"); + assert!(body.updated_at.is_some(), "Permission must have updated_at timestamp"); + assert!(body.is_active == true, "Permission should be active"); + assert!(body.is_deleted == false, "Permission should not be deleted"); // Clean up let _ = repo.query_delete_permission(permission_id).await; @@ -128,8 +140,14 @@ mod tests { // Verify response body contains updated permission data let body: PermissionsSchema = crate::common::response_helpers::parse_response(response, 1024).await; + + // Validate all required fields in PermissionsSchema 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"); + assert!(body.created_at.is_some(), "Updated permission must have created_at timestamp"); + assert!(body.updated_at.is_some(), "Updated permission must have updated_at timestamp"); + assert!(body.is_active == true, "Updated permission should be active"); + assert!(body.is_deleted == false, "Updated permission should not be deleted"); // Verify permission was updated in database let updated_permission = repo diff --git a/tests/src/iam/roles/roles_controller_test.rs b/tests/src/iam/roles/roles_controller_test.rs index b3ea6a2..13801a6 100644 --- a/tests/src/iam/roles/roles_controller_test.rs +++ b/tests/src/iam/roles/roles_controller_test.rs @@ -32,9 +32,15 @@ mod tests { // 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; + + // Validate all required fields in RolesDetailItemDto 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"); + assert!(created_role.is_deleted == false, "Created role should not be marked as deleted"); + assert!(created_role.permissions.len() >= 0, "Created role must have permissions array"); + assert!(created_role.created_at.is_some(), "Created role must have created_at timestamp"); + assert!(created_role.updated_at.is_some(), "Created role must have updated_at timestamp"); // Verify role was created in database let db_role = repo @@ -125,12 +131,15 @@ mod tests { 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 + // Verify all items have required fields in RolesListItemDto 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"); + assert!(item.get("permissions_count").is_some(), "Role list items must have permissions_count"); + assert!(item.get("created_at").is_some(), "Role list items must have created_at timestamp"); + assert!(item.get("updated_at").is_some(), "Role list items must have updated_at timestamp"); } let names: Vec = arr.iter().filter_map(|it| it.get("name").and_then(|n| n.as_str()).map(|s| s.to_string())).collect(); @@ -180,9 +189,14 @@ mod tests { let role: imphnen_iam::v1::roles::roles_dto::RolesDetailItemDto = crate::common::response_helpers::parse_response(response, 1024).await; + // Validate all required fields in RolesDetailItemDto 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"); + assert!(role.is_deleted == false, "Role should not be marked as deleted"); + assert!(role.permissions.len() >= 0, "Role must have permissions array"); + assert!(role.created_at.is_some(), "Role must have created_at timestamp"); + assert!(role.updated_at.is_some(), "Role must have updated_at timestamp"); // Clean up let _ = repo.query_delete_role(role_id).await; diff --git a/tests/src/iam/roles/roles_service_test.rs b/tests/src/iam/roles/roles_service_test.rs index 9ae6493..86f98cb 100644 --- a/tests/src/iam/roles/roles_service_test.rs +++ b/tests/src/iam/roles/roles_service_test.rs @@ -31,8 +31,14 @@ mod tests { // 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; + + // Validate all required fields in RolesDetailItemDto 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!(created_role.is_deleted == false, "Created role should not be marked as deleted"); + assert!(created_role.permissions.len() >= 0, "Created role must have permissions array"); + assert!(created_role.created_at.is_some(), "Created role must have created_at timestamp"); + assert!(created_role.updated_at.is_some(), "Created role must have updated_at timestamp"); // Verify role was created in database let db_role = repo @@ -84,8 +90,13 @@ mod tests { }; let role: imphnen_iam::v1::roles::roles_dto::RolesDetailItemDto = role_data; + // Validate all required fields in RolesDetailItemDto assert!(!role.id.is_empty(), "Role must have non-empty id"); assert_eq!(role.name, role_name, "Role name must match created role"); + assert!(role.is_deleted == false, "Role should not be marked as deleted"); + assert!(role.permissions.len() >= 0, "Role must have permissions array"); + assert!(role.created_at.is_some(), "Role must have created_at timestamp"); + assert!(role.updated_at.is_some(), "Role must have updated_at timestamp"); // Clean up let _ = repo.query_delete_role(role_id).await; @@ -221,14 +232,24 @@ mod tests { let list: imphnen_entities::ResponseListSuccessDto> = 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(), "Role list items must have non-empty id"); - assert!(!list.data[0].name.is_empty(), "Role list items must have non-empty name"); + let role = &list.data[0]; + // Validate all required fields in RolesListItemDto + assert!(!role.id.is_empty(), "Role list items must have non-empty id"); + assert!(!role.name.is_empty(), "Role list items must have non-empty name"); + assert!(role.permissions_count >= 0, "Role list items must have permissions_count"); + assert!(role.created_at.is_some(), "Role list items must have created_at timestamp"); + assert!(role.updated_at.is_some(), "Role list items must have updated_at timestamp"); } } else if v.is_array() { let arr: Vec = serde_json::from_value(v).unwrap_or_default(); if !arr.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"); + let role = &arr[0]; + // Validate all required fields in RolesListItemDto + assert!(!role.id.is_empty(), "Role list items must have non-empty id"); + assert!(!role.name.is_empty(), "Role list items must have non-empty name"); + assert!(role.permissions_count >= 0, "Role list items must have permissions_count"); + assert!(role.created_at.is_some(), "Role list items must have created_at timestamp"); + assert!(role.updated_at.is_some(), "Role list items must have updated_at timestamp"); } } else { // accept other object shapes diff --git a/tests/src/iam/teams/admin_teams_controller_tests.rs b/tests/src/iam/teams/admin_teams_controller_tests.rs index 9c87965..ecee0be 100644 --- a/tests/src/iam/teams/admin_teams_controller_tests.rs +++ b/tests/src/iam/teams/admin_teams_controller_tests.rs @@ -119,15 +119,28 @@ async fn test_admin_team_endpoints_sensitive_data_exposure() { let response_json: ResponseListSuccessDto> = serde_json::from_value(v).unwrap(); - // Verify sensitive fields are present in admin response + // Verify ALL fields are present and not empty in admin response (AdminTeamsListItemDto) 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 - !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"); + !team.id.is_empty() && // Required: non-empty id + !team.name.is_empty() && // Required: non-empty name + team.description.is_some() && // Required: description field exists + team.leader.is_some() && // Required: leader field exists + team.leader.as_ref().map_or(false, |l| !l.id.is_empty()) && // Leader has id + team.leader.as_ref().map_or(false, |l| !l.user_id.is_empty()) && // Leader has user_id + team.leader.as_ref().map_or(false, |l| !l.fullname.is_empty()) && // Leader has fullname + team.leader.as_ref().map_or(false, |l| !l.role.is_empty()) && // Leader has role + team.is_open != false && // Required: is_open field exists + team.current_member_count >= 0 && // Required: current_member_count exists + team.max_members.is_some() && // Required: max_members field exists + team.skills_required.is_some() && // Required: skills_required field exists + team.location.is_some() && // Required: location field exists + team.avatar.is_some() && // Required: avatar field exists + team.website_url.is_some() && // Required: website_url field exists + team.github_url.is_some() && // Required: github_url field exists + team.is_active != false && // Required: is_active field exists + team.is_deleted != false && // Required: is_deleted field exists + team.created_at.is_some() // Required: created_at field exists + }), "Admin team list should expose ALL required fields and sensitive 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( @@ -143,22 +156,45 @@ async fn test_admin_team_endpoints_sensitive_data_exposure() { serde_json::from_value(v).unwrap(); let admin_team = response_json.data; - // Verify sensitive fields are present + // Verify ALL fields are present and not empty in admin team detail response (AdminTeamsDetailItemDto) 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.description.is_some(), "Admin team detail should have description field"); + assert!(admin_team.leader.is_some(), "Admin team detail should have leader field"); + + // Validate leader object + let leader = admin_team.leader.as_ref().unwrap(); + assert!(!leader.id.is_empty(), "Admin team leader should have non-empty id"); + assert!(!leader.user_id.is_empty(), "Admin team leader should have non-empty user_id"); + assert!(!leader.fullname.is_empty(), "Admin team leader should have non-empty fullname"); + assert!(leader.role.is_some(), "Admin team leader should have role field"); + assert!(leader.joined_at.is_some(), "Admin team leader should have joined_at field"); + + assert!(admin_team.is_open != false, "Admin team detail should show is_open field"); + assert!(admin_team.current_member_count >= 0, "Admin team detail should show current_member_count"); + assert!(admin_team.max_members.is_some(), "Admin team detail should show max_members field"); + assert!(admin_team.skills_required.is_some(), "Admin team detail should show skills_required field"); + assert!(admin_team.location.is_some(), "Admin team detail should show location field"); + assert!(admin_team.avatar.is_some(), "Admin team detail should show avatar field"); assert!(admin_team.website_url.is_some(), "Admin team detail should show website_url"); assert!(admin_team.github_url.is_some(), "Admin team detail should show github_url"); assert!(admin_team.members.len() >= 2, "Admin team detail should show all members"); + assert!(admin_team.is_active != false, "Admin team detail should show is_active field"); + assert!(admin_team.is_deleted != false, "Admin team detail should show is_deleted field"); + assert!(admin_team.created_at.is_some(), "Admin team detail should show created_at field"); + assert!(admin_team.updated_at.is_some(), "Admin team detail should show updated_at field"); - // Verify all members have sensitive info (email should be present for admins) + // Verify ALL member fields are present and not empty (TeamMemberDto) let has_all_member_info = admin_team.members.iter().all(|member| { - 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 - }); + !member.id.is_empty() && // Required: non-empty id + !member.user_id.is_empty() && // Required: non-empty user_id + !member.fullname.is_empty() && // Required: non-empty fullname + member.email.is_some() && // Required: email field exists (admin can see emails) + !member.role.is_empty() && // Required: non-empty role + member.skills.is_some() && // Required: skills field exists + member.joined_at.is_some() && // Required: joined_at field exists + member.avatar.is_some() // Required: avatar field exists + }); assert!(has_all_member_info, "Admin team detail should expose all member sensitive information"); @@ -176,13 +212,17 @@ async fn test_admin_team_endpoints_sensitive_data_exposure() { serde_json::from_value(v).unwrap(); let admin_members = response_json.data; - // Verify all members have sensitive info + // Verify ALL member fields are present and not empty (TeamMemberDto) let has_all_member_info = admin_members.iter().all(|member| { - 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 - }); + !member.id.is_empty() && // Required: non-empty id + !member.user_id.is_empty() && // Required: non-empty user_id + !member.fullname.is_empty() && // Required: non-empty fullname + member.email.is_some() && // Required: email field exists (admin can see emails) + !member.role.is_empty() && // Required: non-empty role + member.skills.is_some() && // Required: skills field exists + member.joined_at.is_some() && // Required: joined_at field exists + member.avatar.is_some() // Required: avatar field exists + }); assert!(has_all_member_info, "Admin team members endpoint should expose all member sensitive information"); diff --git a/tests/src/iam/teams/teams_controller_test.rs b/tests/src/iam/teams/teams_controller_test.rs index 3151972..9904cbd 100644 --- a/tests/src/iam/teams/teams_controller_test.rs +++ b/tests/src/iam/teams/teams_controller_test.rs @@ -46,8 +46,20 @@ mod tests { let team_response: imphnen_iam::v1::teams::teams_dto::TeamsCreateResponseDto = crate::common::response_helpers::parse_response(response, 2048).await; + // Validate all required fields in TeamsCreateResponseDto 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"); + assert!(team_response.team.is_some(), "Created team must include team data"); + + // Validate nested team data in response + let team = team_response.team.as_ref().unwrap(); + assert!(!team.id.is_empty(), "Team must have non-empty id"); + assert!(!team.name.is_empty(), "Team must have non-empty name"); + assert!(team.description.is_some(), "Team must have description field"); + assert!(team.leader.is_some(), "Team must have leader field"); + assert!(team.is_open != false, "Team must have is_open field"); + assert!(team.current_member_count >= 0, "Team must have current_member_count"); + assert!(team.created_at.is_some(), "Team must have created_at timestamp"); // Verify team was created in database let team_thing = make_thing_from_enum(ResourceEnum::Teams, &user.id.id.to_raw()); @@ -109,7 +121,32 @@ mod tests { let inner = v.get("data").expect("get team should return data field").clone(); let team: imphnen_iam::v1::teams::teams_dto::TeamsDetailResponseDto = serde_json::from_value(inner).expect("response data must deserialize to TeamsDetailResponseDto"); + + // Validate all required fields in TeamsDetailResponseDto + assert!(!team.id.is_empty(), "Team must have non-empty id"); assert_eq!(team.name, "Test Get Team"); + assert!(team.description.is_some(), "Team must have description field"); + assert!(team.leader.is_some(), "Team must have leader field"); + assert!(team.is_open != false, "Team must have is_open field"); + assert!(team.current_member_count >= 0, "Team must have current_member_count"); + assert!(team.max_members.is_some(), "Team must have max_members field"); + assert!(team.skills_required.is_some(), "Team must have skills_required field"); + assert!(team.location.is_some(), "Team must have location field"); + assert!(team.avatar.is_some(), "Team must have avatar field"); + assert!(team.website_url.is_some(), "Team must have website_url field"); + assert!(team.github_url.is_some(), "Team must have github_url field"); + assert!(team.members.is_some(), "Team must have members field"); + assert!(team.is_active != false, "Team must have is_active field"); + assert!(team.created_at.is_some(), "Team must have created_at timestamp"); + assert!(team.updated_at.is_some(), "Team must have updated_at timestamp"); + + // Validate leader object + let leader = team.leader.as_ref().unwrap(); + assert!(!leader.id.is_empty(), "Leader must have non-empty id"); + assert!(!leader.user_id.is_empty(), "Leader must have non-empty user_id"); + assert!(!leader.fullname.is_empty(), "Leader must have non-empty fullname"); + assert!(leader.role.is_some(), "Leader must have role field"); + assert!(leader.joined_at.is_some(), "Leader must have joined_at timestamp"); // Clean up let _ = repo.query_delete_team(team_id).await; @@ -331,10 +368,27 @@ mod tests { assert!(!search_response.data.is_empty(), "Search should return at least one team"); - // Verify all results have required fields + // Verify all results have required fields in TeamsListItemDto 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"); + assert!(team.description.is_some(), "Search result team must have description field"); + assert!(team.leader.is_some(), "Search result team must have leader field"); + assert!(team.is_open != false, "Search result team must have is_open field"); + assert!(team.current_member_count >= 0, "Search result team must have current_member_count"); + assert!(team.max_members.is_some(), "Search result team must have max_members field"); + assert!(team.skills_required.is_some(), "Search result team must have skills_required field"); + assert!(team.location.is_some(), "Search result team must have location field"); + assert!(team.avatar.is_some(), "Search result team must have avatar field"); + assert!(team.created_at.is_some(), "Search result team must have created_at timestamp"); + + // Validate leader object in search results + let leader = team.leader.as_ref().unwrap(); + assert!(!leader.id.is_empty(), "Search result leader must have non-empty id"); + assert!(!leader.user_id.is_empty(), "Search result leader must have non-empty user_id"); + assert!(!leader.fullname.is_empty(), "Search result leader must have non-empty fullname"); + assert!(leader.role.is_some(), "Search result leader must have role field"); + assert!(leader.joined_at.is_some(), "Search result leader must have joined_at timestamp"); } // Verify our team is in results diff --git a/tests/src/iam/teams/teams_service_test.rs b/tests/src/iam/teams/teams_service_test.rs index 397fed7..a79d221 100644 --- a/tests/src/iam/teams/teams_service_test.rs +++ b/tests/src/iam/teams/teams_service_test.rs @@ -26,9 +26,26 @@ mod tests { let arr = list_val.as_array().expect("team list should be an array"); if !arr.is_empty() { let first = &arr[0]; + // Validate all required fields in TeamsListItemDto 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"); + assert!(first.get("description").is_some(), "team items must have description"); + assert!(first.get("leader").is_some(), "team items must have leader"); + + // Validate leader object (TeamMemberDto) + let leader = first.get("leader").expect("leader should exist").as_object().expect("leader should be an object"); + assert!(leader.get("id").is_some(), "leader must have id"); + assert!(leader.get("user_id").is_some(), "leader must have user_id"); + assert!(leader.get("fullname").is_some(), "leader must have fullname"); + assert!(leader.get("fullname").and_then(|n| n.as_str()).map_or(false, |s| !s.is_empty()), "leader fullname must not be empty"); + assert!(leader.get("role").is_some(), "leader must have role"); + assert!(leader.get("role").and_then(|n| n.as_str()).map_or(false, |s| !s.is_empty()), "leader role must not be empty"); + assert!(leader.get("joined_at").is_some(), "leader must have joined_at"); + + assert!(first.get("is_open").is_some(), "team items must have is_open"); + assert!(first.get("current_member_count").is_some(), "team items must have current_member_count"); + assert!(first.get("created_at").is_some(), "team items must have created_at"); } } diff --git a/tests/src/iam/users/users_controller_test.rs b/tests/src/iam/users/users_controller_test.rs index fa53d65..3c50040 100644 --- a/tests/src/iam/users/users_controller_test.rs +++ b/tests/src/iam/users/users_controller_test.rs @@ -40,10 +40,37 @@ mod tests { // 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; + + // Validate all required fields in UsersDetailItemDto assert!(!created_user.id.is_empty(), "Created user must have non-empty id"); + assert!(!created_user.role.id.is_empty(), "Created user must have non-empty role id"); + assert!(!created_user.role.name.is_empty(), "Created user must have non-empty role name"); + assert!(!created_user.fullname.is_empty(), "Created user must have non-empty fullname"); 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!(!created_user.phone_number.is_empty(), "Created user must have non-empty phone_number"); assert_eq!(created_user.is_active, true, "Created user must be active"); + assert!(!created_user.created_at.is_empty(), "Created user must have non-empty created_at"); + assert!(!created_user.updated_at.is_empty(), "Created user must have non-empty updated_at"); + + // Validate optional fields that should exist + assert!(created_user.avatar.is_some(), "Created user should have avatar field"); + assert!(created_user.phone_for_verification.is_some(), "Created user should have phone_for_verification field"); + assert!(created_user.gender.is_some(), "Created user should have gender field"); + assert!(created_user.birthdate.is_some(), "Created user should have birthdate field"); + assert!(created_user.domicile.is_some(), "Created user should have domicile field"); + assert!(created_user.bio.is_some(), "Created user should have bio field"); + assert!(created_user.last_education.is_some(), "Created user should have last_education field"); + assert!(created_user.linkedin_url.is_some(), "Created user should have linkedin_url field"); + assert!(created_user.github_url.is_some(), "Created user should have github_url field"); + assert!(created_user.cv_url.is_some(), "Created user should have cv_url field"); + assert!(created_user.portfolio_url.is_some(), "Created user should have portfolio_url field"); + assert!(created_user.website_url.is_some(), "Created user should have website_url field"); + assert!(created_user.twitter_url.is_some(), "Created user should have twitter_url field"); + assert!(created_user.location.is_some(), "Created user should have location field"); + assert!(created_user.skills.is_some(), "Created user should have skills field"); + assert!(created_user.experience.is_some(), "Created user should have experience field"); + assert!(created_user.education.is_some(), "Created user should have education field"); + assert!(created_user.career_status.is_some(), "Created user should have career_status field"); // Verify user was created in database let db_user = repo diff --git a/tests/src/iam/users/users_service_test.rs b/tests/src/iam/users/users_service_test.rs index 88dcaf4..cf24a24 100644 --- a/tests/src/iam/users/users_service_test.rs +++ b/tests/src/iam/users/users_service_test.rs @@ -31,14 +31,30 @@ mod tests { let list: imphnen_entities::ResponseListSuccessDto> = 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(), "User list items must have non-empty id"); - assert!(!list.data[0].email.is_empty(), "User list items must have non-empty email"); + let user = &list.data[0]; + // Validate all required fields in UsersListItemDto + assert!(!user.id.is_empty(), "User list items must have non-empty id"); + assert!(!user.role.is_empty(), "User list items must have non-empty role"); + assert!(!user.fullname.is_empty(), "User list items must have non-empty fullname"); + assert!(!user.email.is_empty(), "User list items must have non-empty email"); + assert!(!user.phone_number.is_empty(), "User list items must have non-empty phone_number"); + assert!(user.is_active != false, "User list items must have is_active field"); + assert!(!user.created_at.is_empty(), "User list items must have non-empty created_at"); + assert!(!user.updated_at.is_empty(), "User list items must have non-empty updated_at"); } } else if v.is_array() { let arr: Vec = serde_json::from_value(v).unwrap_or_default(); if !arr.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"); + let user = &arr[0]; + // Validate all required fields in UsersListItemDto + assert!(!user.id.is_empty(), "User list items must have non-empty id"); + assert!(!user.role.is_empty(), "User list items must have non-empty role"); + assert!(!user.fullname.is_empty(), "User list items must have non-empty fullname"); + assert!(!user.email.is_empty(), "User list items must have non-empty email"); + assert!(!user.phone_number.is_empty(), "User list items must have non-empty phone_number"); + assert!(user.is_active != false, "User list items must have is_active field"); + assert!(!user.created_at.is_empty(), "User list items must have non-empty created_at"); + assert!(!user.updated_at.is_empty(), "User list items must have non-empty updated_at"); } } else { // other shapes (object without data) — accept for now @@ -109,10 +125,36 @@ mod tests { // 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; + + // Validate all required fields in UsersDetailItemDto assert!(!created_user.id.is_empty(), "Created user must have non-empty id"); + assert!(!created_user.role.id.is_empty(), "Created user must have non-empty role id"); + assert!(!created_user.role.name.is_empty(), "Created user must have non-empty role name"); + assert!(!created_user.fullname.is_empty(), "Created user must have non-empty fullname"); 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!(!created_user.phone_number.is_empty(), "Created user must have non-empty phone_number"); assert_eq!(created_user.is_active, true, "Created user must be active"); + assert!(!created_user.created_at.is_empty(), "Created user must have non-empty created_at"); + assert!(!created_user.updated_at.is_empty(), "Created user must have non-empty updated_at"); + + // Validate optional fields that should exist + assert!(created_user.phone_for_verification.is_some(), "Created user should have phone_for_verification field"); + assert!(created_user.gender.is_some(), "Created user should have gender field"); + assert!(created_user.birthdate.is_some(), "Created user should have birthdate field"); + assert!(created_user.domicile.is_some(), "Created user should have domicile field"); + assert!(created_user.bio.is_some(), "Created user should have bio field"); + assert!(created_user.last_education.is_some(), "Created user should have last_education field"); + assert!(created_user.linkedin_url.is_some(), "Created user should have linkedin_url field"); + assert!(created_user.github_url.is_some(), "Created user should have github_url field"); + assert!(created_user.cv_url.is_some(), "Created user should have cv_url field"); + assert!(created_user.portfolio_url.is_some(), "Created user should have portfolio_url field"); + assert!(created_user.website_url.is_some(), "Created user should have website_url field"); + assert!(created_user.twitter_url.is_some(), "Created user should have twitter_url field"); + assert!(created_user.location.is_some(), "Created user should have location field"); + assert!(created_user.skills.is_some(), "Created user should have skills field"); + assert!(created_user.experience.is_some(), "Created user should have experience field"); + assert!(created_user.education.is_some(), "Created user should have education field"); + assert!(created_user.career_status.is_some(), "Created user should have career_status field"); // Verify user was created in database let db_user = repo.query_user_by_email(email.clone()).await.unwrap();