diff --git a/.env b/.env new file mode 100644 index 00000000..11b1bf20 --- /dev/null +++ b/.env @@ -0,0 +1,3 @@ +# "DO NOT COMMIT THIS FILE" + +BCSS_PASS= diff --git a/pages/bcss_home_page.py b/pages/bcss_home_page.py new file mode 100644 index 00000000..a6fad576 --- /dev/null +++ b/pages/bcss_home_page.py @@ -0,0 +1,93 @@ +from playwright.sync_api import Page + + +class BcssHomePage: + def __init__(self, page: Page): + self.page = page + # Homepage links + self.sub_menu_link = self.page.get_by_role("link", name="Show Sub-menu") + self.hide_sub_menu_link = self.page.get_by_role("link", name="Hide Sub-menu") + self.select_org_link = self.page.get_by_role("link", name="Select Org") + self.back_button = self.page.get_by_role("link", name="Back") + self.release_notes_link = self.page.get_by_role("link", name="- Release Notes") + self.refresh_alerts_link = self.page.get_by_role("link", name="Refresh alerts") + self.user_guide_link = self.page.get_by_role("link", name="User guide") + self.help_link = self.page.get_by_role("link", name="Help") + + def click_sub_menu_link(self): + self.sub_menu_link.click() + + def click_hide_sub_menu_link(self): + self.hide_sub_menu_link.click() + + def click_select_org_link(self): + self.select_org_link.click() + + def click_back_button(self): + self.back_button.click() + + def click_release_notes_link(self): + self.release_notes_link.click() + + def click_refresh_alerts_link(self): + self.refresh_alerts_link.click() + + def click_user_guide_link(self): + self.user_guide_link.click() + + def click_help_link(self): + self.help_link.click() + + +class MainMenu: + def __init__(self, page: Page): + self.page = page + # Main menu - page links + self.contacts_list_page = self.page.get_by_role("link", name="Contacts List") + self.bowel_scope_page = self.page.get_by_role("link", name="Bowel Scope") + self.call_and_recall_page = self.page.get_by_role("link", name="Call and Recall") + self.communications_production_page = self.page.get_by_role("link", name="Communications Production") + self.download_page = self.page.get_by_role("link", name="Download") + self.fit_test_kits_page = self.page.get_by_role("link", name="FIT Test Kits") + self.gfob_test_kits_page = self.page.get_by_role("link", name="gFOBT Test Kits") + self.lynch_surveillance_page = self.page.get_by_role("link", name="Lynch Surveillance") + self.organisations_page = self.page.get_by_role("link", name="Organisations") + self.reports_page = self.page.get_by_role("link", name="Reports") + self.screening_practitioner_appointments_page = self.page.get_by_role("link", name="Screening Practitioner") + self.screening_subject_search_page = self.page.get_by_role("link", name="Screening Subject Search") + + def go_to_contacts_list_page(self): + self.contacts_list_page.click() + + def go_to_bowel_scope_page(self): + self.bowel_scope_page.click() + + def go_to_call_and_recall_page(self): + self.call_and_recall_page.click() + + def go_to_communications_production_page(self): + self.communications_production_page.click() + + def go_to_download_page(self): + self.download_page.click() + + def go_to_fit_test_kits_page(self): + self.fit_test_kits_page.click() + + def go_to_gfob_test_kits_page(self): + self.gfob_test_kits_page.click() + + def go_to_lynch_surveillance_page(self): + self.lynch_surveillance_page.click() + + def go_to_organisations_page(self): + self.organisations_page.click() + + def go_to_reports_page(self): + self.reports_page.click() + + def go_to_screening_practitioner_appointments_page(self): + self.screening_practitioner_appointments_page.click() + + def go_to_screening_subject_search_page(self): + self.screening_subject_search_page.click() diff --git a/pages/cognito_login_page.py b/pages/cognito_login_page.py new file mode 100644 index 00000000..b3fffdbd --- /dev/null +++ b/pages/cognito_login_page.py @@ -0,0 +1,25 @@ +import os + +from playwright.sync_api import Page + + +class CognitoLoginPage: + + def __init__(self, page: Page): + self.page = page + self.username = page.get_by_role("textbox", name="Username") + self.password = page.get_by_role("textbox", name="Password") + self.submit_button = page.get_by_role("button", name="submit") + + def login_as_user(self, username: str, password: str) -> None: + """Logs in to bcss with specified user credentials + Args: + username (str) enter a username that exists in users.json + password (str) the password for the user provided + """ + # Retrieve and enter username from users.json + self.username.fill(username) + # Retrieve and enter password from .env file + self.password.fill(password) + # Click Submit + self.submit_button.click() diff --git a/pages/reports_page.py b/pages/reports_page.py new file mode 100644 index 00000000..2afff849 --- /dev/null +++ b/pages/reports_page.py @@ -0,0 +1,109 @@ +from datetime import datetime +from utils import date_time_utils +from playwright.sync_api import Page + + +class ReportsPageUtils: + def __init__(self): + pass + + +# Timestamp Date Formatting +def report_timestamp_date_format() -> str: + """Gets the current date time and converts it to the timestamp format used on the report pages + + Returns: + date report last requested (str): The current datetime in the "date report last requested" timestamp format. + + """ + dtu = date_time_utils.DateTimeUtils + return dtu.format_date(datetime.now(), "%d/%m/%Y" + " at " + "%H:%M:%S") + + +def fobt_kits_logged_but_not_read_report_timestamp_date_format() -> str: + """Gets the current date time and converts it to the timestamp format used on the fobt_kits_logged_but_not_read report page + + Returns: + fobt_kits_logged_but_not_read timestamp (str): The current datetime in the "fobt_kits_logged_but_not_read report" timestamp format. + + """ + dtu = date_time_utils.DateTimeUtils + return dtu.format_date(datetime.now(), "%d %b %Y %H:%M:%S") + + +def screening_practitioner_appointments_report_timestamp_date_format() -> str: + """Gets the current date time and converts it to the timestamp format used on the screening practitioner appointments report page + + Returns: + screening practitioner appointments timestamp (str): The current datetime in the "screening practitioner appointments report" timestamp format. + + """ + dtu = date_time_utils.DateTimeUtils + return dtu.format_date(datetime.now(), "%d.%m.%Y" + " at " + "%H:%M:%S") + + +# Reports page main menu links +def go_to_failsafe_reports_page(page: Page) -> None: + page.get_by_role("link", name="Failsafe Reports").click() + + +def go_to_operational_reports_page(page: Page) -> None: + page.get_by_role("link", name="Operational Reports").click() + + +def go_to_strategic_reports_page(page: Page) -> None: + page.get_by_role("link", name="Strategic Reports").click() + + +def go_to_cancer_waiting_times_reports_page(page: Page) -> None: + page.get_by_role("link", name="Cancer Waiting Times Reports").click() + + +def go_to_dashboard(page: Page) -> None: + page.get_by_role("link", name="Dashboard").click() + + +# Failsafe Reports menu links +def go_to_date_report_last_requested_page(page: Page) -> None: + page.get_by_role("link", name="Date Report Last Requested").click() + + +def go_to_screening_subjects_with_inactive_open_episode_link_page(page: Page) -> None: + page.get_by_role("link", name="Screening Subjects With").click() + + +def go_to_subjects_ceased_due_to_date_of_birth_changes_page(page: Page) -> None: + page.get_by_role("link", name="Subjects Ceased Due to Date").click() + + +def go_to_allocate_sc_for_patient_movements_within_hub_boundaries_page(page: Page) -> None: + page.get_by_role("link", name="Allocate SC for Patient Movements within Hub Boundaries").click() + + +def go_to_allocate_sc_for_patient_movements_into_your_hub_page(page: Page) -> None: + page.get_by_role("link", name="Allocate SC for Patient Movements into your Hub").click() + + +def go_to_identify_and_link_new_gp_page(page: Page) -> None: + page.get_by_role("link", name="Identify and link new GP").click() + + +# Operational Reports menu links +def go_to_appointment_attendance_not_updated_page(page: Page) -> None: + page.get_by_role("link", name="Appointment Attendance Not").click() + + +def go_to_fobt_kits_logged_but_not_read_page(page: Page) -> None: + page.get_by_role("link", name="FOBT Kits Logged but Not Read").click() + + +def go_to_demographic_update_inconsistent_with_manual_update_page(page: Page) -> None: + page.get_by_role("link", name="Demographic Update").click() + + +def go_to_screening_practitioner_6_weeks_availability_not_set_up_report_page(page: Page) -> None: + page.get_by_role("link", name="Screening Practitioner 6").click() + + +def go_to_screening_practitioner_appointments_page(page: Page) -> None: + page.get_by_role("link", name="Screening Practitioner Appointments").click() diff --git a/pages/screening_subject_search_page.py b/pages/screening_subject_search_page.py new file mode 100644 index 00000000..fbd601d1 --- /dev/null +++ b/pages/screening_subject_search_page.py @@ -0,0 +1,111 @@ +from playwright.sync_api import Page + + +class ScreeningStatusSearchOptions: + CALL_STATUS = "4001" + INACTIVE_STATUS = "4002" + RECALL_STATUS = "4004" + OPT_IN_STATUS = "4003" + SELF_REFERRAL_STATUS = "4005" + SURVEILLANCE_STATUS = "4006" + SEEKING_FURTHER_DATA_STATUS = "4007" + CEASED_STATUS = "4008" + BOWEL_SCOPE_STATUS = "4009" + LYNCH_SURVEILLANCE_STATUS = "306442" + LYNCH_SELF_REFERRAL_STATUS = "307129" + + def __init__(self, page: Page): + self.page = page + + # Locate screening status dropdown list + self.select_status = self.page.locator("#A_C_ScreeningStatus") + + # Select screening status options + def select_status_call(self): + self.select_status.select_option(self.CALL_STATUS) + + def select_status_inactive(self): + self.select_status.select_option(self.INACTIVE_STATUS) + + def select_status_recall(self): + self.select_status.select_option(self.RECALL_STATUS) + + def select_status_opt_in(self): + self.select_status.select_option(self.OPT_IN_STATUS) + + def select_status_self_referral(self): + self.select_status.select_option(self.SELF_REFERRAL_STATUS) + + def select_status_surveillance(self): + self.select_status.select_option(self.SURVEILLANCE_STATUS) + + def select_status_seeking_further_data(self): + self.select_status.select_option(self.SEEKING_FURTHER_DATA_STATUS) + + def select_status_ceased(self): + self.select_status.select_option(self.CEASED_STATUS) + + def select_status_bowel_scope(self): + self.select_status.select_option(self.BOWEL_SCOPE_STATUS) + + def select_status_lynch_surveillance(self): + self.select_status.select_option(self.LYNCH_SURVEILLANCE_STATUS) + + def select_status_lynch_self_referral(self): + self.select_status.select_option(self.LYNCH_SELF_REFERRAL_STATUS) + + +class LatestEpisodeStatusSearchOptions: + OPEN_PAUSED_STATUS = "1" + CLOSED_STATUS = "2" + NO_EPISODE_STATUS = "3" + + def __init__(self, page: Page): + self.page = page + + # Locate latest episode status status dropdown list + self.select_status = self.page.locator("#A_C_EpisodeStatus") + + # Select latest episode status options + def select_status_open_paused(self): + self.select_status.select_option(self.OPEN_PAUSED_STATUS) + + def select_status_closed(self): + self.select_status.select_option(self.CLOSED_STATUS) + + def select_status_no_episode(self): + self.select_status.select_option(self.NO_EPISODE_STATUS) + + +class SearchAreaSearchOptions: + SEARCH_AREA_HOME_HUB = "01" + SEARCH_AREA_GP_PRACTICE = "02" + SEARCH_AREA_CCG = "03" + SEARCH_AREA_SCREENING_CENTRE = "05" + SEARCH_AREA_OTHER_HUB = "06" + SEARCH_AREA_WHOLE_DATABASE = "07" + + def __init__(self, page: Page): + self.page = page + + # Locate search area dropdown list + self.select_area = self.page.locator("#A_C_SEARCH_DOMAIN") + + # Select search area options + def select_search_area_home_hub(self): + self.select_area.select_option(self.SEARCH_AREA_HOME_HUB) + + def select_search_area_gp_practice(self): + self.select_area.select_option(self.SEARCH_AREA_GP_PRACTICE) + + def select_search_area_ccg(self): + self.select_area.select_option(self.SEARCH_AREA_CCG) + + def select_search_area_screening_centre(self): + self.select_area.select_option(self.SEARCH_AREA_SCREENING_CENTRE) + + def select_search_area_other_hub(self): + self.select_area.select_option(self.SEARCH_AREA_OTHER_HUB) + + def select_search_area_whole_database(self): + self.select_area.select_option(self.SEARCH_AREA_WHOLE_DATABASE) diff --git a/pytest.ini b/pytest.ini index 40fa9d53..7a20b124 100644 --- a/pytest.ini +++ b/pytest.ini @@ -12,14 +12,18 @@ addopts = --json-report-file=test-results/results.json --json-report-omit=collectors --tracing=retain-on-failure + --base-url=https://bcss-bcss-18680-ddc-bcss.k8s-nonprod.texasplatform.uk/ # Allows pytest to identify the base of this project as the pythonpath pythonpath = . # These are the tags that pytest will recognise when using @pytest.mark markers = - example: tests used for example purposes by this blueprint - utils: tests for utility classes provided by this blueprint - branch: tests designed to run at a branch level - main: tests designed to run against the main branch - release: tests designed to run specifically against a release branch + #example: tests used for example purposes by this blueprint + #utils: tests for utility classes provided by this blueprint + #branch: tests designed to run at a branch level + #main: tests designed to run against the main branch + #release: tests designed to run specifically against a release branch + utils: test setup and support methods + smoke: tests designed to run as part of the smokescreen regression test suite + wip: tests that are currently in progress diff --git a/requirements.txt b/requirements.txt index c4ebc377..6f7bb08c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ pytest-playwright>=0.5.1 pytest-html>=4.1.1 pytest-json-report>=1.5.0 +python-dotenv~=1.0.1 diff --git a/tests/test_bowel_scope_page.py b/tests/test_bowel_scope_page.py new file mode 100644 index 00000000..26946ade --- /dev/null +++ b/tests/test_bowel_scope_page.py @@ -0,0 +1,31 @@ +import pytest +from playwright.sync_api import Page, expect +from pages.bcss_home_page import MainMenu +from utils.user_tools import UserTools + + +@pytest.fixture(scope="function", autouse=True) +def before_each(page: Page): + """ + Before every test is executed, this fixture logs in to BCSS as the specified user and navigates to the bowel scope page + """ + # Log in to BCSS + UserTools.user_login(page, "Hub Manager State Registered") + + # Go to bowel scope page + MainMenu(page).go_to_bowel_scope_page() + + +@pytest.mark.smoke +def test_bowel_scope_page_navigation(page: Page) -> None: + """ + Confirms that the bowel scope appointments page loads, the appointments calendar is displayed and the + main menu button returns the user to the main menu + """ + # Bowel scope appointments page loads as expected + page.get_by_role("link", name="View Bowel Scope Appointments").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Appointment Calendar") + + # Return to main menu + page.get_by_role("link", name="Main Menu").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Main Menu") diff --git a/tests/test_call_and_recall_page.py b/tests/test_call_and_recall_page.py new file mode 100644 index 00000000..5a013a10 --- /dev/null +++ b/tests/test_call_and_recall_page.py @@ -0,0 +1,68 @@ +import pytest +from playwright.sync_api import Page, expect +from pages.bcss_home_page import MainMenu +from utils.user_tools import UserTools + + +@pytest.fixture(scope="function", autouse=True) +def before_each(page: Page): + """ + Before every test is executed, this fixture logs in to BCSS as the specified user and navigates to the call and recall page + """ + # Log in to BCSS + UserTools.user_login(page, "Hub Manager State Registered") + + # Go to call and recall page + MainMenu(page).go_to_call_and_recall_page() + + +@pytest.mark.smoke +def test_call_and_recall_page_navigation(page: Page) -> None: + """ + Confirms that the Call and Recall menu displays all menu options and confirms they load the correct pages + """ + # Planning and monitoring page loads as expected + page.get_by_role("link", name="Planning and Monitoring").click() + expect(page.locator("#page-title")).to_contain_text("Invitations Monitoring - Screening Centre") + page.get_by_role("link", name="Back").click() + + # Generate invitations page loads as expected + page.get_by_role("link", name="Generate Invitations").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Generate Invitations") + page.get_by_role("link", name="Back").click() + + # Invitation generation progress page loads as expected + page.get_by_role("link", name="Invitation Generation Progress").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Invitation Generation Progress") + page.get_by_role("link", name="Back").click() + + # Non invitation days page loads as expected + page.get_by_role("link", name="Non Invitation Days").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Non-Invitation Days") + page.get_by_role("link", name="Back").click() + + # Age extension rollout page loads as expected + page.get_by_role("link", name="Age Extension Rollout Plans").click() + expect(page.locator("#page-title")).to_contain_text("Age Extension Rollout Plans") + page.get_by_role("link", name="Back").click() + + # Return to main menu + page.get_by_role("link", name="Main Menu").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Main Menu") + + +def test_view_an_invitation_plan(page: Page) -> None: + """ + Confirms that an invitation plan can be viewed via a screening centre from the planning ad monitoring page + """ + # Go to planning and monitoring page + page.get_by_role("link", name="Planning and Monitoring").click() + + # Select a screening centre + page.get_by_role("link", name="BCS009").click() + + # Select an invitation plan + page.get_by_role("row").nth(1).get_by_role("link").click() + + # Verify invitation page is displayed + expect(page.locator("#page-title")).to_contain_text("View a plan") diff --git a/tests/test_communications_production_page.py b/tests/test_communications_production_page.py new file mode 100644 index 00000000..b3d8a80b --- /dev/null +++ b/tests/test_communications_production_page.py @@ -0,0 +1,55 @@ +import pytest +from playwright.sync_api import Page, expect +from utils.user_tools import UserTools +from pages.bcss_home_page import MainMenu + + +@pytest.fixture(scope="function", autouse=True) +def before_each(page: Page): + """ + Before every test is executed, this fixture logs in to BCSS as the specified user and navigates to the communications + production page + """ + # Log in to BCSS + UserTools.user_login(page, "Hub Manager State Registered") + + # Go to communications production page + MainMenu(page).go_to_communications_production_page() + + +@pytest.mark.smoke +def test_communications_production_page_navigation(page: Page) -> None: + """ + Confirms all menu items are displayed on the communications production page, and that the relevant pages + are loaded when the links are clicked + """ + # Active batch list page loads as expected + page.get_by_role("link", name="Active Batch List").click() + expect(page.locator("#page-title")).to_contain_text("Active Batch List") + page.get_by_role("link", name="Back").click() + + # Archived batch list page loads as expected + page.get_by_role("link", name="Archived Batch List").click() + expect(page.locator("#page-title")).to_contain_text("Archived Batch List") + page.get_by_role("link", name="Back").click() + + # Letter library index page loads as expected + page.get_by_role("link", name="Letter Library Index").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Letter Library Index") + page.get_by_role("link", name="Back", exact=True).click() + + # Manage individual letter link is visible (not clickable due to user role permissions) + expect(page.get_by_text("Manage Individual Letter")).to_be_visible() + + # Letter signatory page loads as expected + page.get_by_role("link", name="Letter Signatory").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Letter Signatory") + page.get_by_role("link", name="Back").click() + + # Electronic communication management page loads as expected + page.get_by_role("link", name="Electronic Communication").click() + expect(page.locator("#page-title")).to_contain_text("Electronic Communication Management") + + # Return to main menu + page.get_by_role("link", name="Main Menu").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Main Menu") diff --git a/tests/test_contacts_list_page.py b/tests/test_contacts_list_page.py new file mode 100644 index 00000000..c8845f0f --- /dev/null +++ b/tests/test_contacts_list_page.py @@ -0,0 +1,51 @@ +import pytest +from playwright.sync_api import Page, expect +from pages.bcss_home_page import MainMenu +from utils.user_tools import UserTools + + +@pytest.fixture(scope="function", autouse=True) +def before_each(page: Page): + """ + Before every test is executed, this fixture logs in to BCSS as the specified user and navigates to the contacts list page + """ + # Log in to BCSS + UserTools.user_login(page, "Hub Manager State Registered") + + # Go to contacts list page + MainMenu(page).go_to_contacts_list_page() + + +@pytest.mark.smoke +def test_contacts_list_page_navigation(page: Page) -> None: + """ + Confirms all menu items are displayed on the contacts list page, and that the relevant pages + are loaded when the links are clicked + """ + # View contacts page loads as expected + page.get_by_role("link", name="View Contacts").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("View Contacts") + page.get_by_role("link", name="Back", exact=True).click() + + # Edit my contact details page loads as expected + page.get_by_role("link", name="Edit My Contact Details").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Edit My Contact Details") + page.get_by_role("link", name="Back").click() + + # Maintain contacts page loads as expected + page.get_by_role("link", name="Maintain Contacts").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Maintain Contacts") + page.get_by_role("link", name="Back").click() + + # My preference settings page loads as expected + page.get_by_role("link", name="My Preference Settings").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("My Preference Settings") + page.get_by_role("link", name="Back").click() + + # Other links are visible (Not clickable due to user role permissions) + expect(page.get_by_text("Extract Contact Details")).to_be_visible() + expect(page.get_by_text("Resect and Discard Accredited")).to_be_visible() + + # Return to main menu + page.get_by_role("link", name="Main Menu").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Main Menu") diff --git a/tests/test_download_page.py b/tests/test_download_page.py new file mode 100644 index 00000000..6c4b3d9d --- /dev/null +++ b/tests/test_download_page.py @@ -0,0 +1,49 @@ +import pytest +from playwright.sync_api import Page, expect +from pages.bcss_home_page import MainMenu +from utils.user_tools import UserTools + + +@pytest.fixture(scope="function", autouse=True) +def before_each(page: Page): + """ + Before every test is executed, this fixture logs in to BCSS as the specified user and navigates to the download page + """ + # Log in to BCSS + UserTools.user_login(page, "Hub Manager State Registered") + + # Go to download page + MainMenu(page).go_to_download_page() + + +@pytest.mark.smoke +def test_download_facility_page_navigation(page: Page) -> None: + """ + Confirms all menu items are displayed on the downloads page, and that the relevant pages + are loaded when the links are clicked. Also confirms that the warning header messages are displayed + on the relevant pages + """ + # Individual download request and retrieval page loads as expected + page.get_by_role("link", name="Individual Download Request").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Individual Download Request and Retrieval") + + # Individual download request and retrieval page contains warning message + expect(page.locator("form[name=\"frm\"]")).to_contain_text("Warning - FS Screening data will not be downloaded") + page.get_by_role("link", name="Back", exact=True).click() + + # List of Individual downloads page loads as expected + page.get_by_role("link", name="List of Individual Downloads").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("List of Individual Downloads") + page.get_by_role("link", name="Back", exact=True).click() + + # Batch download request and retrieval page loads as expected + page.get_by_role("link", name="Batch Download Request and").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Batch Download Request and Retrieval") + + # Batch download request and retrieval page contains warning message + expect(page.locator("form[name=\"frm\"]")).to_contain_text("Warning - FS Screening data will not be downloaded") + page.get_by_role("link", name="Back", exact=True).click() + + # Return to main menu + page.get_by_role("link", name="Main Menu").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Main Menu") diff --git a/tests/test_example.py b/tests/test_example.py deleted file mode 100644 index a6b86845..00000000 --- a/tests/test_example.py +++ /dev/null @@ -1,78 +0,0 @@ -""" -This file provides a very basic test to confirm how to get started with test execution, and also -a way to prove that the blueprint has been copied and built correctly for teams getting stated. - -You can invoke this test once the blueprint has been installed by using the following command -to see the test executing and producing a trace report: - pytest --tracing on --headed -""" - -import pytest -from playwright.sync_api import Page, expect - - -@pytest.fixture(autouse=True) -def initial_navigation(page: Page) -> None: - ''' - This fixture (or hook) is used for each test in this file to navigate to this repository before - each test, to reduce the need for repeated code within the tests directly. - - This specific fixture has been designated to run for every test by setting autouse=True. - ''' - - # Navigate to page - page.goto("https://github.com/nhs-england-tools/playwright-python-blueprint") - - -@pytest.mark.example -def test_basic_example(page: Page) -> None: - ''' - This test demonstrates how to quickly get started using Playwright Python, which runs using pytest. - - This example starts with @pytest.mark.example, which indicates this test has been tagged - with the term "example", to demonstrate how tests can be independently tagged. - - When running using the pytest command, Playwright automatically instantiates certain objects - available for use, including the Page object (which is how Playwright interacts with the - system under test). - - This test does the following: - 1) Navigates to this repository (via the initial_navigation fixture above) - 2) Asserts that the README contents rendered by GitHub contains the text "Playwright Python Blueprint" - 3) Asserts that the main section of the page contains the topic label "playwright-python" - ''' - - # Assert repo text is present - expect(page.get_by_role("article")).to_contain_text("Playwright Python Blueprint") - - # Assert the page loaded contains a reference to the playwright-python topic page - expect(page.get_by_role("main")).to_contain_text("playwright-python") - - -@pytest.mark.example -def test_textbox_example(page: Page) -> None: - """ - This test demonstrates another example of quickly getting started using Playwright Python. - - This is specifically designed to outline some of the principals that Playwright uses, for - example when looking for a specific textbox to enter information into, rather than using a - direct HTML or CSS reference, you can use attributes of the field (in this case the placeholder - text) to find the element as a user would navigating your application. You can also use - locators to find specific HTML or CSS elements as required (in this case the locator for the - assertion). - - This test does the following: - 1) Navigates to this repository (via the initial_navigation fixture above) - 2) Uses the "Go to file" textbox and searches for this file, "text_example.py" - 3) Selects the label for the dropdown element presented for the search results and clicks - 4) Asserts that the filename for the now selected file is "test_example.py" - """ - - # Select the "Go to file" textbox and search for this file - page.get_by_placeholder("Go to file").fill("test_example.py") - - # Click the file name presented in the dropdown - page.get_by_label("tests/test_example.").click() - - # Confirm we are viewing the correct file - expect(page.locator("#file-name-id-wide")).to_contain_text("test_example.py") diff --git a/tests/test_fit_test_kits_page.py b/tests/test_fit_test_kits_page.py new file mode 100644 index 00000000..433be1b0 --- /dev/null +++ b/tests/test_fit_test_kits_page.py @@ -0,0 +1,79 @@ +import pytest +from playwright.sync_api import Page, expect +from pages.bcss_home_page import MainMenu +from utils.user_tools import UserTools + + +@pytest.fixture(scope="function", autouse=True) +def before_each(page: Page): + """ + Before every test is executed, this fixture logs in to BCSS as the specified user and navigates to the + fit test kits page + """ + # Log in to BCSS + UserTools.user_login(page, "Hub Manager State Registered") + + # Go to fit test kits page + MainMenu(page).go_to_fit_test_kits_page() + + +@pytest.mark.smoke +def test_fit_test_kits_page_navigation(page: Page) -> None: + """ + Confirms all menu items are displayed on the fit test kits page, and that the relevant pages + are loaded when the links are clicked + """ + # Verify FIT rollout summary page opens as expected + page.get_by_role("link", name="FIT Rollout Summary").click() + expect(page.locator("body")).to_contain_text("FIT Rollout Summary") + page.get_by_role("link", name="Back").click() + + # Verify Log Devices page opens as expected + page.get_by_role("link", name="Log Devices").click() + expect(page.locator("#page-title")).to_contain_text("Scan Device") + page.get_by_role("link", name="Back").click() + + # Verify View FIT Kit Result page opens as expected + page.get_by_role("link", name="View FIT Kit Result").click() + expect(page.locator("body")).to_contain_text("View FIT Kit Result") + page.get_by_role("link", name="Back").click() + + # Verify Kit Service Management page opens as expected + page.get_by_role("link", name="Kit Service Management").click() + expect(page.locator("#page-title")).to_contain_text("Kit Service Management") + page.get_by_role("link", name="Back").click() + + # Verify Kit Result Audit page opens as expected + page.get_by_role("link", name="Kit Result Audit").click() + expect(page.locator("#page-title")).to_contain_text("Kit Result Audit") + page.get_by_role("link", name="Back").click() + + # Verify View Algorithm page opens as expected + page.get_by_role("link", name="View Algorithm").click() + expect(page.locator("body")).to_contain_text("Select Algorithm") + page.get_by_role("link", name="Back").click() + + # Verify View Screening Centre FIT page opens as expected + page.get_by_role("link", name="View Screening Centre FIT").click() + expect(page.locator("body")).to_contain_text("Select Screening Centre") + page.get_by_role("link", name="Back").click() + + # Verify Screening Incidents List page opens as expected + page.get_by_role("link", name="Screening Incidents List").click() + expect(page.locator("#page-title")).to_contain_text("Screening Incidents List") + page.get_by_role("link", name="Back").click() + + # Verify FIT QC Products page opens as expected + page.get_by_role("link", name="Manage QC Products").click() + expect(page.locator("#page-title")).to_contain_text("FIT QC Products") + page.get_by_role("link", name="Back").click() + + # Verify Maintain Analysers page opens as expected + page.get_by_role("link", name="Maintain Analysers").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Maintain Analysers") + page.get_by_role("link", name="Back").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("FIT Test Kits") + + # Return to main menu + page.get_by_role("link", name="Main Menu").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Main Menu") diff --git a/tests/test_gfobt_test_kits_page.py b/tests/test_gfobt_test_kits_page.py new file mode 100644 index 00000000..f92ac1d8 --- /dev/null +++ b/tests/test_gfobt_test_kits_page.py @@ -0,0 +1,69 @@ +import pytest +from playwright.sync_api import Page, expect +from pages.bcss_home_page import MainMenu +from utils.user_tools import UserTools + + +@pytest.fixture(scope="function", autouse=True) +def before_each(page: Page): + """ + Before every test is executed, this fixture logs in to BCSS as the specified user and navigates to the + gfob test kits page + """ + # Log in to BCSS + UserTools.user_login(page, "Hub Manager State Registered") + + # Go to gFOBT test kits page + MainMenu(page).go_to_gfob_test_kits_page() + + +@pytest.mark.smoke +def test_gfob_test_kit_page_navigation(page: Page) -> None: + """ + Confirms all menu items are displayed on the gfob test kits page, and that the relevant pages + are loaded when the links are clicked + """ + # Test kit logging page opens as expected + page.get_by_role("link", name="Test Kit Logging").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Test Kit Logging") + page.get_by_role("link", name="Back").click() + + # Test kit reading page opens as expected + page.get_by_role("link", name="Test Kit Reading").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Test Kit Quality Control Reading") + page.get_by_role("link", name="Back").click() + + # View test kit result page opens as expected + page.get_by_role("link", name="View Test Kit Result").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("View Test Kit Result") + page.get_by_role("link", name="Back").click() + + # Create qc kit page opens as expected + page.get_by_role("link", name="Create QC Kit").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Create QC Kit") + + # Return to main menu + page.get_by_role("link", name="Main Menu").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Main Menu") + + +def test_create_a_qc_kit(page: Page) -> None: + """ + Confirms that a qc test kit can be created and that each of the dropdowns has an option set available for selection + """ + # Navigate to create QC kit page + page.get_by_role("link", name="Create QC Kit").click() + + # Select QC kit drop down options + page.locator("#A_C_Reading_999_0_0").select_option("NEGATIVE") + page.locator("#A_C_Reading_999_0_1").select_option("POSITIVE") + page.locator("#A_C_Reading_999_1_0").select_option("POSITIVE") + page.locator("#A_C_Reading_999_1_1").select_option("UNUSED") + page.locator("#A_C_Reading_999_2_0").select_option("NEGATIVE") + page.locator("#A_C_Reading_999_2_1").select_option("POSITIVE") + + # Click save + page.get_by_role("button", name="Save Kit").click() + + # Verify kit has saved + expect(page.locator("th")).to_contain_text("A quality control kit has been created with the following values:") diff --git a/tests/test_home_page_links.py b/tests/test_home_page_links.py new file mode 100644 index 00000000..39c15a9f --- /dev/null +++ b/tests/test_home_page_links.py @@ -0,0 +1,71 @@ +import pytest +from playwright.sync_api import Page, expect +from utils.user_tools import UserTools +from pages.bcss_home_page import BcssHomePage +from utils.date_time_utils import DateTimeUtils + + +@pytest.fixture(scope="function", autouse=True) +def before_each(page: Page): + """ + Before every test is executed, this fixture logs in to BCSS as the specified user and results in the home page + being displayed + """ + # Log in to BCSS + UserTools.user_login(page, "Hub Manager State Registered") + + +@pytest.mark.smoke +def test_home_page_links_navigation(page: Page) -> None: + """ + Confirms that homepage links are visible and clickable, and the expected pages open when clicking the links + """ + homepage = BcssHomePage(page) + + # Click 'show sub menu' link + homepage.click_sub_menu_link() + # Verify a sub menu is visible + expect(page.get_by_role("link", name="List All Sites")).to_be_visible() + + # Click 'hide sub menu' link + homepage.click_hide_sub_menu_link() + # Verify sub menu is hidden (alerts are visible) + expect(page.get_by_role("cell", name="Alerts", exact=True)).to_be_visible() + + # Click 'select org' link + homepage.click_select_org_link() + # Verify select org page is displayed + expect(page.locator("form")).to_contain_text("Choose an Organisation") + + # Click the 'back' link + homepage.click_back_button() + # Verify main menu is displayed + expect(page.get_by_role("cell", name="Alerts", exact=True)).to_be_visible() + + # Click release notes link + homepage.click_release_notes_link() + # Verify release notes are displayed + expect(page.locator("#page-title")).to_contain_text("Release Notes") + # Click the 'back' button + homepage.click_back_button() + + # Click the refresh alerts link + homepage.click_refresh_alerts_link() + # Verify that the 'last updated' timestamp matches the current date and time + expect(page.locator("form[name=\"refreshCockpit\"]")).to_contain_text( + f"Refresh alerts (last updated :{DateTimeUtils.current_datetime()})" + ) + + # Click the user guide link + with page.expect_popup() as page1_info: + # Check the user guide link works + page.get_by_role("link", name="User guide").click() + # Check that the user guide page can be accessed + page1 = page1_info.value + + # Click 'help' link + with page.expect_popup() as page2_info: + # Check the help link works + page.get_by_role("link", name="Help").click() + # Check that the help page can be accessed + page2 = page2_info.value diff --git a/tests/test_login_to_bcss.py b/tests/test_login_to_bcss.py new file mode 100644 index 00000000..79cd64b5 --- /dev/null +++ b/tests/test_login_to_bcss.py @@ -0,0 +1,13 @@ +from playwright.sync_api import Page, expect +from utils.user_tools import UserTools + + +def test_successful_login_to_bcss(page: Page) -> None: + """ + Confirms that a user with valid credentials can log in to bcss + """ + # Enter a valid username and password and click 'sign in' button + UserTools.user_login(page, "Hub Manager State Registered") + + # Confirm user has successfully signed in and is viewing the bcss homepage + expect(page.locator("#ntshAppTitle")).to_contain_text("Bowel Cancer Screening System") diff --git a/tests/test_lynch_surveillance_page.py b/tests/test_lynch_surveillance_page.py new file mode 100644 index 00000000..157a3fb6 --- /dev/null +++ b/tests/test_lynch_surveillance_page.py @@ -0,0 +1,32 @@ +import pytest +from playwright.sync_api import Page, expect +from pages.bcss_home_page import MainMenu +from utils.user_tools import UserTools + + +@pytest.fixture(scope="function", autouse=True) +def before_each(page: Page): + """ + Before every test is executed, this fixture logs in to BCSS as the specified user and navigates to the + lynch surveillance page + """ + # Log in to BCSS + UserTools.user_login(page, "Hub Manager State Registered") + + # Go to Lynch Surveillance page + MainMenu(page).go_to_lynch_surveillance_page() + + +@pytest.mark.smoke +def test_lynch_surveillance_page_navigation(page: Page) -> None: + """ + Confirms that the 'set lynch invitation rates' link is visible and clickable, and navigates to the + expected page when clicked + """ + # 'Set lynch invitation rates' page loads as expected + page.get_by_role("link", name="Set Lynch Invitation Rates").click() + expect(page.locator("#page-title")).to_contain_text("Set Lynch Surveillance Invitation Rates") + + # Return to main menu + page.get_by_role("link", name="Main Menu").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Main Menu") diff --git a/tests/test_organisations_page.py b/tests/test_organisations_page.py new file mode 100644 index 00000000..c5d5874a --- /dev/null +++ b/tests/test_organisations_page.py @@ -0,0 +1,63 @@ +import pytest +from playwright.sync_api import Page, expect +from pages.bcss_home_page import MainMenu +from utils.user_tools import UserTools + + +@pytest.fixture(scope="function", autouse=True) +def before_each(page: Page): + """ + Before every test is executed, this fixture logs in to BCSS as the specified user and navigates to the + organisations page + """ + # Log in to BCSS + UserTools.user_login(page, "Hub Manager State Registered") + + # Go to organisations page + MainMenu(page).go_to_organisations_page() + + +@pytest.mark.smoke +def test_organisations_page_navigation(page: Page) -> None: + """ + Confirms all menu items are displayed on the organisations page, and that the relevant pages + are loaded when the links are clicked + """ + # Screening centre parameters page loads as expected + page.get_by_role("link", name="Screening Centre Parameters").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Screening Centre Parameters") + page.get_by_role("link", name="Back", exact=True).click() + + # Organisation parameters page loads as expected + page.get_by_role("link", name="Organisation Parameters").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("System Parameters") + page.get_by_role("link", name="Back", exact=True).click() + + # Organisation and site details page loads as expected + page.get_by_role("link", name="Organisation and Site Details").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Organisation and Site Details") + page.get_by_role("link", name="Back").click() + + # The links below are visible (not clickable due to user role permissions) + expect(page.get_by_text("Upload NACS data (Bureau)")).to_be_visible() + expect(page.get_by_text("Bureau", exact=True)).to_be_visible() + + # GP practice endorsement page loads as expected + page.get_by_role("link", name="GP Practice Endorsement").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("GP Practice Endorsement") + + # Return to main menu + page.get_by_role("link", name="Main Menu").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Main Menu") + + +def test_view_an_organisations_system_parameters(page: Page) -> None: + """ + Confirms that an organisation's system parameters can be accessed and viewed + """ + # Go to screening centre parameters page + page.get_by_role("link", name="Screening Centre Parameters").click() + + # View an Organisation + page.get_by_role("link", name="BCS001").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("System Parameters") diff --git a/tests/test_reports_page.py b/tests/test_reports_page.py new file mode 100644 index 00000000..726af521 --- /dev/null +++ b/tests/test_reports_page.py @@ -0,0 +1,392 @@ +import pytest +from playwright.sync_api import Page, expect +from pages import reports_page +from pages.bcss_home_page import MainMenu +from utils.user_tools import UserTools + + +@pytest.fixture(scope="function", autouse=True) +def before_each(page: Page): + """ + Before every test is executed, this fixture logs in to BCSS as the specified user and navigates to the + reports page + """ + # Log in to BCSS + UserTools.user_login(page, "Hub Manager State Registered") + + # Open reports page + MainMenu(page).go_to_reports_page() + + +@pytest.mark.smoke +def test_reports_page_navigation(page: Page) -> None: + """ + Confirms all menu items are displayed on the reports page, and that the relevant pages + are loaded when the links are clicked + """ + # Bureau reports link is visible + expect(page.get_by_text("Bureau Reports")).to_be_visible() + + # Failsafe reports page opens as expected + reports_page.go_to_failsafe_reports_page(page) + expect(page.locator("#ntshPageTitle")).to_contain_text("Failsafe Reports") + page.get_by_role("link", name="Back").click() + + # Operational reports page opens as expected + reports_page.go_to_operational_reports_page(page) + expect(page.locator("#ntshPageTitle")).to_contain_text("Operational Reports") + page.get_by_role("link", name="Back").click() + + # Strategic reports page opens as expected + reports_page.go_to_strategic_reports_page(page) + expect(page.locator("#ntshPageTitle")).to_contain_text("Strategic Reports") + page.get_by_role("link", name="Back").click() + + # "Cancer waiting times reports" page opens as expected + reports_page.go_to_cancer_waiting_times_reports_page(page) + expect(page.locator("#ntshPageTitle")).to_contain_text("Cancer Waiting Times Reports") + page.get_by_role("link", name="Back").click() + + # Dashboard opens as expected TODO - this step may be failing legitimately + # reports_page.go_to_dashboard(page) + # expect(page.locator("#ntshPageTitle")).to_contain_text("Dashboard") + # page.get_by_role("link", name="Back").click() + + # QA Report : Dataset Completion link is visible + expect(page.get_by_text("QA Report : Dataset Completion")).to_be_visible() + + # Return to main menu + page.get_by_role("link", name="Main Menu").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Main Menu") + + +# Failsafe Reports +def test_failsafe_reports_date_report_last_requested(page: Page) -> None: + """ + Confirms 'date_report_last_requested' page loads, 'generate report' and 'refresh' buttons work as expected + and the timestamp updates to current date and time when refreshed + """ + # Go to failsafe reports page + reports_page.go_to_failsafe_reports_page(page) + + # Click 'date report last requested' link + reports_page.go_to_date_report_last_requested_page(page) + + # Verify 'Date Report Last Requested' is the page title + expect(page.locator("#ntshPageTitle")).to_contain_text("Date Report Last Requested") + + # Click 'generate report' button + page.get_by_role("button", name="Generate Report").click() + + # Verify timestamp has updated (equals current date and time) + report_timestamp = reports_page.report_timestamp_date_format() + expect(page.locator("b")).to_contain_text(report_timestamp) + + # Click 'refresh' button + page.get_by_role("button", name="Refresh").click() + + # Verify timestamp has updated (equals current date and time) + report_timestamp = reports_page.report_timestamp_date_format() + expect(page.locator("b")).to_contain_text(report_timestamp) + + +def test_failsafe_reports_screening_subjects_with_inactive_open_episode(page: Page) -> None: + """ + Confirms 'screening_subjects_with_inactive_open_episode' page loads, 'generate report' button works as expected + and that a screening subject record can be opened + """ + # Go to failsafe reports page + reports_page.go_to_failsafe_reports_page(page) + + # Click screening subjects with inactive open episode link + reports_page.go_to_screening_subjects_with_inactive_open_episode_link_page(page) + + # Verify "Screening Subjects With Inactive Open Episode" is the page title + expect(page.locator("#page-title")).to_contain_text("Screening Subjects With Inactive Open Episode") + + # Click 'Generate Report' button + page.get_by_role("button", name="Generate Report").click() + + # Open a screening subject record + page.get_by_role("cell", name="401 7652").click() + + # Verify "Subject Screening Summary" is the page title + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Screening Summary") + + +def test_failsafe_reports_subjects_ceased_due_to_date_of_birth_changes(page: Page) -> None: + """ + Confirms 'subjects_ceased_due_to_date_of_birth_changes' page loads, + the datepicker and 'generate report' button works as expected + the timestamp updates to current date and time when refreshed and + a screening subject record can be opened + """ + # Go to failsafe reports page + reports_page.go_to_failsafe_reports_page(page) + + # Click on "Subjects Ceased Due to Date Of Birth Changes" link + reports_page.go_to_subjects_ceased_due_to_date_of_birth_changes_page(page) + + # Select a "report start date" from the calendar + page.get_by_role("button", name="Calendar").click() + page.get_by_text("«").click() + page.get_by_role("cell", name="18", exact=True).click() + + # Click "Generate Report" + page.get_by_role("button", name="Generate Report").click() + + # Verify timestamp has updated to current date and time + report_timestamp = reports_page.report_timestamp_date_format() + expect(page.locator("b")).to_contain_text(report_timestamp) + + # Open a screening subject record from the search results + page.get_by_role("cell", name="954 296 8175", exact=True).click() + + # Verify page title is "Subject Demographic" + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Demographic") + + +def test_failsafe_reports_allocate_sc_for_patient_movements_within_hub_boundaries(page: Page) -> None: + """ + Confirms 'allocate_sc_for_patient_movements_within_hub_boundaries' page loads, + the 'generate report' button works as expected + the timestamp updates to current date and time when refreshed + a screening subject record can be opened and + a different SC can be allocated to a patient record + """ + # Go to failsafe reports page + reports_page.go_to_failsafe_reports_page(page) + + # Click on the "Allocate SC for Patient Movements within Hub Boundaries" link + reports_page.go_to_allocate_sc_for_patient_movements_within_hub_boundaries_page(page) + + # Verify page title is "Allocate SC for Patient Movements within Hub Boundaries" + expect(page.locator("#ntshPageTitle")).to_contain_text("Allocate SC for Patient Movements within Hub Boundaries") + + # Click "Generate Report" + page.get_by_role("button", name="Generate Report").click() + + # Verify timestamp has updated to current date and time + report_timestamp = reports_page.report_timestamp_date_format() + expect(page.locator("b")).to_contain_text(report_timestamp) + + # Open a screening subject record from the first row/first cell of the table + page.locator("//*[@id='listReportDataTable']/tbody/tr[3]/td[1]").click() + + # Verify page title is "Set Patient's Screening Centre" + expect(page.locator("#ntshPageTitle")).to_contain_text("Set Patient's Screening Centre") + + # Select another screening centre + page.locator("#cboScreeningCentre").select_option("23643") + + # Click update + page.get_by_role("button", name="Update").click() + + # Verify new screening centre has saved + expect(page.locator("#cboScreeningCentre")).to_have_value("23643") + + +def test_failsafe_reports_allocate_sc_for_patient_movements_into_your_hub(page: Page) -> None: + """ + Confirms 'allocate_sc_for_patient_movements_into_your_hub' page loads, + the 'generate report' and 'refresh' buttons work as expected and + the timestamp updates to current date and time when refreshed + """ + # Go to failsafe reports page + reports_page.go_to_failsafe_reports_page(page) + + # Click on "allocate sc for patient movements into your hub" link + reports_page.go_to_allocate_sc_for_patient_movements_into_your_hub_page(page) + + # Verify page title is "Date Report Last Requested" + expect(page.locator("#ntshPageTitle")).to_contain_text("Allocate SC for Patient Movements into your Hub") + + # Click "Generate Report" button + page.get_by_role("button", name="Generate Report").click() + + # Verify timestamp has updated to current date and time + report_timestamp = reports_page.report_timestamp_date_format() + expect(page.locator("b")).to_contain_text(report_timestamp) + + # Click "Refresh" button + page.get_by_role("button", name="Refresh").click() + + # Verify timestamp has updated to current date and time + report_timestamp = reports_page.report_timestamp_date_format() + expect(page.locator("b")).to_contain_text(report_timestamp) + + +def test_failsafe_reports_identify_and_link_new_gp(page: Page) -> None: + """ + Confirms 'identify_and_link_new_gp' page loads, + the 'generate report' and 'refresh' buttons work as expected + the timestamp updates to current date and time when refreshed + a screening subject record can be opened and the Link GP practice to Screening Centre page + can be opened from here + """ + # Go to failsafe reports page + reports_page.go_to_failsafe_reports_page(page) + + # Click on "Identify and link new GP" link + reports_page.go_to_identify_and_link_new_gp_page(page) + + # Verify page title is "Identify and link new GP practices" + expect(page.locator("#ntshPageTitle")).to_contain_text("Identify and link new GP practices") + + # Click on "Generate Report" + page.get_by_role("button", name="Generate Report").click() + + # Verify timestamp has updated to current date and time + report_timestamp = reports_page.report_timestamp_date_format() + expect(page.locator("b")).to_contain_text(report_timestamp) + + # Click "Refresh" button + page.get_by_role("button", name="Refresh").click() + + # Verify timestamp has updated to current date and time + report_timestamp = reports_page.report_timestamp_date_format() + expect(page.locator("b")).to_contain_text(report_timestamp) + + # Open a screening subject record from the first row/second cell of the table + page.locator("//*[@id='listReportDataTable']/tbody/tr[3]/td[2]").click() + + # Verify page title is "Link GP practice to Screening Centre" + expect(page.locator("#ntshPageTitle")).to_contain_text("Link GP practice to Screening Centre") + + +# Operational Reports +def test_operational_reports_appointment_attendance_not_updated(page: Page) -> None: + """ + Confirms 'appointment_attendance_not_updated' page loads, + a SC can be selected from the dropdown + the 'generate report' button works as expected + the timestamp updates to current date and time when refreshed and + an appointment record can be opened from here + """ + # Go to operational reports page + reports_page.go_to_operational_reports_page(page) + + # Go to "appointment attendance not updated" report page + reports_page.go_to_appointment_attendance_not_updated_page(page) + + # Verify page title is "Appointment Attendance Not Updated" + expect(page.locator("#ntshPageTitle")).to_contain_text("Appointment Attendance Not Updated") + + # Select a screening centre from the drop-down options + page.get_by_label("Screening Centre").select_option("23643") + + # Click "Generate Report" button + page.get_by_role("button", name="Generate Report").click() + + # Verify timestamp has updated to current date and time + report_timestamp = reports_page.report_timestamp_date_format() + expect(page.locator("b")).to_contain_text(report_timestamp) + + # Open an appointment record from the report + page.locator("#listReportDataTable > tbody > tr:nth-child(3) > td:nth-child(1) > a").click() + + # Verify the page title is "Appointment Detail" + expect(page.locator("#ntshPageTitle")).to_contain_text("Appointment Detail") + + +def test_operational_reports_fobt_kits_logged_but_not_read(page: Page) -> None: + """ + Confirms 'fobt_kits_logged_but_not_read' page loads, + the 'refresh' button works as expected and + the timestamp updates to current date and time when refreshed + """ + # Go to operational reports page + reports_page.go_to_operational_reports_page(page) + + # Go to "FOBT Kits Logged but Not Read" page + reports_page.go_to_fobt_kits_logged_but_not_read_page(page) + + # Verify page title is "FOBT Kits Logged but Not Read - Summary View" + expect(page.locator("#page-title")).to_contain_text("FOBT Kits Logged but Not Read - Summary View") + + # Click refresh button + page.get_by_role("button", name="Refresh").click() + + # Verify timestamp has updated to current date and time + report_timestamp = reports_page.fobt_kits_logged_but_not_read_report_timestamp_date_format() + expect(page.locator("#report-generated")).to_contain_text(f"Report generated on {report_timestamp}.") + + +def test_operational_reports_demographic_update_inconsistent_with_manual_update(page: Page) -> None: + """ + Confirms 'demographic_update_inconsistent_with_manual_update' page loads, + the 'refresh' button works as expected and + the timestamp updates to current date and time when refreshed + """ + # Go to operational reports page + reports_page.go_to_operational_reports_page(page) + + # Go to "Demographic Update Inconsistent With Manual Update" page + reports_page.go_to_demographic_update_inconsistent_with_manual_update_page(page) + + # Verify page title is "Demographic Update Inconsistent With Manual Update" + expect(page.locator("#page-title")).to_contain_text("Demographic Update Inconsistent With Manual Update") + + +def test_operational_reports_screening_practitioner_6_weeks_availability_not_set_up(page: Page) -> None: + """ + Confirms 'screening_practitioner_6_weeks_availability_not_set_up_report' page loads, + a SC can be selected + the 'generate report' and 'refresh' buttons work as expected and + the timestamp updates to current date and time when refreshed + """ + # Go to operational reports page + reports_page.go_to_operational_reports_page(page) + + # Go to "Screening Practitioner 6 Weeks Availability Not Set Up" page + reports_page.go_to_screening_practitioner_6_weeks_availability_not_set_up_report_page(page) + + # Verify page title is "Screening Practitioner 6 Weeks Availability Not Set Up" + expect(page.locator("#ntshPageTitle")).to_contain_text("Screening Practitioner 6 Weeks Availability Not Set Up") + + # Select a screening centre + page.get_by_label("Screening Centre").select_option("23643") + + # Click "Generate Report" + page.get_by_role("button", name="Generate Report").click() + + # Verify timestamp has updated to current date and time + report_timestamp = reports_page.report_timestamp_date_format() + expect(page.locator("#displayGenerateDate")).to_contain_text(report_timestamp) + + # Click "Refresh" button + page.get_by_role("button", name="Refresh").click() + + # Verify timestamp has updated to current date and time + report_timestamp = reports_page.report_timestamp_date_format() + expect(page.locator("#displayGenerateDate")).to_contain_text(report_timestamp) + + +def test_operational_reports_screening_practitioner_appointments(page: Page) -> None: + """ + Confirms 'screening_practitioner_appointments' page loads, + a SC and Screening Practitioner can be selected + the 'generate report' button works as expected and + the timestamp updates to current date and time when refreshed + """ + # Go to operational reports page + reports_page.go_to_operational_reports_page(page) + + # Go to "Screening Practitioner Appointments" page + reports_page.go_to_screening_practitioner_appointments_page(page) + + # Verify page title is "Screening Practitioner Appointments" + expect(page.locator("#ntshPageTitle")).to_contain_text("Screening Practitioner Appointments") + + # Select a screening centre + page.get_by_label("Screening Centre").select_option("23643") + + # Select a screening practitioner + page.locator("#A_C_NURSE").select_option("1982") + + # Click "Generate Report" + page.locator("#submitThisForm").click() + + # Verify timestamp has updated to current date and time + report_timestamp = reports_page.screening_practitioner_appointments_report_timestamp_date_format() + expect(page.locator("b")).to_contain_text(report_timestamp) diff --git a/tests/test_screening_practitioner_appointments_page.py b/tests/test_screening_practitioner_appointments_page.py new file mode 100644 index 00000000..f5c46a78 --- /dev/null +++ b/tests/test_screening_practitioner_appointments_page.py @@ -0,0 +1,44 @@ +import pytest +from playwright.sync_api import Page, expect +from pages.bcss_home_page import MainMenu +from utils.user_tools import UserTools + + +@pytest.fixture(scope="function", autouse=True) +def before_each(page: Page): + """ + Before every test is executed, this fixture logs in to BCSS as the specified user and navigates to the + screening_practitioner_appointments page + """ + # Log in to BCSS + UserTools.user_login(page, "Hub Manager State Registered") + + # Go to screening practitioner appointments page + MainMenu(page).go_to_screening_practitioner_appointments_page() + + +@pytest.mark.smoke +def test_screening_practitioner_appointments_page_navigation(page: Page) -> None: + """ + Confirms screening_practitioner_appointments page loads and the expected links are visible + and clickable (where the user has required permissions). + """ + # Verify View appointments page opens as expected + page.get_by_role("link", name="View appointments").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Appointment Calendar") + page.get_by_role("link", name="Back").click() + + # Verify Patients that Require Colonoscopy Assessment Appointments page opens as expected + page.get_by_role("link", name="Patients that Require").click() + expect(page.locator("#page-title")).to_contain_text("Patients that Require Colonoscopy Assessment Appointments") + page.get_by_role("link", name="Back").click() + + # Verify below links are visible (not clickable due to user role permissions) + expect(page.get_by_text("Patients that Require Colonoscopy Assessment Appointments - Bowel Scope")).to_be_visible() + expect(page.get_by_text("Patients that Require Surveillance Appointments")).to_be_visible() + expect(page.get_by_text("Patients that Require Post-")).to_be_visible() + expect(page.get_by_text("Set Availability")).to_be_visible() + + # Return to main menu + page.get_by_role("link", name="Main Menu").click() + expect(page.locator("#ntshPageTitle")).to_contain_text("Main Menu") diff --git a/tests/test_screening_subject_search_page.py b/tests/test_screening_subject_search_page.py new file mode 100644 index 00000000..a9056407 --- /dev/null +++ b/tests/test_screening_subject_search_page.py @@ -0,0 +1,482 @@ +import pytest +from playwright.sync_api import Page, expect +from pages.bcss_home_page import MainMenu +from pages.screening_subject_search_page import ScreeningStatusSearchOptions, LatestEpisodeStatusSearchOptions, \ + SearchAreaSearchOptions +from utils.user_tools import UserTools + + +@pytest.fixture(scope="function", autouse=True) +def before_each(page: Page): + """ + Before every test is executed, this fixture logs in to BCSS as the specified user and navigates to the + screening_subject_search page + """ + # Log in to BCSS + UserTools.user_login(page, "Hub Manager State Registered") + + # Go to screening subject search page + MainMenu(page).go_to_screening_subject_search_page() + + +@pytest.mark.smoke +def test_search_screening_subject_by_nhs_number(page: Page) -> None: + """ + Confirms a screening subject can be searched for, using their nhs number + """ + # Clear filters (if any filters have persisted the NHS number field is inactive) + page.get_by_role("button", name="Clear Filters").click() + + # Enter an NHS number + page.get_by_label("NHS Number").fill("966 529 9271") + + # Press Tab (required after text input, to make the search button become active). + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the Subject Screening Summary page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Screening Summary") + + +def test_search_screening_subject_by_surname(page: Page) -> None: + """ + Confirms a screening subject can be searched for, using their surname + """ + # Enter a surname + page.locator("#A_C_Surname").fill("Absurd") + + # Press Tab (required after text input, to make the search button become active). + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject summary page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Screening Summary") + + +def test_search_screening_subject_by_forename(page: Page) -> None: + """ + Confirms a screening subject can be searched for, using their forename + """ + # Enter a forename + page.get_by_label("Forename").fill("Pentagram") + + # Press Tab (required after text input, to make the search button become active). + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject summary page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Screening Summary") + + +def test_search_screening_subject_by_dob(page: Page) -> None: + """ + Confirms a screening subject can be searched for, using their date of birth + """ + # Enter a date in the dob field + page.locator("#A_C_DOB_From").fill("11/01/1934") + + # Press Tab (required after text input, to make the search button become active). + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +def test_search_screening_subject_by_postcode(page: Page) -> None: + """ + Confirms a screening subject can be searched for, using their postcode + """ + # Enter a postcode + page.locator("#A_C_Postcode").fill("*") + + # Press Tab (required after text input, to make the search button become active). + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +def test_search_screening_subject_by_episode_closed_date(page: Page) -> None: + """ + Confirms a screening subject can be searched for, using their episode closed date + """ + # Enter an "episode closed date" + page.get_by_label("Episode Closed Date").fill("22/09/2020") + + # Press Tab (required after text input, to make the search button become active). + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + # Verify the results contain the date that was searched for + expect(page.locator("#displayRS")).to_contain_text("22/09/2020") + + +def test_search_criteria_clear_filters_button(page: Page) -> None: + """ + Confirms the 'clear filters' button on the search page works as expected + """ + # Enter number in NHS field and verify value + page.get_by_label("NHS Number").fill("34344554353") + expect(page.get_by_label("NHS Number")).to_have_value("34344554353") + + # Click clear filters button and verify field is empty + page.get_by_role("button", name="Clear Filters").click() + expect(page.get_by_label("NHS Number")).to_be_empty() + + +# Tests searching via the "Screening Status" drop down list +def test_search_screening_subject_by_status_call(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the screening status (call) + """ + # Select status from dropdown + ScreeningStatusSearchOptions(page).select_status_call() + + # Pressing Tab is required after text input, to make the search button become active. + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +def test_search_screening_subject_by_status_inactive(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the screening status (inactive) + """ + # Select status from dropdown + ScreeningStatusSearchOptions(page).select_status_inactive() + + # Pressing Tab is required after text input, to make the search button become active. + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +def test_search_screening_subject_by_status_opt_in(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the screening status (opt-in) + """ + # Select status from dropdown + ScreeningStatusSearchOptions(page).select_status_opt_in() + + # Pressing Tab is required after text input, to make the search button become active. + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +def test_search_screening_subject_by_status_recall(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the screening status (recall) + """ + # Select status from dropdown + ScreeningStatusSearchOptions(page).select_status_recall() + + # Pressing Tab is required after text input, to make the search button become active. + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +def test_search_screening_subject_by_status_self_referral(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the screening status (self-referral) + """ + # Select status from dropdown + ScreeningStatusSearchOptions(page).select_status_self_referral() + + # Pressing Tab is required after text input, to make the search button become active. + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +def test_search_screening_subject_by_status_surveillance(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the screening status (surveillance) + """ + # Select status from dropdown + ScreeningStatusSearchOptions(page).select_status_surveillance() + + # Pressing Tab is required after text input, to make the search button become active. + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +def test_search_screening_subject_by_status_seeking_further_data(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the screening status (seeking further data) + """ + # Select status from dropdown + ScreeningStatusSearchOptions(page).select_status_seeking_further_data() + + # Pressing Tab is required after text input, to make the search button become active. + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +def test_search_screening_subject_by_status_ceased(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the screening status (ceased) + """ + # Select status from dropdown + ScreeningStatusSearchOptions(page).select_status_ceased() + + # Pressing Tab is required after text input, to make the search button become active. + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +def test_search_screening_subject_by_status_bowel_scope(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the screening status (bowel scope) + """ + # Select status from dropdown + ScreeningStatusSearchOptions(page).select_status_bowel_scope() + + # Pressing Tab is required after text input, to make the search button become active. + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +def test_search_screening_subject_by_status_lynch_surveillance(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the screening status (lynch surveillance) + """ + # Select status from dropdown + ScreeningStatusSearchOptions(page).select_status_lynch_surveillance() + + # Pressing Tab is required after text input, to make the search button become active. + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +def test_search_screening_subject_by_status_lynch_self_referral(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the screening status (lynch self-referral) + """ + # Select status from dropdown + ScreeningStatusSearchOptions(page).select_status_lynch_self_referral() + + # Pressing Tab is required after text input, to make the search button become active. + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Screening Summary") + + +# Tests searching via the "Latest Episode Status" drop down list +def test_search_screening_subject_by_latest_episode_status_open_paused(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the latest episode status (open-paused) + """ + # Select status from dropdown + LatestEpisodeStatusSearchOptions(page).select_status_open_paused() + + # Pressing Tab is required after text input, to make the search button become active. + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +def test_search_screening_subject_by_latest_episode_status_closed(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the latest episode status (closed) + """ + # Select status from dropdown + LatestEpisodeStatusSearchOptions(page).select_status_closed() + + # Pressing Tab is required after text input, to make the search button become active. + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +def test_search_screening_subject_by_latest_episode_status_no_episode(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the latest episode status (no episode) + """ + # Select status from dropdown + LatestEpisodeStatusSearchOptions(page).select_status_no_episode() + + # Pressing Tab is required after text input, to make the search button become active. + page.keyboard.press("Tab") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +# Tests searching via the "Search Area" drop down list +def test_search_screening_subject_by_home_hub(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the search area (home hub) + """ + # Select screening status "recall" (searching by search area requires another search option to be selected) + ScreeningStatusSearchOptions(page).select_status_recall() + + # Select "whole database" option from dropdown + SearchAreaSearchOptions(page).select_search_area_home_hub() + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify search results are displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +def test_search_screening_subject_by_gp_practice(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the search area (gp practice) + """ + # Select screening status "call" (searching by search area requires another search option to be selected) + ScreeningStatusSearchOptions(page).select_status_call() + + # Select search area from dropdown + SearchAreaSearchOptions(page).select_search_area_gp_practice() + + # Enter GP practice code + page.get_by_label("Appropriate Code").fill("C81001") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify the subject search results page is displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + # Verify springs health centre is visible in search results + expect(page.locator("#displayRS")).to_contain_text("SPRINGS HEALTH CENTRE") + + +def test_search_screening_subject_by_ccg(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the search area (ccg) + """ + # Select screening status "call" (searching by search area requires another search option to be selected) + ScreeningStatusSearchOptions(page).select_status_call() + + # Select ccg option from dropdown + SearchAreaSearchOptions(page).select_search_area_ccg() + + # Enter CCG code + page.get_by_label("Appropriate Code").fill("Z1Z1Z") + + # Enter GP practice code + page.get_by_label("GP Practice in CCG").fill("C81001") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify search results are displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +def test_search_screening_subject_by_screening_centre(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the search area (screening centre) + """ + # Select screening status "call" (searching by search area requires another search option to be selected) + ScreeningStatusSearchOptions(page).select_status_call() + + # Select "screening centre" option from dropdown + SearchAreaSearchOptions(page).select_search_area_screening_centre() + + # Enter a screening centre code + page.get_by_label("Appropriate Code").fill("BCS001") + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify search results are displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") + + +def test_search_screening_subject_by_whole_database(page: Page) -> None: + """ + Confirms screening subjects can be searched for, using the search area (whole database) + """ + # Select screening status "recall" (searching by search area requires another search option to be selected) + ScreeningStatusSearchOptions(page).select_status_recall() + + # Select "whole database" option from dropdown + SearchAreaSearchOptions(page).select_search_area_whole_database() + + # Click search button + page.get_by_role("button", name="Search").click() + + # Verify search results are displayed + expect(page.locator("#ntshPageTitle")).to_contain_text("Subject Search Results") diff --git a/users.json b/users.json index 2fdbee1b..798c07b6 100644 --- a/users.json +++ b/users.json @@ -1,11 +1,16 @@ { - "_comment": "This file can be used to store data on users for your application, and then pulled through using the utils.user_tools UserTools utility. The documentation for this utility explains how this file is read.", - "Example User 1": { - "username": "EXAMPLE_USER1", - "roles": ["Example Role A"] - }, - "Example User 2": { - "username": "EXAMPLE_USER2", - "roles": ["Example Role B", "Example Role C"] - } + "_comment": "This file can be used to store data on users for your application, and then pulled through using the utils.user_tools UserTools utility. The documentation for this utility explains how this file is read.", + + "Hub Manager State Registered": { + "username": "BCSS401", + "roles": [ + "Hub Manager State Registered, Midlands and North West" + ] + }, + "Screening Centre Manager": { + "username": "BCSS118", + "roles": [ + "Screening Centre Manager for Wolverhampton, Midlands and North West" + ] + } } diff --git a/utils/user_tools.py b/utils/user_tools.py index 85f19f22..9ec9c79b 100644 --- a/utils/user_tools.py +++ b/utils/user_tools.py @@ -1,7 +1,11 @@ import json import logging +import os from pathlib import Path +from dotenv import load_dotenv +from playwright.sync_api import Page +from pages.cognito_login_page import CognitoLoginPage logger = logging.getLogger(__name__) USERS_FILE = Path(__file__).parent.parent / "users.json" @@ -12,6 +16,24 @@ class UserTools: A utility class for retrieving and doing common actions with users. """ + @staticmethod + def user_login(page: Page, username: str) -> None: + """ + Logs into the BCSS application as a specified user. + + Args: + page (playwright.sync_api.Page): The Playwright page object to interact with. + username (str): Enter a username that exists in the users.json file. + """ + # Load dotenv to enable retrieval of a password from .env file + load_dotenv() + # Go to base url + page.goto("/") + # Retrieve username from users.json + user_details = UserTools.retrieve_user(username) + # Login to bcss using retrieved username and a password stored in the .env file + CognitoLoginPage(page).login_as_user(user_details["username"], os.getenv("BCSS_PASS")) + @staticmethod def retrieve_user(user: str) -> dict: """