You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

842 lines
33 KiB

import { describe, it, expect } from "vitest";
import {
canonicalRule,
ruleMatches,
isQuestionVisible,
isQuestionRequired,
} from "./conditional-rules";
import type { QuestionField } from "./schema-adapter";
describe("Conditional Rules Evaluator", () => {
const dummyQuestion: QuestionField = {
id: "child.q",
title: "Child Question",
type: "text",
order: 1,
required: false,
baseRequired: false,
isVisible: true,
description: "",
tooltip: "",
extras: { placeHolder: "", range: [0, 0], options: [] },
options: [],
};
it("should evaluate single trigger option match correctly", () => {
const rule = {
parent_question_id: "appearance_health.physical_health_status",
trigger_option_ids: [
"appearance_health.physical_health_status.i_have_a_specific_or_chronic_illness",
"appearance_health.physical_health_status.i_have_a_physical_deformity_disability_or_limitation",
],
operator: "any_of",
};
// 1. When parent is not answered
expect(ruleMatches(rule, {})).toBe(false);
// 2. When parent is answered with non-matching option
expect(
ruleMatches(rule, {
"appearance_health.physical_health_status": {
value: "i_am_in_perfect_health",
option_id: "appearance_health.physical_health_status.i_am_in_perfect_health",
},
}),
).toBe(false);
// 3. When parent is answered with matching option (full slug)
expect(
ruleMatches(rule, {
"appearance_health.physical_health_status": {
value: "i_have_a_specific_or_chronic_illness",
option_id:
"appearance_health.physical_health_status.i_have_a_specific_or_chronic_illness",
},
}),
).toBe(true);
// 4. When parent value only contains the short value
expect(
ruleMatches(rule, {
"appearance_health.physical_health_status": {
value: "i_have_a_physical_deformity_disability_or_limitation",
},
}),
).toBe(true);
});
it("should evaluate complex nested conditions (e.g. number of children rule)", () => {
// marital_history.number_of_children:
// parent: children_and_guardianship_status (have_children_living_with_me, have_children_not_living_with_me)
// conditions: current_marital_status in (divorced_after_living_together, widowed)
const rule = {
parent_question_id: "marital_history.children_and_guardianship_status",
trigger_option_ids: [
"marital_history.children_and_guardianship_status.have_children_living_with_me",
"marital_history.children_and_guardianship_status.have_children_not_living_with_me",
],
operator: "any_of",
conditions: [
{
parent_question_id: "marital_history.current_marital_status",
trigger_option_ids: [
"marital_history.current_marital_status.divorced_after_living_together",
"marital_history.current_marital_status.widowed",
],
operator: "any_of",
},
],
conditions_operator: "all_of",
root_operator: "all_of",
};
// Case 1: Single, no children -> false
expect(
ruleMatches(rule, {
"marital_history.current_marital_status": {
value: "single_never_married",
},
"marital_history.children_and_guardianship_status": {
value: "no_children",
},
}),
).toBe(false);
// Case 2: Divorced, but no children -> false
expect(
ruleMatches(rule, {
"marital_history.current_marital_status": {
value: "divorced_after_living_together",
option_id:
"marital_history.current_marital_status.divorced_after_living_together",
},
"marital_history.children_and_guardianship_status": {
value: "no_children",
option_id:
"marital_history.children_and_guardianship_status.no_children",
},
}),
).toBe(false);
// Case 3: Divorced AND has children -> true
expect(
ruleMatches(rule, {
"marital_history.current_marital_status": {
value: "divorced_after_living_together",
option_id:
"marital_history.current_marital_status.divorced_after_living_together",
},
"marital_history.children_and_guardianship_status": {
value: "have_children_living_with_me",
option_id:
"marital_history.children_and_guardianship_status.have_children_living_with_me",
},
}),
).toBe(true);
});
it("should evaluate audience rules by gender and age", () => {
const questionForMen: QuestionField = {
...dummyQuestion,
id: "education_career.ability_to_support_marriage_expenses",
audience: {
genders: ["male"],
},
};
const questionForWomen: QuestionField = {
...dummyQuestion,
id: "beliefs_lifestyle.makeup_in_public",
audience: {
genders: ["female"],
},
};
// Male user
expect(isQuestionVisible(questionForMen, {}, { gender: "male" })).toBe(true);
expect(isQuestionVisible(questionForWomen, {}, { gender: "male" })).toBe(false);
// Female user
expect(isQuestionVisible(questionForMen, {}, { gender: "female" })).toBe(false);
expect(isQuestionVisible(questionForWomen, {}, { gender: "female" })).toBe(true);
});
it("should evaluate dynamic requirement via requiredWhen", () => {
const q: QuestionField = {
...dummyQuestion,
required: false,
baseRequired: false,
requiredWhen: {
parent_question_id: "family_background.parents_marital_status",
trigger_option_ids: [
"family_background.parents_marital_status.i_have_special_family_circumstances_and_will_provide_the_details_in_the_description",
],
operator: "any_of",
},
conditionalRule: {
parent_question_id: "family_background.parents_marital_status",
trigger_option_ids: [
"family_background.parents_marital_status.i_have_special_family_circumstances_and_will_provide_the_details_in_the_description",
],
operator: "any_of",
},
};
// When condition not met -> not visible, not required
expect(isQuestionVisible(q, {})).toBe(false);
expect(isQuestionRequired(q, {})).toBe(false);
// When condition met -> visible AND required
const matchingAnswers = {
"family_background.parents_marital_status": {
value:
"i_have_special_family_circumstances_and_will_provide_the_details_in_the_description",
option_id:
"family_background.parents_marital_status.i_have_special_family_circumstances_and_will_provide_the_details_in_the_description",
},
};
expect(isQuestionVisible(q, matchingAnswers)).toBe(true);
expect(isQuestionRequired(q, matchingAnswers)).toBe(true);
});
it("should evaluate representative questions as optional for men and conditional for women based on age", () => {
const repNameQuestion: QuestionField = {
...dummyQuestion,
id: "contact_residence.representative_s_full_name",
title: "Representative's Full Name",
required: false,
baseRequired: false,
requiredWhen: {
genders: ["female"],
maxAge: 26,
},
};
const repPhoneQuestion: QuestionField = {
...dummyQuestion,
id: "contact_residence.representative_s_contact_number",
title: "Representative's Contact Number",
type: "phone",
required: false,
baseRequired: false,
requiredWhen: {
genders: ["female"],
maxAge: 26,
},
};
const repRelQuestion: QuestionField = {
...dummyQuestion,
id: "contact_residence.relationship_to_representative",
title: "Relationship to Representative",
type: "dropdown",
required: false,
baseRequired: false,
requiredWhen: {
genders: ["female"],
maxAge: 26,
},
};
const repQuestions = [repNameQuestion, repPhoneQuestion, repRelQuestion];
// For Male (regardless of age: 20, 26, 30): ALWAYS OPTIONAL
for (const age of [18, 20, 25, 26, 27, 35]) {
const maleContext = { gender: "male", age };
for (const question of repQuestions) {
expect(isQuestionRequired(question, {}, maleContext)).toBe(false);
}
}
// For Female <= 26: REQUIRED
for (const age of [18, 20, 25, 26]) {
const youngFemaleContext = { gender: "female", age };
for (const question of repQuestions) {
expect(isQuestionRequired(question, {}, youngFemaleContext)).toBe(true);
}
}
// For Female >= 27: OPTIONAL
for (const age of [27, 30, 35]) {
const olderFemaleContext = { gender: "female", age };
for (const question of repQuestions) {
expect(isQuestionRequired(question, {}, olderFemaleContext)).toBe(false);
}
}
// When gender is unknown: OPTIONAL
for (const question of repQuestions) {
expect(isQuestionRequired(question, {}, {})).toBe(false);
}
});
it("should correctly handle physical health 4-option visibility and medication requirement", () => {
// 1. Physical Health Description
const physicalHealthDescription: QuestionField = {
...dummyQuestion,
id: "appearance_health.physical_health_description",
title: "Physical Health Description",
required: false,
baseRequired: false,
visibility: {
parent_question_id: "appearance_health.physical_health_status",
trigger_option_ids: [
"appearance_health.physical_health_status.i_have_a_specific_or_chronic_illness",
"appearance_health.physical_health_status.i_have_a_disability_or_physical_limitation",
"appearance_health.physical_health_status.i_have_other_illness_or_physical_conditions",
],
operator: "any_of",
},
requiredWhen: {
parent_question_id: "appearance_health.physical_health_status",
trigger_option_ids: [
"appearance_health.physical_health_status.i_have_a_specific_or_chronic_illness",
"appearance_health.physical_health_status.i_have_a_disability_or_physical_limitation",
"appearance_health.physical_health_status.i_have_other_illness_or_physical_conditions",
],
operator: "any_of",
},
};
// Option A: No illness -> hidden and not required
const optionAAnswers = {
"appearance_health.physical_health_status": {
value: "i_currently_have_no_specific_illness_or_physical_limitation",
option_id:
"appearance_health.physical_health_status.i_currently_have_no_specific_illness_or_physical_limitation",
},
};
expect(isQuestionVisible(physicalHealthDescription, optionAAnswers)).toBe(false);
expect(isQuestionRequired(physicalHealthDescription, optionAAnswers)).toBe(false);
// Options B, C, D -> visible and required
const optionBAnswers = {
"appearance_health.physical_health_status": {
value: "i_have_a_specific_or_chronic_illness",
option_id:
"appearance_health.physical_health_status.i_have_a_specific_or_chronic_illness",
},
};
expect(isQuestionVisible(physicalHealthDescription, optionBAnswers)).toBe(true);
expect(isQuestionRequired(physicalHealthDescription, optionBAnswers)).toBe(true);
const optionCAnswers = {
"appearance_health.physical_health_status": {
value: "i_have_a_disability_or_physical_limitation",
option_id:
"appearance_health.physical_health_status.i_have_a_disability_or_physical_limitation",
},
};
expect(isQuestionVisible(physicalHealthDescription, optionCAnswers)).toBe(true);
expect(isQuestionRequired(physicalHealthDescription, optionCAnswers)).toBe(true);
const optionDAnswers = {
"appearance_health.physical_health_status": {
value: "i_have_other_illness_or_physical_conditions",
option_id:
"appearance_health.physical_health_status.i_have_other_illness_or_physical_conditions",
},
};
expect(isQuestionVisible(physicalHealthDescription, optionDAnswers)).toBe(true);
expect(isQuestionRequired(physicalHealthDescription, optionDAnswers)).toBe(true);
// 2. Medication Name and Reason
const medicationDescription: QuestionField = {
...dummyQuestion,
id: "appearance_health.medication_name_and_reason_for_use",
title: "Medication Name and Reason for Use",
required: false,
baseRequired: false,
visibility: {
parent_question_id:
"appearance_health.do_you_currently_take_any_medication_on_an_ongoing_basis",
trigger_option_ids: [
"appearance_health.do_you_currently_take_any_medication_on_an_ongoing_basis.yes",
],
operator: "any_of",
conditions: [
{
parent_question_id:
"appearance_health.are_you_currently_taking_medication_for_mental_health_related_issues",
trigger_option_ids: [
"appearance_health.are_you_currently_taking_medication_for_mental_health_related_issues.yes",
],
operator: "any_of",
},
],
root_operator: "any_of",
},
requiredWhen: {
parent_question_id:
"appearance_health.do_you_currently_take_any_medication_on_an_ongoing_basis",
trigger_option_ids: [
"appearance_health.do_you_currently_take_any_medication_on_an_ongoing_basis.yes",
],
operator: "any_of",
conditions: [
{
parent_question_id:
"appearance_health.are_you_currently_taking_medication_for_mental_health_related_issues",
trigger_option_ids: [
"appearance_health.are_you_currently_taking_medication_for_mental_health_related_issues.yes",
],
operator: "any_of",
},
],
root_operator: "any_of",
},
};
// Both No -> hidden
const medNoAnswers = {
"appearance_health.do_you_currently_take_any_medication_on_an_ongoing_basis": {
value: "no",
option_id:
"appearance_health.do_you_currently_take_any_medication_on_an_ongoing_basis.no",
},
"appearance_health.are_you_currently_taking_medication_for_mental_health_related_issues": {
value: "no",
option_id:
"appearance_health.are_you_currently_taking_medication_for_mental_health_related_issues.no",
},
};
expect(isQuestionVisible(medicationDescription, medNoAnswers)).toBe(false);
expect(isQuestionRequired(medicationDescription, medNoAnswers)).toBe(false);
// Mental health med Yes -> visible and required
const medMentalYesAnswers = {
"appearance_health.do_you_currently_take_any_medication_on_an_ongoing_basis": {
value: "no",
option_id:
"appearance_health.do_you_currently_take_any_medication_on_an_ongoing_basis.no",
},
"appearance_health.are_you_currently_taking_medication_for_mental_health_related_issues": {
value: "yes",
option_id:
"appearance_health.are_you_currently_taking_medication_for_mental_health_related_issues.yes",
},
};
expect(isQuestionVisible(medicationDescription, medMentalYesAnswers)).toBe(true);
expect(isQuestionRequired(medicationDescription, medMentalYesAnswers)).toBe(true);
// Ongoing med Yes -> visible and required
const medOngoingYesAnswers = {
"appearance_health.do_you_currently_take_any_medication_on_an_ongoing_basis": {
value: "yes",
option_id:
"appearance_health.do_you_currently_take_any_medication_on_an_ongoing_basis.yes",
},
"appearance_health.are_you_currently_taking_medication_for_mental_health_related_issues": {
value: "no",
option_id:
"appearance_health.are_you_currently_taking_medication_for_mental_health_related_issues.no",
},
};
expect(isQuestionVisible(medicationDescription, medOngoingYesAnswers)).toBe(true);
expect(isQuestionRequired(medicationDescription, medOngoingYesAnswers)).toBe(true);
});
it("should hide job title, work location, and monthly income for student, unemployed, student & job seeking, and homemaker", () => {
const jobTitle: QuestionField = {
...dummyQuestion,
id: "education_career.job_title",
title: "عنوان شغلی",
visibility: {
parent_question_id: "education_career.employment_status",
trigger_option_ids: [
"education_career.employment_status.full_time_employed",
"education_career.employment_status.part_time_employed",
"education_career.employment_status.self_employed_freelancer",
"education_career.employment_status.entrepreneur_business_owner",
"education_career.employment_status.working_student",
"education_career.employment_status.retired",
],
operator: "any_of",
},
};
const workLocation: QuestionField = {
...dummyQuestion,
id: "education_career.work_location",
title: "محل فعالیت",
visibility: {
parent_question_id: "education_career.employment_status",
trigger_option_ids: [
"education_career.employment_status.full_time_employed",
"education_career.employment_status.part_time_employed",
"education_career.employment_status.self_employed_freelancer",
"education_career.employment_status.entrepreneur_business_owner",
"education_career.employment_status.working_student",
],
operator: "any_of",
},
};
const monthlyIncome: QuestionField = {
...dummyQuestion,
id: "education_career.monthly_income",
title: "میزان درآمد ماهانه",
required: false,
visibility: {
parent_question_id: "education_career.employment_status",
trigger_option_ids: [
"education_career.employment_status.full_time_employed",
"education_career.employment_status.part_time_employed",
"education_career.employment_status.self_employed_freelancer",
"education_career.employment_status.entrepreneur_business_owner",
"education_career.employment_status.working_student",
"education_career.employment_status.retired",
],
operator: "any_of",
},
requiredWhen: {
parent_question_id: "education_career.employment_status",
trigger_option_ids: [
"education_career.employment_status.full_time_employed",
"education_career.employment_status.part_time_employed",
"education_career.employment_status.self_employed_freelancer",
"education_career.employment_status.entrepreneur_business_owner",
"education_career.employment_status.working_student",
"education_career.employment_status.retired",
],
operator: "any_of",
},
};
// Hidden cases: دانشجو, دانشجو و جویای کار, جویای کار / بیکار, خانه‌دار
const hiddenStatuses = [
"student",
"student_and_job_seeking",
"job_seeking_unemployed",
"homemaker",
];
for (const status of hiddenStatuses) {
const answers = {
"education_career.employment_status": {
value: status,
option_id: `education_career.employment_status.${status}`,
},
};
expect(isQuestionVisible(jobTitle, answers)).toBe(false);
expect(isQuestionVisible(workLocation, answers)).toBe(false);
expect(isQuestionVisible(monthlyIncome, answers)).toBe(false);
expect(isQuestionRequired(monthlyIncome, answers)).toBe(false);
}
// Visible case: Full time employed
const fullTimeAnswers = {
"education_career.employment_status": {
value: "full_time_employed",
option_id: "education_career.employment_status.full_time_employed",
},
};
expect(isQuestionVisible(jobTitle, fullTimeAnswers)).toBe(true);
expect(isQuestionVisible(workLocation, fullTimeAnswers)).toBe(true);
expect(isQuestionVisible(monthlyIncome, fullTimeAnswers)).toBe(true);
expect(isQuestionRequired(monthlyIncome, fullTimeAnswers)).toBe(true);
// Visible case: Working student
const workingStudentAnswers = {
"education_career.employment_status": {
value: "working_student",
option_id: "education_career.employment_status.working_student",
},
};
expect(isQuestionVisible(jobTitle, workingStudentAnswers)).toBe(true);
expect(isQuestionVisible(workLocation, workingStudentAnswers)).toBe(true);
expect(isQuestionVisible(monthlyIncome, workingStudentAnswers)).toBe(true);
expect(isQuestionRequired(monthlyIncome, workingStudentAnswers)).toBe(true);
// Retired case: Job title and monthly income visible, work location hidden
const retiredAnswers = {
"education_career.employment_status": {
value: "retired",
option_id: "education_career.employment_status.retired",
},
};
expect(isQuestionVisible(jobTitle, retiredAnswers)).toBe(true);
expect(isQuestionVisible(workLocation, retiredAnswers)).toBe(false);
expect(isQuestionVisible(monthlyIncome, retiredAnswers)).toBe(true);
expect(isQuestionRequired(monthlyIncome, retiredAnswers)).toBe(true);
});
it("should show parents marital status only when both parents are alive (Option A) and hide for options B, C, D", () => {
const parentsMaritalStatus: QuestionField = {
...dummyQuestion,
id: "family_background.parents_marital_status",
title: "وضعیت تأهل والدین",
required: false,
visibility: {
parent_question_id: "family_background.parents_survival_status",
trigger_option_ids: [
"family_background.parents_survival_status.both_parents_are_alive",
],
operator: "any_of",
},
requiredWhen: {
parent_question_id: "family_background.parents_survival_status",
trigger_option_ids: [
"family_background.parents_survival_status.both_parents_are_alive",
],
operator: "any_of",
},
};
// Option A: Both parents are alive -> Visible & Required
const optionAAnswers = {
"family_background.parents_survival_status": {
value: "both_parents_are_alive",
option_id: "family_background.parents_survival_status.both_parents_are_alive",
},
};
expect(isQuestionVisible(parentsMaritalStatus, optionAAnswers)).toBe(true);
expect(isQuestionRequired(parentsMaritalStatus, optionAAnswers)).toBe(true);
// Option B: Father has passed away -> Hidden & Not Required
const optionBAnswers = {
"family_background.parents_survival_status": {
value: "father_has_passed_away",
option_id: "family_background.parents_survival_status.father_has_passed_away",
},
};
expect(isQuestionVisible(parentsMaritalStatus, optionBAnswers)).toBe(false);
expect(isQuestionRequired(parentsMaritalStatus, optionBAnswers)).toBe(false);
// Option C: Mother has passed away -> Hidden & Not Required
const optionCAnswers = {
"family_background.parents_survival_status": {
value: "mother_has_passed_away",
option_id: "family_background.parents_survival_status.mother_has_passed_away",
},
};
expect(isQuestionVisible(parentsMaritalStatus, optionCAnswers)).toBe(false);
expect(isQuestionRequired(parentsMaritalStatus, optionCAnswers)).toBe(false);
// Option D: Both parents have passed away -> Hidden & Not Required
const optionDAnswers = {
"family_background.parents_survival_status": {
value: "both_parents_have_passed_away",
option_id: "family_background.parents_survival_status.both_parents_have_passed_away",
},
};
expect(isQuestionVisible(parentsMaritalStatus, optionDAnswers)).toBe(false);
expect(isQuestionRequired(parentsMaritalStatus, optionDAnswers)).toBe(false);
});
it("should show family responsibility follow-up questions (live with you, additional details) and make them required only when responsibility options are selected", () => {
const parentId = "family_background.do_you_currently_have_an_ongoing_financial_caregiving_or_guardianship_responsibility_for_a_family_member";
const triggerOptionIds = [
`${parentId}.i_am_responsible_for_caring_for_my_father`,
`${parentId}.i_am_responsible_for_caring_for_my_mother`,
`${parentId}.i_am_responsible_for_caring_for_both_parents`,
`${parentId}.i_am_responsible_for_caring_for_a_sibling_brother_sister`,
`${parentId}.i_am_the_legal_guardian_or_supervisor_of_a_family_member`,
`${parentId}.i_regularly_provide_financial_support_for_a_family_member_s_living_expenses`,
`${parentId}.i_have_other_circumstances_and_will_explain_in_the_description`,
`${parentId}.i_am_responsible_for_caring_for_my_parent_s_father_mother_or_both`,
];
const liveWithYou: QuestionField = {
...dummyQuestion,
id: "family_background.do_the_supported_individual_s_live_with_you",
title: "آیا فرد یا افراد تحت حمایت با شما زندگی می‌کنند؟",
required: false,
visibility: {
parent_question_id: parentId,
trigger_option_ids: triggerOptionIds,
operator: "any_of",
},
requiredWhen: {
parent_question_id: parentId,
trigger_option_ids: triggerOptionIds,
operator: "any_of",
},
};
const additionalDetails: QuestionField = {
...dummyQuestion,
id: "family_background.additional_details_about_family_responsibility",
title: "توضیحات تکمیلی درباره مسئولیت خانوادگی",
required: false,
visibility: {
parent_question_id: parentId,
trigger_option_ids: triggerOptionIds,
operator: "any_of",
},
requiredWhen: {
parent_question_id: parentId,
trigger_option_ids: triggerOptionIds,
operator: "any_of",
},
};
// Case 1: No ongoing responsibility selected -> Hidden & Not Required
const noRespAnswers = {
[parentId]: {
value: ["خیر، مسئولیت مستمری ندارم."],
option_id: [`${parentId}.no_i_do_not_have_any_ongoing_responsibility`],
},
};
expect(isQuestionVisible(liveWithYou, noRespAnswers)).toBe(false);
expect(isQuestionRequired(liveWithYou, noRespAnswers)).toBe(false);
expect(isQuestionVisible(additionalDetails, noRespAnswers)).toBe(false);
expect(isQuestionRequired(additionalDetails, noRespAnswers)).toBe(false);
// Case 2: Responsibility selected (e.g. Caring for father) -> Visible & Required
const fatherRespAnswers = {
[parentId]: {
value: ["مسئولیت مراقبت از پدر را بر عهده دارم."],
option_id: [`${parentId}.i_am_responsible_for_caring_for_my_father`],
},
};
expect(isQuestionVisible(liveWithYou, fatherRespAnswers)).toBe(true);
expect(isQuestionRequired(liveWithYou, fatherRespAnswers)).toBe(true);
expect(isQuestionVisible(additionalDetails, fatherRespAnswers)).toBe(true);
expect(isQuestionRequired(additionalDetails, fatherRespAnswers)).toBe(true);
// Case 3: Multiple responsibilities selected -> Visible & Required
const multiRespAnswers = {
[parentId]: {
value: ["مسئولیت مراقبت از پدر", "حمایت مالی"],
option_id: [
`${parentId}.i_am_responsible_for_caring_for_my_father`,
`${parentId}.i_regularly_provide_financial_support_for_a_family_member_s_living_expenses`,
],
},
};
expect(isQuestionVisible(liveWithYou, multiRespAnswers)).toBe(true);
expect(isQuestionRequired(liveWithYou, multiRespAnswers)).toBe(true);
expect(isQuestionVisible(additionalDetails, multiRespAnswers)).toBe(true);
expect(isQuestionRequired(additionalDetails, multiRespAnswers)).toBe(true);
});
it("should handle Section 6 marital history and children follow-up rules properly", () => {
const mStatusId = "marital_history.current_marital_status";
const previousTriggerIds = [
`${mStatusId}.failed_engagement_annulled_marriage_without_living_together`,
`${mStatusId}.failed_marriage_contract_annulled_engagement_without_starting_joint_life`,
`${mStatusId}.divorced_after_living_together`,
`${mStatusId}.widowed`,
];
const divorcedOrAnnulledIds = [
`${mStatusId}.failed_engagement_annulled_marriage_without_living_together`,
`${mStatusId}.failed_marriage_contract_annulled_engagement_without_starting_joint_life`,
`${mStatusId}.divorced_after_living_together`,
];
const cStatusId = "marital_history.children_and_guardianship_status";
const hasChildrenTriggerIds = [
`${cStatusId}.have_children_living_with_me`,
`${cStatusId}.have_children_not_living_with_me`,
];
const prevDuration: QuestionField = {
...dummyQuestion,
id: "marital_history.previous_marriage_duration",
title: "مدت ازدواج یا عقد قبلی",
required: false,
visibility: { parent_question_id: mStatusId, trigger_option_ids: previousTriggerIds, operator: "any_of" },
requiredWhen: { parent_question_id: mStatusId, trigger_option_ids: previousTriggerIds, operator: "any_of" },
};
const reasonSeparation: QuestionField = {
...dummyQuestion,
id: "marital_history.reason_for_separation",
title: "علت جدایی، در صورت وجود",
required: false,
visibility: { parent_question_id: mStatusId, trigger_option_ids: divorcedOrAnnulledIds, operator: "any_of" },
};
const childrenStatus: QuestionField = {
...dummyQuestion,
id: "marital_history.children_and_guardianship_status",
title: "وضعیت فرزند و تکفل",
required: false,
visibility: { parent_question_id: mStatusId, trigger_option_ids: previousTriggerIds, operator: "any_of" },
requiredWhen: { parent_question_id: mStatusId, trigger_option_ids: previousTriggerIds, operator: "any_of" },
};
const numChildren: QuestionField = {
...dummyQuestion,
id: "marital_history.number_of_children",
title: "تعداد فرزندان",
required: false,
visibility: { parent_question_id: cStatusId, trigger_option_ids: hasChildrenTriggerIds, operator: "any_of" },
requiredWhen: { parent_question_id: cStatusId, trigger_option_ids: hasChildrenTriggerIds, operator: "any_of" },
};
const custodyStatus: QuestionField = {
...dummyQuestion,
id: "marital_history.what_is_the_custody_status_of_your_child_ren",
title: "وضعیت حضانت فرزند یا فرزندان شما چگونه است؟",
required: false,
visibility: { parent_question_id: cStatusId, trigger_option_ids: hasChildrenTriggerIds, operator: "any_of" },
requiredWhen: { parent_question_id: cStatusId, trigger_option_ids: hasChildrenTriggerIds, operator: "any_of" },
};
// 1. Single: previous duration, reason for separation, and children status are all HIDDEN
const singleAns = {
[mStatusId]: {
value: "single_never_married",
option_id: `${mStatusId}.single_never_married`,
},
};
expect(isQuestionVisible(prevDuration, singleAns)).toBe(false);
expect(isQuestionVisible(reasonSeparation, singleAns)).toBe(false);
expect(isQuestionVisible(childrenStatus, singleAns)).toBe(false);
// 2. Divorced: duration, reason, and children status are all VISIBLE
const divorcedAns = {
[mStatusId]: {
value: "divorced_after_living_together",
option_id: `${mStatusId}.divorced_after_living_together`,
},
};
expect(isQuestionVisible(prevDuration, divorcedAns)).toBe(true);
expect(isQuestionRequired(prevDuration, divorcedAns)).toBe(true);
expect(isQuestionVisible(reasonSeparation, divorcedAns)).toBe(true);
expect(isQuestionVisible(childrenStatus, divorcedAns)).toBe(true);
expect(isQuestionRequired(childrenStatus, divorcedAns)).toBe(true);
// 3. Widowed: duration & children VISIBLE, reason for separation HIDDEN
const widowedAns = {
[mStatusId]: {
value: "widowed",
option_id: `${mStatusId}.widowed`,
},
};
expect(isQuestionVisible(prevDuration, widowedAns)).toBe(true);
expect(isQuestionRequired(prevDuration, widowedAns)).toBe(true);
expect(isQuestionVisible(reasonSeparation, widowedAns)).toBe(false);
expect(isQuestionVisible(childrenStatus, widowedAns)).toBe(true);
expect(isQuestionRequired(childrenStatus, widowedAns)).toBe(true);
// 4. Children follow-ups: when children exist -> VISIBLE & REQUIRED
const hasChildAns = {
[cStatusId]: {
value: "have_children_living_with_me",
option_id: `${cStatusId}.have_children_living_with_me`,
},
};
expect(isQuestionVisible(numChildren, hasChildAns)).toBe(true);
expect(isQuestionRequired(numChildren, hasChildAns)).toBe(true);
expect(isQuestionVisible(custodyStatus, hasChildAns)).toBe(true);
expect(isQuestionRequired(custodyStatus, hasChildAns)).toBe(true);
// 5. No children: child questions HIDDEN & NOT REQUIRED
const noChildAns = {
[cStatusId]: {
value: "no_children",
option_id: `${cStatusId}.no_children`,
},
};
expect(isQuestionVisible(numChildren, noChildAns)).toBe(false);
expect(isQuestionRequired(numChildren, noChildAns)).toBe(false);
expect(isQuestionVisible(custodyStatus, noChildAns)).toBe(false);
expect(isQuestionRequired(custodyStatus, noChildAns)).toBe(false);
});
});