diff --git a/backend/hct_mis_api/apps/core/base_test_case.py b/backend/hct_mis_api/apps/core/base_test_case.py index 88bffa2d20..d48a4a6073 100644 --- a/backend/hct_mis_api/apps/core/base_test_case.py +++ b/backend/hct_mis_api/apps/core/base_test_case.py @@ -199,7 +199,7 @@ def rebuild_search_index(cls) -> None: @pytest.fixture(autouse=True) def _setup_elasticsearch(self, django_elasticsearch_setup: None) -> None: # Setup elasticsearch to work in parallel - pass + yield class UploadDocumentsBase(APITestCase): diff --git a/backend/hct_mis_api/apps/core/fixtures/data-selenium.json b/backend/hct_mis_api/apps/core/fixtures/data-selenium.json index a1eac6294c..66209e304a 100644 --- a/backend/hct_mis_api/apps/core/fixtures/data-selenium.json +++ b/backend/hct_mis_api/apps/core/fixtures/data-selenium.json @@ -8,6 +8,7 @@ "code": "full_test", "description": "Full individual collected", "active": true, + "type": "STANDARD", "individual_filters_available": true, "household_filters_available": true, "compatible_types": [], diff --git a/backend/hct_mis_api/apps/household/fixtures.py b/backend/hct_mis_api/apps/household/fixtures.py index f0de6f51fa..ceeaf16fb1 100644 --- a/backend/hct_mis_api/apps/household/fixtures.py +++ b/backend/hct_mis_api/apps/household/fixtures.py @@ -424,33 +424,38 @@ def create_household_and_individuals( if household_data.get("size") is None: household_data["size"] = len(individuals_data) if "program" not in household_data: - program = ProgramFactory() - else: - program = household_data["program"] - if "registration_data_import" not in household_data: - rdi = RegistrationDataImportFactory(program=program) - household_data["registration_data_import"] = rdi + household_data["program"] = ProgramFactory() + household: Household = HouseholdFactory.build(**household_data) household.program.save() household.household_collection.save() - household.registration_data_import.imported_by.save() + household.registration_data_import.program = household.program household.registration_data_import.program.save() + household.registration_data_import.imported_by.save() household.registration_data_import.save() - household.program.save() for individual_data in individuals_data: if "program" not in individual_data: - individual_data["program"] = program + individual_data["program"] = household.program if "registration_data_import" not in individual_data: - individual_data["registration_data_import"] = household_data["registration_data_import"] + individual_data["registration_data_import"] = household.registration_data_import individuals: List[Individual] = [ IndividualFactory( - household=household, + household=None, **individual_data, ) for individual_data in individuals_data ] household.head_of_household = individuals[0] household.save() + + individuals_to_update = [] + for index, individual in enumerate(individuals): + if index == 0: + individual.relationship = "HEAD" + individual.household = household + individuals_to_update.append(individual) + Individual.objects.bulk_update(individuals_to_update, ("relationship", "household")) + return household, individuals diff --git a/backend/hct_mis_api/apps/targeting/fixtures/data-cypress.json b/backend/hct_mis_api/apps/targeting/fixtures/data-cypress.json index a588c4447e..301a665a14 100644 --- a/backend/hct_mis_api/apps/targeting/fixtures/data-cypress.json +++ b/backend/hct_mis_api/apps/targeting/fixtures/data-cypress.json @@ -66,12 +66,12 @@ "vulnerability_score_max": null, "excluded_ids": "", "exclusion_reason": "", - "total_households_count": 2, - "total_individuals_count": 8, - "child_male_count": 0, - "child_female_count": 0, - "adult_male_count": 0, - "adult_female_count": 0, + "total_households_count": 3, + "total_individuals_count": 7, + "child_male_count": 1, + "child_female_count": 6, + "adult_male_count": 1, + "adult_female_count": 2, "storage_file": null } }, diff --git a/backend/hct_mis_api/apps/targeting/mutations.py b/backend/hct_mis_api/apps/targeting/mutations.py index dd1a08d259..93f8fb288a 100644 --- a/backend/hct_mis_api/apps/targeting/mutations.py +++ b/backend/hct_mis_api/apps/targeting/mutations.py @@ -98,10 +98,18 @@ def get_unicef_ids(ids_string: str, type_id: str, program: Program) -> str: ids_list = [i.strip() for i in ids_list] if type_id == "household": hh_ids = [hh_id for hh_id in ids_list if hh_id.startswith("HH")] - list_ids = Household.objects.filter(unicef_id__in=hh_ids, program=program).values_list("unicef_id", flat=True) + list_ids = ( + Household.objects.filter(unicef_id__in=hh_ids, program=program) + .order_by("unicef_id") + .values_list("unicef_id", flat=True) + ) if type_id == "individual": ind_ids = [ind_id for ind_id in ids_list if ind_id.startswith("IND")] - list_ids = Individual.objects.filter(unicef_id__in=ind_ids, program=program).values_list("unicef_id", flat=True) + list_ids = ( + Individual.objects.filter(unicef_id__in=ind_ids, program=program) + .order_by("unicef_id") + .values_list("unicef_id", flat=True) + ) return ", ".join(list_ids) diff --git a/backend/selenium_tests/conftest.py b/backend/selenium_tests/conftest.py index 06a91c2c28..5da5d78d73 100644 --- a/backend/selenium_tests/conftest.py +++ b/backend/selenium_tests/conftest.py @@ -176,7 +176,7 @@ def driver() -> Chrome: chrome_options.add_argument("--no-sandbox") chrome_options.add_argument("--enable-logging") chrome_options.add_argument("--window-size=1920,1080") - return webdriver.Chrome(options=chrome_options) + yield webdriver.Chrome(options=chrome_options) @pytest.fixture(autouse=True) @@ -201,7 +201,7 @@ def login(browser: Chrome) -> Chrome: browser.add_cookie({"name": "csrftoken", "value": pytest.CSRF}) browser.add_cookie({"name": "sessionid", "value": pytest.SESSION_ID}) browser.get(f"{browser.live_server.url}") - return browser + yield browser @pytest.fixture @@ -397,6 +397,7 @@ def business_area() -> BusinessArea: "region_code": "64", "region_name": "SAR", "slug": "afghanistan", + "screen_beneficiary": True, "has_data_sharing_agreement": True, "is_payment_plan_applicable": True, "is_accountability_applicable": True, @@ -406,7 +407,7 @@ def business_area() -> BusinessArea: FlagState.objects.get_or_create( **{"name": "ALLOW_ACCOUNTABILITY_MODULE", "condition": "boolean", "value": "True", "required": False} ) - return business_area + yield business_area @pytest.fixture diff --git a/backend/selenium_tests/drawer/test_drawer.py b/backend/selenium_tests/drawer/test_drawer.py index 8598b4e688..46ccdbb9cc 100644 --- a/backend/selenium_tests/drawer/test_drawer.py +++ b/backend/selenium_tests/drawer/test_drawer.py @@ -16,27 +16,27 @@ @pytest.fixture def social_worker_program() -> Program: - return get_program_with_dct_type_and_name("Worker Program", "WORK", DataCollectingType.Type.SOCIAL) + yield get_program_with_dct_type_and_name("Worker Program", "WORK", DataCollectingType.Type.SOCIAL) @pytest.fixture def normal_program() -> Program: - return get_program_with_dct_type_and_name("Normal Program", "NORM", DataCollectingType.Type.STANDARD) + yield get_program_with_dct_type_and_name("Normal Program", "NORM", DataCollectingType.Type.STANDARD) @pytest.fixture def active_program() -> Program: - return get_program_with_dct_type_and_name("Active Program", "ACTI", status=Program.ACTIVE) + yield get_program_with_dct_type_and_name("Active Program", "ACTI", status=Program.ACTIVE) @pytest.fixture def draft_program() -> Program: - return get_program_with_dct_type_and_name("Draft Program", "DRAF", status=Program.DRAFT) + yield get_program_with_dct_type_and_name("Draft Program", "DRAF", status=Program.DRAFT) @pytest.fixture def finished_program() -> Program: - return get_program_with_dct_type_and_name("Finished Program", "FINI", status=Program.FINISHED) + yield get_program_with_dct_type_and_name("Finished Program", "FINI", status=Program.FINISHED) def get_program_with_dct_type_and_name( diff --git a/backend/selenium_tests/filters/test_filters.py b/backend/selenium_tests/filters/test_filters.py index b4f9c26509..80c2bdaa23 100644 --- a/backend/selenium_tests/filters/test_filters.py +++ b/backend/selenium_tests/filters/test_filters.py @@ -277,7 +277,7 @@ def create_rdi() -> None: def create_programs() -> None: call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/core/fixtures/data-selenium.json") call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/program/fixtures/data-cypress.json") - return + yield @pytest.mark.usefixtures("login") diff --git a/backend/selenium_tests/grievance/feedback/test_feedback.py b/backend/selenium_tests/grievance/feedback/test_feedback.py index aec38b6c53..2cb3856cf5 100644 --- a/backend/selenium_tests/grievance/feedback/test_feedback.py +++ b/backend/selenium_tests/grievance/feedback/test_feedback.py @@ -18,7 +18,7 @@ def add_feedbacks(django_db_setup: Generator[None, None, None], django_db_blocker: DjangoDbBlocker) -> None: with django_db_blocker.unblock(): call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/accountability/fixtures/data-cypress.json") - return + yield @pytest.fixture @@ -26,7 +26,7 @@ def add_households(django_db_setup: Generator[None, None, None], django_db_block with django_db_blocker.unblock(): call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/registration_data/fixtures/data-cypress.json") call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/household/fixtures/data-cypress.json") - return + yield @pytest.fixture @@ -34,7 +34,7 @@ def create_programs(django_db_setup: Generator[None, None, None], django_db_bloc with django_db_blocker.unblock(): call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/core/fixtures/data-selenium.json") call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/program/fixtures/data-cypress.json") - return + yield @pytest.mark.usefixtures("login") diff --git a/backend/selenium_tests/grievance/grievance_tickets/test_grievance_tickets.py b/backend/selenium_tests/grievance/grievance_tickets/test_grievance_tickets.py index 5635646e12..0374aee44b 100644 --- a/backend/selenium_tests/grievance/grievance_tickets/test_grievance_tickets.py +++ b/backend/selenium_tests/grievance/grievance_tickets/test_grievance_tickets.py @@ -16,7 +16,7 @@ def add_grievance(django_db_setup: Generator[None, None, None], django_db_blocker: DjangoDbBlocker) -> None: with django_db_blocker.unblock(): call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/grievance/fixtures/data-cypress.json") - return + yield @pytest.fixture @@ -24,7 +24,7 @@ def add_households(django_db_setup: Generator[None, None, None], django_db_block with django_db_blocker.unblock(): call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/registration_data/fixtures/data-cypress.json") call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/household/fixtures/data-cypress.json") - return + yield @pytest.fixture @@ -32,7 +32,7 @@ def create_programs(django_db_setup: Generator[None, None, None], django_db_bloc with django_db_blocker.unblock(): call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/core/fixtures/data-selenium.json") call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/program/fixtures/data-cypress.json") - return + yield @pytest.mark.usefixtures("login") diff --git a/backend/selenium_tests/helpers/helper.py b/backend/selenium_tests/helpers/helper.py index a990e40a03..076df7ee16 100644 --- a/backend/selenium_tests/helpers/helper.py +++ b/backend/selenium_tests/helpers/helper.py @@ -11,7 +11,7 @@ class Common: - DEFAULT_TIMEOUT = 10 + DEFAULT_TIMEOUT = 20 def __init__(self, driver: Chrome): self.driver = driver @@ -137,3 +137,10 @@ def get_value_of_attributes(self, attribute: str = "data-cy") -> None: print(f"{ii.text}: {ii.get_attribute(attribute)}") # type: ignore except BaseException: print(f"No text: {ii.get_attribute(attribute)}") # type: ignore + + def mouse_on_element(self, element: WebElement) -> None: + hover = ActionChains(self.driver).move_to_element(element) # type: ignore + hover.perform() + + def wait_for_element_clickable(self, locator: str) -> bool: + return self._wait().until(EC.element_to_be_clickable((By.XPATH, locator))) diff --git a/backend/selenium_tests/managerial_console/test_managerial_console.py b/backend/selenium_tests/managerial_console/test_managerial_console.py index 406db855a3..2704960224 100644 --- a/backend/selenium_tests/managerial_console/test_managerial_console.py +++ b/backend/selenium_tests/managerial_console/test_managerial_console.py @@ -16,7 +16,7 @@ @pytest.fixture def create_active_test_program() -> Program: - return create_program("Test Programm") + yield create_program("Test Programm") def create_program( diff --git a/backend/selenium_tests/page_object/filters.py b/backend/selenium_tests/page_object/filters.py index a3ea15a863..e8a1efbc75 100644 --- a/backend/selenium_tests/page_object/filters.py +++ b/backend/selenium_tests/page_object/filters.py @@ -1,3 +1,5 @@ +from time import sleep + from page_object.base_components import BaseComponents from selenium.webdriver.common.by import By from selenium.webdriver.remote.webelement import WebElement @@ -87,7 +89,7 @@ class Filters(BaseComponents): importedByInput = 'div[data-cy="Imported By-input"]' def getFiltersSearch(self) -> WebElement: - return self.wait_for(self.filtersSearch) + return self.wait_for(self.filtersSearch).find_element(By.XPATH, "./div/input") def getFiltersDocumentType(self) -> WebElement: return self.wait_for(self.filtersDocumentType) @@ -101,6 +103,17 @@ def getFiltersProgram(self) -> WebElement: def getFiltersStatus(self) -> WebElement: return self.wait_for(self.filtersStatus) + def selectFiltersSatus(self, status: str) -> None: + self.getFiltersStatus().click() + self.wait_for(f'li[data-value="{status.upper()}"]').click() + for _ in range(10): + sleep(1) + if status.capitalize() in self.getFiltersStatus().text: + self.getButtonFiltersApply().click() + break + else: + raise Exception(f"Status: {status.capitalize()} does not occur.") + def getFiltersFsp(self) -> WebElement: return self.wait_for(self.filtersFsp) @@ -138,10 +151,10 @@ def getFiltersSector(self) -> WebElement: return self.wait_for(self.filtersSector) def getFiltersNumberOfHouseholdsMin(self) -> WebElement: - return self.wait_for(self.filtersNumberOfHouseholdsMin) + return self.wait_for(self.filtersNumberOfHouseholdsMin).find_element(By.XPATH, "./div/input") def getFiltersNumberOfHouseholdsMax(self) -> WebElement: - return self.wait_for(self.filtersNumberOfHouseholdsMax) + return self.wait_for(self.filtersNumberOfHouseholdsMax).find_element(By.XPATH, "./div/input") def getFiltersBudgetMin(self) -> WebElement: return self.wait_for(self.filtersBudgetMin) @@ -186,10 +199,10 @@ def getMenuItemFiltersText(self) -> WebElement: return self.wait_for(self.menuItemFiltersText) def getFiltersTotalHouseholdsCountMin(self) -> WebElement: - return self.wait_for(self.filtersTotalHouseholdsCountMin) + return self.wait_for(self.filtersTotalHouseholdsCountMin).find_element(By.XPATH, "./div/input") def getFiltersTotalHouseholdsCountMax(self) -> WebElement: - return self.wait_for(self.filtersTotalHouseholdsCountMax) + return self.wait_for(self.filtersTotalHouseholdsCountMax).find_element(By.XPATH, "./div/input") def getGlobalProgramFilterContainer(self) -> WebElement: return self.wait_for(self.globalProgramFilterContainer) diff --git a/backend/selenium_tests/page_object/targeting/create_new.py b/backend/selenium_tests/page_object/targeting/create_new.py deleted file mode 100644 index ead99a221b..0000000000 --- a/backend/selenium_tests/page_object/targeting/create_new.py +++ /dev/null @@ -1,87 +0,0 @@ -from page_object.base_components import BaseComponents -from selenium.webdriver.remote.webelement import WebElement - - -class CreateNew(BaseComponents): - pageHeaderContainer = 'div[data-cy="page-header-container"]' - pageHeaderTitle = 'h5[data-cy="page-header-title"]' - buttonTargetPopulationCreate = 'button[data-cy="button-target-population-create"]' - inputDivName = 'div[data-cy="input-name"]' - inputIncludedHouseholdIds = 'div[data-cy="input-included-household-ids"]' - inputHouseholdids = 'input[data-cy="input-householdIds"]' - inputIncludedIndividualIds = 'div[data-cy="input-included-individual-ids"]' - inputIndividualids = 'input[data-cy="input-individualIds"]' - inputFlagexcludeifactiveadjudicationticket = 'span[data-cy="input-flagExcludeIfActiveAdjudicationTicket"]' - inputName = 'input[data-cy="input-name"]' - - pageHeaderContainer = 'div[data-cy="page-header-container"]' - pageHeaderTitle = 'h5[data-cy="page-header-title"]' - buttonTargetPopulationCreate = 'button[data-cy="button-target-population-create"]' - divTargetPopulationAddCriteria = 'div[data-cy="button-target-population-add-criteria"]' - inputFlagexcludeifactiveadjudicationticket = 'span[data-cy="input-flagExcludeIfActiveAdjudicationTicket"]' - titleExcludedEntries = 'h6[data-cy="title-excluded-entries"]' - buttonShowHideExclusions = 'button[data-cy="button-show-hide-exclusions"]' - inputExcludedIds = 'div[data-cy="input-excluded-ids"]' - inputExcludedids = 'input[data-cy="input-excludedIds"]' - inputExclusionReason = 'div[data-cy="input-exclusion-reason"]' - titleAddFilter = 'h6[data-cy="title-add-filter"]' - autocompleteTargetCriteria = 'div[data-cy="autocomplete-target-criteria"]' - fieldChooserFilters = 'div[data-cy="field-chooser-filters[0]"]' - autocompleteTargetCriteriaOption = 'input[data-cy="autocomplete-target-criteria-option-0"]' - buttonHouseholdRule = 'button[data-cy="button-household-rule"]' - buttonIndividualRule = 'button[data-cy="button-individual-rule"]' - buttonTargetPopulationAddCriteria = 'button[data-cy="button-target-population-add-criteria"]' - - def getPageHeaderTitle(self) -> WebElement: - return self.wait_for(self.pageHeaderTitle) - - def getButtonTargetPopulationCreate(self) -> WebElement: - return self.wait_for(self.buttonTargetPopulationCreate) - - def getInputName(self) -> WebElement: - return self.wait_for(self.inputName) - - def getInputIncludedHouseholdIds(self) -> WebElement: - return self.wait_for(self.inputIncludedHouseholdIds) - - def getInputHouseholdids(self) -> WebElement: - return self.wait_for(self.inputHouseholdids) - - def getInputIncludedIndividualIds(self) -> WebElement: - return self.wait_for(self.inputIncludedIndividualIds) - - def getInputIndividualids(self) -> WebElement: - return self.wait_for(self.inputIndividualids) - - def getInputFlagexcludeifactiveadjudicationticket(self) -> WebElement: - return self.wait_for(self.inputFlagexcludeifactiveadjudicationticket) - - def getButtonTargetPopulationAddCriteria(self) -> WebElement: - return self.wait_for(self.buttonTargetPopulationAddCriteria) - - def getDivTargetPopulationAddCriteria(self) -> WebElement: - return self.wait_for(self.divTargetPopulationAddCriteria) - - def getTitleExcludedEntries(self) -> WebElement: - return self.wait_for(self.titleExcludedEntries) - - def getButtonShowHideExclusions(self) -> WebElement: - return self.wait_for(self.buttonShowHideExclusions) - - def getInputExcludedIds(self) -> WebElement: - return self.wait_for(self.inputExcludedIds) - - def getInputExcludedids(self) -> WebElement: - return self.wait_for(self.inputExcludedids) - - def getInputExclusionReason(self) -> WebElement: - return self.wait_for(self.inputExclusionReason) - - def getButtonHouseholdRule(self) -> WebElement: - return self.wait_for(self.buttonHouseholdRule) - - def getButtonIndividualRule(self) -> WebElement: - return self.wait_for(self.buttonIndividualRule) - - def getAutocompleteTargetCriteriaOption(self) -> WebElement: - return self.wait_for(self.autocompleteTargetCriteriaOption) diff --git a/backend/selenium_tests/page_object/targeting/t_details_page.py b/backend/selenium_tests/page_object/targeting/t_details_page.py deleted file mode 100644 index edf2795c02..0000000000 --- a/backend/selenium_tests/page_object/targeting/t_details_page.py +++ /dev/null @@ -1,130 +0,0 @@ -from page_object.base_components import BaseComponents -from selenium.webdriver.remote.webelement import WebElement - - -class DetailsTargeting(BaseComponents): - pageHeaderContainer = 'div[data-cy="page-header-container"]' - pageHeaderTitle = 'h5[data-cy="page-header-title"]' - buttonTargetPopulationDuplicate = 'button[data-cy="button-target-population-duplicate"]' - buttonDelete = 'button[data-cy="button-delete"]' - buttonEdit = 'a[data-cy="button-edit"]' - buttonRebuild = 'button[data-cy="button-rebuild"]' - buttonTargetPopulationLock = 'button[data-cy="button-target-population-lock"]' - detailsTitle = 'div[data-cy="details-title"]' - detailsGrid = 'div[data-cy="details-grid"]' - labelStatus = 'div[data-cy="label-Status"]' - targetPopulationStatus = 'div[data-cy="target-population-status"]' - labelizedFieldContainerCreatedBy = 'div[data-cy="labelized-field-container-created-by"]' - labelCreatedBy = 'div[data-cy="label-created by"]' - labelizedFieldContainerCloseDate = 'div[data-cy="labelized-field-container-close-date"]' - labelProgrammePopulationCloseDate = 'div[data-cy="label-Programme population close date"]' - labelizedFieldContainerProgramName = 'div[data-cy="labelized-field-container-program-name"]' - labelProgramme = 'div[data-cy="label-Programme"]' - labelizedFieldContainerSendBy = 'div[data-cy="labelized-field-container-send-by"]' - labelSendBy = 'div[data-cy="label-Send by"]' - labelizedFieldContainerSendDate = 'div[data-cy="labelized-field-container-send-date"]' - labelSendDate = 'div[data-cy="label-Send date"]' - criteriaContainer = 'div[data-cy="criteria-container"]' - checkboxExcludeIfActiveAdjudicationTicket = 'span[data-cy="checkbox-exclude-if-active-adjudication-ticket"]' - labelFemaleChildren = 'div[data-cy="label-Female Children"]' - labelFemaleAdults = 'div[data-cy="label-Female Adults"]' - labelMaleChildren = 'div[data-cy="label-Male Children"]' - labelMaleAdults = 'div[data-cy="label-Male Adults"]' - labelTotalNumberOfHouseholds = 'div[data-cy="label-Total Number of Households"]' - labelTargetedIndividuals = 'div[data-cy="label-Targeted Individuals"]' - tableTitle = 'h6[data-cy="table-title"]' - tableLabel = 'span[data-cy="table-label"]' - tablePagination = 'div[data-cy="table-pagination"]' - - def getPageHeaderTitle(self) -> WebElement: - return self.wait_for(self.pageHeaderTitle) - - def getButtonTargetPopulationDuplicate(self) -> WebElement: - return self.wait_for(self.buttonTargetPopulationDuplicate) - - def getButtonDelete(self) -> WebElement: - return self.wait_for(self.buttonDelete) - - def getButtonEdit(self) -> WebElement: - return self.wait_for(self.buttonEdit) - - def getButtonRebuild(self) -> WebElement: - return self.wait_for(self.buttonRebuild) - - def getButtonTargetPopulationLock(self) -> WebElement: - return self.wait_for(self.buttonTargetPopulationLock) - - def getDetailsTitle(self) -> WebElement: - return self.wait_for(self.detailsTitle) - - def getDetailsGrid(self) -> WebElement: - return self.wait_for(self.detailsGrid) - - def getLabelStatus(self) -> WebElement: - return self.wait_for(self.labelStatus) - - def getTargetPopulationStatus(self) -> WebElement: - return self.wait_for(self.targetPopulationStatus) - - def getLabelizedFieldContainerCreatedBy(self) -> WebElement: - return self.wait_for(self.labelizedFieldContainerCreatedBy) - - def getLabelCreatedBy(self) -> WebElement: - return self.wait_for(self.labelCreatedBy) - - def getLabelizedFieldContainerCloseDate(self) -> WebElement: - return self.wait_for(self.labelizedFieldContainerCloseDate) - - def getLabelProgrammePopulationCloseDate(self) -> WebElement: - return self.wait_for(self.labelProgrammePopulationCloseDate) - - def getLabelizedFieldContainerProgramName(self) -> WebElement: - return self.wait_for(self.labelizedFieldContainerProgramName) - - def getLabelProgramme(self) -> WebElement: - return self.wait_for(self.labelProgramme) - - def getLabelizedFieldContainerSendBy(self) -> WebElement: - return self.wait_for(self.labelizedFieldContainerSendBy) - - def getLabelSendBy(self) -> WebElement: - return self.wait_for(self.labelSendBy) - - def getLabelizedFieldContainerSendDate(self) -> WebElement: - return self.wait_for(self.labelizedFieldContainerSendDate) - - def getLabelSendDate(self) -> WebElement: - return self.wait_for(self.labelSendDate) - - def getCriteriaContainer(self) -> WebElement: - return self.wait_for(self.criteriaContainer) - - def getCheckboxExcludeIfActiveAdjudicationTicket(self) -> WebElement: - return self.wait_for(self.checkboxExcludeIfActiveAdjudicationTicket) - - def getLabelFemaleChildren(self) -> WebElement: - return self.wait_for(self.labelFemaleChildren) - - def getLabelFemaleAdults(self) -> WebElement: - return self.wait_for(self.labelFemaleAdults) - - def getLabelMaleChildren(self) -> WebElement: - return self.wait_for(self.labelMaleChildren) - - def getLabelMaleAdults(self) -> WebElement: - return self.wait_for(self.labelMaleAdults) - - def getLabelTotalNumberOfHouseholds(self) -> WebElement: - return self.wait_for(self.labelTotalNumberOfHouseholds) - - def getLabelTargetedIndividuals(self) -> WebElement: - return self.wait_for(self.labelTargetedIndividuals) - - def getTableTitle(self) -> WebElement: - return self.wait_for(self.tableTitle) - - def getTableLabel(self) -> WebElement: - return self.get_elements(self.tableLabel) - - def getTablePagination(self) -> WebElement: - return self.wait_for(self.tablePagination) diff --git a/backend/selenium_tests/page_object/targeting/targeting.py b/backend/selenium_tests/page_object/targeting/targeting.py index 6191b89369..00fdc03a60 100644 --- a/backend/selenium_tests/page_object/targeting/targeting.py +++ b/backend/selenium_tests/page_object/targeting/targeting.py @@ -1,6 +1,7 @@ from time import sleep from page_object.base_components import BaseComponents +from selenium.webdriver.common.by import By from selenium.webdriver.remote.webelement import WebElement from hct_mis_api.apps.core.utils import encode_id_base64 @@ -22,9 +23,23 @@ class Targeting(BaseComponents): rows = 'tr[role="checkbox"]' createUserFilters = 'div[data-cy="menu-item-filters-text"]' createUseIDs = 'div[data-cy="menu-item-ids-text"]' + buttonInactiveCreateNew = 'a[data-cy="button-target-population-create-new"]' + tooltip = 'div[role="tooltip"]' + statusContainer = 'div[data-cy="status-container"]' + loadingRows = 'tr[data-cy="table-row"]' + buttonTargetPopulation = 'button[data-cy="button-target-population-info"]' + buttonApply = 'button[data-cy="button-filters-apply"]' + buttonClear = 'button[data-cy="button-filters-clear"]' + tabFieldList = 'button[data-cy="tab-field-list"]' + tabTargetingDiagram = 'button[data-cy="tab-targeting-diagram"]' + name = 'th[data-cy="name"]' + status = 'th[data-cy="status"]' + numOfHouseholds = 'th[data-cy="num-of-households"]' + dateCreated = 'th[data-cy="date-created"]' + lastEdited = 'th[data-cy="last-edited"]' + createdBy = 'th[data-cy="created-by"]' # Texts - textTitlePage = "Targeting" textCreateNew = "Create new" textTabTitle = "Target Populations" @@ -35,8 +50,6 @@ class Targeting(BaseComponents): textTabDateCreated = "Date Created" textTabLastEdited = "Last Edited" textTabCreatedBy = "Created by" - buttonApply = 'button[data-cy="button-filters-apply"]' - buttonClear = 'button[data-cy="button-filters-clear"]' def navigate_to_page(self, business_area_slug: str, program_id: str) -> None: self.driver.get(self.get_page_url(business_area_slug, program_id)) @@ -50,6 +63,9 @@ def get_page_url(self, business_area_slug: str, program_id: str) -> str: def getTitlePage(self) -> WebElement: return self.wait_for(self.titlePage) + def waitForTextTitlePage(self, text: str) -> bool: + return self.wait_for_text(text, self.titlePage) + def getSearchFilter(self) -> WebElement: return self.wait_for(self.searchFilter) @@ -97,8 +113,61 @@ def chooseTargetPopulations(self, number: int) -> WebElement: sleep(1) return self.get_elements(self.rows)[number] + def countTargetPopulations(self, number: int) -> None: + for _ in range(5): + if len(self.getTargetPopulationsRows()) == number: + break + else: + raise TimeoutError(f"{len(self.getTargetPopulationsRows())} target populations instead of {number}") + def getCreateUseFilters(self) -> WebElement: return self.wait_for(self.createUserFilters) def getCreateUseIDs(self) -> WebElement: return self.wait_for(self.createUseIDs) + + def getButtonInactiveCreateNew(self) -> WebElement: + return self.wait_for(self.buttonInactiveCreateNew) + + def geTooltip(self) -> WebElement: + return self.wait_for(self.tooltip) + + def getStatusContainer(self) -> WebElement: + return self.wait_for(self.statusContainer) + + def getTabFieldList(self) -> WebElement: + return self.wait_for(self.tabFieldList) + + def getTabTargetingDiagram(self) -> WebElement: + return self.wait_for(self.tabTargetingDiagram) + + def getButtonTargetPopulation(self) -> WebElement: + return self.wait_for(self.buttonTargetPopulation) + + def getLoadingRows(self) -> WebElement: + return self.wait_for(self.loadingRows) + + def getColumnName(self) -> WebElement: + return self.wait_for(self.name).find_element(By.CSS_SELECTOR, self.tabColumnLabel) + + def getColumnStatus(self) -> WebElement: + return self.wait_for(self.status).find_element(By.CSS_SELECTOR, self.tabColumnLabel) + + def getColumnNumOfHouseholds(self) -> WebElement: + return self.wait_for(self.numOfHouseholds).find_element(By.CSS_SELECTOR, self.tabColumnLabel) + + def getColumnDateCreated(self) -> WebElement: + return self.wait_for(self.dateCreated).find_element(By.CSS_SELECTOR, self.tabColumnLabel) + + def getColumnLastEdited(self) -> WebElement: + return self.wait_for(self.lastEdited).find_element(By.CSS_SELECTOR, self.tabColumnLabel) + + def getColumnCreatedBy(self) -> WebElement: + return self.wait_for(self.createdBy).find_element(By.CSS_SELECTOR, self.tabColumnLabel) + + def disappearLoadingRows(self) -> WebElement: + try: + self.getLoadingRows() + except BaseException: + self.getStatusContainer() + return self.wait_for_disappear(self.loadingRows) diff --git a/backend/selenium_tests/page_object/targeting/targeting_create.py b/backend/selenium_tests/page_object/targeting/targeting_create.py index e77c2408f1..712cb10763 100644 --- a/backend/selenium_tests/page_object/targeting/targeting_create.py +++ b/backend/selenium_tests/page_object/targeting/targeting_create.py @@ -1,3 +1,5 @@ +from time import sleep + from page_object.base_components import BaseComponents from selenium.webdriver.remote.webelement import WebElement @@ -14,6 +16,7 @@ class TargetingCreate(BaseComponents): targetingCriteriaAutoComplete = 'input[data-cy="autocomplete-target-criteria-option-{}"]' targetingCriteriaValue = '[data-cy="select-filters[{}].value"]' targetingCriteriaAddDialogSaveButton = 'button[data-cy="button-target-population-add-criteria"]' + targetingCriteriaAddDialogSaveButtonEdit = 'button[data-cy="button-target-population-add-criteria"]' criteriaContainer = 'div[data-cy="criteria-container"]' targetPopulationSaveButton = 'button[data-cy="button-target-population-create"]' pageHeaderContainer = 'div[data-cy="page-header-container"]' @@ -24,7 +27,10 @@ class TargetingCreate(BaseComponents): inputHouseholdids = 'input[data-cy="input-householdIds"]' inputIncludedIndividualIds = 'div[data-cy="input-included-individual-ids"]' inputIndividualids = 'input[data-cy="input-individualIds"]' + inputFlagexcludeifonsanctionlist = 'span[data-cy="input-flagExcludeIfOnSanctionList"]' inputFlagexcludeifactiveadjudicationticket = 'span[data-cy="input-flagExcludeIfActiveAdjudicationTicket"]' + iconSelected = '[data-testid="CheckBoxIcon"]' + iconNotSelected = '[data-testid="CheckBoxOutlineBlankIcon"]' inputName = 'input[data-cy="input-name"]' divTargetPopulationAddCriteria = 'div[data-cy="button-target-population-add-criteria"]' titleExcludedEntries = 'h6[data-cy="title-excluded-entries"]' @@ -39,15 +45,35 @@ class TargetingCreate(BaseComponents): buttonHouseholdRule = 'button[data-cy="button-household-rule"]' buttonIndividualRule = 'button[data-cy="button-individual-rule"]' buttonTargetPopulationAddCriteria = 'button[data-cy="button-target-population-add-criteria"]' + buttonSave = 'button[data-cy="button-save"]' + inputFiltersValueFrom = 'input[data-cy="input-filters[{}].value.from"]' + inputFiltersValueTo = 'input[data-cy="input-filters[{}].value.to"]' + inputFiltersValue = 'input[data-cy="input-filters[{}].value"]' + autocompleteTargetCriteriaValues = 'div[data-cy="autocomplete-target-criteria-values"]' + selectMany = 'div[data-cy="select-many"]' + buttonEdit = 'button[data-cy="button-edit"]' + # Texts textTargetingCriteria = "Targeting Criteria" def getPageHeaderTitle(self) -> WebElement: return self.wait_for(self.pageHeaderTitle) - def getButtonTargetPopulationCreate(self) -> WebElement: + def getButtonTargetPopulationCreate(self) -> bool: return self.wait_for(self.buttonTargetPopulationCreate) + def clickButtonTargetPopulationCreate(self) -> bool: + for _ in range(10): + self.wait_for(self.buttonTargetPopulationCreate).click() + try: + self.wait_for_disappear(self.buttonTargetPopulationCreate) + break + except BaseException: + print("Error: Try again to click Save button during Target Population creation") + else: + raise Exception(f"Element {self.buttonTargetPopulationCreate} not found") + return True + def getInputName(self) -> WebElement: return self.wait_for(self.inputName) @@ -66,6 +92,15 @@ def getInputIndividualids(self) -> WebElement: def getInputFlagexcludeifactiveadjudicationticket(self) -> WebElement: return self.wait_for(self.inputFlagexcludeifactiveadjudicationticket) + def getInputFlagexcludeifonsanctionlist(self) -> WebElement: + return self.wait_for(self.inputFlagexcludeifonsanctionlist) + + def getIconNotSelected(self) -> WebElement: + return self.wait_for(self.iconNotSelected) + + def getIconSelected(self) -> WebElement: + return self.wait_for(self.iconSelected) + def getButtonTargetPopulationAddCriteria(self) -> WebElement: return self.wait_for(self.buttonTargetPopulationAddCriteria) @@ -117,6 +152,13 @@ def getAddPeopleRuleButton(self) -> WebElement: def getTargetingCriteriaAutoComplete(self, index: int = 0) -> WebElement: return self.wait_for(self.targetingCriteriaAutoComplete.format(index)) + def getTargetingCriteriaAutoCompleteIndividual(self, index: int = 0) -> WebElement: + for _ in range(5): + if len(self.get_elements(self.targetingCriteriaAutoComplete.format(index))) >= 2: + break + sleep(1) + return self.get_elements(self.targetingCriteriaAutoComplete.format(index))[1] + def getTargetingCriteriaValue(self, index: int = 0) -> WebElement: return self.wait_for(self.targetingCriteriaValue.format(index)) @@ -131,3 +173,24 @@ def getFieldName(self) -> WebElement: def getTargetPopulationSaveButton(self) -> WebElement: return self.wait_for(self.targetPopulationSaveButton) + + def getButtonSave(self) -> WebElement: + return self.wait_for(self.buttonSave) + + def getInputFiltersValueFrom(self, fiter_number: int = 0) -> WebElement: + return self.wait_for(self.inputFiltersValueFrom.format(fiter_number)) + + def getInputFiltersValueTo(self, fiter_number: int = 0) -> WebElement: + return self.wait_for(self.inputFiltersValueTo.format(fiter_number)) + + def getInputFiltersValue(self, fiter_number: str) -> WebElement: + return self.wait_for(self.inputFiltersValue.format(fiter_number)) + + def getAutocompleteTargetCriteriaValues(self) -> WebElement: + return self.wait_for(self.autocompleteTargetCriteriaValues) + + def getSelectMany(self) -> WebElement: + return self.wait_for(self.selectMany) + + def getButtonEdit(self) -> WebElement: + return self.wait_for(self.buttonEdit) diff --git a/backend/selenium_tests/page_object/targeting/targeting_details.py b/backend/selenium_tests/page_object/targeting/targeting_details.py index 56625451cc..63ca3186a7 100644 --- a/backend/selenium_tests/page_object/targeting/targeting_details.py +++ b/backend/selenium_tests/page_object/targeting/targeting_details.py @@ -1,3 +1,5 @@ +from time import sleep + from page_object.base_components import BaseComponents from selenium.webdriver.remote.webelement import WebElement @@ -8,20 +10,24 @@ class TargetingDetails(BaseComponents): status = 'div[data-cy="target-population-status"]' criteria_container = 'div[data-cy="criteria-container"]' lock_button = 'button[data-cy="button-target-population-lock"]' + lockPopupButton = 'button[data-cy="button-target-population-modal-lock"]' household_table_cell = "table tr:nth-of-type({}) td:nth-of-type({})" people_table_rows = '[data-cy="target-population-people-row"]' household_table_rows = '[data-cy="target-population-household-row"]' - pageHeaderContainer = 'div[data-cy="page-header-container"]' pageHeaderTitle = 'h5[data-cy="page-header-title"]' buttonTargetPopulationDuplicate = 'button[data-cy="button-target-population-duplicate"]' + inputName = 'input[data-cy="input-name"]' buttonDelete = 'button[data-cy="button-delete"]' buttonEdit = 'a[data-cy="button-edit"]' + buttonIconEdit = 'button[data-cy="button-edit"]' buttonRebuild = 'button[data-cy="button-rebuild"]' buttonTargetPopulationLock = 'button[data-cy="button-target-population-lock"]' detailsTitle = 'div[data-cy="details-title"]' detailsGrid = 'div[data-cy="details-grid"]' labelStatus = 'div[data-cy="label-Status"]' + buttonMarkReady = 'button[data-cy="button-target-population-send-to-hope"]' + buttonPopupMarkReady = 'button[data-cy="button-target-population-modal-send-to-hope"]' targetPopulationStatus = 'div[data-cy="target-population-status"]' labelizedFieldContainerCreatedBy = 'div[data-cy="labelized-field-container-created-by"]' labelCreatedBy = 'div[data-cy="label-created by"]' @@ -35,6 +41,11 @@ class TargetingDetails(BaseComponents): labelSendDate = 'div[data-cy="label-Send date"]' criteriaContainer = 'div[data-cy="criteria-container"]' checkboxExcludeIfActiveAdjudicationTicket = 'span[data-cy="checkbox-exclude-if-active-adjudication-ticket"]' + checkboxExcludePeopleIfActiveAdjudicationTicket = ( + 'span[data-cy="checkbox-exclude-people-if-active-adjudication-ticket"]' + ) + checkboxExcludeIfOnSanctionList = 'span[data-cy="checkbox-exclude-if-on-sanction-list"]' + iconSelected = '[data-testid="CheckBoxIcon"]' labelFemaleChildren = 'div[data-cy="label-Female Children"]' labelFemaleAdults = 'div[data-cy="label-Female Adults"]' labelMaleChildren = 'div[data-cy="label-Male Children"]' @@ -44,6 +55,10 @@ class TargetingDetails(BaseComponents): tableTitle = 'h6[data-cy="table-title"]' tableLabel = 'span[data-cy="table-label"]' tablePagination = 'div[data-cy="table-pagination"]' + statusContainer = 'div[data-cy="status-container"]' + householdSizeFrom = 'input[data-cy="input-filters[0].value.from"]' + householdSizeTo = 'input[data-cy="input-filters[0].value.to"]' + dialogBox = 'div[role="dialog"]' # Texts # Elements @@ -51,15 +66,27 @@ class TargetingDetails(BaseComponents): def getPageHeaderTitle(self) -> WebElement: return self.wait_for(self.pageHeaderTitle) + def waitForTextTitlePage(self, text: str) -> bool: + return self.wait_for_text(text, self.titlePage) + def getButtonTargetPopulationDuplicate(self) -> WebElement: return self.wait_for(self.buttonTargetPopulationDuplicate) + def getInputName(self) -> WebElement: + return self.wait_for(self.inputName) + + def disappearInputName(self) -> WebElement: + return self.wait_for_disappear(self.inputName) + def getButtonDelete(self) -> WebElement: return self.wait_for(self.buttonDelete) def getButtonEdit(self) -> WebElement: return self.wait_for(self.buttonEdit) + def getButtonIconEdit(self) -> WebElement: + return self.wait_for(self.buttonIconEdit) + def getButtonRebuild(self) -> WebElement: return self.wait_for(self.buttonRebuild) @@ -75,9 +102,23 @@ def getDetailsGrid(self) -> WebElement: def getLabelStatus(self) -> WebElement: return self.wait_for(self.labelStatus) + def waitForLabelStatus(self, status: str) -> WebElement: + for _ in range(10): + sleep(1) + if status.upper() in self.getLabelStatus().text: + return self.wait_for(self.labelStatus) + else: + raise Exception(f"Status: {status.capitalize()} does not occur.") + def getTargetPopulationStatus(self) -> WebElement: return self.wait_for(self.targetPopulationStatus) + def getButtonMarkReady(self) -> WebElement: + return self.wait_for(self.buttonMarkReady) + + def getButtonPopupMarkReady(self) -> WebElement: + return self.wait_for(self.buttonPopupMarkReady) + def getLabelizedFieldContainerCreatedBy(self) -> WebElement: return self.wait_for(self.labelizedFieldContainerCreatedBy) @@ -112,7 +153,16 @@ def getCriteriaContainer(self) -> WebElement: return self.wait_for(self.criteriaContainer) def getCheckboxExcludeIfActiveAdjudicationTicket(self) -> WebElement: - return self.wait_for(self.checkboxExcludeIfActiveAdjudicationTicket) + return self.get(self.checkboxExcludeIfActiveAdjudicationTicket) + + def getCheckboxExcludePeopleIfActiveAdjudicationTicket(self) -> WebElement: + return self.get(self.checkboxExcludePeopleIfActiveAdjudicationTicket) + + def getCheckboxExcludeIfOnSanctionList(self) -> WebElement: + return self.wait_for(self.checkboxExcludeIfOnSanctionList) + + def getIconSelected(self) -> WebElement: + return self.wait_for(self.iconSelected) def getLabelFemaleChildren(self) -> WebElement: return self.wait_for(self.labelFemaleChildren) @@ -150,6 +200,9 @@ def getStatus(self) -> WebElement: def getLockButton(self) -> WebElement: return self.wait_for(self.lock_button) + def getLockPopupButton(self) -> WebElement: + return self.wait_for(self.lockPopupButton) + def getHouseholdTableCell(self, row: int, column: int) -> WebElement: return self.wait_for(self.household_table_cell.format(row, column)) @@ -158,3 +211,18 @@ def getPeopleTableRows(self) -> list[WebElement]: def getHouseholdTableRows(self) -> list[WebElement]: return self.get_elements(self.household_table_rows) + + def getStatusContainer(self) -> WebElement: + return self.wait_for(self.statusContainer) + + def disappearStatusContainer(self) -> bool: + return self.wait_for_disappear(self.statusContainer) + + def getHouseholdSizeFrom(self) -> WebElement: + return self.wait_for(self.householdSizeFrom) + + def getHouseholdSizeTo(self) -> WebElement: + return self.wait_for(self.householdSizeTo) + + def getDialogBox(self) -> WebElement: + return self.wait_for(self.dialogBox) diff --git a/backend/selenium_tests/payment_module/test_payment_module.py b/backend/selenium_tests/payment_module/test_payment_module.py index 386248362a..83c857f016 100644 --- a/backend/selenium_tests/payment_module/test_payment_module.py +++ b/backend/selenium_tests/payment_module/test_payment_module.py @@ -25,7 +25,7 @@ def create_test_program() -> Program: BusinessArea.objects.filter(slug="afghanistan").update(is_payment_plan_applicable=True) dct = DataCollectingTypeFactory(type=DataCollectingType.Type.STANDARD) - return ProgramFactory( + yield ProgramFactory( name="Test Program", programme_code="1234", start_date=datetime.now() - relativedelta(months=1), @@ -61,7 +61,7 @@ def create_payment_plan(create_test_program: Program) -> PaymentPlan: is_follow_up=False, program_id=tp.program.id, ) - return payment_plan[0] + yield payment_plan[0] @pytest.mark.usefixtures("login") diff --git a/backend/selenium_tests/program_details/test_program_details.py b/backend/selenium_tests/program_details/test_program_details.py index dcaf0c3793..c506d6f95c 100644 --- a/backend/selenium_tests/program_details/test_program_details.py +++ b/backend/selenium_tests/program_details/test_program_details.py @@ -20,7 +20,7 @@ @pytest.fixture def standard_program() -> Program: - return get_program_with_dct_type_and_name("Test For Edit", "TEST") + yield get_program_with_dct_type_and_name("Test For Edit", "TEST") def get_program_with_dct_type_and_name( @@ -43,7 +43,7 @@ def get_program_with_dct_type_and_name( def create_programs() -> None: call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/core/fixtures/data-selenium.json") call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/program/fixtures/data-cypress.json") - return + yield @pytest.mark.usefixtures("login") @@ -54,12 +54,10 @@ def test_program_details(self, standard_program: Program, pageProgrammeDetails: pageProgrammeDetails.selectGlobalProgramFilter("Test For Edit").click() # Check Details page assert "Test For Edit" in pageProgrammeDetails.getHeaderTitle().text - pageProgrammeDetails.screenshot("0") assert "DRAFT" in pageProgrammeDetails.getProgramStatus().text assert "Test For Edit" in pageProgrammeDetails.getHeaderTitle().text assert "REMOVE" in pageProgrammeDetails.getButtonRemoveProgram().text assert "EDIT PROGRAMME" in pageProgrammeDetails.getButtonEditProgram().text - pageProgrammeDetails.screenshot("1") assert "ACTIVATE" in pageProgrammeDetails.getButtonActivateProgram().text assert "" in pageProgrammeDetails.getCopyProgram().text assert "DRAFT" in pageProgrammeDetails.getProgramStatus().text diff --git a/backend/selenium_tests/programme_management/test_programme_management.py b/backend/selenium_tests/programme_management/test_programme_management.py index 06221ad6a1..32fda41520 100644 --- a/backend/selenium_tests/programme_management/test_programme_management.py +++ b/backend/selenium_tests/programme_management/test_programme_management.py @@ -18,7 +18,7 @@ def create_programs() -> None: call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/core/fixtures/data-selenium.json") call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/program/fixtures/data-cypress.json") - return + yield @pytest.mark.usefixtures("login") diff --git a/backend/selenium_tests/programme_population/test_households.py b/backend/selenium_tests/programme_population/test_households.py index 7d79b8dd1f..5f2b37ddf4 100644 --- a/backend/selenium_tests/programme_population/test_households.py +++ b/backend/selenium_tests/programme_population/test_households.py @@ -12,14 +12,14 @@ def create_programs() -> None: call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/core/fixtures/data-selenium.json") call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/program/fixtures/data-cypress.json") - return + yield @pytest.fixture def add_households() -> None: call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/registration_data/fixtures/data-cypress.json") call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/household/fixtures/data-cypress.json") - return + yield @pytest.mark.usefixtures("login") diff --git a/backend/selenium_tests/programme_population/test_individuals.py b/backend/selenium_tests/programme_population/test_individuals.py index c552891623..f66a42b427 100644 --- a/backend/selenium_tests/programme_population/test_individuals.py +++ b/backend/selenium_tests/programme_population/test_individuals.py @@ -12,14 +12,14 @@ def create_programs() -> None: call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/core/fixtures/data-selenium.json") call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/program/fixtures/data-cypress.json") - return + yield @pytest.fixture def add_households() -> None: call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/registration_data/fixtures/data-cypress.json") call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/household/fixtures/data-cypress.json") - return + yield @pytest.mark.usefixtures("login") diff --git a/backend/selenium_tests/registration_data_import/test_registration_data_import.py b/backend/selenium_tests/registration_data_import/test_registration_data_import.py index a196e8ab20..2bcf2d636c 100644 --- a/backend/selenium_tests/registration_data_import/test_registration_data_import.py +++ b/backend/selenium_tests/registration_data_import/test_registration_data_import.py @@ -28,13 +28,13 @@ def registration_datahub(db) -> None: # type: ignore def create_programs() -> None: call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/core/fixtures/data-selenium.json") call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/program/fixtures/data-cypress.json") - return + yield @pytest.fixture def add_rdi() -> None: call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/registration_data/fixtures/data-cypress.json") - return + yield @pytest.fixture diff --git a/backend/selenium_tests/targeting/test_targeting.py b/backend/selenium_tests/targeting/test_targeting.py index 25fd27fbc1..0a0b4272a2 100644 --- a/backend/selenium_tests/targeting/test_targeting.py +++ b/backend/selenium_tests/targeting/test_targeting.py @@ -1,77 +1,83 @@ from datetime import datetime +from uuid import UUID from django.conf import settings from django.core.management import call_command -from django.db import transaction import pytest from dateutil.relativedelta import relativedelta from page_object.targeting.targeting import Targeting from page_object.targeting.targeting_create import TargetingCreate from page_object.targeting.targeting_details import TargetingDetails +from selenium.common import NoSuchElementException from selenium.webdriver import ActionChains, Keys +from selenium.webdriver.common.by import By +from hct_mis_api.apps.account.models import User from hct_mis_api.apps.core.fixtures import DataCollectingTypeFactory from hct_mis_api.apps.core.models import BusinessArea, DataCollectingType -from hct_mis_api.apps.household.fixtures import create_household_and_individuals +from hct_mis_api.apps.household.fixtures import ( + create_household, + create_household_and_individuals, +) from hct_mis_api.apps.household.models import HEARING, HOST, REFUGEE, SEEING, Household from hct_mis_api.apps.program.fixtures import ProgramFactory from hct_mis_api.apps.program.models import Program +from hct_mis_api.apps.targeting.fixtures import TargetingCriteriaFactory +from hct_mis_api.apps.targeting.models import TargetPopulation +from selenium_tests.page_object.filters import Filters pytestmark = pytest.mark.django_db(transaction=True, databases=["registration_datahub", "default"]) @pytest.fixture def sw_program() -> Program: - return get_program_with_dct_type_and_name( - "SW Program", dct_type=DataCollectingType.Type.SOCIAL, status=Program.ACTIVE + yield get_program_with_dct_type_and_name( + "Test Programm", dct_type=DataCollectingType.Type.SOCIAL, status=Program.ACTIVE ) @pytest.fixture def non_sw_program() -> Program: - return get_program_with_dct_type_and_name( - "Non SW Program", dct_type=DataCollectingType.Type.STANDARD, status=Program.ACTIVE + yield get_program_with_dct_type_and_name( + "Test Programm", dct_type=DataCollectingType.Type.STANDARD, status=Program.ACTIVE ) +def create_custom_household(observed_disability: list[str], residence_status: str = HOST) -> Household: + program = Program.objects.get(name="Test Programm") + household, _ = create_household_and_individuals( + household_data={ + "unicef_id": "HH-00-0000.0442", + "rdi_merge_status": "MERGED", + "business_area": program.business_area, + "program": program, + "residence_status": residence_status, + }, + individuals_data=[ + { + "rdi_merge_status": "MERGED", + "business_area": program.business_area, + "observed_disability": observed_disability, + }, + ], + ) + return household + + @pytest.fixture def household_with_disability() -> Household: - program = Program.objects.first() - with transaction.atomic(): - household, individuals = create_household_and_individuals( - household_data={"business_area": program.business_area, "program": program, "residence_status": HOST}, - individuals_data=[ - {"business_area": program.business_area, "observed_disability": [SEEING, HEARING]}, - ], - ) - return household + yield create_custom_household(observed_disability=[SEEING, HEARING]) @pytest.fixture def household_without_disabilities() -> Household: - program = Program.objects.first() - with transaction.atomic(): - household, individuals = create_household_and_individuals( - household_data={"business_area": program.business_area, "program": program, "residence_status": HOST}, - individuals_data=[ - {"business_area": program.business_area, "observed_disability": []}, - ], - ) - return household + yield create_custom_household(observed_disability=[]) @pytest.fixture def household_refugee() -> Household: - program = Program.objects.first() - with transaction.atomic(): - household, individuals = create_household_and_individuals( - household_data={"business_area": program.business_area, "program": program, "residence_status": REFUGEE}, - individuals_data=[ - {"business_area": program.business_area, "observed_disability": []}, - ], - ) - return household + yield create_custom_household(observed_disability=[], residence_status=REFUGEE) def get_program_with_dct_type_and_name( @@ -89,11 +95,36 @@ def get_program_with_dct_type_and_name( return program +@pytest.fixture +def create_targeting(household_without_disabilities: Household) -> TargetPopulation: + program = Program.objects.first() + target_population = TargetPopulation.objects.update_or_create( + pk=UUID("00000000-0000-0000-0000-faceb00c0123"), + name="Test Target Population", + targeting_criteria=TargetingCriteriaFactory(), + status=TargetPopulation.STATUS_OPEN, + business_area=BusinessArea.objects.get(slug="afghanistan"), + program=Program.objects.get(name="Test Programm"), + created_by=User.objects.first(), + )[0] + target_population.save() + household, _ = create_household( + household_args={ + "unicef_id": "HH-00-0000.0442", + "business_area": program.business_area, + "program": program, + "residence_status": HOST, + }, + ) + target_population.households.set([household]) + yield target_population + + @pytest.fixture def create_programs() -> None: call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/core/fixtures/data-selenium.json") call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/program/fixtures/data-cypress.json") - return + yield @pytest.fixture @@ -101,6 +132,7 @@ def add_targeting() -> None: call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/registration_data/fixtures/data-cypress.json") call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/household/fixtures/data-cypress.json") call_command("loaddata", f"{settings.PROJECT_ROOT}/apps/targeting/fixtures/data-cypress.json") + yield @pytest.mark.usefixtures("login") @@ -175,11 +207,12 @@ def test_smoke_targeting_details_page( assert "-" in pageTargetingDetails.getLabelSendBy().text assert "-" in pageTargetingDetails.getLabelSendDate().text assert "-" in pageTargetingDetails.getCriteriaContainer().text - assert "0" in pageTargetingDetails.getLabelFemaleChildren().text - assert "0" in pageTargetingDetails.getLabelMaleChildren().text - assert "0" in pageTargetingDetails.getLabelMaleAdults().text - assert "2" in pageTargetingDetails.getLabelTotalNumberOfHouseholds().text - assert "8" in pageTargetingDetails.getLabelTargetedIndividuals().text + assert "6" in pageTargetingDetails.getLabelFemaleChildren().text + assert "1" in pageTargetingDetails.getLabelMaleChildren().text + assert "2" in pageTargetingDetails.getLabelFemaleAdults().text + assert "1" in pageTargetingDetails.getLabelMaleAdults().text + assert "3" in pageTargetingDetails.getLabelTotalNumberOfHouseholds().text + assert "7" in pageTargetingDetails.getLabelTargetedIndividuals().text assert "Households" in pageTargetingDetails.getTableTitle().text expected_menu_items = [ "ID", @@ -269,3 +302,492 @@ def test_create_targeting_for_normal_program( actions = ActionChains(pageTargetingDetails.driver) actions.move_to_element(pageTargetingDetails.getHouseholdTableCell(1, 1)).perform() # type: ignore assert len(pageTargetingDetails.getHouseholdTableRows()) == 1 + + +@pytest.mark.usefixtures("login") +class TestTargeting: + def test_targeting_create_use_ids_hh( + self, + create_programs: None, + household_with_disability: Household, + add_targeting: None, + pageTargeting: Targeting, + pageTargetingDetails: TargetingDetails, + pageTargetingCreate: TargetingCreate, + ) -> None: + pageTargeting.selectGlobalProgramFilter("Test Programm").click() + pageTargeting.getNavTargeting().click() + pageTargeting.getButtonCreateNew().click() + pageTargeting.getCreateUseIDs().click() + assert "New Target Population" in pageTargetingCreate.getPageHeaderTitle().text + assert "SAVE" in pageTargetingCreate.getButtonTargetPopulationCreate().text + pageTargetingCreate.getInputHouseholdids().send_keys(household_with_disability.unicef_id) + pageTargetingCreate.getInputName().send_keys(f"Target Population for {household_with_disability.unicef_id}") + pageTargetingCreate.clickButtonTargetPopulationCreate() + target_population = TargetPopulation.objects.get( + name=f"Target Population for {household_with_disability.unicef_id}" + ) + assert ( + "1" + == str(target_population.total_individuals_count) + == pageTargetingDetails.getLabelTargetedIndividuals().text + ) + assert ( + str(target_population.total_households_count) == pageTargetingDetails.getLabelTotalNumberOfHouseholds().text + ) + assert str(target_population.status) in pageTargetingDetails.getLabelStatus().text + + def test_targeting_create_use_ids_individual( + self, + create_programs: None, + household_with_disability: Household, + add_targeting: None, + pageTargeting: Targeting, + pageTargetingDetails: TargetingDetails, + pageTargetingCreate: TargetingCreate, + ) -> None: + pageTargeting.selectGlobalProgramFilter("Test Programm").click() + pageTargeting.getNavTargeting().click() + pageTargeting.getButtonCreateNew().click() + pageTargeting.getCreateUseIDs().click() + assert "New Target Population" in pageTargetingCreate.getPageHeaderTitle().text + assert "SAVE" in pageTargetingCreate.getButtonTargetPopulationCreate().text + pageTargetingCreate.getInputIndividualids().send_keys("IND-88-0000.0002") + pageTargetingCreate.getInputName().send_keys("Target Population for IND-88-0000.0002") + pageTargetingCreate.clickButtonTargetPopulationCreate() + target_population = TargetPopulation.objects.get(name="Target Population for IND-88-0000.0002") + assert ( + "4" + == str(target_population.total_individuals_count) + == pageTargetingDetails.getLabelTargetedIndividuals().text + ) + assert ( + str(target_population.total_households_count) == pageTargetingDetails.getLabelTotalNumberOfHouseholds().text + ) + assert str(target_population.status) in pageTargetingDetails.getLabelStatus().text + pageTargetingDetails.getButtonRebuild().click() + + def test_targeting_rebuild( + self, + create_programs: None, + create_targeting: TargetPopulation, + pageTargeting: Targeting, + pageTargetingDetails: TargetingDetails, + pageTargetingCreate: TargetingCreate, + ) -> None: + pageTargeting.selectGlobalProgramFilter("Test Programm").click() + pageTargeting.getNavTargeting().click() + pageTargeting.chooseTargetPopulations(0).click() + pageTargetingDetails.getLabelStatus() + pageTargetingDetails.getButtonRebuild().click() + pageTargetingDetails.getStatusContainer() + pageTargetingDetails.disappearStatusContainer() + + def test_targeting_mark_ready( + self, + create_programs: None, + household_with_disability: Household, + add_targeting: None, + pageTargeting: Targeting, + filters: Filters, + pageTargetingDetails: TargetingDetails, + pageTargetingCreate: TargetingCreate, + ) -> None: + pageTargeting.selectGlobalProgramFilter("Test Programm").click() + pageTargeting.getNavTargeting().click() + filters.selectFiltersSatus("OPEN") + pageTargeting.chooseTargetPopulations(0).click() + pageTargetingDetails.getLabelStatus() + pageTargetingDetails.getLockButton().click() + pageTargetingDetails.getLockPopupButton().click() + pageTargetingDetails.waitForLabelStatus("LOCKED") + pageTargetingDetails.getButtonMarkReady().click() + pageTargetingDetails.getButtonPopupMarkReady().click() + pageTargetingDetails.waitForLabelStatus("READY") + + def test_copy_targeting( + self, + create_programs: None, + add_targeting: None, + pageTargeting: Targeting, + pageTargetingDetails: TargetingDetails, + pageTargetingCreate: TargetingCreate, + ) -> None: + program = Program.objects.get(name="Test Programm") + pageTargeting.selectGlobalProgramFilter(program.name).click() + pageTargeting.getNavTargeting().click() + pageTargeting.chooseTargetPopulations(0).click() + pageTargetingDetails.getButtonTargetPopulationDuplicate().click() + pageTargetingDetails.getInputName().send_keys("a1!") + pageTargetingDetails.get_elements(pageTargetingDetails.buttonTargetPopulationDuplicate)[1].click() + pageTargetingDetails.disappearInputName() + assert "a1!" in pageTargetingDetails.getTitlePage().text + assert "OPEN" in pageTargetingDetails.getTargetPopulationStatus().text + assert "PROGRAMME" in pageTargetingDetails.getLabelizedFieldContainerProgramName().text + assert "Test Programm" in pageTargetingDetails.getLabelProgramme().text + assert "2" in pageTargetingDetails.getLabelTotalNumberOfHouseholds().text + assert "8" in pageTargetingDetails.getLabelTargetedIndividuals().text + + def test_edit_targeting( + self, + create_programs: None, + household_with_disability: Household, + add_targeting: None, + pageTargeting: Targeting, + pageTargetingDetails: TargetingDetails, + pageTargetingCreate: TargetingCreate, + ) -> None: + pageTargeting.selectGlobalProgramFilter("Test Programm").click() + pageTargeting.getNavTargeting().click() + pageTargeting.chooseTargetPopulations(0).click() + pageTargetingDetails.getButtonEdit().click() + pageTargetingDetails.getInputName().send_keys(Keys.CONTROL + "a") + pageTargetingDetails.getInputName().send_keys("New Test Data") + pageTargetingDetails.getButtonIconEdit().click() + pageTargetingDetails.getHouseholdSizeFrom().send_keys(Keys.CONTROL + "a") + pageTargetingDetails.getHouseholdSizeFrom().send_keys("0") + pageTargetingDetails.getHouseholdSizeTo().send_keys(Keys.CONTROL + "a") + pageTargetingDetails.getHouseholdSizeTo().send_keys("9") + pageTargetingCreate.get_elements(pageTargetingCreate.targetingCriteriaAddDialogSaveButton)[1].click() + pageTargetingCreate.getButtonSave().click() + pageTargetingDetails.getButtonEdit() + assert pageTargetingDetails.waitForTextTitlePage("New Test Data") + assert "9" in pageTargetingDetails.getCriteriaContainer().text + + def test_delete_targeting( + self, + create_programs: None, + household_with_disability: Household, + add_targeting: None, + pageTargeting: Targeting, + pageTargetingDetails: TargetingDetails, + ) -> None: + pageTargeting.selectGlobalProgramFilter("Test Programm").click() + pageTargeting.getNavTargeting().click() + pageTargeting.disappearLoadingRows() + old_list = pageTargeting.getTargetPopulationsRows() + assert 2 == len(old_list) + assert "Copy TP" in old_list[0].text + + pageTargeting.chooseTargetPopulations(0).click() + pageTargetingDetails.getButtonDelete().click() + pageTargetingDetails.getDialogBox() + pageTargetingDetails.get_elements(pageTargetingDetails.buttonDelete)[1].click() + pageTargeting.disappearLoadingRows() + new_list = pageTargeting.getTargetPopulationsRows() + assert 1 == len(new_list) + assert "Test NEW TP" in new_list[0].text + + def test_targeting_different_program_statuses( + self, + create_programs: None, + pageTargeting: Targeting, + pageTargetingDetails: TargetingDetails, + pageTargetingCreate: TargetingCreate, + ) -> None: + program = Program.objects.get(name="Test Programm") + program.status = Program.DRAFT + program.save() + pageTargeting.selectGlobalProgramFilter("Test Programm").click() + pageTargeting.getNavTargeting().click() + pageTargeting.mouse_on_element(pageTargeting.getButtonInactiveCreateNew()) + assert "Program has to be active to create a new Target Population" in pageTargeting.geTooltip().text + program.status = Program.ACTIVE + program.save() + pageTargeting.driver.refresh() + pageTargeting.getButtonCreateNew() + program.status = Program.FINISHED + program.save() + pageTargeting.driver.refresh() + pageTargeting.mouse_on_element(pageTargeting.getButtonInactiveCreateNew()) + assert "Program has to be active to create a new Target Population" in pageTargeting.geTooltip().text + + @pytest.mark.parametrize( + "test_data", + [ + pytest.param( + { + "type": "SOCIAL", + "text": "Exclude People with Active Adjudication Ticket", + }, + id="People", + ), + pytest.param( + { + "type": "STANDARD", + "text": "Exclude Households with Active Adjudication Ticket", + }, + id="Program population", + ), + ], + ) + def test_exclude_households_with_active_adjudication_ticket( + self, + test_data: dict, + create_programs: None, + household_with_disability: Household, + add_targeting: None, + pageTargeting: Targeting, + pageTargetingDetails: TargetingDetails, + pageTargetingCreate: TargetingCreate, + ) -> None: + program = Program.objects.get(name="Test Programm") + program.data_collecting_type.type = test_data["type"] + program.data_collecting_type.save() + pageTargeting.selectGlobalProgramFilter("Test Programm").click() + pageTargeting.getNavTargeting().click() + pageTargeting.getButtonCreateNew().click() + pageTargeting.getCreateUseIDs().click() + pageTargetingCreate.getInputHouseholdids().send_keys(household_with_disability.unicef_id) + pageTargetingCreate.getInputName().send_keys(f"Test {household_with_disability.unicef_id}") + pageTargetingCreate.getInputFlagexcludeifactiveadjudicationticket().click() + pageTargetingCreate.clickButtonTargetPopulationCreate() + with pytest.raises(NoSuchElementException): + pageTargetingDetails.getCheckboxExcludeIfOnSanctionList().find_element( + By.CSS_SELECTOR, pageTargetingDetails.iconSelected + ) + if test_data["type"] == "SOCIAL": + pageTargetingDetails.getCheckboxExcludePeopleIfActiveAdjudicationTicket() + pageTargetingDetails.getCheckboxExcludePeopleIfActiveAdjudicationTicket().find_element( + By.CSS_SELECTOR, pageTargetingDetails.iconSelected + ) + assert ( + test_data["text"] + in pageTargetingDetails.getCheckboxExcludePeopleIfActiveAdjudicationTicket() + .find_element(By.XPATH, "./..") + .text + ) + elif test_data["type"] == "STANDARD": + pageTargetingDetails.getCheckboxExcludeIfActiveAdjudicationTicket() + pageTargetingDetails.getCheckboxExcludeIfActiveAdjudicationTicket().find_element( + By.CSS_SELECTOR, pageTargetingDetails.iconSelected + ) + assert ( + test_data["text"] + in pageTargetingDetails.getCheckboxExcludeIfActiveAdjudicationTicket() + .find_element(By.XPATH, "./..") + .text + ) + + @pytest.mark.parametrize( + "test_data", + [ + pytest.param( + { + "type": "SOCIAL", + "text": "Exclude People with an active sanction screen flag", + }, + id="People", + ), + pytest.param( + { + "type": "STANDARD", + "text": "Exclude Households with an active sanction screen flag", + }, + id="Program population", + ), + ], + ) + def test_exclude_households_with_sanction_screen_flag( + self, + test_data: dict, + create_programs: None, + household_with_disability: Household, + add_targeting: None, + pageTargeting: Targeting, + pageTargetingDetails: TargetingDetails, + pageTargetingCreate: TargetingCreate, + ) -> None: + program = Program.objects.get(name="Test Programm") + program.data_collecting_type.type = test_data["type"] + program.data_collecting_type.save() + pageTargeting.selectGlobalProgramFilter("Test Programm").click() + pageTargeting.getNavTargeting().click() + pageTargeting.getButtonCreateNew().click() + pageTargeting.getCreateUseIDs().click() + pageTargetingCreate.getInputHouseholdids().send_keys(household_with_disability.unicef_id) + pageTargetingCreate.getInputName().send_keys(f"Test {household_with_disability.unicef_id}") + pageTargetingCreate.getInputFlagexcludeifonsanctionlist().click() + pageTargetingCreate.clickButtonTargetPopulationCreate() + pageTargetingDetails.getCheckboxExcludeIfOnSanctionList() + # ToDo: Add after merge to develop + # assert ( + # test_data["text"] + # in pageTargetingDetails.getCheckboxExcludeIfOnSanctionList().find_element(By.XPATH, "./..").text + # ) + pageTargetingDetails.getCheckboxExcludeIfOnSanctionList().find_element( + By.CSS_SELECTOR, pageTargetingDetails.iconSelected + ) + with pytest.raises(NoSuchElementException): + pageTargetingDetails.getCheckboxExcludePeopleIfActiveAdjudicationTicket().find_element( + By.CSS_SELECTOR, pageTargetingDetails.iconSelected + ) + + def test_targeting_info_button( + self, + create_programs: None, + pageTargeting: Targeting, + ) -> None: + pageTargeting.selectGlobalProgramFilter("Test Programm").click() + pageTargeting.getNavTargeting().click() + pageTargeting.getButtonTargetPopulation().click() + pageTargeting.getTabFieldList() + pageTargeting.getTabTargetingDiagram().click() + + def test_targeting_filters( + self, + create_programs: None, + household_with_disability: Household, + add_targeting: None, + pageTargeting: Targeting, + filters: Filters, + ) -> None: + pageTargeting.selectGlobalProgramFilter("Test Programm").click() + pageTargeting.getNavTargeting().click() + filters.getFiltersSearch().send_keys("Copy") + filters.getButtonFiltersApply().click() + pageTargeting.countTargetPopulations(1) + assert "OPEN" in pageTargeting.getStatusContainer().text + filters.getButtonFiltersClear().click() + filters.getFiltersStatus().click() + filters.select_listbox_element("Open").click() + filters.getButtonFiltersApply().click() + pageTargeting.countTargetPopulations(1) + assert "OPEN" in pageTargeting.getStatusContainer().text + filters.getButtonFiltersClear().click() + filters.getFiltersTotalHouseholdsCountMin().send_keys("10") + filters.getFiltersTotalHouseholdsCountMax().send_keys("10") + filters.getButtonFiltersApply().click() + pageTargeting.countTargetPopulations(0) + filters.getButtonFiltersClear().click() + filters.getFiltersTotalHouseholdsCountMin().send_keys("1") + filters.getFiltersTotalHouseholdsCountMax().send_keys("3") + pageTargeting.countTargetPopulations(2) + filters.getButtonFiltersClear().click() + + def test_targeting_and_labels( + self, + create_programs: None, + household_with_disability: Household, + add_targeting: None, + pageTargeting: Targeting, + ) -> None: + pageTargeting.selectGlobalProgramFilter("Test Programm").click() + pageTargeting.getNavTargeting().click() + pageTargeting.getColumnName().click() + pageTargeting.disappearLoadingRows() + assert "Copy TP" in pageTargeting.chooseTargetPopulations(0).text + pageTargeting.getColumnName().click() + pageTargeting.disappearLoadingRows() + assert "Test NEW TP" in pageTargeting.chooseTargetPopulations(0).text + pageTargeting.getColumnStatus().click() + pageTargeting.disappearLoadingRows() + assert "Test NEW TP" in pageTargeting.chooseTargetPopulations(0).text + pageTargeting.getColumnStatus().click() + pageTargeting.disappearLoadingRows() + assert "Copy TP" in pageTargeting.chooseTargetPopulations(0).text + pageTargeting.getColumnNumOfHouseholds().click() + pageTargeting.disappearLoadingRows() + assert "Test NEW TP" in pageTargeting.chooseTargetPopulations(0).text + pageTargeting.getColumnDateCreated().click() + pageTargeting.disappearLoadingRows() + assert "Test NEW TP" in pageTargeting.chooseTargetPopulations(0).text + pageTargeting.getColumnDateCreated().click() + pageTargeting.disappearLoadingRows() + assert "Copy TP" in pageTargeting.chooseTargetPopulations(0).text + pageTargeting.getColumnLastEdited().click() + pageTargeting.disappearLoadingRows() + assert "Test NEW TP" in pageTargeting.chooseTargetPopulations(0).text + pageTargeting.getColumnLastEdited().click() + pageTargeting.disappearLoadingRows() + assert "Copy TP" in pageTargeting.chooseTargetPopulations(0).text + pageTargeting.getColumnCreatedBy().click() + pageTargeting.disappearLoadingRows() + assert "est NEW TP" in pageTargeting.chooseTargetPopulations(0).text + + def test_targeting_parametrized_rules_filters( + self, + create_programs: None, + household_with_disability: Household, + add_targeting: None, + pageTargeting: Targeting, + pageTargetingDetails: TargetingDetails, + pageTargetingCreate: TargetingCreate, + ) -> None: + pageTargeting.selectGlobalProgramFilter("Test Programm").click() + pageTargeting.getNavTargeting().click() + pageTargeting.getButtonCreateNew().click() + pageTargeting.getButtonCreateNewByFilters().click() + assert "New Target Population" in pageTargetingCreate.getTitlePage().text + pageTargetingCreate.getAddCriteriaButton().click() + pageTargetingCreate.getAddPeopleRuleButton().click() + pageTargetingCreate.getTargetingCriteriaAutoComplete().click() + pageTargetingCreate.select_listbox_element("Females Age 0 - 5").click() + pageTargetingCreate.getInputFiltersValueFrom(0).send_keys("0") + pageTargetingCreate.getInputFiltersValueTo(0).send_keys("1") + pageTargetingCreate.getInputFiltersValueTo(0).send_keys("1") + pageTargetingCreate.getButtonTargetPopulationAddCriteria().click() + pageTargetingCreate.getInputName().send_keys("Target Population for Females Age 0 - 5") + pageTargetingCreate.getInputFlagexcludeifactiveadjudicationticket().click() + pageTargetingCreate.clickButtonTargetPopulationCreate() + assert "Females Age 0 - 5: 11" in pageTargetingCreate.getCriteriaContainer().text + + def test_targeting_parametrized_rules_filters_and_or( + self, + create_programs: None, + household_with_disability: Household, + add_targeting: None, + pageTargeting: Targeting, + pageTargetingDetails: TargetingDetails, + pageTargetingCreate: TargetingCreate, + ) -> None: + pageTargeting.selectGlobalProgramFilter("Test Programm").click() + pageTargeting.getNavTargeting().click() + pageTargeting.getButtonCreateNew().click() + pageTargeting.getButtonCreateNewByFilters().click() + assert "New Target Population" in pageTargetingCreate.getTitlePage().text + pageTargetingCreate.getAddCriteriaButton().click() + pageTargetingCreate.getAddPeopleRuleButton().click() + pageTargetingCreate.getTargetingCriteriaAutoComplete().click() + pageTargetingCreate.select_listbox_element("Females Age 0 - 5").click() + pageTargetingCreate.getInputFiltersValueFrom(0).send_keys("0") + pageTargetingCreate.getInputFiltersValueTo(0).send_keys("1") + pageTargetingCreate.getButtonHouseholdRule().click() + pageTargetingCreate.getTargetingCriteriaAutoComplete(1).click() + pageTargetingCreate.select_listbox_element("Village").click() + pageTargetingCreate.getInputFiltersValue(1).send_keys("Testtown") + pageTargetingCreate.getButtonIndividualRule().click() + pageTargetingCreate.getTargetingCriteriaAutoCompleteIndividual().click() + pageTargetingCreate.select_listbox_element("Does the Individual have disability?").click() + pageTargetingCreate.getSelectMany().click() + pageTargetingCreate.select_multiple_option_by_name(HEARING, SEEING) + pageTargetingCreate.getTargetingCriteriaAddDialogSaveButton().click() + assert "Females Age 0 - 5: 1" in pageTargetingCreate.getCriteriaContainer().text + assert "Village: Testtown" in pageTargetingCreate.getCriteriaContainer().text + assert ( + "Does the Individual have disability?: Difficulty hearing (even if using a hearing aid), Difficulty seeing (even if wearing glasses)" + in pageTargetingCreate.getCriteriaContainer().text + ) + pageTargetingCreate.getButtonEdit().click() + pageTargetingCreate.getTargetingCriteriaAutoCompleteIndividual() + pageTargetingCreate.get_elements(pageTargetingCreate.targetingCriteriaAddDialogSaveButton)[1].click() + pageTargetingCreate.getInputName().send_keys("Target Population") + assert "ADD 'OR'FILTER" in pageTargetingCreate.getTargetingCriteriaAddDialogSaveButton().text + pageTargetingCreate.getTargetingCriteriaAddDialogSaveButton().click() + pageTargetingCreate.getAddHouseholdRuleButton().click() + pageTargetingCreate.getTargetingCriteriaAutoComplete().click() + pageTargetingCreate.select_listbox_element("Males age 0 - 5 with disability").click() + pageTargetingCreate.getInputFiltersValueFrom(0).send_keys("1") + pageTargetingCreate.getInputFiltersValueTo(0).send_keys("10") + pageTargetingCreate.get_elements(pageTargetingCreate.targetingCriteriaAddDialogSaveButton)[1].click() + pageTargetingCreate.getTargetPopulationSaveButton().click() + assert "Females Age 0 - 5: 1" in pageTargetingCreate.getCriteriaContainer().text + assert "Village: Testtown" in pageTargetingCreate.getCriteriaContainer().text + assert ( + "Does the Individual have disability?: Difficulty hearing (even if using a hearing aid), Difficulty seeing (even if wearing glasses)" + in pageTargetingCreate.getCriteriaContainer().text + ) + assert ( + "Males age 0 - 5 with disability: 1 -10" + in pageTargetingCreate.get_elements(pageTargetingCreate.criteriaContainer)[1].text + ) diff --git a/deployment/docker-compose.selenium.yml b/deployment/docker-compose.selenium.yml index 7fa7859afb..7d17e14278 100644 --- a/deployment/docker-compose.selenium.yml +++ b/deployment/docker-compose.selenium.yml @@ -33,7 +33,7 @@ services: command: | bash -c " waitforit -host=db -port=5432 -timeout=30 - pytest -svvv selenium_tests --reruns 3 --reruns-delay 1 --cov-report xml:./coverage.xml --html-report=./report/report.html --randomly-seed=42 + pytest -svvv selenium_tests --cov-report xml:./coverage.xml --html-report=./report/report.html --randomly-seed=42 " depends_on: db: diff --git a/frontend/src/components/targeting/TargetPopulationCore.tsx b/frontend/src/components/targeting/TargetPopulationCore.tsx index 44097e944e..36802db922 100644 --- a/frontend/src/components/targeting/TargetPopulationCore.tsx +++ b/frontend/src/components/targeting/TargetPopulationCore.tsx @@ -101,11 +101,15 @@ export const TargetPopulationCore = ({ {householdIds.length > 0 && ( - {householdIds} + + {householdIds} + )} {individualIds.length > 0 && ( - {individualIds} + + {individualIds} + )}