diff --git a/.gitignore b/.gitignore index 0b634dcf3..c06481dfe 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ allure-report/ tox.log node_modules/ package-lock.json +downloads/RAVs-Vaccination-Report.csv diff --git a/conftest.py b/conftest.py index 26bf641fd..696a014b3 100644 --- a/conftest.py +++ b/conftest.py @@ -1,5 +1,9 @@ import pytest +from pytest_bdd import given, when, then, scenarios, scenario +from pytest_bdd.parsers import parse # from pages.add_vaccines_page import * +from pages.check_and_confirm_vaccinated_record_page import * +from pages.delete_vaccination_page import * from pages.settings_page import * from pages.site_vaccine_batches_page import * from pages.vaccines_page import * @@ -24,6 +28,7 @@ from datetime import datetime, timedelta from allure_commons.types import LabelType import logging +from test_data.get_values_from_models import * # Define marks pytest.mark.login = pytest.mark.mark(login=True) @@ -52,20 +57,6 @@ def format_nhs_number(nhs_number): formatted_number = re.sub(r"(\d{3})(\d{3})(\d{4})", r"\1 \2 \3", nhs_number) return formatted_number - -# @pytest.fixture(scope='function') -# def playwright_helper(request): -# helper = PlaywrightHelper(get_working_directory(), config) -# def teardown(): -# try: -# helper.quit_browser() -# except Exception as e: -# print(f"An error occurred during teardown: {e}") -# raise - -# request.addfinalizer(teardown) -# return helper - # Fixture for site parameter @pytest.fixture(params=["NEELIMA HOUSE", "ALBERT HOUSE", "ST JOHN'S HOUSE"]) def site(request): @@ -430,3 +421,162 @@ def navigate_and_login_with_username(username): attach_screenshot("entered_password") click_nhs_signin_button() attach_screenshot("clicked_nhs_signin_button") + +@given(parse("I login to RAVS and set vaccinator details with {site} and {care_model} and get patient details for {nhs_number} with option {index} and choose to vaccinate with vaccine details as {chosen_vaccine}, {batch_number} with {batch_expiry_date}")) +def step_login_to_ravs(site, care_model, nhs_number, index, chosen_vaccine, batch_number, batch_expiry_date, shared_data): + shared_data["nhs_number"] = nhs_number + shared_data["index"] = index + shared_data["chosen_vaccine"] = chosen_vaccine + shared_data["chosen_vaccine_type"] = get_vaccination_type(index, chosen_vaccine) + shared_data["batch_number"] = batch_number + shared_data["site"] = site + shared_data["care_model"] = get_care_model(index) + + today_str = datetime.today().strftime('%d/%m/%Y') + today = datetime.strptime(today_str, '%d/%m/%Y') + if datetime.strptime(batch_expiry_date, '%d/%m/%Y') <= today: + batch_expiry_date = today + timedelta(days=7) + batch_expiry_date = standardize_date_format(batch_expiry_date) + shared_data["batch_expiry_date"] = batch_expiry_date + check_vaccine_and_batch_exists_in_site(site, chosen_vaccine, shared_data["chosen_vaccine_type"], batch_number, batch_expiry_date) + return shared_data + +@given("I search for a patient with the NHS number in the find a patient screen") +@then("I search for a patient with the NHS number in the find a patient screen") +def step_search_for_patient(shared_data): + nhs_number = shared_data["nhs_number"] + click_find_a_patient_and_search_with_nhs_number(nhs_number) + +@given(parse("I open the patient record by clicking on patient {name}")) +@then(parse("I open the patient record by clicking on patient {name}")) +def step_search_for_patient(shared_data, name): + attach_screenshot("before_clicking_patient_name") + click_on_patient_name(name) + attach_screenshot("before_clicking_patient_name") + shared_data["patient_name"] = name + +@when(parse("I click choose vaccine button and choose the {chosen_vaccine}, {batch_number} with {batch_expiry_date} and click continue")) +def step_choose_vaccine_and_vaccine_type(shared_data, chosen_vaccine, batch_number, batch_expiry_date): + time.sleep(3) + immunisation_history_records_count_before_vaccination = click_on_patient_search_result_and_click_choose_vaccine(shared_data['patient_name'], chosen_vaccine) + shared_data["immunisation_history_records_count_before_vaccination"] = immunisation_history_records_count_before_vaccination + choose_vaccine_and_vaccine_type_for_patient(shared_data['site'], chosen_vaccine, shared_data['chosen_vaccine_type']) + +@when(parse("I assess the patient's {eligibility} with the details and date as {assess_date} and click continue to record consent screen button")) +def step_assess_eligibility_and_click_continue_record_consent_screen(shared_data, eligibility, assess_date): + shared_data['eligible_decision'] = eligibility + shared_data['legal_mechanism'] = get_legal_mechanism(shared_data["index"]) + shared_data['eligibility_type'] = get_eligibility_type(shared_data["index"], shared_data["chosen_vaccine"]) + shared_data["healthcare_worker"] = get_staff_role(shared_data["index"]) + shared_data['eligibility_assessing_clinician'] = get_random_assessing_clinician() + assess_date = format_date(str(get_date_value(assess_date)), config["browser"]) + shared_data['eligibility_assessment_date'] = assess_date + shared_data['eligibility_assessment_outcome'] = get_assessment_outcome(0) + shared_data['eligibility_assessment_no_vaccine_given_reason'] = get_assess_vaccine_not_given_reason(shared_data["index"]) + shared_data['assessment_comments'] = "Assessment comments " + assess_date + shared_data["patient_name"] + assess_patient_with_details_and_click_continue_to_consent(eligibility, shared_data['eligibility_type'], shared_data["healthcare_worker"], shared_data['eligibility_assessing_clinician'], None, assess_date, shared_data['legal_mechanism'], shared_data['eligibility_assessment_outcome'], shared_data['assessment_comments'],shared_data['eligibility_assessment_no_vaccine_given_reason']) + +@when(parse("I assess the pregnant patient's {eligibility} with the details of due date as {due_date} and assessment date as {assess_date} and click continue to record consent screen button")) +def step_assess_eligibility_and_click_continue_record_consent_screen(shared_data, eligibility, due_date, assess_date): + shared_data['eligible_decision'] = eligibility + shared_data['legal_mechanism'] = get_legal_mechanism(shared_data["index"]) + shared_data['eligibility_type'] = "Pregnancy" + shared_data["healthcare_worker"] = get_staff_role(shared_data["index"]) + shared_data['eligibility_assessing_clinician'] = get_random_assessing_clinician() + due_date = format_date(str(get_date_value(due_date)), config["browser"]) + shared_data['eligibility_due_date'] = due_date + assess_date = format_date(str(get_date_value(assess_date)), config["browser"]) + shared_data['eligibility_assessment_date'] = assess_date + shared_data['eligibility_assessment_outcome'] = get_assessment_outcome(0) + shared_data['eligibility_assessment_no_vaccine_given_reason'] = get_assess_vaccine_not_given_reason(shared_data["index"]) + shared_data['assessment_comments'] = "Assessment comments " + assess_date + shared_data["patient_name"] + assess_patient_with_details_and_click_continue_to_consent(eligibility, shared_data['eligibility_type'], shared_data["healthcare_worker"], shared_data['eligibility_assessing_clinician'], due_date, assess_date, shared_data['legal_mechanism'], shared_data['eligibility_assessment_outcome'], shared_data['assessment_comments'],shared_data['eligibility_assessment_no_vaccine_given_reason']) + +@when(parse("I record {consent} with the details and click continue to vaccinate button")) +def step_record_consent_and_click_continue_to_vaccinate_screen(shared_data, consent): + shared_data['consent_decision'] = consent + if shared_data["eligibility_assessment_outcome"].lower() == "give vaccine": + shared_data['consent_given_by'] = get_consent_given_by(shared_data["index"]) + name_of_person_consenting = "Automation tester" + relationship_to_patient = "RAVS tester" + if shared_data['legal_mechanism'] == "Patient Group Direction (PGD)": + shared_data['consent_clinician_details'] = shared_data['eligibility_assessing_clinician'] + else: + shared_data['consent_clinician_details'] = get_consenting_clinician(shared_data["index"]) + shared_data["no_consent_reason"] = get_no_consent_reason(shared_data["index"]) + record_consent_details_and_click_continue_to_vaccinate(shared_data['consent_decision'],shared_data['consent_given_by'], name_of_person_consenting, relationship_to_patient, shared_data['consent_clinician_details'], shared_data['legal_mechanism'], shared_data["no_consent_reason"]) + +@when(parse("I record {vaccination} details and date as {vaccination_date} and click Continue to Check and confirm screen")) +def step_enter_vaccination_details_and_continue_to_check_and_confirm_screen(shared_data, vaccination, vaccination_date): + shared_data["vaccinated_decision"] = vaccination + if shared_data["consent_decision"].lower() == "yes": + if shared_data["eligibility_assessment_outcome"].lower() == "give vaccine": + shared_data["vaccination_date"] = format_date(str(get_date_value(vaccination_date)), config["browser"]) + chosen_vaccine = shared_data["chosen_vaccine"] + shared_data["vaccination_site"] = get_vaccination_site(shared_data["index"]) + shared_data["dose_amount"] = str(get_vaccine_dose_amount(shared_data["chosen_vaccine_type"])) + if shared_data['legal_mechanism'] == "Patient Group Direction (PGD)": + shared_data['vaccinator'] = shared_data['eligibility_assessing_clinician'] + else: + shared_data["vaccinator"] = get_vaccinator(shared_data["index"]) + shared_data["vaccination_comments"] = shared_data["chosen_vaccine_type"] + "vaccination given on " + shared_data["vaccination_date"] + " for " + shared_data["patient_name"] + shared_data["no_vaccination_reason"] = get_vaccination_not_given_reason(shared_data["index"]) + enter_vaccine_details_and_click_continue_to_check_and_confirm(shared_data["vaccinated_decision"], shared_data["care_model"], shared_data["vaccination_date"], chosen_vaccine, shared_data["chosen_vaccine_type"], shared_data["vaccination_site"], shared_data["batch_number"], shared_data["batch_expiry_date"], shared_data["dose_amount"], shared_data["vaccinator"], shared_data["vaccination_comments"], shared_data["legal_mechanism"], shared_data["no_vaccination_reason"]) + attach_screenshot("entered_vaccination_details") + logging.info(shared_data) + +@then(parse("I need to be able to see the patient {name}, {dob}, {address} and vaccination details on the check and confirm screen")) +def step_see_patient_details_on_check_and_confirm_screen(shared_data, name, dob, address): + if shared_data["vaccinated_decision"].lower() == "Yes".lower() and shared_data["consent_decision"].lower() == "Yes".lower() and shared_data["eligibility_assessment_outcome"].lower() == "Give vaccine".lower(): + attach_screenshot("check_and_confirm_screen_before_assertion") + assert get_patient_name_value() == shared_data["patient_name"] + assert get_patient_address_value() == address + assert get_patient_vaccination_dose_amount_value() == shared_data["dose_amount"] + assert get_patient_vaccinated_chosen_vaccine_value() == shared_data["chosen_vaccine"] + assert get_patient_vaccinated_chosen_vaccine_product_value() == shared_data["chosen_vaccine_type"] + assert get_patient_eligibility_assessment_date_value() == date_format_with_day_of_week(shared_data['eligibility_assessment_date']) + assert get_patient_vaccinated_date_value() == date_format_with_day_of_week(shared_data['vaccination_date']) + assert get_patient_dob_value() == date_format_with_age(dob) + assert get_patient_vaccination_batch_expiry_date_value() == date_format_with_name_of_month(shared_data['batch_expiry_date']) + assert get_patient_eligibility_assessing_clinician_vaccine_value() == shared_data['eligibility_assessing_clinician'] + assert get_patient_consent_recorded_by_clinician_value() == shared_data['consent_clinician_details'] + assert get_patient_vaccination_vaccinator_value() == shared_data['vaccinator'] + attach_screenshot("check_and_confirm_screen_after_assertion") + +@then("when I click confirm and save button, I should see a record saved dialogue") +def click_confirm_and_save_button_record_saved(shared_data): + attach_screenshot("patient_details_screen_with_immunisation_history") + click_confirm_details_and_save_button() + attach_screenshot("before_assert_record_saved") + assert check_record_saved_element_exists(False) + +@then("the immunisation history of the patient should be updated in the patient details page") +def immunisation_history_should_be_updated(shared_data): + attach_screenshot("immunisation_history_records_count_after_vaccination") + immunisation_history_records_count_after_vaccination = get_count_of_immunisation_history_records(shared_data["chosen_vaccine"]) + assert int(immunisation_history_records_count_after_vaccination) >= int(shared_data["immunisation_history_records_count_before_vaccination"]) + 1 + click_delete_history_link(shared_data["chosen_vaccine"]) + attach_screenshot("click_delete_history_link") + click_delete_vaccination_button() + attach_screenshot("click_delete_vaccination_button") + shared_data.clear() + +@then("the immunisation history of the patient should be updated in the patient details page and not be deleted") +def immunisation_history_should_be_updated(shared_data): + attach_screenshot("immunisation_history_records_count_after_vaccination") + immunisation_history_records_count_after_vaccination = get_count_of_immunisation_history_records(shared_data["chosen_vaccine"]) + assert int(immunisation_history_records_count_after_vaccination) >= int(shared_data["immunisation_history_records_count_before_vaccination"]) + 1 + +@then("when I click confirm and save button, the immunisation history of the patient should be updated in the patient details page") +def click_confirm_and_save_button_immunisation_history_should_be_updated(shared_data): + attach_screenshot("patient_details_screen_with_immunisation_history") + if shared_data["vaccinated_decision"].lower() == "yes" and shared_data["consent_decision"].lower() == "yes" and shared_data["eligibility_assessment_outcome"].lower() == "give vaccine": + click_confirm_details_and_save_button() + immunisation_history_records_count_after_vaccination = get_count_of_immunisation_history_records(shared_data["chosen_vaccine"]) + assert int(immunisation_history_records_count_after_vaccination) >= int(shared_data["immunisation_history_records_count_before_vaccination"]) + 1 + shared_data.clear() + else: + immunisation_history_records_count_after_vaccination = get_count_of_immunisation_history_records(shared_data["chosen_vaccine"]) + assert int(immunisation_history_records_count_after_vaccination) == int(shared_data["immunisation_history_records_count_before_vaccination"]) + shared_data.clear() + attach_screenshot("patient_details_screen_with_immunisation_history") diff --git a/data/attachments/dev_edge_131.0.2903.63_Choose vaccines page should be visible.png b/data/attachments/dev_edge_131.0.2903.63_Choose vaccines page should be visible.png deleted file mode 100644 index a965fedae..000000000 Binary files a/data/attachments/dev_edge_131.0.2903.63_Choose vaccines page should be visible.png and /dev/null differ diff --git a/data/attachments/dev_edge_131.0.2903.63_clicked_continue_to_reports_select_vaccine_button.png b/data/attachments/dev_edge_131.0.2903.63_clicked_continue_to_reports_select_vaccine_button.png deleted file mode 100644 index a965fedae..000000000 Binary files a/data/attachments/dev_edge_131.0.2903.63_clicked_continue_to_reports_select_vaccine_button.png and /dev/null differ diff --git a/data/attachments/dev_edge_131.0.2903.63_create_report_button_is_clicked.png b/data/attachments/dev_edge_131.0.2903.63_create_report_button_is_clicked.png deleted file mode 100644 index 21c682cd5..000000000 Binary files a/data/attachments/dev_edge_131.0.2903.63_create_report_button_is_clicked.png and /dev/null differ diff --git a/data/attachments/dev_edge_131.0.2903.63_day_range_radio_button_is_clicked_and_date_range_Selected.png b/data/attachments/dev_edge_131.0.2903.63_day_range_radio_button_is_clicked_and_date_range_Selected.png deleted file mode 100644 index 19b4c7d90..000000000 Binary files a/data/attachments/dev_edge_131.0.2903.63_day_range_radio_button_is_clicked_and_date_range_Selected.png and /dev/null differ diff --git a/data/attachments/dev_edge_131.0.2903.63_reports_navigation_link_clicked.png b/data/attachments/dev_edge_131.0.2903.63_reports_navigation_link_clicked.png deleted file mode 100644 index 3f07e2a8b..000000000 Binary files a/data/attachments/dev_edge_131.0.2903.63_reports_navigation_link_clicked.png and /dev/null differ diff --git a/features/record_a_vaccine_for_patient_with_nhs_number.feature b/features/record_a_vaccine_for_patient_with_nhs_number.feature index 2d475cf77..0a79bff26 100644 --- a/features/record_a_vaccine_for_patient_with_nhs_number.feature +++ b/features/record_a_vaccine_for_patient_with_nhs_number.feature @@ -62,5 +62,5 @@ Feature: Record vaccine | 1 | 9693632109 | BECCLES HOUSE | Vaccination Centre | yes | today+100 | today-1 | yes | yes | today-1 | Bill GARTON | 23/6/1946 | 1 MOUNT AVENUE, BARTON-UPON-HUMBER, S HUMBERSIDE, DN18 5DW | Pertussis | AUTOMATION-BIS | 19/10/2028 | | 2 | 9470040228 | BIRCH HOUSE | Hospital hub for staff and patients | yes | today+290 | today-1 | yes | yes | today | HERBERT HAAG | 14/12/1922 | 10 COASTAL ROAD, HEST BANK, LANCASTER, LA2 6HN | Pertussis | AUTOMATION-RVS | 19/2/2029 | | 3 | 9472710255 | ALBERT HOUSE | Housebound patient's home | yes | today+5 | today-3 | yes | yes | today-2 | DELICE PINKER | 10/11/1926 | HARDCRAGG HOUSE, HARDCRAGG WAY, GRANGE-OVER-SANDS, CUMBRIA, LA11 6BH | Respiratory syncytial virus (RSV) | AUTOMATION-ARX | 19/10/2026 | - | 4 | 9473629885 | BECCLES HOUSE | Outreach event | yes | today+50 | today-4 | yes | yes | today-3 | MARGIE PUCKEY | 27/5/1924 | MANSART COURT, 10 OLIVE SHAPLEY AVENUE, MANCHESTER, M20 6QB | Respiratory syncytial virus (RSV) | AREX2-15A | 19/10/2026 | + # | 4 | 9473629885 | BECCLES HOUSE | Outreach event | yes | today+50 | today-4 | yes | yes | today-3 | MARGIE PUCKEY | 27/5/1924 | MANSART COURT, 10 OLIVE SHAPLEY AVENUE, MANCHESTER, M20 6QB | Respiratory syncytial virus (RSV) | AREX2-15A | 19/10/2026 | - # This test is no longer needed as Arexvy has been decommissioned on 29th Nov 2024 diff --git a/features/reports.feature b/features/reports.feature index 18f7149f0..c8f805f35 100644 --- a/features/reports.feature +++ b/features/reports.feature @@ -82,7 +82,25 @@ Scenario Outline: Choose data page is displayed And I click the today date range button and click continue And I select the vaccine type and click continue And I select the site and click continue - Then the choose data page should be displayed + Then the choose data page should be displayed and all data options should be checked by default + + + Examples: + |vaccineType | site | + | COVID-19 | Albert House | + | Flu | Albert House | + | Pertussis | Albert House | + | Respiratory syncytial virus (RSV) | Albert House | + +Scenario Outline: Check and confirm page should be displayed + Given I am logged into the RAVS app + When I click the reports navigation link + And I click the create report button + And I click the today date range button and click continue + And I select the vaccine type and click continue + And I select the site and click continue + And I click continue on the data page + Then the check and confirm page should be displayed Examples: |vaccineType | site | @@ -90,3 +108,73 @@ Scenario Outline: Choose data page is displayed | Flu | Albert House | | Pertussis | Albert House | | Respiratory syncytial virus (RSV) | Albert House | + | COVID-19 | Albert House | + +Scenario Outline: Report is ready page should be displayed + Given I am logged into the RAVS app + When I click the reports navigation link + And I click the create report button + And I click the today date range button and click continue + And I select the vaccine type and click continue + And I select the site and click continue + And I click continue on the data page + And I click Confirm and create report button in the check and confirm page + Then Creating your page element should be displayed and Download Report button should be visible + + Examples: + |vaccineType | site | + | COVID-19 | Albert House | + | Flu | Albert House | + | Pertussis | Albert House | + | Respiratory syncytial virus (RSV) | Albert House | + | COVID-19 | Albert House | + +Scenario Outline: User can download the report + Given I am logged into the RAVS app + When I click the reports navigation link + And I click the create report button + And I click the radio button and click Continue + And I select the vaccine type and click continue + And I select the site and click continue + And I click continue on the data page + And I click Confirm and create report button in the check and confirm page + And I click download report button + Then the report is downloaded successfully + + Examples: + |vaccineType | site | day | + | COVID-19 | Albert House | Last 31 days (includes today) | + | Flu | Albert House | Last 31 days (includes today) | + | Pertussis | Albert House | Last 7 days (includes today) | + | Respiratory syncytial virus (RSV) | Albert House | Last 14 days (includes today) | + | COVID-19 | Albert House | Last 31 days (includes today) | + | COVID-19 | Albert House | Select a custom date range up to 31 days | + + Scenario Outline: Record a vaccine and generate a report for today + Given I am logged into the RAVS app + And I login to RAVS and set vaccinator details with and and get patient details for with option and choose to vaccinate with vaccine details as , with + And I search for a patient with the NHS number in the find a patient screen + And I open the patient record by clicking on patient + When I click choose vaccine button and choose the , with and click continue + And I assess the patient's with the details and date as and click continue to record consent screen button + And I record with the details and click continue to vaccinate button + And I record details and date as and click Continue to Check and confirm screen + Then I need to be able to see the patient , ,
and vaccination details on the check and confirm screen + And when I click confirm and save button, I should see a record saved dialogue + And I search for a patient with the NHS number in the find a patient screen + And I open the patient record by clicking on patient + And the immunisation history of the patient should be updated in the patient details page and not be deleted + When I click the reports navigation link + And I click the create report button + And I click the Today radio button and click Continue + And I select the vaccine type and click continue + And I select the site and click continue + And I click continue on the data page + And I click Confirm and create report button in the check and confirm page + And I click download report button + Then the report is downloaded successfully and contains the vaccine record for + + Examples: + | index | nhs_number | site | care_model | eligibility | assess_date | consent | vaccination | vaccination_date | name | dob | address | chosen_vaccine | batch_number | batch_expiry_date | + | 0 | 9693632109 | Albert House | Vaccination Centre open to the public | yes | today | yes | yes | today | Bill GARTON | 23/6/1946 | 1 MOUNT AVENUE, BARTON-UPON-HUMBER, S HUMBERSIDE, DN18 5DW | COVID-19 | AUTOMATION-SJ1 | 19/10/2026 | + | 0 | 9693632109 | Albert House | Vaccination Centre open to the public | yes | today | yes | yes | today-32 | Bill GARTON | 23/6/1946 | 1 MOUNT AVENUE, BARTON-UPON-HUMBER, S HUMBERSIDE, DN18 5DW | COVID-19 | AUTOMATION-SJ1 | 19/10/2026 | diff --git a/helpers/playwrightHelper.py b/helpers/playwrightHelper.py index 74c095e87..70885410b 100644 --- a/helpers/playwrightHelper.py +++ b/helpers/playwrightHelper.py @@ -4,6 +4,7 @@ from init_helpers import * import pytest import logging +import platform class BasePlaywrightHelper: def __init__(self, working_directory, config): @@ -84,19 +85,6 @@ def launch_mobile_browser(self, device_name, headless_mode): except Exception as e: print(f"Error launching mobile browser for {device_name}: {e}") - # def capture_screenshot(self, full_path): - # try: - # logging.debug("Scrolling to the top of the page.") - # self.page.evaluate("window.scrollTo(0, 0);") - # self.page.screenshot(path=full_path) - # except Exception as error: - # if "Timeout" in str(error): - # print('Screenshot taking timed out, ignoring...') - # return None - # else: - # raise error - # return full_path - def capture_screenshot(self, full_path): try: # Get the current mouse position @@ -219,6 +207,12 @@ def check_element_enabled(self, selector, wait=False): return element.is_enabled() return False + def check_element_checked(self, selector, wait=False): + element = self.get_element(selector, wait=wait) + if element: + return element.is_checked() + return False + def is_page_responsive(self): try: # Check for a specific element that indicates responsiveness @@ -233,6 +227,38 @@ def handle_unresponsive_page(self): self.page.reload(wait_until="networkidle") self.wait_for_page_to_load() + def click_and_get_download_path(self, locator_or_element, action="click", timeout=30, download_dir="downloads"): + """ + Clicks an element and waits for a file to be downloaded, then returns the download path. + The file is saved in a custom directory to prevent deletion after the test. + This works cross-platform (Windows and Linux). + """ + try: + # Ensure the custom download directory exists + if not os.path.isabs(download_dir): # Make sure the download_dir is an absolute path + download_dir = os.path.join(os.getcwd(), download_dir) # Use current working directory as base + + os.makedirs(download_dir, exist_ok=True) + + # Set the download behavior in Playwright to download files to the specified directory + self.page.on("download", lambda download: download.save_as(os.path.join(download_dir, download.suggested_filename))) + + # Use Playwright's download expectation + with self.page.expect_download(timeout=timeout * 1000) as download_info: + self.find_element_and_perform_action(locator_or_element, action) + + # Get the download object + download = download_info.value + downloaded_file_path = download.path() + + print(f"Download completed: {downloaded_file_path}") + return downloaded_file_path + + except Exception as e: + print(f"Error during download: {e}") + raise + + def find_element_and_perform_action(self, locator_or_element, action, inputValue=None, screenshot_name=None): # Generate screenshot filename if not provided if not screenshot_name: diff --git a/init_helpers.py b/init_helpers.py index a225340e6..b14f3f28f 100644 --- a/init_helpers.py +++ b/init_helpers.py @@ -256,6 +256,16 @@ def check_element_enabled(element, wait=False): except Exception as e: pytest.fail(f"An error occurred: {e}") +def check_element_checked(element, wait=False): + if isinstance(element, (tuple, list)): + element = get_element_by_type(*element) + elif isinstance(element, str): + element = get_element_by_type(element) + try: + return playwright_helper_instance.check_element_checked(element, wait) + except Exception as e: + pytest.fail(f"An error occurred: {e}") + def check_element_by_locator_enabled(element, wait=False): if isinstance(element, (tuple, list)): element = get_element_by_type(*element) @@ -289,6 +299,14 @@ def capture_screenshot(filename): def handle_unresponsive_page(): return playwright_helper_instance.handle_unresponsive_page() +def click_and_get_download_path(element, action, timeout, download_dir='downloads'): + if isinstance(element, (tuple, list)): + element = get_element_by_type(*element) # Unpack the tuple/list + else: + # If it's a string, treat it as a selector directly + element = get_element_by_type(element) + return playwright_helper_instance.click_and_get_download_path(element, action, timeout, 'downloads') + def find_element_and_perform_action(element, action, inputValue=None): if isinstance(element, (tuple, list)): element = get_element_by_type(*element) # Unpack the tuple/list diff --git a/pages/find_a_patient_page.py b/pages/find_a_patient_page.py index 883b9d2fb..f7441e48c 100644 --- a/pages/find_a_patient_page.py +++ b/pages/find_a_patient_page.py @@ -22,10 +22,10 @@ GENDER_OPTIONAL_SELECT = ("label", "Gender field optional") POSTCODE_OPTIONAL_INPUT = ("label", "Postcode field optional") GENDER_SELECT = ("label", "Gender") -POSTCODE_INPUT = ("label", "Full postcode") -DOB_DAY_INPUT = ("placeholder", "DD") -DOB_MONTH_INPUT = ("placeholder", "MM") -DOB_YEAR_INPUT = ("placeholder", "YYYY") +POSTCODE_INPUT = ("label", "Postcode") +DOB_DAY_INPUT = ("label", "Day") +DOB_MONTH_INPUT = ("label", "Month") +DOB_YEAR_INPUT = ("label", "Year") NHS_NUMBER_INPUT_ERROR_LABEL= ("text", "Error: Enter an NHS number") NHS_NUMBER_INPUT_ERROR_BUTTON = ("button", "Enter an NHS number") @@ -36,7 +36,6 @@ GENDER_SELECT_ERROR_LABEL = ("#GenderIdError") POSTCODE_INVALID_INPUT_ERROR_LABEL = ("text", "Error: Enter the full postcode in the correct format") DOB_INPUT_ERROR_LABEL = ("text", "Error: Enter the date of birth") - CREATE_NEW_PATIENT_BUTTON = ("role", "button", "Create new patient") SEARCH_TIPS_LINK = ("link", "search tips") PATIENT_NAME_LINK = ("//span[@class='nhsuk-action-link__text']") diff --git a/pages/reports_check_and_confirm_page.py b/pages/reports_check_and_confirm_page.py new file mode 100644 index 000000000..f774efa4f --- /dev/null +++ b/pages/reports_check_and_confirm_page.py @@ -0,0 +1,84 @@ +from init_helpers import * + +PAGE_LOADING_ELEMENT = ("text", "Loading...Loading...") +SELECT_DATA_FOR_REPORT_ERROR_MESSAGE_LINK = ("role", "button", "Select data for report") +SELECT_DATA_FOR_REPORT_ERROR_MESSAGE_TEXT = ("text", "Select data for report") +CHANGE_DATE_BUTTON = ("role", "button", "Change date") +CHANGE_VACCINES_BUTTON = ("role", "button", "Change vaccines") +CHANGE_SITES_BUTTON = ("role", "button", "Change sites") +CHANGE_DATA_BUTTON = ("role", "button", "Change data") +CONFIRM_AND_CREATE_REPORT_BUTTON = ("role", "button", "Confirm and create report") +BACK_TO_SELECT_DATA_BUTTON = ("role", "button", "Back") + +def check_reports_change_date_button_exists(): + wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) + wait_for_element_to_appear(CHANGE_DATE_BUTTON) + return check_element_exists(CHANGE_DATE_BUTTON) + +def click_reports_change_date_button(): + wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) + wait_for_element_to_appear(CHANGE_DATE_BUTTON) + find_element_and_perform_action(CHANGE_DATE_BUTTON, "click") + +def check_reports_change_vaccines_button_exists(): + wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) + wait_for_element_to_appear(CHANGE_VACCINES_BUTTON) + return check_element_exists(CHANGE_VACCINES_BUTTON) + +def click_reports_change_vaccines_button(): + wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) + wait_for_element_to_appear(CHANGE_VACCINES_BUTTON) + find_element_and_perform_action(CHANGE_VACCINES_BUTTON, "click") + +def check_reports_change_sites_button_exists(): + wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) + wait_for_element_to_appear(CHANGE_SITES_BUTTON) + return check_element_exists(CHANGE_SITES_BUTTON) + +def click_reports_change_sites_button(): + wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) + wait_for_element_to_appear(CHANGE_SITES_BUTTON) + find_element_and_perform_action(CHANGE_SITES_BUTTON, "click") + +def check_reports_change_data_button_exists(): + wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) + wait_for_element_to_appear(CHANGE_DATA_BUTTON) + return check_element_exists(CHANGE_DATA_BUTTON) + +def click_reports_change_data_button(): + wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) + wait_for_element_to_appear(CHANGE_DATA_BUTTON) + find_element_and_perform_action(CHANGE_DATA_BUTTON, "click") + +def check_select_site_error_message_text_exists(): + wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) + wait_for_element_to_appear(SELECT_DATA_FOR_REPORT_ERROR_MESSAGE_TEXT) + return check_element_exists(SELECT_DATA_FOR_REPORT_ERROR_MESSAGE_TEXT) + +def check_select_vaccine_error_message_link_exists(): + wait_for_element_to_appear(SELECT_DATA_FOR_REPORT_ERROR_MESSAGE_LINK) + return check_element_exists(SELECT_DATA_FOR_REPORT_ERROR_MESSAGE_LINK) + +def click_select_vaccine_error_message_link(): + wait_for_element_to_appear(SELECT_DATA_FOR_REPORT_ERROR_MESSAGE_LINK) + find_element_and_perform_action(SELECT_DATA_FOR_REPORT_ERROR_MESSAGE_LINK, "click") + +def check_continue_to_confirm_and_create_report_button_exists(): + wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) + wait_for_element_to_appear(CONFIRM_AND_CREATE_REPORT_BUTTON) + return check_element_exists(CONFIRM_AND_CREATE_REPORT_BUTTON) + +def click_continue_to_confirm_and_create_report_button(): + wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) + wait_for_element_to_appear(CONFIRM_AND_CREATE_REPORT_BUTTON) + find_element_and_perform_action(CONFIRM_AND_CREATE_REPORT_BUTTON, "click") + +def check_back_to_select_data_page_button_exists(): + wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) + wait_for_element_to_appear(BACK_TO_SELECT_DATA_BUTTON) + return check_element_exists(BACK_TO_SELECT_DATA_BUTTON) + +def click_back_to_select_data_page_button(): + wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) + wait_for_element_to_appear(BACK_TO_SELECT_DATA_BUTTON) + find_element_and_perform_action(BACK_TO_SELECT_DATA_BUTTON, "click") diff --git a/pages/reports_creating_report_page.py b/pages/reports_creating_report_page.py new file mode 100644 index 000000000..463b9e7ea --- /dev/null +++ b/pages/reports_creating_report_page.py @@ -0,0 +1,15 @@ +from init_helpers import * + +CREATING_REPORT_ELEMENT = ("text", "Loading...Loading...") +DOWNLOAD_REPORT_BUTTON = ("role", "button", "Download report") + +def check_reports_download_report_button_exists(): + wait_for_element_to_disappear(CREATING_REPORT_ELEMENT) + wait_for_element_to_appear(DOWNLOAD_REPORT_BUTTON) + return check_element_exists(DOWNLOAD_REPORT_BUTTON) + +def click_reports_download_report_button(): + wait_for_element_to_disappear(CREATING_REPORT_ELEMENT) + wait_for_element_to_appear(DOWNLOAD_REPORT_BUTTON) + return click_and_get_download_path(DOWNLOAD_REPORT_BUTTON, "click", 300, "downloads") + diff --git a/pages/reports_data_selection_page.py b/pages/reports_data_selection_page.py index 0e144f978..e3de0ce3d 100644 --- a/pages/reports_data_selection_page.py +++ b/pages/reports_data_selection_page.py @@ -6,24 +6,24 @@ CONTINUE_TO_REPORTS_CHECK_AND_CONFIRM_BUTTON = ("role", "button", "Continue") BACK_TO_SELECT_SITE_BUTTON = ("role", "button", "Back") -def check_data_check_box_exists(data): +def check_reports_data_check_box_checked(data): wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) element = ("label", data) wait_for_element_to_appear(element) - return check_element_exists(element) + return check_element_checked(element) -def click_data_check_box(data): +def click_reports_data_check_box(data): wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) element = ("label", data) wait_for_element_to_appear(element) find_element_and_perform_action(element, "check") -def check_select_site_error_message_text_exists(): +def check_reports_select_site_error_message_text_exists(): wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) wait_for_element_to_appear(SELECT_DATA_FOR_REPORT_ERROR_MESSAGE_TEXT) return check_element_exists(SELECT_DATA_FOR_REPORT_ERROR_MESSAGE_TEXT) -def check_select_vaccine_error_message_link_exists(): +def check_reports_select_vaccine_error_message_link_exists(): wait_for_element_to_appear(SELECT_DATA_FOR_REPORT_ERROR_MESSAGE_LINK) return check_element_exists(SELECT_DATA_FOR_REPORT_ERROR_MESSAGE_LINK) @@ -35,18 +35,18 @@ def check_continue_to_reports_check_and_confirm_button_exists(): wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) wait_for_element_to_appear(CONTINUE_TO_REPORTS_CHECK_AND_CONFIRM_BUTTON) return check_element_exists(CONTINUE_TO_REPORTS_CHECK_AND_CONFIRM_BUTTON) - + def click_continue_to_reports_select_data_button(): wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) wait_for_element_to_appear(CONTINUE_TO_REPORTS_CHECK_AND_CONFIRM_BUTTON) find_element_and_perform_action(CONTINUE_TO_REPORTS_CHECK_AND_CONFIRM_BUTTON, "click") -def check_back_to_select_vaccine_page_button_exists(): +def check_reports_back_to_select_vaccine_page_button_exists(): wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) wait_for_element_to_appear(BACK_TO_SELECT_SITE_BUTTON) return check_element_exists(BACK_TO_SELECT_SITE_BUTTON) -def click_back_to_select_vaccine_page_button(): +def click_reports_back_to_select_vaccine_page_button(): wait_for_element_to_disappear(PAGE_LOADING_ELEMENT) wait_for_element_to_appear(BACK_TO_SELECT_SITE_BUTTON) find_element_and_perform_action(BACK_TO_SELECT_SITE_BUTTON, "click") diff --git a/test_data/models/rsv_vaccine_types.py b/test_data/models/rsv_vaccine_types.py index 1d5611d04..c34dea2a9 100644 --- a/test_data/models/rsv_vaccine_types.py +++ b/test_data/models/rsv_vaccine_types.py @@ -1,4 +1,4 @@ rsv_vaccine_types = [ "Abrysvo", - "Arexvy", + # "Arexvy", # This has been decommissioned on 29th 11 2024 ] diff --git a/tests/test_record_a_vaccine_for_patient_with_nhs_number_steps.py b/tests/test_record_a_vaccine_for_patient_with_nhs_number_steps.py index 359820d8a..cff82be2c 100644 --- a/tests/test_record_a_vaccine_for_patient_with_nhs_number_steps.py +++ b/tests/test_record_a_vaccine_for_patient_with_nhs_number_steps.py @@ -36,162 +36,5 @@ def test_record_a_vaccine_with_nhs_number(navigate_and_login): def test_record_a_maternity_vaccine_with_nhs_number(navigate_and_login): pass -@given(parse("I login to RAVS and set vaccinator details with {site} and {care_model} and get patient details for {nhs_number} with option {index} and choose to vaccinate with vaccine details as {chosen_vaccine}, {batch_number} with {batch_expiry_date}")) -def step_login_to_ravs(site, care_model, nhs_number, index, chosen_vaccine, batch_number, batch_expiry_date, shared_data): - shared_data["nhs_number"] = nhs_number - shared_data["index"] = index - shared_data["chosen_vaccine"] = chosen_vaccine - shared_data["chosen_vaccine_type"] = get_vaccination_type(index, chosen_vaccine) - shared_data["batch_number"] = batch_number - shared_data["site"] = site - shared_data["care_model"] = get_care_model(index) - today_str = datetime.today().strftime('%d/%m/%Y') - today = datetime.strptime(today_str, '%d/%m/%Y') - if datetime.strptime(batch_expiry_date, '%d/%m/%Y') <= today: - batch_expiry_date = today + timedelta(days=7) - batch_expiry_date = standardize_date_format(batch_expiry_date) - shared_data["batch_expiry_date"] = batch_expiry_date - check_vaccine_and_batch_exists_in_site(site, chosen_vaccine, shared_data["chosen_vaccine_type"], batch_number, batch_expiry_date) - return shared_data - -@given("I search for a patient with the NHS number in the find a patient screen") -@then("I search for a patient with the NHS number in the find a patient screen") -def step_search_for_patient(shared_data): - nhs_number = shared_data["nhs_number"] - click_find_a_patient_and_search_with_nhs_number(nhs_number) - -@given(parse("I open the patient record by clicking on patient {name}")) -@then(parse("I open the patient record by clicking on patient {name}")) -def step_search_for_patient(shared_data, name): - attach_screenshot("before_clicking_patient_name") - click_on_patient_name(name) - attach_screenshot("before_clicking_patient_name") - shared_data["patient_name"] = name - -@when(parse("I click choose vaccine button and choose the {chosen_vaccine}, {batch_number} with {batch_expiry_date} and click continue")) -def step_choose_vaccine_and_vaccine_type(shared_data, chosen_vaccine, batch_number, batch_expiry_date): - time.sleep(3) - immunisation_history_records_count_before_vaccination = click_on_patient_search_result_and_click_choose_vaccine(shared_data['patient_name'], chosen_vaccine) - shared_data["immunisation_history_records_count_before_vaccination"] = immunisation_history_records_count_before_vaccination - choose_vaccine_and_vaccine_type_for_patient(shared_data['site'], chosen_vaccine, shared_data['chosen_vaccine_type']) - -@when(parse("I assess the patient's {eligibility} with the details and date as {assess_date} and click continue to record consent screen button")) -def step_assess_eligibility_and_click_continue_record_consent_screen(shared_data, eligibility, assess_date): - shared_data['eligible_decision'] = eligibility - shared_data['legal_mechanism'] = get_legal_mechanism(shared_data["index"]) - shared_data['eligibility_type'] = get_eligibility_type(shared_data["index"], shared_data["chosen_vaccine"]) - shared_data["healthcare_worker"] = get_staff_role(shared_data["index"]) - shared_data['eligibility_assessing_clinician'] = get_random_assessing_clinician() - assess_date = format_date(str(get_date_value(assess_date)), config["browser"]) - shared_data['eligibility_assessment_date'] = assess_date - shared_data['eligibility_assessment_outcome'] = get_assessment_outcome(0) - shared_data['eligibility_assessment_no_vaccine_given_reason'] = get_assess_vaccine_not_given_reason(shared_data["index"]) - shared_data['assessment_comments'] = "Assessment comments " + assess_date + shared_data["patient_name"] - assess_patient_with_details_and_click_continue_to_consent(eligibility, shared_data['eligibility_type'], shared_data["healthcare_worker"], shared_data['eligibility_assessing_clinician'], None, assess_date, shared_data['legal_mechanism'], shared_data['eligibility_assessment_outcome'], shared_data['assessment_comments'],shared_data['eligibility_assessment_no_vaccine_given_reason']) - -@when(parse("I assess the pregnant patient's {eligibility} with the details of due date as {due_date} and assessment date as {assess_date} and click continue to record consent screen button")) -def step_assess_eligibility_and_click_continue_record_consent_screen(shared_data, eligibility, due_date, assess_date): - shared_data['eligible_decision'] = eligibility - shared_data['legal_mechanism'] = get_legal_mechanism(shared_data["index"]) - shared_data['eligibility_type'] = "Pregnancy" - shared_data["healthcare_worker"] = get_staff_role(shared_data["index"]) - shared_data['eligibility_assessing_clinician'] = get_random_assessing_clinician() - due_date = format_date(str(get_date_value(due_date)), config["browser"]) - shared_data['eligibility_due_date'] = due_date - assess_date = format_date(str(get_date_value(assess_date)), config["browser"]) - shared_data['eligibility_assessment_date'] = assess_date - shared_data['eligibility_assessment_outcome'] = get_assessment_outcome(0) - shared_data['eligibility_assessment_no_vaccine_given_reason'] = get_assess_vaccine_not_given_reason(shared_data["index"]) - shared_data['assessment_comments'] = "Assessment comments " + assess_date + shared_data["patient_name"] - assess_patient_with_details_and_click_continue_to_consent(eligibility, shared_data['eligibility_type'], shared_data["healthcare_worker"], shared_data['eligibility_assessing_clinician'], due_date, assess_date, shared_data['legal_mechanism'], shared_data['eligibility_assessment_outcome'], shared_data['assessment_comments'],shared_data['eligibility_assessment_no_vaccine_given_reason']) - -@when(parse("I record {consent} with the details and click continue to vaccinate button")) -def step_record_consent_and_click_continue_to_vaccinate_screen(shared_data, consent): - shared_data['consent_decision'] = consent - if shared_data["eligibility_assessment_outcome"].lower() == "give vaccine": - shared_data['consent_given_by'] = get_consent_given_by(shared_data["index"]) - name_of_person_consenting = "Automation tester" - relationship_to_patient = "RAVS tester" - if shared_data['legal_mechanism'] == "Patient Group Direction (PGD)": - shared_data['consent_clinician_details'] = shared_data['eligibility_assessing_clinician'] - else: - shared_data['consent_clinician_details'] = get_consenting_clinician(shared_data["index"]) - shared_data["no_consent_reason"] = get_no_consent_reason(shared_data["index"]) - record_consent_details_and_click_continue_to_vaccinate(shared_data['consent_decision'],shared_data['consent_given_by'], name_of_person_consenting, relationship_to_patient, shared_data['consent_clinician_details'], shared_data['legal_mechanism'], shared_data["no_consent_reason"]) - -@when(parse("I record {vaccination} details and date as {vaccination_date} and click Continue to Check and confirm screen")) -def step_enter_vaccination_details_and_continue_to_check_and_confirm_screen(shared_data, vaccination, vaccination_date): - shared_data["vaccinated_decision"] = vaccination - if shared_data["consent_decision"].lower() == "yes": - if shared_data["eligibility_assessment_outcome"].lower() == "give vaccine": - shared_data["vaccination_date"] = format_date(str(get_date_value(vaccination_date)), config["browser"]) - chosen_vaccine = shared_data["chosen_vaccine"] - shared_data["vaccination_site"] = get_vaccination_site(shared_data["index"]) - shared_data["dose_amount"] = str(get_vaccine_dose_amount(shared_data["chosen_vaccine_type"])) - if shared_data['legal_mechanism'] == "Patient Group Direction (PGD)": - shared_data['vaccinator'] = shared_data['eligibility_assessing_clinician'] - else: - shared_data["vaccinator"] = get_vaccinator(shared_data["index"]) - shared_data["vaccination_comments"] = shared_data["chosen_vaccine_type"] + "vaccination given on " + shared_data["vaccination_date"] + " for " + shared_data["patient_name"] - shared_data["no_vaccination_reason"] = get_vaccination_not_given_reason(shared_data["index"]) - enter_vaccine_details_and_click_continue_to_check_and_confirm(shared_data["vaccinated_decision"], shared_data["care_model"], shared_data["vaccination_date"], chosen_vaccine, shared_data["chosen_vaccine_type"], shared_data["vaccination_site"], shared_data["batch_number"], shared_data["batch_expiry_date"], shared_data["dose_amount"], shared_data["vaccinator"], shared_data["vaccination_comments"], shared_data["legal_mechanism"], shared_data["no_vaccination_reason"]) - attach_screenshot("entered_vaccination_details") - logging.info(shared_data) - -@then(parse("I need to be able to see the patient {name}, {dob}, {address} and vaccination details on the check and confirm screen")) -def step_see_patient_details_on_check_and_confirm_screen(shared_data, name, dob, address): - if shared_data["vaccinated_decision"].lower() == "Yes".lower() and shared_data["consent_decision"].lower() == "Yes".lower() and shared_data["eligibility_assessment_outcome"].lower() == "Give vaccine".lower(): - attach_screenshot("check_and_confirm_screen_before_assertion") - assert get_patient_name_value() == shared_data["patient_name"] - assert get_patient_address_value() == address - assert get_patient_vaccination_dose_amount_value() == shared_data["dose_amount"] - assert get_patient_vaccinated_chosen_vaccine_value() == shared_data["chosen_vaccine"] - assert get_patient_vaccinated_chosen_vaccine_product_value() == shared_data["chosen_vaccine_type"] - assert get_patient_eligibility_assessment_date_value() == date_format_with_day_of_week(shared_data['eligibility_assessment_date']) - assert get_patient_vaccinated_date_value() == date_format_with_day_of_week(shared_data['vaccination_date']) - assert get_patient_dob_value() == date_format_with_age(dob) - assert get_patient_vaccination_batch_expiry_date_value() == date_format_with_name_of_month(shared_data['batch_expiry_date']) - assert get_patient_eligibility_assessing_clinician_vaccine_value() == shared_data['eligibility_assessing_clinician'] - assert get_patient_consent_recorded_by_clinician_value() == shared_data['consent_clinician_details'] - assert get_patient_vaccination_vaccinator_value() == shared_data['vaccinator'] - attach_screenshot("check_and_confirm_screen_after_assertion") - -@then("when I click confirm and save button, I should see a record saved dialogue") -def click_confirm_and_save_button_record_saved(shared_data): - attach_screenshot("patient_details_screen_with_immunisation_history") - click_confirm_details_and_save_button() - attach_screenshot("before_assert_record_saved") - assert check_record_saved_element_exists(False) - -@then("the immunisation history of the patient should be updated in the patient details page") -def immunisation_history_should_be_updated(shared_data): - attach_screenshot("immunisation_history_records_count_after_vaccination") - immunisation_history_records_count_after_vaccination = get_count_of_immunisation_history_records(shared_data["chosen_vaccine"]) - assert int(immunisation_history_records_count_after_vaccination) >= int(shared_data["immunisation_history_records_count_before_vaccination"]) + 1 - click_delete_history_link(shared_data["chosen_vaccine"]) - attach_screenshot("click_delete_history_link") - click_delete_vaccination_button() - attach_screenshot("click_delete_vaccination_button") - shared_data.clear() - -@then("when I click confirm and save button, the immunisation history of the patient should be updated in the patient details page") -def click_confirm_and_save_button_immunisation_history_should_be_updated(shared_data): - attach_screenshot("patient_details_screen_with_immunisation_history") - if shared_data["vaccinated_decision"].lower() == "yes" and shared_data["consent_decision"].lower() == "yes" and shared_data["eligibility_assessment_outcome"].lower() == "give vaccine": - click_confirm_details_and_save_button() - immunisation_history_records_count_after_vaccination = get_count_of_immunisation_history_records(shared_data["chosen_vaccine"]) - assert int(immunisation_history_records_count_after_vaccination) >= int(shared_data["immunisation_history_records_count_before_vaccination"]) + 1 - # assert get_vaccine_program_details(index) == shared_data["chosen_vaccine"] - # click_delete_history_button(shared_data["chosen_vaccine"], index) - # attach_screenshot("delete_history_button_clicked") - # click_delete_vaccination_button() - # attach_screenshot("delete_vaccination_button_clicked") - # time.sleep(10) - shared_data.clear() - else: - immunisation_history_records_count_after_vaccination = get_count_of_immunisation_history_records(shared_data["chosen_vaccine"]) - assert int(immunisation_history_records_count_after_vaccination) == int(shared_data["immunisation_history_records_count_before_vaccination"]) - shared_data.clear() - attach_screenshot("patient_details_screen_with_immunisation_history") diff --git a/tests/test_reports_steps.py b/tests/test_reports_steps.py index 66a9c669b..c42db545b 100644 --- a/tests/test_reports_steps.py +++ b/tests/test_reports_steps.py @@ -1,4 +1,6 @@ from asyncio import sleep +import csv +from logging.handlers import RotatingFileHandler import secrets import string from pytest_bdd import given, when, then, scenarios, scenario @@ -6,6 +8,8 @@ from pages.login_page import * from pages.home_page import * from pages.nhs_signin_page import * +from pages.reports_check_and_confirm_page import * +from pages.reports_creating_report_page import * from pages.reports_data_selection_page import * from pages.reports_date_range_selection_page import * import logging @@ -18,8 +22,79 @@ scenarios(f'{features_directory}/reports.feature') -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) +logger = logging.getLogger() +logger.setLevel(logging.DEBUG) # Or any other level like INFO, WARNING, etc. + +# Create a rotating file handler to log to tox.log +log_handler = RotatingFileHandler('tox.log', maxBytes=1024*1024, backupCount=3) # Log rotation (optional) +log_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')) + +# Add the handler to the logger +logger.addHandler(log_handler) + +def validate_report_headers(file_path, expected_headers): + try: + with open(file_path, mode="r", newline="", encoding="utf-8") as file: + reader = csv.reader(file) + headers = next(reader) + + # Check headers + if headers == expected_headers: + logger.info("Headers are valid!") + logger.info(headers) + return True, headers + else: + logger.info("Headers are invalid!") + logger.info("Expected Headers:") + logger.info(expected_headers) + logger.info("Found Headers:") + logger.info(headers) + + # Find missing or extra headers + missing_headers = [h for h in expected_headers if h not in headers] + extra_headers = [h for h in headers if h not in expected_headers] + + if missing_headers: + logger.info("Missing Headers:") + logger.info(missing_headers) + if extra_headers: + logger.info("Extra Headers:") + logger.info(extra_headers) + + return False, headers + + except Exception as e: + logger.error(f"An error occurred while validating headers: {e}") + return False, None + +def validate_value_in_header(file_path, header, value): + try: + with open(file_path, mode="r", newline="", encoding="utf-8") as file: + reader = csv.DictReader(file) + + # Ensure the specified header exists + if header not in reader.fieldnames: + logger.error(f"Header '{header}' not found in the report.") + return False + + # Search for the value under the specified header + for row in reader: + if row.get(header) == value: + logger.info(f"Value '{value}' found under header '{header}' in the report.") + return True + + logger.error(f"Value '{value}' not found under header '{header}' in the report.") + return False + except Exception as e: + logger.error(f"An error occurred while searching for value '{value}' under header '{header}': {e}") + return False + +@pytest.fixture(scope="session", autouse=True) +def setup_logging(): + # You can add logging setup here if needed + logger.info("Logging setup complete") + yield + logger.info("Test session complete") @pytest.fixture(scope='function') def shared_data(): @@ -154,11 +229,11 @@ def I_click_today_date_range_and_click_continue(shared_data): @when(parse('I select the vaccine type {vaccineType} and click continue')) def I_select_vaccinetype_and_click_continue(shared_data, vaccineType): click_vaccine_check_box_on_reports_page(vaccineType) - attach_screenshot("click_" + vaccineType.lower() + "_check_box_on_reports_page") - logging.info("click_" + vaccineType.lower() + "_check_box_on_reports_page") + attach_screenshot("clicked_" + vaccineType.lower() + "_check_box_on_reports_page") + logging.info("clicked_" + vaccineType.lower() + "_check_box_on_reports_page") click_continue_to_reports_select_site_button() - attach_screenshot("click_continue_to_reports_select_site_button") - logging.info("click_continue_to_reports_select_site_button") + attach_screenshot("clicked_continue_to_reports_select_site_button") + logging.info("clicked_continue_to_reports_select_site_button") @then("the choose sites page should be displayed") def the_choose_sites_page_should_be_displayed(): @@ -169,6 +244,160 @@ def the_choose_sites_page_should_be_displayed(): @when(parse('I select the site {site} and click continue')) def I_select_vaccinetype_and_click_continue(shared_data, site): check_site_check_box(site) + attach_screenshot("clicked_" + site.lower() + "_check_box_on_reports_page") + logging.info("clicked_" + site.lower() + "_check_box_on_reports_page") + click_continue_to_reports_select_data_button() + attach_screenshot("clicked_continue_to_reports_select_data_button") + logging.info("clicked_continue_to_reports_select_data_button") + +@then("the choose data page should be displayed and all data options should be checked by default") +def the_choose_data_page_should_be_displayed(): + assert check_reports_data_check_box_exists("Patients") == True + assert check_reports_data_check_box_checked("Patients") == True + assert check_reports_data_check_box_checked("Staff") == True + assert check_reports_data_check_box_checked("Site or delivery team") == True + assert check_reports_data_check_box_checked("Assessment and consent") == True + assert check_reports_data_check_box_checked("Vaccination") == True + attach_screenshot("check_choose_data_pages_reports_exists") + logging.info("check_choose_data_pages_reports_exists") + +@when(parse('I click continue on the data page')) +def I_select_data_and_click_continue(shared_data): + click_continue_to_reports_select_data_button() + attach_screenshot("clicked_continue_to_reports_select_data_button") + logging.info("clicked_continue_to_reports_select_data_button") + +@then("the check and confirm page should be displayed") +def the_check_and_confirm_page_should_be_displayed(): + assert check_reports_change_data_button_exists() == True + attach_screenshot("check_reports_change_data_pages_reports_exists") + logging.info("check_reports_change_data_pages_reports_exists") + +@when('I click Confirm and create report button in the check and confirm page') +def I_click_confirm_to_generate_report(shared_data): + click_continue_to_confirm_and_create_report_button() + attach_screenshot("clicked_continue_to_confirm_and_create_report_button") + logging.info("clicked_continue_to_confirm_and_create_report_button") + +@then("Creating your page element should be displayed and Download Report button should be visible") +def the_check_and_confirm_page_should_be_displayed(): + assert check_reports_download_report_button_exists() == True + attach_screenshot("check_reports_change_data_pages_reports_exists") + logging.info("check_reports_change_data_pages_reports_exists") + +@when('I click download report button') +def I_click_confirm_to_generate_report(shared_data): + shared_data['report_download_path'] = click_reports_download_report_button() + attach_screenshot("clicked_reports_download_report_button") + logging.info("clicked_reports_download_report_button") + +@then("the report is downloaded successfully") +def the_report_is_downloaded_successfully(shared_data): + assert os.path.exists(shared_data['report_download_path']), f"Downloaded file not found: {shared_data['report_download_path']}" + attach_screenshot("check_report_downloaded") + logger.info("check_report_downloaded_to_" + str(shared_data['report_download_path'])) + expected_headers = [ + "NhsNumber", "PatientName", "Gender", "DateOfBirth", "Address", "Postcode", + "SiteName", "SiteODS", "OrganisationName", "OrganisationODS", "CareModel", + "Vaccinated", "NoVaccinationReason", "AssessmentDate", "Consented", "ConsentType", + "ConsentingPersonName", "ConsentingPersonRelationship", "EligibilityType", "StaffType", + "AssessmentComments", "VaccinationDate", "Vaccine", "VaccineProduct", "DoseAmount", + "VaccineRoute", "PrescribingMethod", "BatchNumber", "BatchExpiryDate", "AuditType", + "DateEntered", "UserEnteringData", "VaccinationComments", "AssessingClinician", + "VaccinatingClinician", "ConsentingClinician" +] + is_valid, _ = validate_report_headers(shared_data['report_download_path'], expected_headers) + assert is_valid, "Report headers are invalid. See logs for details." + +@then(parse("the report is downloaded successfully and contains the vaccine record for {nhs_number}")) +def the_report_is_downloaded_successfully(shared_data, nhs_number): + assert os.path.exists(shared_data['report_download_path']), f"Downloaded file not found: {shared_data['report_download_path']}" + attach_screenshot("check_report_downloaded") + logger.info("check_report_downloaded_to_" + str(shared_data['report_download_path'])) + expected_headers = [ + "NhsNumber", "PatientName", "Gender", "DateOfBirth", "Address", "Postcode", + "SiteName", "SiteODS", "OrganisationName", "OrganisationODS", "CareModel", + "Vaccinated", "NoVaccinationReason", "AssessmentDate", "Consented", "ConsentType", + "ConsentingPersonName", "ConsentingPersonRelationship", "EligibilityType", "StaffType", + "AssessmentComments", "VaccinationDate", "Vaccine", "VaccineProduct", "DoseAmount", + "VaccineRoute", "PrescribingMethod", "BatchNumber", "BatchExpiryDate", "AuditType", + "DateEntered", "UserEnteringData", "VaccinationComments", "AssessingClinician", + "VaccinatingClinician", "ConsentingClinician" +] + is_valid, _ = validate_report_headers(shared_data['report_download_path'], expected_headers) + assert is_valid, "Report headers are invalid. See logs for details." + + vaccination_date = shared_data.get("vaccination_date") + vaccinated_decision = shared_data["vaccinated_decision"] + consent_given_by = shared_data['consent_given_by'] + eligibility_type = shared_data['eligibility_type'] + + if vaccination_date: + # Convert the vaccination date from shared_data to a datetime object + vaccination_date_obj = datetime.strptime(vaccination_date, "%d/%m/%Y") # Adjust format as needed + current_date = datetime.now() + date_diff = (current_date - vaccination_date_obj).days + + if 0 <= date_diff <= 31: + # If vaccination date is within the last 31 days, ensure all columns have values + logger.info(f"Vaccination date '{vaccination_date}' is within the last 31 days. Verifying all columns have values...") + + with open(shared_data['report_download_path'], mode="r", newline="", encoding="utf-8") as file: + reader = csv.DictReader(file) + for row in reader: + # For each row, ensure that all columns have non-empty values + for header in expected_headers: + if header == "NoVaccinationReason": + # If vaccinated_decision is "yes", NoVaccinationReason should be empty + if vaccinated_decision.lower() == "yes": + assert not row[header], f"Column 'NoVaccinationReason' should be empty for NHS number {shared_data['nhs_number']} as vaccinated_decision is 'yes'." + else: + assert row[header], f"Missing value in column '{header}' for NHS number {shared_data['nhs_number']}." + elif header == "ConsentingPersonName" or header == "ConsentingPersonRelationship": + if consent_given_by == "Patient (informed consent)": + assert not row[header], f"Column 'ConsentingPersonName' and 'ConsentingPersonRelationship' should be empty for NHS number {shared_data['nhs_number']} as consent given by patient (informed consent)" + else: + assert row[header], f"Missing value in column '{header}' for NHS number {shared_data['nhs_number']}." + elif header == "StaffType": + if eligibility_type == "Healthcare workers": + assert row[header], f"Column 'StaffType' should not be empty for NHS number {shared_data['nhs_number']} as eligibility_type is 'Healthcare workers'." + else: + assert not row[header], f"Column 'StaffType' should be empty for NHS number {shared_data['nhs_number']} as eligibility_type is not 'Healthcare workers'." + else: + # For other columns, ensure they are not empty + assert row[header], f"Missing value in column '{header}' for NHS number {shared_data['nhs_number']}." + + # Validate the presence of the vaccination date in the report + is_vaccination_date_present = validate_value_in_header( + shared_data['report_download_path'], + "VaccinationDate", + vaccination_date + ) + assert is_vaccination_date_present, ( + f"Value '{vaccination_date}' not found under header 'VaccinationDate' in the report." + ) + + # Validate the presence of the NHS number only if the vaccination date is within the last 31 days + is_nhsNumber_present = validate_value_in_header(shared_data['report_download_path'], "NhsNumber", shared_data["nhs_number"]) + assert is_nhsNumber_present, f"Value '{shared_data['nhs_number']}' not found under header 'NhsNumber' in the report." + + else: + # If vaccination date is more than 31 days old, ensure no rows for that date + logger.info(f"Vaccination date '{vaccination_date}' is more than 31 days old. Ensuring no rows exist with this date in the report.") + + with open(shared_data['report_download_path'], mode="r", newline="", encoding="utf-8") as file: + reader = csv.DictReader(file) + found_invalid_row = False + for row in reader: + if row["VaccinationDate"] == vaccination_date: + found_invalid_row = True + break + + assert not found_invalid_row, ( + f"Row with vaccination date '{vaccination_date}' found in the report, but it should not be present since it's older than 31 days." + ) + + logger.info(f"Vaccination date '{vaccination_date}' is correctly not present in the report.") attach_screenshot("click_" + site.lower() + "_check_box_on_reports_page") logging.info("click_" + site.lower() + "_check_box_on_reports_page") click_continue_to_reports_select_data_button() @@ -180,3 +409,4 @@ def the_choose_data_page_should_be_displayed(): assert check_data_check_box_exists("Patients") == True attach_screenshot("check_choose_data_pages_reports_exists") logging.info("check_choose_data_pages_reports_exists") +