From e31a731002cdcf4e145599753a0ab2dd61c6d1fc Mon Sep 17 00:00:00 2001 From: szymon-kellton <130459593+szymon-kellton@users.noreply.github.com> Date: Thu, 12 Sep 2024 13:33:08 +0200 Subject: [PATCH] Selenium: People module tests (#4164) * Test people module * In progress PDU tests to people * Selenium: Fix tests (#4206) * Fixing login tests; RDI test; seatch filter tests; * Fixing tests * Fixing test_create_programme_check_empty_mandatory_fields * Added People module tests --------- Co-authored-by: Jan Romaniak Co-authored-by: Marek Biczysko <34810846+MarekBiczysko@users.noreply.github.com> --- .../grievance/details_grievance_page.py | 11 + backend/selenium_tests/people/test_people.py | 86 ++++- .../test_people_periodic_data_update.py | 308 ++++++++++++++++++ .../test_periodic_data_update_upload.py | 19 +- 4 files changed, 416 insertions(+), 8 deletions(-) create mode 100644 backend/selenium_tests/people/test_people_periodic_data_update.py diff --git a/backend/selenium_tests/page_object/grievance/details_grievance_page.py b/backend/selenium_tests/page_object/grievance/details_grievance_page.py index 592df14310..b2b8139e8f 100644 --- a/backend/selenium_tests/page_object/grievance/details_grievance_page.py +++ b/backend/selenium_tests/page_object/grievance/details_grievance_page.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 @@ -87,7 +88,9 @@ class GrievanceDetailsPage(BaseComponents): labelPartner = 'div[data-cy="label-Partner"]' labelAdministrativeLevel2 = 'div[data-cy="label-Administrative Level 2"]' checkboxHouseholdData = 'span[data-cy="checkbox-household-data"]' + checkboxApprove = '//*[contains(@data, "checkbox")]' checkboxIndividualData = 'span[data-cy="checkbox-requested-data-change"]' + checkboxRequestedDataChange = 'span[data-cy="checkbox-requested-data-change"]' approveBoxNeedsAdjudicationTitle = 'h6[data-cy="approve-box-needs-adjudication-title"]' buttonCreateLinkedTicket = 'button[data-cy="button-create-linked-ticket"]' buttonMarkDistinct = 'button[data-cy="button-mark-distinct"]' @@ -458,9 +461,17 @@ def getApproveBoxNeedsAdjudicationTitle(self) -> WebElement: def getCheckboxHouseholdData(self) -> WebElement: return self.wait_for(self.checkboxHouseholdData) + def getCheckboxApprove(self) -> [WebElement]: + self.wait_for(self.checkboxApprove, By.XPATH) + return self.get_elements(self.checkboxApprove, By.XPATH) + def getCheckboxIndividualData(self) -> WebElement: return self.wait_for(self.checkboxIndividualData) + def getCheckboxRequestedDataChange(self) -> [WebElement]: + self.wait_for(self.checkboxRequestedDataChange) + return self.get_elements(self.checkboxRequestedDataChange) + def getButtonCreateLinkedTicket(self) -> WebElement: return self.wait_for(self.buttonCreateLinkedTicket) diff --git a/backend/selenium_tests/people/test_people.py b/backend/selenium_tests/people/test_people.py index 24b6b4ee3a..5c3452c1a2 100644 --- a/backend/selenium_tests/people/test_people.py +++ b/backend/selenium_tests/people/test_people.py @@ -6,6 +6,7 @@ import pytest from dateutil.relativedelta import relativedelta from page_object.people.people import People +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 @@ -24,6 +25,11 @@ TargetPopulationFactory, ) from selenium_tests.page_object.filters import Filters +from selenium_tests.page_object.grievance.details_grievance_page import ( + GrievanceDetailsPage, +) +from selenium_tests.page_object.grievance.grievance_tickets import GrievanceTickets +from selenium_tests.page_object.grievance.new_ticket import NewTicket from selenium_tests.page_object.people.people_details import PeopleDetails pytestmark = pytest.mark.django_db(transaction=True) @@ -237,6 +243,80 @@ def test_people_happy_path( assert "DELIVERED FULLY" in pagePeopleDetails.getRows()[0].text assert add_people_with_payment_record.unicef_id in pagePeopleDetails.getRows()[0].text - @pytest.mark.skip(reason="ToDo") - def test_check_data_after_grievance_ticket_processed(self) -> None: - pass + +@pytest.mark.usefixtures("login") +class TestPeople: + @pytest.mark.parametrize( + "test_data", + [ + pytest.param( + {"category": "Data Change", "type": "Individual Data Update"}, + id="Data Change People Data Update", + ) + ], + ) + def test_check_people_data_after_grievance_ticket_processed( + self, + pageGrievanceTickets: GrievanceTickets, + pageGrievanceNewTicket: NewTicket, + pageGrievanceDetailsPage: GrievanceDetailsPage, + add_people: List, + test_data: dict, + pagePeople: People, + pagePeopleDetails: PeopleDetails, + ) -> None: + pageGrievanceTickets.getNavGrievance().click() + assert "Grievance Tickets" in pageGrievanceTickets.getGrievanceTitle().text + pageGrievanceTickets.getButtonNewTicket().click() + pageGrievanceNewTicket.getSelectCategory().click() + pageGrievanceNewTicket.select_option_by_name(str(test_data["category"])) + pageGrievanceNewTicket.getIssueType().click() + pageGrievanceNewTicket.element_clickable(f'li[data-cy="select-option-{test_data["type"]}"]') + pageGrievanceNewTicket.select_listbox_element(str(test_data["type"])) + assert test_data["category"] in pageGrievanceNewTicket.getSelectCategory().text + assert test_data["type"] in pageGrievanceNewTicket.getIssueType().text + pageGrievanceNewTicket.getButtonNext().click() + pageGrievanceNewTicket.getHouseholdTab() + pageGrievanceNewTicket.getIndividualTab().click() + pageGrievanceNewTicket.getIndividualTableRows(0).click() + pageGrievanceDetailsPage.screenshot("0") + pageGrievanceNewTicket.getButtonNext().click() + pageGrievanceNewTicket.getReceivedConsent().click() + pageGrievanceNewTicket.getButtonNext().click() + + pageGrievanceNewTicket.getDescription().send_keys("Add Individual - TEST") + pageGrievanceNewTicket.getButtonAddNewField().click() + pageGrievanceNewTicket.getIndividualFieldName(0).click() + pageGrievanceNewTicket.select_option_by_name("Gender") + pageGrievanceNewTicket.getInputIndividualData("Gender").click() + pageGrievanceNewTicket.select_listbox_element("Female") + pageGrievanceNewTicket.getIndividualFieldName(1).click() + pageGrievanceNewTicket.select_option_by_name("Preferred language") + pageGrievanceNewTicket.getInputIndividualData("Preferred language").click() + pageGrievanceNewTicket.select_listbox_element("English | English") + + pageGrievanceNewTicket.getButtonNext().click() + pageGrievanceDetailsPage.getCheckboxIndividualData() + row0 = pageGrievanceDetailsPage.getRows()[0].text.split(" ") + assert "Gender" in row0[0] + assert "Female" in row0[-1] + + row1 = pageGrievanceDetailsPage.getRows()[1].text.split(" ") + assert "Preferred Language" in f"{row1[0]} {row1[1]}" + assert "English" in row1[-1] + + pageGrievanceDetailsPage.getButtonAssignToMe().click() + pageGrievanceDetailsPage.getButtonSetInProgress().click() + pageGrievanceDetailsPage.getButtonSendForApproval().click() + pageGrievanceDetailsPage.getButtonCloseTicket() + pageGrievanceDetailsPage.getCheckboxRequestedDataChange() + pageGrievanceDetailsPage.getCheckboxRequestedDataChange()[0].find_element(By.TAG_NAME, "input").click() + pageGrievanceDetailsPage.getCheckboxRequestedDataChange()[1].find_element(By.TAG_NAME, "input").click() + pageGrievanceDetailsPage.getButtonApproval().click() + pageGrievanceDetailsPage.getButtonConfirm().click() + pageGrievanceDetailsPage.getButtonCloseTicket().click() + pageGrievanceDetailsPage.getButtonConfirm().click() + assert "Ticket ID" in pageGrievanceDetailsPage.getTitle().text + pagePeople.selectGlobalProgramFilter("Worker Program") + pagePeople.getNavPeople().click() + pagePeople.getIndividualTableRow(0).click() diff --git a/backend/selenium_tests/people/test_people_periodic_data_update.py b/backend/selenium_tests/people/test_people_periodic_data_update.py new file mode 100644 index 0000000000..3a9c02af93 --- /dev/null +++ b/backend/selenium_tests/people/test_people_periodic_data_update.py @@ -0,0 +1,308 @@ +import os +from datetime import datetime +from time import sleep + +import pytest +from dateutil.relativedelta import relativedelta + +from hct_mis_api.apps.account.models import User +from hct_mis_api.apps.core.fixtures import DataCollectingTypeFactory, create_afghanistan +from hct_mis_api.apps.core.models import ( + BusinessArea, + DataCollectingType, + FlexibleAttribute, + PeriodicFieldData, +) +from hct_mis_api.apps.household.fixtures import create_household_and_individuals +from hct_mis_api.apps.household.models import HOST, SEEING, Individual +from hct_mis_api.apps.payment.fixtures import CashPlanFactory, PaymentRecordFactory +from hct_mis_api.apps.payment.models import GenericPayment +from hct_mis_api.apps.periodic_data_update.fixtures import ( + PeriodicDataUpdateTemplateFactory, + PeriodicDataUpdateUploadFactory, +) +from hct_mis_api.apps.periodic_data_update.models import ( + PeriodicDataUpdateTemplate, + PeriodicDataUpdateUpload, +) +from hct_mis_api.apps.periodic_data_update.utils import ( + field_label_to_field_name, + populate_pdu_with_null_values, +) +from hct_mis_api.apps.program.fixtures import ProgramFactory +from hct_mis_api.apps.program.models import Program +from hct_mis_api.apps.registration_data.fixtures import RegistrationDataImportFactory +from hct_mis_api.apps.targeting.fixtures import ( + TargetingCriteriaFactory, + TargetPopulationFactory, +) +from selenium_tests.page_object.people.people import People +from selenium_tests.page_object.people.people_details import PeopleDetails +from selenium_tests.page_object.programme_population.individuals import Individuals +from selenium_tests.page_object.programme_population.periodic_data_update_templates import ( + PeriodicDatUpdateTemplates, +) +from selenium_tests.page_object.programme_population.periodic_data_update_uploads import ( + PeriodicDataUpdateUploads, +) +from selenium_tests.programme_population.test_periodic_data_update_upload import ( + prepare_xlsx_file, +) + +pytestmark = pytest.mark.django_db(transaction=True) + + +@pytest.fixture +def clear_downloaded_files() -> None: + yield + for file in os.listdir("./report/downloads/"): + os.remove(os.path.join("./report/downloads", file)) + + +@pytest.fixture +def program() -> Program: + business_area = create_afghanistan() + dct = DataCollectingTypeFactory(type=DataCollectingType.Type.SOCIAL) + return ProgramFactory( + name="Test Program", + status=Program.ACTIVE, + business_area=business_area, + data_collecting_type=dct, + ) + + +@pytest.fixture +def date_attribute(program: Program) -> FlexibleAttribute: + return create_flexible_attribute( + label="Test Date Attribute", + subtype=FlexibleAttribute.DATE, + number_of_rounds=1, + rounds_names=["Test Round"], + program=program, + ) + + +@pytest.fixture +def individual(add_people: Individual) -> Individual: + program = Program.objects.filter(name="Test Program").first() + + cash_plan = CashPlanFactory( + name="TEST", + program=program, + business_area=BusinessArea.objects.first(), + start_date=datetime.now() - relativedelta(months=1), + end_date=datetime.now() + relativedelta(months=1), + ) + + targeting_criteria = TargetingCriteriaFactory() + + target_population = TargetPopulationFactory( + created_by=User.objects.first(), + targeting_criteria=targeting_criteria, + business_area=BusinessArea.objects.first(), + ) + PaymentRecordFactory( + household=add_people.household, + parent=cash_plan, + target_population=target_population, + entitlement_quantity="21.36", + delivered_quantity="21.36", + currency="PLN", + status=GenericPayment.STATUS_DISTRIBUTION_SUCCESS, + ) + add_people.total_cash_received_usd = "21.36" + add_people.save() + return add_people + + +@pytest.fixture +def add_people(program: Program) -> Individual: + business_area = program.business_area + rdi = RegistrationDataImportFactory() + household, individuals = create_household_and_individuals( + household_data={ + "business_area": business_area, + "program": program, + "residence_status": HOST, + "registration_data_import": rdi, + }, + individuals_data=[ + { + "full_name": "Stacey Freeman", + "given_name": "Stacey", + "middle_name": "", + "family_name": "Freeman", + "business_area": business_area, + "observed_disability": [SEEING], + "registration_data_import": rdi, + }, + ], + ) + yield individuals[0] + + +def create_flexible_attribute( + label: str, subtype: str, number_of_rounds: int, rounds_names: list[str], program: Program +) -> FlexibleAttribute: + name = field_label_to_field_name(label) + flexible_attribute = FlexibleAttribute.objects.create( + label={"English(EN)": label}, + name=name, + type=FlexibleAttribute.PDU, + associated_with=FlexibleAttribute.ASSOCIATED_WITH_INDIVIDUAL, + program=program, + ) + flexible_attribute.pdu_data = PeriodicFieldData.objects.create( + subtype=subtype, number_of_rounds=number_of_rounds, rounds_names=rounds_names + ) + flexible_attribute.save() + return flexible_attribute + + +@pytest.fixture +def string_attribute() -> FlexibleAttribute: + program = Program.objects.filter(name="Test Program").first() + return create_flexible_attribute( + label="Test String Attribute", + subtype=FlexibleAttribute.STRING, + number_of_rounds=1, + rounds_names=["Test Round"], + program=program, + ) + + +@pytest.mark.usefixtures("login") +class TestPeoplePeriodicDataUpdateUpload: + def test_people_periodic_data_update_upload_success( + self, + clear_downloaded_files: None, + pagePeople: People, + pagePeopleDetails: PeopleDetails, + individual: Individual, + string_attribute: FlexibleAttribute, + pageIndividuals: Individuals, + ) -> None: + program = Program.objects.filter(name="Test Program").first() + populate_pdu_with_null_values(program, individual.flex_fields) + individual.save() + flexible_attribute = string_attribute + tmp_file = prepare_xlsx_file( + [ + { + "field": flexible_attribute.name, + "round": 1, + "round_name": flexible_attribute.pdu_data.rounds_names[0], + "number_of_records": 0, + } + ], + [["Test Value", "2021-05-02"]], + program, + ) + pagePeople.selectGlobalProgramFilter(program.name) + pagePeople.getNavPeople().click() + pageIndividuals.getTabPeriodicDataUpdates().click() + pageIndividuals.getButtonImport().click() + pageIndividuals.getDialogImport() + assert "IMPORT" in pageIndividuals.getButtonImportSubmit().text + pageIndividuals.upload_file(tmp_file.name) + pageIndividuals.getButtonImportSubmit().click() + pageIndividuals.getPduUpdates().click() + for i in range(5): + periodic_data_update_upload = PeriodicDataUpdateUpload.objects.first() + if periodic_data_update_upload.status == PeriodicDataUpdateUpload.Status.SUCCESSFUL: + break + pageIndividuals.screenshot(i) + sleep(1) + else: + assert periodic_data_update_upload.status == PeriodicDataUpdateUpload.Status.SUCCESSFUL + assert periodic_data_update_upload.error_message is None + individual.refresh_from_db() + assert individual.flex_fields[flexible_attribute.name]["1"]["value"] == "Test Value" + assert individual.flex_fields[flexible_attribute.name]["1"]["collection_date"] == "2021-05-02" + assert pageIndividuals.getUpdateStatus(periodic_data_update_upload.pk).text == "SUCCESSFUL" + pageIndividuals.screenshot("0") + + @pytest.mark.night + def test_people_periodic_data_update_upload_form_error( + self, + clear_downloaded_files: None, + program: Program, + individual: Individual, + date_attribute: FlexibleAttribute, + pageIndividuals: Individuals, + pagePeople: People, + pagePeopleDetails: PeopleDetails, + ) -> None: + populate_pdu_with_null_values(program, individual.flex_fields) + individual.save() + flexible_attribute = date_attribute + tmp_file = prepare_xlsx_file( + [ + { + "field": flexible_attribute.name, + "round": 1, + "round_name": flexible_attribute.pdu_data.rounds_names[0], + "number_of_records": 0, + } + ], + [["Test Value", "2021-05-02"]], + program, + ) + pagePeople.selectGlobalProgramFilter(program.name) + pagePeople.getNavPeople().click() + pageIndividuals.getTabPeriodicDataUpdates().click() + pageIndividuals.getButtonImport().click() + pageIndividuals.getDialogImport() + pageIndividuals.upload_file(tmp_file.name) + pageIndividuals.getButtonImportSubmit().click() + pageIndividuals.getPduUpdates().click() + pageIndividuals.getStatusContainer() + periodic_data_update_upload = PeriodicDataUpdateUpload.objects.first() + assert periodic_data_update_upload.status == PeriodicDataUpdateUpload.Status.FAILED + assert pageIndividuals.getStatusContainer().text == "FAILED" + assert pageIndividuals.getUpdateStatus(periodic_data_update_upload.pk).text == "FAILED" + pageIndividuals.getUpdateDetailsBtn(periodic_data_update_upload.pk).click() + error_text = "Row: 2\ntest_date_attribute__round_value\nEnter a valid date." + assert pageIndividuals.getPduFormErrors().text == error_text + + @pytest.mark.night + def test_people_periodic_data_uploads_list( + self, + clear_downloaded_files: None, + program: Program, + string_attribute: FlexibleAttribute, + pageIndividuals: Individuals, + pagePeriodicDataUpdateTemplates: PeriodicDatUpdateTemplates, + pagePeriodicDataUploads: PeriodicDataUpdateUploads, + pagePeople: People, + pagePeopleDetails: PeopleDetails, + ) -> None: + periodic_data_update_template = PeriodicDataUpdateTemplateFactory( + program=program, + business_area=program.business_area, + status=PeriodicDataUpdateTemplate.Status.TO_EXPORT, + filters=dict(), + rounds_data=[ + { + "field": string_attribute.name, + "round": 1, + "round_name": string_attribute.pdu_data.rounds_names[0], + "number_of_records": 0, + } + ], + ) + pdu_upload = PeriodicDataUpdateUploadFactory( + template=periodic_data_update_template, + status=PeriodicDataUpdateUpload.Status.SUCCESSFUL, + ) + pagePeople.selectGlobalProgramFilter(program.name) + pagePeople.getNavPeople().click() + pageIndividuals.getTabPeriodicDataUpdates().click() + pagePeriodicDataUpdateTemplates.getPduUpdatesBtn().click() + + index = pdu_upload.id + assert str(index) in pagePeriodicDataUploads.getUpdateId(index).text + assert str(pdu_upload.template.id) in pagePeriodicDataUploads.getUpdateTemplate(index).text + assert f"{pdu_upload.created_at:%-d %b %Y}" in pagePeriodicDataUploads.getUpdateCreatedAt(index).text + assert pdu_upload.created_by.get_full_name() in pagePeriodicDataUploads.getUpdateCreatedBy(index).text + assert "SUCCESSFUL" in pagePeriodicDataUploads.getUpdateStatus(index).text diff --git a/backend/selenium_tests/programme_population/test_periodic_data_update_upload.py b/backend/selenium_tests/programme_population/test_periodic_data_update_upload.py index 265acc4159..e589ba5081 100644 --- a/backend/selenium_tests/programme_population/test_periodic_data_update_upload.py +++ b/backend/selenium_tests/programme_population/test_periodic_data_update_upload.py @@ -11,8 +11,12 @@ PeriodicDataUpdateUploads, ) -from hct_mis_api.apps.core.fixtures import create_afghanistan -from hct_mis_api.apps.core.models import FlexibleAttribute, PeriodicFieldData +from hct_mis_api.apps.core.fixtures import DataCollectingTypeFactory, create_afghanistan +from hct_mis_api.apps.core.models import ( + DataCollectingType, + FlexibleAttribute, + PeriodicFieldData, +) from hct_mis_api.apps.household.fixtures import create_household_and_individuals from hct_mis_api.apps.household.models import Individual from hct_mis_api.apps.periodic_data_update.fixtures import ( @@ -48,7 +52,13 @@ def clear_downloaded_files() -> None: @pytest.fixture def program() -> Program: business_area = create_afghanistan() - return ProgramFactory(name="Test Program", status=Program.ACTIVE, business_area=business_area) + dct = DataCollectingTypeFactory(type=DataCollectingType.Type.SOCIAL) + return ProgramFactory( + name="Test Program", + status=Program.ACTIVE, + business_area=business_area, + data_collecting_type=dct, + ) @pytest.fixture @@ -168,8 +178,7 @@ def test_periodic_data_update_upload_success( program, ) pageIndividuals.selectGlobalProgramFilter(program.name) - pageIndividuals.getNavProgrammePopulation().click() - pageIndividuals.getNavIndividuals().click() + pageIndividuals.getNavPeople().click() pageIndividuals.getTabPeriodicDataUpdates().click() pageIndividuals.getButtonImport().click() pageIndividuals.getDialogImport()