diff --git a/mavis/test/__init__.py b/mavis/test/__init__.py index 12f9999254f..3556dcf0051 100644 --- a/mavis/test/__init__.py +++ b/mavis/test/__init__.py @@ -56,7 +56,18 @@ schedule_session_and_get_consent_url, school_moves_page, schools, - sessions_page, + sessions_children_page, + sessions_consent_page, + sessions_edit_page, + sessions_overview_page, + sessions_patient_page, + sessions_patient_session_activity_page, + sessions_psd_page, + sessions_record_vaccinations_page, + sessions_register_page, + sessions_search_page, + sessions_triage_page, + sessions_vaccination_wizard_page, set_feature_flags, setup_session_and_batches_with_fixed_child, start_page, @@ -134,7 +145,18 @@ "schedule_session_and_get_consent_url", "school_moves_page", "schools", - "sessions_page", + "sessions_children_page", + "sessions_consent_page", + "sessions_edit_page", + "sessions_overview_page", + "sessions_patient_page", + "sessions_patient_session_activity_page", + "sessions_psd_page", + "sessions_record_vaccinations_page", + "sessions_register_page", + "sessions_search_page", + "sessions_triage_page", + "sessions_vaccination_wizard_page", "set_feature_flags", "setup_session_and_batches_with_fixed_child", "start_page", diff --git a/mavis/test/fixtures/__init__.py b/mavis/test/fixtures/__init__.py index c29463d4f33..e79662f4b42 100644 --- a/mavis/test/fixtures/__init__.py +++ b/mavis/test/fixtures/__init__.py @@ -63,7 +63,18 @@ reports_vaccinations_page, review_school_move_page, school_moves_page, - sessions_page, + sessions_children_page, + sessions_consent_page, + sessions_edit_page, + sessions_overview_page, + sessions_patient_page, + sessions_patient_session_activity_page, + sessions_psd_page, + sessions_record_vaccinations_page, + sessions_register_page, + sessions_search_page, + sessions_triage_page, + sessions_vaccination_wizard_page, start_page, team_page, unmatched_consent_responses_page, @@ -136,7 +147,18 @@ "schedule_session_and_get_consent_url", "school_moves_page", "schools", - "sessions_page", + "sessions_children_page", + "sessions_consent_page", + "sessions_edit_page", + "sessions_overview_page", + "sessions_patient_page", + "sessions_patient_session_activity_page", + "sessions_psd_page", + "sessions_record_vaccinations_page", + "sessions_register_page", + "sessions_search_page", + "sessions_triage_page", + "sessions_vaccination_wizard_page", "set_feature_flags", "setup_session_and_batches_with_fixed_child", "start_page", diff --git a/mavis/test/fixtures/helpers.py b/mavis/test/fixtures/helpers.py index 10957572e90..242008ac304 100644 --- a/mavis/test/fixtures/helpers.py +++ b/mavis/test/fixtures/helpers.py @@ -45,25 +45,25 @@ def schedule_session_and_get_consent_url( team, dashboard_page, log_in_page, - sessions_page, + sessions_edit_page, + sessions_search_page, + sessions_overview_page, ): def wrapper(school: School, *programmes: Programme): - try: - log_in_page.navigate() - log_in_page.log_in_and_choose_team_if_necessary(nurse, team) - dashboard_page.click_sessions() - sessions_page.ensure_session_scheduled_for_next_week( - school, programmes[0].group + log_in_page.navigate() + log_in_page.log_in_and_choose_team_if_necessary(nurse, team) + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group( + school, programmes[0].group + ) + if not sessions_overview_page.is_date_scheduled(get_offset_date(7)): + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_session( + offset_days=7, skip_weekends=False ) - url = sessions_page.get_online_consent_url(*programmes) - log_in_page.log_out() - yield url - finally: - log_in_page.navigate() - log_in_page.log_in_and_choose_team_if_necessary(nurse, team) - dashboard_page.click_sessions() - sessions_page.delete_all_sessions(school) - log_in_page.log_out() + url = sessions_overview_page.get_online_consent_url(*programmes) + log_in_page.log_out() + yield url return wrapper @@ -75,25 +75,25 @@ def schedule_mmr_session_and_get_consent_url( team, dashboard_page, log_in_page, - sessions_page, + sessions_edit_page, + sessions_search_page, + sessions_overview_page, ): def wrapper(school: School, *programmes: Programme): try: log_in_page.navigate() log_in_page.log_in_and_choose_team_if_necessary(nurse, team) dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, programmes[0].group) - sessions_page.schedule_a_valid_mmr_session() - url = sessions_page.get_online_consent_url(*programmes) + sessions_search_page.click_session_for_programme_group( + school, programmes[0].group + ) + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_mmr_session() + url = sessions_overview_page.get_online_consent_url(*programmes) log_in_page.log_out() yield url finally: log_in_page.log_out() - log_in_page.navigate() - log_in_page.log_in_and_choose_team_if_necessary(nurse, team) - dashboard_page.click_sessions() - sessions_page.delete_all_sessions(school) - log_in_page.log_out() return wrapper @@ -133,7 +133,9 @@ def upload_offline_vaccination( schools, dashboard_page, import_records_wizard_page, - sessions_page, + sessions_edit_page, + sessions_search_page, + sessions_overview_page, programmes_list_page, programme_children_page, programme_overview_page, @@ -161,44 +163,41 @@ def wrapper( msg = "Update upload_offline_vaccination to handle programme" raise ValueError(msg) - try: - dashboard_page.click_sessions() - sessions_page.ensure_session_scheduled_for_today( - school, - programme, + dashboard_page.click_mavis() + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group(school, programme.group) + if not sessions_overview_page.is_date_scheduled(get_offset_date(0)): + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_session( + offset_days=0, skip_weekends=False ) - sessions_page.click_import_class_lists() - import_records_wizard_page.import_class_list( - ClassFileMapping.FIXED_CHILD, - child.year_group, - programme.group, - ) - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, programme) - session_id = sessions_page.get_session_id_from_offline_excel() - dashboard_page.click_mavis() - dashboard_page.click_import_records() - imports_page.click_import_records() - import_records_wizard_page.navigate_to_vaccination_records_import() - import_records_wizard_page.upload_and_verify_output( - file_mapping=vaccs_file, - session_id=session_id, - programme_group=programme.group, - ) - dashboard_page.click_mavis() - dashboard_page.click_programmes() - programmes_list_page.click_programme_for_current_year(programme) - programme_overview_page.click_children_tab() - programme_children_page.search_for_child(child) - programme_children_page.click_child(child) - child_record_page.click_vaccination_details(programme) - yield - finally: - dashboard_page.navigate() - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.delete_all_sessions(school) + sessions_overview_page.click_import_class_lists() + import_records_wizard_page.import_class_list( + ClassFileMapping.FIXED_CHILD, + child.year_group, + programme.group, + ) + dashboard_page.click_mavis() + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group(school, programme) + session_id = sessions_overview_page.get_session_id_from_offline_excel() + dashboard_page.click_mavis() + dashboard_page.click_import_records() + imports_page.click_import_records() + import_records_wizard_page.navigate_to_vaccination_records_import() + import_records_wizard_page.upload_and_verify_output( + file_mapping=vaccs_file, + session_id=session_id, + programme_group=programme.group, + ) + dashboard_page.click_mavis() + dashboard_page.click_programmes() + programmes_list_page.click_programme_for_current_year(programme) + programme_overview_page.click_children_tab() + programme_children_page.search_for_child(child) + programme_children_page.click_child(child) + child_record_page.click_vaccination_details(programme) + yield return wrapper @@ -208,7 +207,8 @@ def setup_session_and_batches_with_fixed_child( add_vaccine_batch, schools, dashboard_page, - sessions_page, + sessions_search_page, + sessions_overview_page, import_records_wizard_page, children, log_in_page, @@ -229,8 +229,10 @@ def _setup(programme_group): } dashboard_page.click_mavis() dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, programme_group) - sessions_page.click_import_class_lists() + sessions_search_page.click_session_for_programme_group( + school, programme_group + ) + sessions_overview_page.click_import_class_lists() import_records_wizard_page.import_class_list( ClassFileMapping.FIXED_CHILD, child.year_group, diff --git a/mavis/test/fixtures/pages.py b/mavis/test/fixtures/pages.py index 90f73dea46b..2a6c59a5f31 100644 --- a/mavis/test/fixtures/pages.py +++ b/mavis/test/fixtures/pages.py @@ -34,7 +34,18 @@ ReportsVaccinationsPage, ReviewSchoolMovePage, SchoolMovesPage, - SessionsPage, + SessionsChildrenPage, + SessionsConsentPage, + SessionsEditPage, + SessionsOverviewPage, + SessionsPatientPage, + SessionsPatientSessionActivityPage, + SessionsPsdPage, + SessionsRecordVaccinationsPage, + SessionsRegisterPage, + SessionsSearchPage, + SessionsTriagePage, + SessionsVaccinationWizardPage, StartPage, TeamPage, UnmatchedConsentResponsesPage, @@ -193,8 +204,65 @@ def school_moves_page(page: Page) -> SchoolMovesPage: @pytest.fixture -def sessions_page(page: Page) -> SessionsPage: - return SessionsPage(page) +def sessions_psd_page(page: Page) -> SessionsPsdPage: + return SessionsPsdPage(page) + + +@pytest.fixture +def sessions_search_page(page: Page) -> SessionsSearchPage: + return SessionsSearchPage(page) + + +@pytest.fixture +def sessions_overview_page(page: Page) -> SessionsOverviewPage: + return SessionsOverviewPage(page) + + +@pytest.fixture +def sessions_edit_page(page: Page) -> SessionsEditPage: + return SessionsEditPage(page) + + +@pytest.fixture +def sessions_children_page(page: Page) -> SessionsChildrenPage: + return SessionsChildrenPage(page) + + +@pytest.fixture +def sessions_consent_page(page: Page) -> SessionsConsentPage: + return SessionsConsentPage(page) + + +@pytest.fixture +def sessions_triage_page(page: Page) -> SessionsTriagePage: + return SessionsTriagePage(page) + + +@pytest.fixture +def sessions_register_page(page: Page) -> SessionsRegisterPage: + return SessionsRegisterPage(page) + + +@pytest.fixture +def sessions_record_vaccinations_page(page: Page) -> SessionsRecordVaccinationsPage: + return SessionsRecordVaccinationsPage(page) + + +@pytest.fixture +def sessions_patient_page(page: Page) -> SessionsPatientPage: + return SessionsPatientPage(page) + + +@pytest.fixture +def sessions_patient_session_activity_page( + page: Page, +) -> SessionsPatientSessionActivityPage: + return SessionsPatientSessionActivityPage(page) + + +@pytest.fixture +def sessions_vaccination_wizard_page(page: Page) -> SessionsVaccinationWizardPage: + return SessionsVaccinationWizardPage(page) @pytest.fixture diff --git a/mavis/test/pages/__init__.py b/mavis/test/pages/__init__.py index d008abe8c60..6b2a292d5d0 100644 --- a/mavis/test/pages/__init__.py +++ b/mavis/test/pages/__init__.py @@ -27,7 +27,20 @@ ) from .reports import ReportsDownloadPage, ReportsVaccinationsPage from .school_moves import DownloadSchoolMovesPage, ReviewSchoolMovePage, SchoolMovesPage -from .sessions import SessionsPage +from .sessions import ( + SessionsChildrenPage, + SessionsConsentPage, + SessionsEditPage, + SessionsOverviewPage, + SessionsPatientPage, + SessionsPatientSessionActivityPage, + SessionsPsdPage, + SessionsRecordVaccinationsPage, + SessionsRegisterPage, + SessionsSearchPage, + SessionsTriagePage, + SessionsVaccinationWizardPage, +) from .start import StartPage from .team import TeamPage from .vaccination_record import EditVaccinationRecordPage, VaccinationRecordPage @@ -67,7 +80,18 @@ "ReportsVaccinationsPage", "ReviewSchoolMovePage", "SchoolMovesPage", - "SessionsPage", + "SessionsChildrenPage", + "SessionsConsentPage", + "SessionsEditPage", + "SessionsOverviewPage", + "SessionsPatientPage", + "SessionsPatientSessionActivityPage", + "SessionsPsdPage", + "SessionsRecordVaccinationsPage", + "SessionsRegisterPage", + "SessionsSearchPage", + "SessionsTriagePage", + "SessionsVaccinationWizardPage", "StartPage", "TeamPage", "UnmatchedConsentResponsesPage", diff --git a/mavis/test/pages/sessions.py b/mavis/test/pages/sessions.py index 4e9403f4c3a..4f35d682b49 100644 --- a/mavis/test/pages/sessions.py +++ b/mavis/test/pages/sessions.py @@ -1,8 +1,7 @@ import re import time -from datetime import datetime +from datetime import date, datetime from pathlib import Path -from zoneinfo import ZoneInfo import pandas as pd from playwright.sync_api import Locator, Page, expect @@ -20,172 +19,359 @@ ) from mavis.test.utils import ( MAVIS_NOTE_LENGTH_LIMIT, - get_current_datetime, get_current_datetime_compact, get_day_month_year_from_compact_date, + get_offset_date, get_offset_date_compact_format, reload_until_element_is_visible, ) -class SessionsPage: +class SearchBarMixin: def __init__( self, page: Page, ) -> None: self.page = page - - self.no_response_checkbox = self.page.get_by_role( - "checkbox", - name="No response", - ) + self.search_textbox = self.page.get_by_role("textbox", name="Search") + self.search_button = self.page.get_by_role("button", name="Search") self.update_results_button = self.page.get_by_role( "button", name="Update results", ) - self.consent_given_checkbox = self.page.get_by_role( - "checkbox", - name="Consent given", - exact=True, - ) - self.consent_given_for_injected_vaccine_checkbox = self.page.get_by_role( - "checkbox", - name="Consent given for gelatine-free injection", - ) - self.consent_given_for_nasal_spray_checkbox = self.page.get_by_role( - "checkbox", - name="Consent given for nasal spray", - ) - self.conflicting_consent_checkbox = self.page.get_by_role( + self.advanced_filters_link = page.get_by_text("Advanced filters") + self.archived_records_checkbox = self.page.get_by_role( "checkbox", - name="Conflicting consent", + name="Archived records", ) - self.import_class_lists_link = self.page.get_by_role( + @step("Search for {1}") + def search_for(self, name: str) -> None: + self.search_textbox.fill(name) + self.search_button.click() + + @step("Click on Update results") + def click_on_update_results(self) -> None: + self.update_results_button.click() + + def verify_search(self) -> None: + self.search_for("a very long string that won't match any names") + expect( + self.page.get_by_text("No children matching search criteria found"), + ).to_be_visible() + + def search_child(self, child: Child) -> None: + self.search_for(str(child)) + child_locator = self.page.get_by_role("link", name=str(child)) + reload_until_element_is_visible(self.page, child_locator) + child_locator.click() + + def search_child_that_should_not_exist(self, child: Child) -> None: + self.search_for(str(child)) + child_locator = self.page.get_by_role("link", name=str(child)) + expect(child_locator).not_to_be_visible() + + @step("Click Advanced filters") + def click_advanced_filters(self) -> None: + self.advanced_filters_link.click() + + @step("Check Archived records") + def check_archived_records_checkbox(self) -> None: + self.archived_records_checkbox.check() + + @step("Click on child {1}") + def click_child(self, child: Child) -> None: + with self.page.expect_navigation(): + self.page.get_by_role("heading", name=str(child)).get_by_role( + "link", + ).first.click() + + @step("Check box for year {1}") + def check_year_checkbox(self, year: int) -> None: + if year == 0: + self.page.get_by_role("checkbox", name="Reception").check() + else: + self.page.get_by_role("checkbox", name=f"Year {year}").check() + + @step("Uncheck box for year {1}") + def uncheck_year_checkbox(self, year: int) -> None: + if year == 0: + self.page.get_by_role("checkbox", name="Reception").uncheck() + else: + self.page.get_by_role("checkbox", name=f"Year {year}").uncheck() + + @step("Check note {2} appears in search for {1}") + def check_note_appears_in_search(self, child: Child, note: str) -> None: + heading = self.page.get_by_role("heading", name=str(child)) + next_element = heading.locator("xpath=following-sibling::*[1]") + expect(next_element.get_by_role("blockquote")).to_have_text(note) + + +class SessionsTabsMixin: + def __init__( + self, + page: Page, + ) -> None: + self.page = page + + def _select_tab(self, name: str) -> None: + link = self.page.get_by_label("Secondary menu").get_by_role("link", name=name) + if link.get_by_role("strong").is_visible(): + return + link.click() + link.get_by_role("strong").wait_for() + + @step("Click on Register tab") + def click_register_tab(self) -> None: + self._select_tab("Register") + + @step("Click on Overview tab") + def click_overview_tab(self) -> None: + self._select_tab("Overview") + + @step("Click on PSDs tab") + def click_psds_tab(self) -> None: + self._select_tab("PSDs") + + @step("Click on Record vaccinations") + def click_record_vaccinations_tab(self) -> None: + self._select_tab("Record vaccinations") + + @step("Click on Consent tab") + def click_consent_tab(self) -> None: + self._select_tab("Consent") + + @step("Click on Children tab") + def click_children_tab(self) -> None: + self._select_tab("Children") + + @step("Click on Triage tab") + def click_triage_tab(self) -> None: + self._select_tab("Triage") + + +class SessionsPsdPage(SearchBarMixin, SessionsTabsMixin): + def __init__(self, page: Page) -> None: + super().__init__(page) + + self.add_new_psds_link = self.page.get_by_role( "link", - name="Import class lists", + name="Add new PSDs", + ) + self.yes_add_psds_button = self.page.get_by_role( + "button", + name="Yes, add PSDs", ) - self.continue_button = self.page.get_by_role("button", name="Continue") - self.file_input = self.page.locator('input[type="file"]') - self.filter_name_textbox = self.page.get_by_role("textbox", name="Name") - self.update_triage_outcome_link = self.page.get_by_role( - "link", - name="Update triage outcome", + @step("Check {1} has PSD") + def check_child_has_psd(self, child: Child) -> None: + patient_card = self.page.locator( + f'div.nhsuk-card.app-card.app-card--compact:has(h4:has-text("{child!s}"))' ) - self.safe_to_vaccinate_radio = self.page.get_by_role( - "radio", - name="Yes, it’s safe to vaccinate", + reload_until_element_is_visible( + self.page, patient_card.get_by_text("PSD added") ) - self.save_triage_button = self.page.get_by_role("button", name="Save triage") - self.assess_gillick_competence_link = self.page.get_by_role( - "link", - name="Assess Gillick competence", + + @step("Check {1} does not have PSD") + def check_child_does_not_have_psd(self, child: Child) -> None: + patient_card = self.page.locator( + f'div.nhsuk-card.app-card.app-card--compact:has(h4:has-text("{child!s}"))' ) - self.edit_gillick_competence_link = self.page.get_by_role( - "link", - name="Edit Gillick competence", + reload_until_element_is_visible( + self.page, patient_card.get_by_text("PSD not added") ) - self.could_not_vaccinate_link = self.page.get_by_role( - "link", - name="Could not vaccinate", + + @step("Click Add new PSDs") + def click_add_new_psds(self) -> None: + self.add_new_psds_link.click() + + @step("Click Yes, add PSDs") + def click_yes_add_psds(self) -> None: + self.yes_add_psds_button.click() + + @step("Check PSD banner") + def verify_psd_banner_has_patients(self, number_of_patients: int) -> None: + psd_banner = self.page.get_by_text( + f"There are {number_of_patients} children with consent" ) - self.consent_refused_checkbox = self.page.get_by_role( - "checkbox", - name="Consent refused", + reload_until_element_is_visible(self.page, psd_banner) + + +class SessionsSearchPage(SearchBarMixin): + def __init__(self, page: Page) -> None: + super().__init__(page) + + @step("Click on {2} session at {1}") + def click_session_for_programme_group( + self, location: str, programme_group: str + ) -> None: + if programme_group != Programme.MMR: + for programme in Programme: + if programme.group == programme_group: + self.page.get_by_role("checkbox", name=str(programme)).check() + else: + self.page.get_by_role("checkbox", name=str(programme)).uncheck() + + self.search_textbox.fill(str(location)) + self.search_button.click() + + self.page.get_by_role("link", name=str(location)).first.click() + + ten_seconds_ms = 10000 + + expect(self.page.locator("h1", has_text=str(location))).to_be_visible( + timeout=ten_seconds_ms, ) - self.record_offline_link = self.page.get_by_role("link", name="Record offline") + + +class SessionsOverviewPage(SessionsTabsMixin): + def __init__(self, page: Page) -> None: + self.page = page self.schedule_sessions_link = self.page.get_by_role( "link", name="Schedule sessions", ) - self.add_session_dates_link = self.page.get_by_role( - "link", - name="Add session dates", - ) - self.day_textbox = self.page.get_by_role("textbox", name="Day") - self.month_textbox = self.page.get_by_role("textbox", name="Month") - self.year_textbox = self.page.get_by_role("textbox", name="Year") self.edit_session_link = self.page.get_by_role("link", name="Edit session") - self.close_session_link = self.page.get_by_role("link", name="Close session") - self.change_session_dates_link = self.page.get_by_role( + self.send_reminders_link = self.page.get_by_role( "link", - name="Change   session dates", + name="Send reminders", ) - self.delete_button = self.page.get_by_role("button", name="Delete") - self.back_link = self.page.get_by_role("link", name="Back", exact=True).first - self.save_changes_link = self.page.get_by_role("button", name="Save changes") - self.mark_as_invalid_link = self.page.get_by_role( + self.import_class_lists_link = self.page.get_by_role( "link", - name="Mark as invalid", + name="Import class lists", ) - self.mark_as_invalid_button = self.page.get_by_role( - "button", - name="Mark as invalid", + self.record_offline_link = self.page.get_by_role("link", name="Record offline") + self.review_no_consent_response_link = self.page.get_by_role( + "link", + name="with no response", ) - self.notes_textbox = self.page.get_by_role("textbox", name="Notes") - self.record_a_new_consent_response_button = self.page.get_by_role( + self.set_session_in_progress_button = self.page.get_by_role( "button", - name="Record a new consent response", + name="Set session in progress for today", ) - self.confirm_button = self.page.get_by_role("button", name="Confirm") - self.search_textbox = self.page.get_by_role("textbox", name="Search") - self.search_button = self.page.get_by_role("button", name="Search") - self.record_vaccinations_link = self.page.get_by_role( - "link", - name="Record vaccinations", + self.consent_refused_link = self.page.get_by_role( + "link", name="Consent refused" ) - self.ready_for_injection_radio = self.page.locator( - "#vaccinate-form-vaccine-method-injection-field", - ) - self.ready_for_nasal_spray_radio = self.page.locator( - "#vaccinate-form-vaccine-method-nasal-field", - ) - self.attending_button = self.page.get_by_role("button", name="Attending").first - self.vaccination_notes = self.page.get_by_role( - "textbox", - name="Notes (optional)", + + def get_total_for_category(self, category: str) -> int: + category_locator = self.page.locator( + ".nhsuk-card__heading.nhsuk-heading-xs", has_text=category ) + total_locator = category_locator.locator("xpath=following-sibling::*[1]") + return int(total_locator.inner_text()) - pre_screening = self.page.locator("section").filter( - has=page.get_by_role("heading", name="Pre-screening checks"), - ) + def get_all_totals(self, programme: Programme) -> dict[str, int]: + return { + category: self.get_total_for_category(category) + for category in programme.tally_categories + } - self.pre_screening_listitem = pre_screening.get_by_role("listitem") - self.pre_screening_checkbox = pre_screening.get_by_role("checkbox") - self.pre_screening_notes = pre_screening.get_by_role( - "textbox", - name="Pre-screening notes (optional)", - ) - self.review_no_consent_response_link = self.page.get_by_role( - "link", - name="with no response", - ) - self.consent_refusal_reason_other_radio = self.page.get_by_text("Other") - self.consent_refusal_details_textbox = self.page.get_by_role( - "textbox", - name="Give details", - ) - self.review_consent_refused_link = self.page.get_by_role( - "link", - name="Review   consent refused", - ) + def check_all_totals(self, totals: dict[str, int]) -> None: + self.click_overview_tab() + for category, expected_total in totals.items(): + actual_total = self.get_total_for_category(category) + assert actual_total == expected_total, ( + f"Expected {expected_total} for {category}, but got {actual_total}" + ) - self.note_textbox = self.page.get_by_role("textbox", name="Note") - self.add_a_note_span = self.page.get_by_text("Add a note") - self.save_note_button = self.page.get_by_role("button", name="Save note") - self.set_session_in_progress_button = self.page.get_by_role( - "button", - name="Set session in progress for today", + @step("Go to Edit session page") + def schedule_or_edit_session(self) -> None: + locator = self.schedule_sessions_link.or_(self.edit_session_link).first + # temporary wait to prevent page not found error + time.sleep(1) + locator.click() + + @step("Click on Schedule sessions") + def click_schedule_sessions(self) -> None: + self.schedule_sessions_link.click() + + @step("Click on Edit session") + def click_edit_session(self) -> None: + self.edit_session_link.click() + + def get_online_consent_url(self, *programmes: list[Programme]) -> str: + programme_names = [str(programme) for programme in programmes] + link_text = f"View the {' and '.join(programme_names)} online consent form" + return str(self.page.get_by_role("link", name=link_text).get_attribute("href")) + + @step("Click on Send reminders") + def click_send_reminders(self, school: School) -> None: + self.send_reminders_link.click() + expect( + self.page.get_by_role("heading", name="Manage consent reminders") + ).to_be_visible() + self.page.get_by_role( + "link", name=school.name + ).click() # Update when MAV-2048 is done + + @step("Click on Import class lists") + def click_import_class_lists(self) -> None: + self.import_class_lists_link.click() + + @step("Review child with no response") + def review_child_with_no_response(self) -> None: + self.review_no_consent_response_link.click() + + @step("Click on Set session in progress for today") + def click_set_session_in_progress_for_today(self) -> None: + self.set_session_in_progress_button.click() + + def get_session_id_from_offline_excel(self) -> str: + file_path = self.download_offline_recording_excel() + return get_session_id(file_path) + + @step("Click on Record offline") + def download_offline_recording_excel(self) -> Path: + _file_path = Path(f"working/excel_{get_current_datetime_compact()}.xlsx") + + with self.page.expect_download() as download_info: + self.record_offline_link.click() + download = download_info.value + download.save_as(_file_path) + + return _file_path + + @step("Download the offline recording excel and verify consent message pattern") + def verify_consent_message_in_excel(self) -> None: + _file_path = self.download_offline_recording_excel() + _data_frame = pd.read_excel(_file_path, sheet_name="Vaccinations", dtype=str) + _consent_details_pattern = ( + r"On \d{4}-\d{2}-\d{2} at \d{2}:\d{2} (GIVEN|REFUSED) by " + r"[A-Z][a-z]+(?: [A-Z][a-z]+)*" ) - vaccinations_card = page.get_by_role("table", name="Vaccination records") - self.vaccinations_card_row = vaccinations_card.get_by_role("row") - self.sessions_link = page.get_by_role("link", name="Sessions", exact=True).first - self.advanced_filters_link = page.get_by_text("Advanced filters") - self.archived_records_checkbox = self.page.get_by_role( - "checkbox", - name="Archived records", + invalid_found = _data_frame["CONSENT_DETAILS"].apply( + lambda x: pd.notna(x) and len(re.findall(_consent_details_pattern, x)) == 0 ) + # Raise error if any invalid entry is found + if invalid_found.any(): + msg = "CONSENT_DETAILS has entries in an invalid format." + raise ValueError(msg) + + @step("Click on Download the {1} consent form (PDF)") + def download_consent_form(self, programme: Programme) -> Path: + _file_path = Path(f"working/consent_{get_current_datetime_compact()}.pdf") + + with self.page.expect_download() as download_info: + self.page.get_by_role( + "link", name=f"Download the {programme} consent form (PDF)" + ).click() + download = download_info.value + download.save_as(_file_path) + + return _file_path + + def is_date_scheduled(self, date: datetime) -> bool: + formatted_display_date = date.strftime("%d %B %Y").replace(" 0", " ") + return self.page.get_by_text(formatted_display_date).is_visible() + + @step("Click Consent refused") + def click_consent_refused(self) -> None: + self.consent_refused_link.click() + + +class SessionsEditPage: + def __init__(self, page: Page) -> None: + self.page = page self.add_another_date_button = self.page.get_by_role( "button", name="Add another date", @@ -196,237 +382,95 @@ def __init__( self.change_programmes_link = self.page.get_by_role( "link", name="Change   programmes" ) - self.notes_length_error = ( - page.locator("div").filter(has_text="There is a problemEnter").nth(3) - ) - self.send_reminders_link = self.page.get_by_role( - "link", - name="Send reminders", - ) - self.add_new_psds_link = self.page.get_by_role( + self.change_session_dates_link = self.page.get_by_role( "link", - name="Add new PSDs", - ) - self.yes_add_psds_button = self.page.get_by_role( - "button", - name="Yes, add PSDs", + name="Change   session dates", ) - self.record_vaccinations_breadcrumb = self.page.get_by_role( + self.add_session_dates_link = self.page.get_by_role( "link", - name="Record vaccinations", + name="Add session dates", ) + self.save_changes_link = self.page.get_by_role("button", name="Save changes") + self.day_textbox = self.page.get_by_role("textbox", name="Day") + self.month_textbox = self.page.get_by_role("textbox", name="Month") + self.year_textbox = self.page.get_by_role("textbox", name="Year") + self.delete_button = self.page.get_by_role("button", name="Delete") self.keep_session_dates_button = self.page.get_by_role( "button", name="Keep session dates" ) - self.consent_refused_link = self.page.get_by_role( - "link", name="Consent refused" - ) - self.withdraw_consent_link = self.page.get_by_role( - "link", name="Withdraw consent" - ) - self.triage_safe_mmr_either_radio = self.page.get_by_role( - "radio", - name="Yes, it’s safe to vaccinate", - exact=True, - ) - self.triage_safe_mmr_gelatine_free_radio = self.page.get_by_role( - "radio", - name="Yes, it’s safe to vaccinate with the gelatine-free injection", - exact=True, - ) + self.back_link = self.page.get_by_role("link", name="Back", exact=True).first + self.continue_button = self.page.get_by_role("button", name="Continue") - def _get_day_month_year_with_day_of_week(self, date_to_format: str) -> str: - _parsed_date = datetime.strptime(date_to_format, "%Y%m%d").replace( - tzinfo=ZoneInfo("Europe/London") - ) - return _parsed_date.strftime("%A, %d %B %Y").replace(" 0", " ") + @step("Click on Continue") + def click_continue_button(self) -> None: + self.continue_button.click() - def _get_day_month_year(self, date_to_format: str) -> str: - _parsed_date = datetime.strptime(date_to_format, "%Y%m%d").replace( - tzinfo=ZoneInfo("Europe/London") - ) - return _parsed_date.strftime("%d %B %Y").replace(" 0", " ") + def __schedule_session(self, date: date) -> None: + compact_date = date.strftime("%Y%m%d") + self.add_or_change_session_dates() + if not self.session_date_already_scheduled(compact_date): + self.fill_date_fields(compact_date) + self.click_continue_button() - @step("Click on Overview tab") - def click_overview_tab(self) -> None: - self._select_tab("Overview") + @step("Go to Change session dates page") + def add_or_change_session_dates(self) -> None: + locator = self.add_session_dates_link.or_(self.change_session_dates_link).first + locator.click() - @step("Click on PSDs tab") - def click_psds_tab(self) -> None: - self._select_tab("PSDs") + def edit_a_session_to_today(self) -> None: + _future_date = get_offset_date_compact_format(offset_days=0) + self.__edit_session(date=_future_date) - @step("Click Consent refused") - def click_consent_refused(self) -> None: - self.consent_refused_link.click() + def __edit_session(self, date: str) -> None: + self.click_change_session_dates() + if not self.session_date_already_scheduled(date): + self.fill_date_fields(date, edit_existing_date=True) + self.click_continue_button() + self.click_save_changes() + expect( + self.page.locator("div") + .filter(has_text=re.compile(r"^Session datesNot provided$")) + .get_by_role("definition"), + ).not_to_be_visible() - @step("Expect Consent refused checkbox to be checked") - def expect_consent_refused_checkbox_to_be_checked(self) -> None: - expect(self.consent_refused_checkbox).to_be_checked() + def create_invalid_session(self) -> None: + _invalid_date = "20251332" + self.add_or_change_session_dates() + self.fill_date_fields(_invalid_date) + self.click_continue_button() + self.expect_alert_text("Enter a date") + self.click_back() - @step("Select No response") - def select_no_response(self) -> None: - self.no_response_checkbox.check() - self.update_results_button.click() + def create_session_in_previous_academic_year(self) -> None: + _previous_year_date = get_offset_date_compact_format(offset_days=-365) + self.add_or_change_session_dates() + self.fill_date_fields(_previous_year_date) + self.click_continue_button() + self.expect_alert_text("Enter a date on or after the start of the school year") + self.click_back() - @step("Select Consent given") - def select_consent_given(self) -> None: - self.consent_given_checkbox.check() - self.update_results_button.click() + def create_session_in_next_academic_year(self) -> None: + _next_year_date = get_offset_date_compact_format(offset_days=365) + self.add_or_change_session_dates() + self.fill_date_fields(_next_year_date) + self.click_continue_button() + self.expect_alert_text( + "Enter a date on or before the end of the current school year" + ) + self.click_back() - @step("Select Consent given for injected vaccine") - def select_consent_given_for_injected_vaccine(self) -> None: - self.consent_given_for_injected_vaccine_checkbox.check() - self.update_results_button.click() + @step("Click Back") + def click_back(self) -> None: + self.back_link.click() - @step("Select Consent given for nasal spray") - def select_consent_given_for_nasal_spray(self) -> None: - self.consent_given_for_nasal_spray_checkbox.check() - self.update_results_button.click() - - def select_consent_given_filters_for_programme( - self, - programme: Programme, - ) -> None: - self.page.wait_for_load_state() - if programme is not Programme.FLU: - for locator in [ - self.consent_given_for_injected_vaccine_checkbox, - self.consent_given_checkbox, - ]: - if locator.is_visible(): - locator.check() - else: - self.consent_given_for_injected_vaccine_checkbox.check() - self.consent_given_for_nasal_spray_checkbox.check() - self.update_results_button.click() - - @step("Select Conflicting consent") - def select_conflicting_consent(self) -> None: - self.conflicting_consent_checkbox.check() - self.update_results_button.click() - - @step("Select Consent refused") - def select_consent_refused(self) -> None: - self.consent_refused_checkbox.check() - self.update_results_button.click() - - def _select_tab(self, name: str) -> None: - link = self.page.get_by_label("Secondary menu").get_by_role("link", name=name) - if link.get_by_role("strong").is_visible(): - return - link.click() - link.get_by_role("strong").wait_for() - - @step("Click on {1} tab") - def click_programme_tab(self, programme: Programme) -> None: - self._select_tab(str(programme)) - - @step("Click on Register tab") - def click_register_tab(self) -> None: - self._select_tab("Register") - - @step("Click on Session activity and notes tab") - def click_session_activity_and_notes(self) -> None: - self._select_tab("Session activity and notes") - - @step("Click on {2} session at {1}") - def click_session_for_programme_group( - self, location: str, programme_group: str - ) -> None: - if programme_group != Programme.MMR: - for programme in Programme: - if programme.group == programme_group: - self.page.get_by_role("checkbox", name=str(programme)).check() - else: - self.page.get_by_role("checkbox", name=str(programme)).uncheck() - - self.search_textbox.fill(str(location)) - self.search_button.click() - - self.page.get_by_role("link", name=str(location)).first.click() - - ten_seconds_ms = 10000 - - expect(self.page.locator("h1", has_text=str(location))).to_be_visible( - timeout=ten_seconds_ms, - ) - - @step("Click on location radio {1}") - def check_location_radio(self, location: str) -> None: - self.page.get_by_role("radio", name=str(location)).check() - - @step("Click on Import class lists") - def click_import_class_lists(self) -> None: - self.import_class_lists_link.click() - - @step("Click on Continue") - def click_continue_button(self) -> None: - self.continue_button.click() - - @step("Upload file {1}") - def choose_file_child_records(self, file_path: str) -> None: - self.file_input.set_input_files(file_path) - - @step("Click on child {1}") - def click_child(self, child: Child) -> None: - with self.page.expect_navigation(): - self.page.get_by_role("heading", name=str(child)).get_by_role( - "link", - ).first.click() - - @step("Search and click on {1}") - def search_and_click_child(self, child: Child) -> None: - self.filter_name_textbox.fill(str(child)) - self.click_child(child) - - @step("Click on Update triage outcome") - def click_update_triage_outcome(self) -> None: - self.update_triage_outcome_link.click() - - @step("Click on Yes, it’s safe to vaccinate") - def select_yes_safe_to_vaccinate(self) -> None: - self.safe_to_vaccinate_radio.click() - - @step("Click on Save triage") - def click_save_triage(self) -> None: - self.save_triage_button.click() - - @step("Click on Consent tab") - def click_consent_tab(self) -> None: - self._select_tab("Consent") - - @step("Click on Children tab") - def click_children_tab(self) -> None: - self._select_tab("Children") - - @step("Click on Triage tab") - def click_triage_tab(self) -> None: - self._select_tab("Triage") - - @step("Click on Assess Gillick competence") - def click_assess_gillick_competence(self) -> None: - self.assess_gillick_competence_link.click() - - @step("Click on Edit Gillick competence") - def click_edit_gillick_competence(self) -> None: - self.edit_gillick_competence_link.click() - - @step("Click on Could not vaccinate") - def click_could_not_vaccinate(self) -> None: - self.could_not_vaccinate_link.click() - - @step("Click on Schedule sessions") - def click_schedule_sessions(self) -> None: - self.schedule_sessions_link.click() + @step("Click on Change patient specific direction") + def click_change_psd(self) -> None: + self.change_psd_link.click() @step("Click on Add session dates") def click_add_session_dates(self) -> None: self.add_session_dates_link.click() - @step("Click on Edit session") - def click_edit_session(self) -> None: - self.edit_session_link.click() - @step("Click on Change programmes") def click_change_programmes(self) -> None: self.change_programmes_link.click() @@ -442,337 +486,380 @@ def expect_session_to_have_programmes(self, programmes: list[Programme]) -> None def click_change_session_dates(self) -> None: self.change_session_dates_link.click() - @step("Review child with no response") - def review_child_with_no_response(self) -> None: - self.review_no_consent_response_link.click() - - @step("Click on session") - def click_session(self, location: str, programme: Programme) -> None: - row = self.page.locator("tr").filter( - has=self.page.locator("strong", has_text=str(programme)), - ) - row.locator("a", has_text=location).click() - - @step("Click Back") - def click_back(self) -> None: - self.back_link.click() - @step("Click Save changes") def click_save_changes(self) -> None: self.save_changes_link.click() - @step("Click on Delete") - def click_delete(self) -> None: - self.delete_button.click() + @step("Fill date fields with {1}") + def fill_date_fields(self, date: str, *, edit_existing_date: bool = False) -> None: + day, month, year = get_day_month_year_from_compact_date(date) - @step("Click on Mark as invalid") - def click_mark_as_invalid_link(self) -> None: - self.mark_as_invalid_link.click() + if ( + not self.day_textbox.first.is_visible() + or self.day_textbox.first.input_value() != "" + ): + self.click_add_another_date() - @step("Click on Mark as invalid") - def click_mark_as_invalid_button(self) -> None: - self.mark_as_invalid_button.click() + if edit_existing_date: + self.day_textbox.first.fill(str(day)) + self.month_textbox.first.fill(str(month)) + self.year_textbox.first.fill(str(year)) + else: + self.day_textbox.last.fill(str(day)) + self.month_textbox.last.fill(str(month)) + self.year_textbox.last.fill(str(year)) - @step("Click on Update results") - def click_on_update_results(self) -> None: - self.update_results_button.click() + def session_date_already_scheduled(self, date: str) -> bool: + day, month, year = get_day_month_year_from_compact_date(date) - @step("Fill notes") - def fill_notes(self, notes: str) -> None: - self.notes_textbox.fill(notes) + for i in range(len(self.day_textbox.all())): + if ( + self.day_textbox.nth(i).input_value() == str(day) + and self.month_textbox.nth(i).input_value() == str(month) + and self.year_textbox.nth(i).input_value() == str(year) + ): + return True - @step("Click on Record a new consent response") - def click_record_a_new_consent_response(self) -> None: - # temporary wait before clicking the button to prevent errors - time.sleep(1) - self.record_a_new_consent_response_button.click() + return False + + @step("Add another date") + def click_add_another_date(self) -> None: + self.add_another_date_button.click() - @step("Click {1} radio button") - def click_parent_radio_button(self, name: str) -> None: - self.page.get_by_role("radio", name=name).check() + def _get_day_month_year_with_day_of_week(self, date_to_format: date) -> str: + return date_to_format.strftime("%A, %d %B %Y").replace(" 0", " ") - def navigate_to_gillick_competence( - self, child: Child, programme: Programme - ) -> None: - self.click_consent_tab() - self.click_child(child) - self.click_programme_tab(programme) - self.click_assess_gillick_competence() - - def navigate_to_consent_response(self, child: Child, programme: Programme) -> None: - self.click_child(child) - self.click_programme_tab(programme) - self.click_record_a_new_consent_response() - - def navigate_to_update_triage_outcome( - self, child: Child, programme: Programme + def schedule_a_valid_session( + self, + offset_days: int = 7, + *, + skip_weekends: bool = True, ) -> None: - self.click_child(child) - self.click_programme_tab(programme) - self.click_update_triage_outcome() - - @step("Click on Confirm") - def click_confirm_button(self) -> None: - self.confirm_button.click() + _future_date = get_offset_date( + offset_days=offset_days, skip_weekends=skip_weekends + ) + self.__schedule_session(date=_future_date) - @step("Check box for year {1}") - def check_year_checkbox(self, year: int) -> None: - if year == 0: - self.page.get_by_role("checkbox", name="Reception").check() - else: - self.page.get_by_role("checkbox", name=f"Year {year}").check() + if self.keep_session_dates_button.is_visible(): + self.click_keep_session_dates() # MAV-2066 - @step("Uncheck box for year {1}") - def uncheck_year_checkbox(self, year: int) -> None: - if year == 0: - self.page.get_by_role("checkbox", name="Reception").uncheck() - else: - self.page.get_by_role("checkbox", name=f"Year {year}").uncheck() + self.expect_details( + "Session dates", + self._get_day_month_year_with_day_of_week(date_to_format=_future_date), + ) + self.click_save_changes() - @step("Click Advanced filters") - def click_advanced_filters(self) -> None: - self.advanced_filters_link.click() + def schedule_a_valid_mmr_session( + self, + offset_days: int = 7, + *, + skip_weekends: bool = True, + ) -> None: + _future_date = get_offset_date( + offset_days=offset_days, skip_weekends=skip_weekends + ) + self.click_change_programmes() + self.add_programme(Programme.MMR) + self.click_continue_button() + self.add_or_change_session_dates() + if not self.session_date_already_scheduled(_future_date.strftime("%Y%m%d")): + self.fill_date_fields(_future_date.strftime("%Y%m%d")) + self.click_continue_button() - @step("Check Archived records") - def check_archived_records_checkbox(self) -> None: - self.archived_records_checkbox.check() + if self.keep_session_dates_button.is_visible(): + self.click_keep_session_dates() # MAV-2066 - @step("Click on Record vaccinations") - def click_record_vaccinations_tab(self) -> None: - self._select_tab("Record vaccinations") + self.expect_details( + "Session dates", + self._get_day_month_year_with_day_of_week(date_to_format=_future_date), + ) + self.click_save_changes() - @step("Confirm pre-screening checks are true") - def confirm_pre_screening_checks( - self, - programme: Programme, - consent_option: ConsentOption = ConsentOption.INJECTION, - ) -> None: - for check in programme.pre_screening_checks(consent_option): - locator = self.pre_screening_listitem.get_by_text(check) - expect(locator).to_be_visible() - self.page.wait_for_load_state() - self.pre_screening_checkbox.check() - - @step("Triage MMR patient") - def triage_mmr_patient(self, child: Child, consent_option: ConsentOption) -> None: - self.click_triage_tab() - self.search_child(child) - self.click_programme_tab(Programme.MMR) - if consent_option is ConsentOption.MMR_EITHER: - self.triage_safe_mmr_either_radio.check() - else: - self.triage_safe_mmr_gelatine_free_radio.check() - self.save_triage_button.click() + @step("Click Keep session dates") + def click_keep_session_dates(self) -> None: + self.keep_session_dates_button.click() - @step("Click on Yes") - def select_identity_confirmed_by_child(self, child: Child) -> None: + @step("Answer whether PSD should be enabled with {1}") + def answer_whether_psd_should_be_enabled(self, answer: str) -> None: self.page.get_by_role( "group", - name=f"Has {child.first_name} confirmed their identity?", - ).get_by_label("Yes").check() + name=( + "Can healthcare assistants administer the flu nasal spray vaccine" + " using a patient specific direction (PSD)?" + ), + ).get_by_label(answer).check() - @step("Click on Yes") - def select_ready_for_vaccination( + def expect_alert_text(self, text: str) -> None: + expect(self.page.get_by_role("alert")).to_contain_text(text) + + def expect_details(self, key: str, value: str) -> None: + detail_key = self.page.locator( + ".nhsuk-summary-list__key", + has_text=re.compile(f"^{key}$"), + ).first + detail_value = detail_key.locator("xpath=following-sibling::*[1]") + + expect(detail_value).to_contain_text(value) + + +class SessionsChildrenPage(SearchBarMixin, SessionsTabsMixin): + def __init__(self, page: Page) -> None: + super().__init__(page) + + +class SessionsConsentPage(SearchBarMixin, SessionsTabsMixin): + def __init__(self, page: Page) -> None: + super().__init__(page) + self.no_response_checkbox = self.page.get_by_role( + "checkbox", + name="No response", + ) + self.consent_given_checkbox = self.page.get_by_role( + "checkbox", + name="Consent given", + exact=True, + ) + self.consent_given_for_injected_vaccine_checkbox = self.page.get_by_role( + "checkbox", + name="Consent given for gelatine-free injection", + ) + self.consent_given_for_nasal_spray_checkbox = self.page.get_by_role( + "checkbox", + name="Consent given for nasal spray", + ) + self.conflicting_consent_checkbox = self.page.get_by_role( + "checkbox", + name="Conflicting consent", + ) + self.consent_refused_checkbox = self.page.get_by_role( + "checkbox", + name="Consent refused", + ) + + def verify_child_shows_correct_flu_consent_method( self, - consent_option: ConsentOption = ConsentOption.INJECTION, + child: Child, + option: ConsentOption, ) -> None: - if consent_option is ConsentOption.INJECTION: - self.ready_for_injection_radio.check() + flu_consent_section = self.get_flu_consent_status_locator_from_search(child) + + expect(flu_consent_section).to_contain_text("Consent given") + if option is ConsentOption.INJECTION: + method_locator = flu_consent_section.get_by_text("injection") else: - self.ready_for_nasal_spray_radio.check() + method_locator = flu_consent_section.get_by_text("nasal spray") - @step("Select vaccination site {1}") - def select_delivery_site(self, site: DeliverySite) -> None: - self.page.get_by_role("radio", name=str(site)).check() + reload_until_element_is_visible(self.page, method_locator) - @step("Click on Attending") - def click_on_attending(self) -> None: - self.attending_button.click() + def get_flu_consent_status_locator_from_search(self, child: Child) -> Locator: + patient_card = self.page.locator( + f'div.nhsuk-card.app-card.app-card--compact:has(h4:has-text("{child!s}"))', + ) + flu_consent_section = patient_card.locator("p:has-text('Flu')") + reload_until_element_is_visible(self.page, flu_consent_section) - @step("Click on Add a note") - def click_add_a_note(self) -> None: - self.add_a_note_span.click() + return flu_consent_section - @step("Fill note textbox with {1}") - def fill_note_textbox(self, note: str) -> None: - self.note_textbox.fill(note) + @step("Expect Consent refused checkbox to be checked") + def expect_consent_refused_checkbox_to_be_checked(self) -> None: + expect(self.consent_refused_checkbox).to_be_checked() - @step("Click on Save note") - def click_save_note(self) -> None: - self.save_note_button.click() + @step("Select No response") + def select_no_response(self) -> None: + self.no_response_checkbox.check() + self.update_results_button.click() - @step("Check that notes appear in order") - def check_notes_appear_in_order(self, notes: list[str]) -> None: - for i, note in enumerate(notes): - expect(self.page.get_by_role("blockquote").nth(i)).to_have_text(note) + @step("Select Consent given") + def select_consent_given(self) -> None: + self.consent_given_checkbox.check() + self.update_results_button.click() - @step("Check note {2} appears in search for {1}") - def check_note_appears_in_search(self, child: Child, note: str) -> None: - heading = self.page.get_by_role("heading", name=str(child)) - next_element = heading.locator("xpath=following-sibling::*[1]") - expect(next_element.get_by_role("blockquote")).to_have_text(note) + @step("Select Consent given for injected vaccine") + def select_consent_given_for_injected_vaccine(self) -> None: + self.consent_given_for_injected_vaccine_checkbox.check() + self.update_results_button.click() - def add_note(self, note: str) -> None: - self.click_add_a_note() - self.fill_note_textbox(note) - with self.page.expect_navigation(): - self.click_save_note() + @step("Select Consent given for nasal spray") + def select_consent_given_for_nasal_spray(self) -> None: + self.consent_given_for_nasal_spray_checkbox.check() + self.update_results_button.click() - self.expect_alert_text("Note added") - reload_until_element_is_visible(self.page, self.page.get_by_text(note)) + def select_consent_given_filters_for_programme( + self, + programme: Programme, + ) -> None: + self.page.wait_for_load_state() + if programme is not Programme.FLU: + for locator in [ + self.consent_given_for_injected_vaccine_checkbox, + self.consent_given_checkbox, + ]: + if locator.is_visible(): + locator.check() + else: + self.consent_given_for_injected_vaccine_checkbox.check() + self.consent_given_for_nasal_spray_checkbox.check() + self.update_results_button.click() - @step("Click on Set session in progress for today") - def click_set_session_in_progress_for_today(self) -> None: - self.set_session_in_progress_button.click() + @step("Select Conflicting consent") + def select_conflicting_consent(self) -> None: + self.conflicting_consent_checkbox.check() + self.update_results_button.click() - @step("Search for {1}") - def search_for(self, name: str) -> None: - self.search_textbox.fill(name) - self.search_button.click() + @step("Select Consent refused") + def select_consent_refused(self) -> None: + self.consent_refused_checkbox.check() + self.update_results_button.click() - @step("Fill date fields with {1}") - def fill_date_fields(self, date: str, *, edit_existing_date: bool = False) -> None: - day, month, year = get_day_month_year_from_compact_date(date) - if ( - not self.day_textbox.first.is_visible() - or self.day_textbox.first.input_value() != "" - ): - self.click_add_another_date() +class SessionsTriagePage(SearchBarMixin, SessionsTabsMixin): + def __init__(self, page: Page) -> None: + super().__init__(page) - if edit_existing_date: - self.day_textbox.first.fill(str(day)) - self.month_textbox.first.fill(str(month)) - self.year_textbox.first.fill(str(year)) - else: - self.day_textbox.last.fill(str(day)) - self.month_textbox.last.fill(str(month)) - self.year_textbox.last.fill(str(year)) - def session_date_already_scheduled(self, date: str) -> bool: - day, month, year = get_day_month_year_from_compact_date(date) +class SessionsRegisterPage(SearchBarMixin, SessionsTabsMixin): + def __init__(self, page: Page) -> None: + super().__init__(page) + self.attending_button = self.page.get_by_role("button", name="Attending").first - for i in range(len(self.day_textbox.all())): - if ( - self.day_textbox.nth(i).input_value() == str(day) - and self.month_textbox.nth(i).input_value() == str(month) - and self.year_textbox.nth(i).input_value() == str(year) - ): - return True + def register_child_as_attending(self, child: Child) -> None: + self.click_register_tab() + self.search_for(str(child)) + reload_until_element_is_visible( + self.page, self.page.get_by_role("link", name=str(child)).first + ) + self.click_on_attending() - return False + @step("Click on Attending") + def click_on_attending(self) -> None: + self.attending_button.click() - @step("Add another date") - def click_add_another_date(self) -> None: - self.add_another_date_button.click() - @step("Click on Record offline") - def download_offline_recording_excel(self) -> Path: - _file_path = Path(f"working/excel_{get_current_datetime_compact()}.xlsx") +class SessionsRecordVaccinationsPage(SearchBarMixin, SessionsTabsMixin): + def __init__(self, page: Page) -> None: + super().__init__(page) - with self.page.expect_download() as download_info: - self.record_offline_link.click() - download = download_info.value - download.save_as(_file_path) - return _file_path +class SessionsPatientPage: + def __init__(self, page: Page) -> None: + self.page = page + self.update_triage_outcome_link = self.page.get_by_role( + "link", + name="Update triage outcome", + ) + self.safe_to_vaccinate_radio = self.page.get_by_role( + "radio", + name="Yes, it’s safe to vaccinate", + ) + self.save_triage_button = self.page.get_by_role("button", name="Save triage") + self.assess_gillick_competence_link = self.page.get_by_role( + "link", + name="Assess Gillick competence", + ) + self.edit_gillick_competence_link = self.page.get_by_role( + "link", + name="Edit Gillick competence", + ) + self.could_not_vaccinate_link = self.page.get_by_role( + "link", + name="Could not vaccinate", + ) + self.mark_as_invalid_link = self.page.get_by_role( + "link", + name="Mark as invalid", + ) + self.mark_as_invalid_button = self.page.get_by_role( + "button", + name="Mark as invalid", + ) + self.notes_textbox = self.page.get_by_role("textbox", name="Notes") + self.record_a_new_consent_response_button = self.page.get_by_role( + "button", + name="Record a new consent response", + ) + self.ready_for_injection_radio = self.page.locator( + "#vaccinate-form-vaccine-method-injection-field", + ) + self.ready_for_nasal_spray_radio = self.page.locator( + "#vaccinate-form-vaccine-method-nasal-field", + ) + pre_screening = self.page.locator("section").filter( + has=page.get_by_role("heading", name="Pre-screening checks"), + ) - @step("Download the offline recording excel and verify consent message pattern") - def verify_consent_message_in_excel(self) -> None: - _file_path = self.download_offline_recording_excel() - _data_frame = pd.read_excel(_file_path, sheet_name="Vaccinations", dtype=str) - _consent_details_pattern = ( - r"On \d{4}-\d{2}-\d{2} at \d{2}:\d{2} (GIVEN|REFUSED) by " - r"[A-Z][a-z]+(?: [A-Z][a-z]+)*" + self.pre_screening_listitem = pre_screening.get_by_role("listitem") + self.pre_screening_checkbox = pre_screening.get_by_role("checkbox") + self.pre_screening_notes = pre_screening.get_by_role( + "textbox", + name="Pre-screening notes (optional)", ) - invalid_found = _data_frame["CONSENT_DETAILS"].apply( - lambda x: pd.notna(x) and len(re.findall(_consent_details_pattern, x)) == 0 + vaccinations_card = page.get_by_role("table", name="Vaccination records") + self.vaccinations_card_row = vaccinations_card.get_by_role("row") + self.withdraw_consent_link = self.page.get_by_role( + "link", name="Withdraw consent" + ) + self.triage_safe_mmr_either_radio = self.page.get_by_role( + "radio", + name="Yes, it’s safe to vaccinate", + exact=True, + ) + self.triage_safe_mmr_gelatine_free_radio = self.page.get_by_role( + "radio", + name="Yes, it’s safe to vaccinate with the gelatine-free injection", + exact=True, + ) + self.record_vaccinations_breadcrumb = self.page.get_by_role( + "link", + name="Record vaccinations", + ) + self.back_link = self.page.get_by_role("link", name="Back", exact=True).first + self.continue_button = self.page.get_by_role("button", name="Continue") + self.notes_length_error = ( + page.locator("div").filter(has_text="There is a problemEnter").nth(3) ) - # Raise error if any invalid entry is found - if invalid_found.any(): - msg = "CONSENT_DETAILS has entries in an invalid format." - raise ValueError(msg) - - @step("Click on Download the {1} consent form (PDF)") - def download_consent_form(self, programme: Programme) -> Path: - _file_path = Path(f"working/consent_{get_current_datetime_compact()}.pdf") - - with self.page.expect_download() as download_info: - self.page.get_by_role( - "link", name=f"Download the {programme} consent form (PDF)" - ).click() - download = download_info.value - download.save_as(_file_path) - - return _file_path - - def expect_consent_refused_text(self, parent: Parent) -> None: - expect( - self.page.get_by_text(f"{parent.relationship} refused to give consent."), - ).to_be_visible() - - def check_session_activity_entry(self, text: str) -> None: - expect(self.page.get_by_role("heading", name=text).first).to_be_visible() - def expect_conflicting_consent_text(self) -> None: - expect( - self.page.get_by_text( - "You can only vaccinate if all respondents give consent.", - ), - ).to_be_visible() + def _select_tab(self, name: str) -> None: + link = self.page.get_by_label("Secondary menu").get_by_role("link", name=name) + if link.get_by_role("strong").is_visible(): + return + link.click() + link.get_by_role("strong").wait_for() - def expect_consent_status(self, programme: Programme, status: str) -> None: - expect(self.page.get_by_text(f"{programme}: {status}")).to_be_visible() + @step("Click on {1} tab") + def click_programme_tab(self, programme: Programme) -> None: + self._select_tab(str(programme)) - def expect_child_safe_to_vaccinate(self, child: Child) -> None: - expect( - self.page.get_by_text( - f"NURSE, Nurse decided that {child!s} is safe to vaccinate.", - ), - ).to_be_visible() + @step("Click on Update triage outcome") + def click_update_triage_outcome(self) -> None: + self.update_triage_outcome_link.click() - def get_session_id_from_offline_excel(self) -> str: - file_path = self.download_offline_recording_excel() - return get_session_id(file_path) + @step("Click on Yes, it’s safe to vaccinate") + def select_yes_safe_to_vaccinate(self) -> None: + self.safe_to_vaccinate_radio.click() - @step("Click Sessions") - def click_sessions(self) -> None: - self.sessions_link.click() + @step("Click on Save triage") + def click_save_triage(self) -> None: + self.save_triage_button.click() - def __schedule_session(self, date: str) -> None: - self.schedule_or_edit_session() - self.add_or_change_session_dates() - if not self.session_date_already_scheduled(date): - self.fill_date_fields(date) - self.click_continue_button() + @step("Click on Assess Gillick competence") + def click_assess_gillick_competence(self) -> None: + self.assess_gillick_competence_link.click() - @step("Go to Edit session page") - def schedule_or_edit_session(self) -> None: - locator = self.schedule_sessions_link.or_(self.edit_session_link).first - # temporary wait to prevent page not found error - time.sleep(1) - locator.click() + @step("Click on Edit Gillick competence") + def click_edit_gillick_competence(self) -> None: + self.edit_gillick_competence_link.click() - @step("Go to Change session dates page") - def add_or_change_session_dates(self) -> None: - locator = self.add_session_dates_link.or_(self.change_session_dates_link).first - locator.click() + @step("Click on Could not vaccinate") + def click_could_not_vaccinate(self) -> None: + self.could_not_vaccinate_link.click() - def __edit_session(self, date: str) -> None: - self.click_edit_session() - self.click_change_session_dates() - if not self.session_date_already_scheduled(date): - self.fill_date_fields(date, edit_existing_date=True) - self.click_continue_button() - self.click_save_changes() - expect( - self.page.locator("div") - .filter(has_text=re.compile(r"^Session datesNot provided$")) - .get_by_role("definition"), - ).not_to_be_visible() + @step("Click on Mark as invalid") + def click_mark_as_invalid_link(self) -> None: + self.mark_as_invalid_link.click() - def verify_triage_updated_for_child(self) -> None: - self.expect_alert_text("Triage outcome updated") + @step("Click on Mark as invalid") + def click_mark_as_invalid_button(self) -> None: + self.mark_as_invalid_button.click() def invalidate_parent_refusal(self, parent: Parent) -> None: invalidation_notes = "Invalidation notes." @@ -787,6 +874,18 @@ def invalidate_parent_refusal(self, parent: Parent) -> None: self.expect_details("Response", "Invalid") expect(self.page.get_by_text("No requests have been sent.")).to_be_visible() + @step("Click Back") + def click_back(self) -> None: + self.back_link.click() + + @step("Click on Continue") + def click_continue_button(self) -> None: + self.continue_button.click() + + @step("Fill notes") + def fill_notes(self, notes: str) -> None: + self.notes_textbox.fill(notes) + def expect_details(self, key: str, value: str) -> None: detail_key = self.page.locator( ".nhsuk-summary-list__key", @@ -796,194 +895,101 @@ def expect_details(self, key: str, value: str) -> None: expect(detail_value).to_contain_text(value) - def ensure_session_scheduled_for_today( + @step("Click on Yes") + def select_identity_confirmed_by_child(self, child: Child) -> None: + self.page.get_by_role( + "group", + name=f"Has {child.first_name} confirmed their identity?", + ).get_by_label("Yes").check() + + @step("Click on Yes") + def select_ready_for_vaccination( self, - location: str, - programme_group: str, + consent_option: ConsentOption = ConsentOption.INJECTION, ) -> None: - self.ensure_session_scheduled_in_n_days( - location=location, - programme_group=programme_group, - offset_days=0, - ) + if consent_option is ConsentOption.INJECTION: + self.ready_for_injection_radio.check() + else: + self.ready_for_nasal_spray_radio.check() - def ensure_session_scheduled_for_next_week( - self, location: str, programme_group: str - ) -> None: - self.ensure_session_scheduled_in_n_days( - location=location, - programme_group=programme_group, - offset_days=7, - ) + @step("Select vaccination site {1}") + def select_delivery_site(self, site: DeliverySite) -> None: + self.page.get_by_role("radio", name=str(site)).check() - def ensure_session_scheduled_in_n_days( - self, location: str, programme_group: str, offset_days: int - ) -> None: - self.click_session_for_programme_group(location, programme_group) - future_date = get_offset_date_compact_format(offset_days=offset_days) - if not self.page.get_by_text( - self._get_day_month_year(date_to_format=future_date), - ).is_visible(): - self.schedule_a_valid_session(offset_days=offset_days, skip_weekends=False) + @step("Click on Record a new consent response") + def click_record_a_new_consent_response(self) -> None: + # temporary wait before clicking the button to prevent errors + time.sleep(1) + self.record_a_new_consent_response_button.click() - def schedule_a_valid_session( - self, - offset_days: int = 7, - *, - skip_weekends: bool = True, - ) -> None: - _future_date = get_offset_date_compact_format( - offset_days=offset_days, skip_weekends=skip_weekends - ) - self.__schedule_session(date=_future_date) + @step("Go back to Record Vaccinations") + def click_back_to_record_vaccinations(self) -> None: + self.record_vaccinations_breadcrumb.click() - if self.keep_session_dates_button.is_visible(): - self.click_keep_session_dates() # MAV-2066 + @step("Click response from {1}") + def click_response_from_parent(self, parent: Parent) -> None: + self.page.get_by_role("link", name=parent.full_name).click() - self.expect_details( - "Session dates", - self._get_day_month_year_with_day_of_week(date_to_format=_future_date), - ) - self.click_save_changes() + def click_withdraw_consent(self) -> None: + self.withdraw_consent_link.click() - def schedule_a_valid_mmr_session( + @step("Confirm pre-screening checks are true") + def confirm_pre_screening_checks( self, - offset_days: int = 7, - *, - skip_weekends: bool = True, + programme: Programme, + consent_option: ConsentOption = ConsentOption.INJECTION, ) -> None: - _future_date = get_offset_date_compact_format( - offset_days=offset_days, skip_weekends=skip_weekends - ) - self.schedule_or_edit_session() - self.click_change_programmes() - self.add_programme(Programme.MMR) - self.click_continue_button() - self.add_or_change_session_dates() - if not self.session_date_already_scheduled(_future_date): - self.fill_date_fields(_future_date) - self.click_continue_button() - - if self.keep_session_dates_button.is_visible(): - self.click_keep_session_dates() # MAV-2066 - - self.expect_details( - "Session dates", - self._get_day_month_year_with_day_of_week(date_to_format=_future_date), - ) - self.click_save_changes() - - @step("Click Keep session dates") - def click_keep_session_dates(self) -> None: - self.keep_session_dates_button.click() - - def is_catch_up(self, programme: Programme, year_group: int) -> bool: - if programme is Programme.MMR: - return True - if programme is Programme.FLU: - return False - - return year_group != programme.year_groups[0] - - def edit_a_session_to_today(self, location: str, programme_group: str) -> None: - _future_date = get_offset_date_compact_format(offset_days=0) - self.click_session_for_programme_group(location, programme_group) - self.__edit_session(date=_future_date) - - def delete_all_sessions(self, school: School) -> None: - sessions_with_dates = ( - self.page.locator("div.nhsuk-card__content.app-card__content") - .filter(has_text=str(school)) - .filter(has_text="Sessions scheduled") - .filter(has_not_text="No sessions scheduled") - ) - for programme in Programme: - self.page.get_by_role("checkbox", name=str(programme)).uncheck() - - self.search_textbox.clear() - self.search_button.click() - - for session in sessions_with_dates.all(): - session.click() - self.click_edit_session() - self.click_change_session_dates() - - for button in self.delete_button.all(): - button.click() - self.page.wait_for_load_state() - - self.click_back() - self.click_save_changes() - self.click_sessions() - - def create_invalid_session(self, location: str, programme_group: str) -> None: - _invalid_date = "20251332" - self.click_session_for_programme_group(location, programme_group) - self.__schedule_session(_invalid_date) - self.expect_alert_text("Enter a date") - self.click_back() - - def create_session_in_previous_academic_year(self) -> None: - _previous_year_date = get_offset_date_compact_format(offset_days=-365) - self.add_or_change_session_dates() - if not self.session_date_already_scheduled(_previous_year_date): - self.fill_date_fields(_previous_year_date) - self.click_continue_button() - self.expect_alert_text("Enter a date on or after the start of the school year") - self.click_back() - - def create_session_in_next_academic_year(self) -> None: - _next_year_date = get_offset_date_compact_format(offset_days=365) - self.add_or_change_session_dates() - if not self.session_date_already_scheduled(_next_year_date): - self.fill_date_fields(_next_year_date) - self.click_continue_button() - self.expect_alert_text( - "Enter a date on or before the end of the current school year" - ) - self.click_back() - - def get_online_consent_url(self, *programmes: list[Programme]) -> str: - programme_names = [str(programme) for programme in programmes] - link_text = f"View the {' and '.join(programme_names)} online consent form" - return str(self.page.get_by_role("link", name=link_text).get_attribute("href")) + for check in programme.pre_screening_checks(consent_option): + locator = self.pre_screening_listitem.get_by_text(check) + expect(locator).to_be_visible() + self.page.wait_for_load_state() + self.pre_screening_checkbox.check() - def register_child_as_attending(self, child: Child) -> None: - self.click_register_tab() - self.search_for(str(child)) - reload_until_element_is_visible( - self.page, self.page.get_by_role("link", name=str(child)).first - ) - self.click_on_attending() + def expect_conflicting_consent_text(self) -> None: + expect( + self.page.get_by_text( + "You can only vaccinate if all respondents give consent.", + ), + ).to_be_visible() - def verify_search(self) -> None: - self.click_consent_tab() - self.search_for("a very long string that won't match any names") + def expect_consent_status(self, programme: Programme, status: str) -> None: + expect(self.page.get_by_text(f"{programme}: {status}")).to_be_visible() + + def expect_child_safe_to_vaccinate(self, child: Child) -> None: expect( - self.page.get_by_text("No children matching search criteria found"), + self.page.get_by_text( + f"NURSE, Nurse decided that {child!s} is safe to vaccinate.", + ), ).to_be_visible() - def search_child(self, child: Child) -> None: - self.search_for(str(child)) - child_locator = self.page.get_by_role("link", name=str(child)) - reload_until_element_is_visible(self.page, child_locator) - child_locator.click() + @step("Click on {1} vaccination details") + def click_vaccination_details(self, school: School) -> None: + with self.page.expect_navigation(): + self.vaccinations_card_row.filter(has_text=str(school)).get_by_role( + "link", + ).click() - def search_child_that_should_not_exist(self, child: Child) -> None: - self.search_for(str(child)) - child_locator = self.page.get_by_role("link", name=str(child)) - expect(child_locator).not_to_be_visible() + def go_back_to_session_for_school(self, school: School) -> None: + self.page.get_by_role("link", name=school.name).click() + expect(self.page.get_by_role("heading", name=school.name).first).to_be_visible() - def record_vaccination_for_child( - self, - vaccination_record: VaccinationRecord, - notes: str = "", - *, - at_school: bool = True, - psd_option: bool = False, - ) -> datetime: - self.click_record_vaccinations_tab() - self.search_child(vaccination_record.child) + def verify_triage_updated_for_child(self) -> None: + self.expect_alert_text("Triage outcome updated") + + def expect_alert_text(self, text: str) -> None: + expect(self.page.get_by_role("alert")).to_contain_text(text) + + @step("Triage MMR patient") + def triage_mmr_patient(self, consent_option: ConsentOption) -> None: + if consent_option is ConsentOption.MMR_EITHER: + self.triage_safe_mmr_either_radio.check() + else: + self.triage_safe_mmr_gelatine_free_radio.check() + self.save_triage_button.click() + + def set_up_vaccination( + self, vaccination_record: VaccinationRecord, notes: str = "" + ) -> None: self.click_programme_tab(vaccination_record.programme) self.confirm_pre_screening_checks( @@ -1003,158 +1009,122 @@ def record_vaccination_for_child( self.pre_screening_notes.fill("Prescreening notes") self.click_continue_button() - self.choose_batch(vaccination_record.batch_name) - - if at_school: # only skips MAV-854 - if psd_option: - self.expect_details("Protocol", "Patient Specific Direction") - else: - self.expect_details("Protocol", "Patient Group Direction (PGD)") - - self.vaccination_notes.fill(notes) - self.click_confirm_button() - - if len(notes) > MAVIS_NOTE_LENGTH_LIMIT: - expect(self.notes_length_error).to_be_visible() - self.vaccination_notes.fill("Confirmation notes") - self.click_confirm_button() - - self.expect_alert_text( - f"Vaccination outcome recorded for {vaccination_record.programme}" - ) - return get_current_datetime() - - @step("Choose batch {1}") - def choose_batch(self, batch_name: str) -> None: - self.page.get_by_role("radio", name=batch_name).check() - self.click_continue_button() + @step("Click on Session activity and notes tab") + def click_session_activity_and_notes(self) -> None: + self._select_tab("Session activity and notes") - def expect_alert_text(self, text: str) -> None: - expect(self.page.get_by_role("alert")).to_contain_text(text) - def verify_child_shows_correct_flu_consent_method( - self, - child: Child, - option: ConsentOption, - ) -> None: - flu_consent_section = self.get_flu_consent_status_locator_from_search(child) +class SessionsPatientSessionActivityPage: + def __init__(self, page: Page) -> None: + self.page = page + self.note_textbox = self.page.get_by_role("textbox", name="Note") + self.add_a_note_span = self.page.get_by_text("Add a note") + self.save_note_button = self.page.get_by_role("button", name="Save note") - expect(flu_consent_section).to_contain_text("Consent given") - if option is ConsentOption.INJECTION: - method_locator = flu_consent_section.get_by_text("injection") - else: - method_locator = flu_consent_section.get_by_text("nasal spray") + @step("Click on Add a note") + def click_add_a_note(self) -> None: + self.add_a_note_span.click() - reload_until_element_is_visible(self.page, method_locator) + @step("Fill note textbox with {1}") + def fill_note_textbox(self, note: str) -> None: + self.note_textbox.fill(note) - def get_flu_consent_status_locator_from_search(self, child: Child) -> Locator: - patient_card = self.page.locator( - f'div.nhsuk-card.app-card.app-card--compact:has(h4:has-text("{child!s}"))', - ) - flu_consent_section = patient_card.locator("p:has-text('Flu')") - reload_until_element_is_visible(self.page, flu_consent_section) + @step("Click on Save note") + def click_save_note(self) -> None: + self.save_note_button.click() - return flu_consent_section + @step("Check that notes appear in order") + def check_notes_appear_in_order(self, notes: list[str]) -> None: + for i, note in enumerate(notes): + expect(self.page.get_by_role("blockquote").nth(i)).to_have_text(note) - @step("Click on {1} vaccination details") - def click_vaccination_details(self, school: School) -> None: + def add_note(self, note: str) -> None: + self.click_add_a_note() + self.fill_note_textbox(note) with self.page.expect_navigation(): - self.vaccinations_card_row.filter(has_text=str(school)).get_by_role( - "link", - ).click() + self.click_save_note() - def expect_text_to_not_be_visible(self, text: str) -> None: - expect(self.page.get_by_text(text)).not_to_be_visible() + self.expect_alert_text("Note added") + reload_until_element_is_visible(self.page, self.page.get_by_text(note)) - @step("Click on Change patient specific direction") - def click_change_psd(self) -> None: - self.change_psd_link.click() + def check_session_activity_entry(self, text: str) -> None: + expect(self.page.get_by_role("heading", name=text).first).to_be_visible() - @step("Answer whether PSD should be enabled with {1}") - def answer_whether_psd_should_be_enabled(self, answer: str) -> None: - self.page.get_by_role( - "group", - name=( - "Can healthcare assistants administer the flu nasal spray vaccine" - " using a patient specific direction (PSD)?" - ), - ).get_by_label(answer).check() + def expect_alert_text(self, text: str) -> None: + expect(self.page.get_by_role("alert")).to_contain_text(text) - @step("Check {1} has PSD") - def check_child_has_psd(self, child: Child) -> None: - patient_card = self.page.locator( - f'div.nhsuk-card.app-card.app-card--compact:has(h4:has-text("{child!s}"))' - ) - reload_until_element_is_visible( - self.page, patient_card.get_by_text("PSD added") - ) - @step("Check {1} does not have PSD") - def check_child_does_not_have_psd(self, child: Child) -> None: - patient_card = self.page.locator( - f'div.nhsuk-card.app-card.app-card--compact:has(h4:has-text("{child!s}"))' +class SessionsVaccinationWizardPage: + def __init__(self, page: Page) -> None: + self.page = page + self.confirm_button = self.page.get_by_role("button", name="Confirm") + self.vaccination_notes = self.page.get_by_role( + "textbox", + name="Notes (optional)", ) - reload_until_element_is_visible( - self.page, patient_card.get_by_text("PSD not added") + self.notes_length_error = ( + page.locator("div").filter(has_text="There is a problemEnter").nth(3) ) + self.continue_button = self.page.get_by_role("button", name="Continue") - @step("Click on Send reminders") - def click_send_reminders(self, school: School) -> None: - self.send_reminders_link.click() + @step("Click on Confirm") + def click_confirm_button(self) -> None: + self.confirm_button.click() + + @step("Click on location radio {1}") + def check_location_radio(self, location: str) -> None: + self.page.get_by_role("radio", name=str(location)).check() + + @step("Click on Continue") + def click_continue_button(self) -> None: + self.continue_button.click() + + def expect_consent_refused_text(self, parent: Parent) -> None: expect( - self.page.get_by_role("heading", name="Manage consent reminders") + self.page.get_by_text(f"{parent.relationship} refused to give consent."), ).to_be_visible() - self.page.get_by_role( - "link", name=school.name - ).click() # Update when MAV-2048 is done - - @step("Click Add new PSDs") - def click_add_new_psds(self) -> None: - self.add_new_psds_link.click() - @step("Click Yes, add PSDs") - def click_yes_add_psds(self) -> None: - self.yes_add_psds_button.click() + @step("Choose batch {1}") + def choose_batch(self, batch_name: str) -> None: + self.page.get_by_role("radio", name=batch_name).check() + self.click_continue_button() - @step("Check PSD banner") - def verify_psd_banner_has_patients(self, number_of_patients: int) -> None: - psd_banner = self.page.get_by_text( - f"There are {number_of_patients} children with consent" - ) - reload_until_element_is_visible(self.page, psd_banner) + def expect_details(self, key: str, value: str) -> None: + detail_key = self.page.locator( + ".nhsuk-summary-list__key", + has_text=re.compile(f"^{key}$"), + ).first + detail_value = detail_key.locator("xpath=following-sibling::*[1]") - @step("Go back to Record Vaccinations") - def click_back_to_record_vaccinations(self) -> None: - self.record_vaccinations_breadcrumb.click() + expect(detail_value).to_contain_text(value) - def get_total_for_category(self, category: str) -> int: - category_locator = self.page.locator( - ".nhsuk-card__heading.nhsuk-heading-xs", has_text=category - ) - total_locator = category_locator.locator("xpath=following-sibling::*[1]") - return int(total_locator.inner_text()) + def expect_alert_text(self, text: str) -> None: + expect(self.page.get_by_role("alert")).to_contain_text(text) - def get_all_totals(self, programme: Programme) -> dict[str, int]: - return { - category: self.get_total_for_category(category) - for category in programme.tally_categories - } + def record_vaccination( + self, + vaccination_record: VaccinationRecord, + *, + notes: str = "", + at_school: bool = True, + psd_option: bool = False, + ) -> None: + self.choose_batch(vaccination_record.batch_name) - def check_all_totals(self, totals: dict[str, int]) -> None: - self.click_overview_tab() - for category, expected_total in totals.items(): - actual_total = self.get_total_for_category(category) - assert actual_total == expected_total, ( - f"Expected {expected_total} for {category}, but got {actual_total}" - ) + if at_school: # only skips MAV-854 + if psd_option: + self.expect_details("Protocol", "Patient Specific Direction") + else: + self.expect_details("Protocol", "Patient Group Direction (PGD)") - @step("Click response from {1}") - def click_response_from_parent(self, parent: Parent) -> None: - self.page.get_by_role("link", name=parent.full_name).click() + self.vaccination_notes.fill(notes) + self.click_confirm_button() - def click_withdraw_consent(self) -> None: - self.withdraw_consent_link.click() + if len(notes) > MAVIS_NOTE_LENGTH_LIMIT: + expect(self.notes_length_error).to_be_visible() + self.vaccination_notes.fill("Confirmation notes") + self.click_confirm_button() - def go_back_to_session_for_school(self, school: School) -> None: - self.page.get_by_role("link", name=school.name).click() - expect(self.page.get_by_role("heading", name=school.name).first).to_be_visible() + self.expect_alert_text( + f"Vaccination outcome recorded for {vaccination_record.programme}" + ) diff --git a/mavis/test/pages/vaccination_record.py b/mavis/test/pages/vaccination_record.py index 99b972b7506..4c5f7450303 100644 --- a/mavis/test/pages/vaccination_record.py +++ b/mavis/test/pages/vaccination_record.py @@ -89,3 +89,6 @@ def click_change_outcome(self) -> None: @step("Click on Continue") def click_continue(self) -> None: self.continue_button.click() + + def expect_text_to_not_be_visible(self, text: str) -> None: + expect(self.page.get_by_text(text)).not_to_be_visible() diff --git a/tests/test_children.py b/tests/test_children.py index 6cb3b0a68f4..4aee23010e0 100644 --- a/tests/test_children.py +++ b/tests/test_children.py @@ -3,6 +3,7 @@ from mavis.test.annotations import issue from mavis.test.data import ClassFileMapping, CohortsFileMapping, VaccsFileMapping from mavis.test.models import Programme +from mavis.test.utils import get_offset_date pytestmark = pytest.mark.children @@ -12,7 +13,9 @@ def setup_children_session( log_in_as_nurse, schools, dashboard_page, - sessions_page, + sessions_edit_page, + sessions_overview_page, + sessions_search_page, import_records_wizard_page, year_groups, ): @@ -20,20 +23,21 @@ def _setup(class_list_file): school = schools[Programme.HPV][0] year_group = year_groups[Programme.HPV] - try: - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.ensure_session_scheduled_for_today(school, Programme.HPV) - sessions_page.click_import_class_lists() - import_records_wizard_page.import_class_list(class_list_file, year_group) - dashboard_page.click_mavis() - dashboard_page.click_children() - yield - finally: - dashboard_page.navigate() - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.delete_all_sessions(school) + dashboard_page.click_mavis() + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group( + school, Programme.HPV.group + ) + if not sessions_overview_page.is_date_scheduled(get_offset_date(0)): + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_session( + offset_days=0, skip_weekends=False + ) + sessions_overview_page.click_import_class_lists() + import_records_wizard_page.import_class_list(class_list_file, year_group) + dashboard_page.click_mavis() + dashboard_page.click_children() + yield return _setup @@ -57,46 +61,44 @@ def setup_mav_853( programmes_list_page, programme_overview_page, programme_children_page, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_edit_page, year_groups, imports_page, ): school = schools[Programme.HPV][0] year_group = year_groups[Programme.HPV] - try: - dashboard_page.click_sessions() - sessions_page.ensure_session_scheduled_for_today(school, Programme.HPV) - sessions_page.click_import_class_lists() - import_records_wizard_page.import_class_list( - ClassFileMapping.RANDOM_CHILD, year_group - ) - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, Programme.HPV) - session_id = sessions_page.get_session_id_from_offline_excel() - dashboard_page.click_mavis() - dashboard_page.click_programmes() - programmes_list_page.click_programme_for_current_year(Programme.HPV) - programme_overview_page.click_children_tab() - programme_children_page.click_import_child_records() - import_records_wizard_page.import_class_list(CohortsFileMapping.FIXED_CHILD) - dashboard_page.click_mavis() - dashboard_page.click_import_records() - imports_page.click_import_records() - import_records_wizard_page.navigate_to_vaccination_records_import() - import_records_wizard_page.upload_and_verify_output( - file_mapping=VaccsFileMapping.NOT_GIVEN, - session_id=session_id, - ) - dashboard_page.click_mavis() - dashboard_page.click_children() - yield - finally: - dashboard_page.navigate() - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.delete_all_sessions(school) + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group(school, Programme.HPV.group) + if not sessions_overview_page.is_date_scheduled(get_offset_date(0)): + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_session(offset_days=0, skip_weekends=False) + sessions_overview_page.click_import_class_lists() + import_records_wizard_page.import_class_list( + ClassFileMapping.RANDOM_CHILD, year_group + ) + dashboard_page.click_mavis() + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) + session_id = sessions_overview_page.get_session_id_from_offline_excel() + dashboard_page.click_mavis() + dashboard_page.click_programmes() + programmes_list_page.click_programme_for_current_year(Programme.HPV) + programme_overview_page.click_children_tab() + programme_children_page.click_import_child_records() + import_records_wizard_page.import_class_list(CohortsFileMapping.FIXED_CHILD) + dashboard_page.click_mavis() + dashboard_page.click_import_records() + imports_page.click_import_records() + import_records_wizard_page.navigate_to_vaccination_records_import() + import_records_wizard_page.upload_and_verify_output( + file_mapping=VaccsFileMapping.NOT_GIVEN, + session_id=session_id, + ) + dashboard_page.click_mavis() + dashboard_page.click_children() @issue("MAV-853") diff --git a/tests/test_e2e_doubles.py b/tests/test_e2e_doubles.py index 468d7a11b6d..78b7d2289f6 100644 --- a/tests/test_e2e_doubles.py +++ b/tests/test_e2e_doubles.py @@ -23,7 +23,12 @@ def test_recording_doubles_vaccination_e2e( doubles_consent_url, setup_session_for_doubles, online_consent_page, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_register_page, + sessions_record_vaccinations_page, + sessions_patient_page, + sessions_vaccination_wizard_page, start_page, schools, children, @@ -81,16 +86,22 @@ def test_recording_doubles_vaccination_e2e( log_in_page.log_in_and_choose_team_if_necessary(nurse, team) dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(schools[0], "doubles") - sessions_page.click_set_session_in_progress_for_today() - sessions_page.register_child_as_attending(str(child)) - sessions_page.record_vaccination_for_child( - VaccinationRecord(child, Programme.MENACWY, menquadfi_batch_name) - ) - sessions_page.click_back_to_record_vaccinations() - sessions_page.record_vaccination_for_child( - VaccinationRecord(child, Programme.TD_IPV, revaxis_batch_name) + sessions_search_page.click_session_for_programme_group(schools[0], "doubles") + sessions_overview_page.click_set_session_in_progress_for_today() + sessions_overview_page.click_register_tab() + sessions_register_page.register_child_as_attending(str(child)) + sessions_register_page.click_record_vaccinations_tab() + sessions_record_vaccinations_page.search_child(child) + + vaccination_record = VaccinationRecord( + child, Programme.MENACWY, menquadfi_batch_name ) + sessions_patient_page.set_up_vaccination(vaccination_record) + sessions_vaccination_wizard_page.record_vaccination(vaccination_record) + + vaccination_record = VaccinationRecord(child, Programme.TD_IPV, revaxis_batch_name) + sessions_patient_page.set_up_vaccination(vaccination_record) + sessions_vaccination_wizard_page.record_vaccination(vaccination_record) dashboard_page.navigate() log_in_page.log_out() diff --git a/tests/test_e2e_flu.py b/tests/test_e2e_flu.py index e69fc0703fd..5c70719bea5 100644 --- a/tests/test_e2e_flu.py +++ b/tests/test_e2e_flu.py @@ -32,7 +32,12 @@ def test_recording_flu_vaccination_e2e( flu_consent_url, setup_session_for_flu, online_consent_page, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_register_page, + sessions_patient_page, + sessions_vaccination_wizard_page, + sessions_record_vaccinations_page, children_search_page, child_record_page, vaccination_record_page, @@ -44,6 +49,7 @@ def test_recording_flu_vaccination_e2e( nurse, team, consent_option, + edit_vaccination_record_page, ): """ Test: End-to-end test for recording a flu vaccination for a child. @@ -90,12 +96,18 @@ def test_recording_flu_vaccination_e2e( log_in_page.log_in_and_choose_team_if_necessary(nurse, team) dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(schools[0], Programme.FLU) - sessions_page.click_set_session_in_progress_for_today() - sessions_page.register_child_as_attending(str(child)) - sessions_page.record_vaccination_for_child( - VaccinationRecord(child, Programme.FLU, batch_name, consent_option) + sessions_search_page.click_session_for_programme_group(schools[0], Programme.FLU) + sessions_overview_page.click_set_session_in_progress_for_today() + sessions_overview_page.click_register_tab() + sessions_register_page.register_child_as_attending(str(child)) + sessions_register_page.click_record_vaccinations_tab() + sessions_record_vaccinations_page.search_child(child) + + vaccination_record = VaccinationRecord( + child, Programme.FLU, batch_name, consent_option ) + sessions_patient_page.set_up_vaccination(vaccination_record) + sessions_vaccination_wizard_page.record_vaccination(vaccination_record) # MAV-1831 dashboard_page.navigate() @@ -104,7 +116,9 @@ def test_recording_flu_vaccination_e2e( children_search_page.click_record_for_child(child) child_record_page.click_vaccination_details(schools[0]) vaccination_record_page.click_edit_vaccination_record() - sessions_page.expect_text_to_not_be_visible("Incorrect vaccine given") + edit_vaccination_record_page.expect_text_to_not_be_visible( + "Incorrect vaccine given" + ) dashboard_page.navigate() log_in_page.log_out() diff --git a/tests/test_e2e_hpv.py b/tests/test_e2e_hpv.py index df14b9593ff..0efb6a8be8a 100644 --- a/tests/test_e2e_hpv.py +++ b/tests/test_e2e_hpv.py @@ -21,7 +21,12 @@ def test_recording_hpv_vaccination_e2e( hpv_consent_url, setup_session_for_hpv, online_consent_page, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_register_page, + sessions_patient_page, + sessions_vaccination_wizard_page, + sessions_record_vaccinations_page, start_page, schools, children, @@ -69,12 +74,16 @@ def test_recording_hpv_vaccination_e2e( log_in_page.log_in_and_choose_team_if_necessary(nurse, team) dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(schools[0], Programme.HPV) - sessions_page.click_set_session_in_progress_for_today() - sessions_page.register_child_as_attending(str(child)) - sessions_page.record_vaccination_for_child( - VaccinationRecord(child, Programme.HPV, gardasil_9_batch_name) - ) + sessions_search_page.click_session_for_programme_group(schools[0], Programme.HPV) + sessions_overview_page.click_set_session_in_progress_for_today() + sessions_overview_page.click_register_tab() + sessions_register_page.register_child_as_attending(str(child)) + sessions_register_page.click_record_vaccinations_tab() + sessions_record_vaccinations_page.search_child(child) + + vaccination_record = VaccinationRecord(child, Programme.HPV, gardasil_9_batch_name) + sessions_patient_page.set_up_vaccination(vaccination_record) + sessions_vaccination_wizard_page.record_vaccination(vaccination_record) dashboard_page.navigate() log_in_page.log_out() diff --git a/tests/test_e2e_mmr.py b/tests/test_e2e_mmr.py index 079fed17391..7bc19cc827c 100644 --- a/tests/test_e2e_mmr.py +++ b/tests/test_e2e_mmr.py @@ -22,7 +22,13 @@ def test_recording_mmr_vaccination_e2e_with_triage( url_with_mmr_session_scheduled, setup_session_for_mmr, online_consent_page, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_register_page, + sessions_triage_page, + sessions_patient_page, + sessions_vaccination_wizard_page, + sessions_record_vaccinations_page, start_page, schools, children, @@ -73,17 +79,25 @@ def test_recording_mmr_vaccination_e2e_with_triage( dashboard_page.click_sessions() # Triage step added for MMR - sessions_page.click_session_for_programme_group(schools[0], Programme.MMR) - sessions_page.triage_mmr_patient(child, ConsentOption.MMR_EITHER) + sessions_search_page.click_session_for_programme_group(schools[0], Programme.MMR) + sessions_overview_page.click_triage_tab() + sessions_triage_page.search_child(child) + sessions_patient_page.click_programme_tab(Programme.MMR) + sessions_patient_page.triage_mmr_patient(ConsentOption.MMR_EITHER) dashboard_page.navigate() dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(schools[0], Programme.MMR) - sessions_page.click_set_session_in_progress_for_today() - sessions_page.register_child_as_attending(str(child)) - sessions_page.record_vaccination_for_child( - VaccinationRecord(child, Programme.MMR, mmr_batch_name) - ) + sessions_search_page.click_session_for_programme_group(schools[0], Programme.MMR) + sessions_overview_page.click_set_session_in_progress_for_today() + + sessions_overview_page.click_register_tab() + sessions_register_page.register_child_as_attending(str(child)) + sessions_register_page.click_record_vaccinations_tab() + sessions_record_vaccinations_page.search_child(child) + + vaccination_record = VaccinationRecord(child, Programme.MMR, mmr_batch_name) + sessions_patient_page.set_up_vaccination(vaccination_record) + sessions_vaccination_wizard_page.record_vaccination(vaccination_record) dashboard_page.navigate() log_in_page.log_out() @@ -93,7 +107,12 @@ def test_verify_child_cannot_be_vaccinated_twice_for_mmr_on_same_day( url_with_mmr_session_scheduled, setup_session_for_mmr, online_consent_page, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_register_page, + sessions_record_vaccinations_page, + sessions_patient_page, + sessions_vaccination_wizard_page, start_page, schools, children, @@ -146,19 +165,23 @@ def test_verify_child_cannot_be_vaccinated_twice_for_mmr_on_same_day( dashboard_page.click_sessions() # Dose 1 flow - sessions_page.click_session_for_programme_group(schools[0], Programme.MMR) - sessions_page.click_set_session_in_progress_for_today() - sessions_page.register_child_as_attending(str(child)) - sessions_page.record_vaccination_for_child( - VaccinationRecord(child, Programme.MMR, mmr_batch_name) - ) + sessions_search_page.click_session_for_programme_group(schools[0], Programme.MMR) + sessions_overview_page.click_set_session_in_progress_for_today() + sessions_overview_page.click_register_tab() + sessions_register_page.register_child_as_attending(str(child)) + sessions_register_page.click_record_vaccinations_tab() + sessions_record_vaccinations_page.search_child(child) + + vaccination_record = VaccinationRecord(child, Programme.MMR, mmr_batch_name) + sessions_patient_page.set_up_vaccination(vaccination_record) + sessions_vaccination_wizard_page.record_vaccination(vaccination_record) # Attempt to record second dose on the same day dashboard_page.navigate() dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(schools[0], Programme.MMR) - sessions_page.click_record_vaccinations_tab() - sessions_page.search_child_that_should_not_exist(child) + sessions_search_page.click_session_for_programme_group(schools[0], Programme.MMR) + sessions_overview_page.click_record_vaccinations_tab() + sessions_record_vaccinations_page.search_child_that_should_not_exist(child) dashboard_page.navigate() log_in_page.log_out() @@ -168,7 +191,13 @@ def test_recording_mmr_vaccination_e2e_with_imported_dose_one( url_with_mmr_session_scheduled, setup_session_for_mmr, online_consent_page, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_register_page, + sessions_triage_page, + sessions_patient_page, + sessions_vaccination_wizard_page, + sessions_record_vaccinations_page, start_page, schools, children, @@ -227,17 +256,24 @@ def test_recording_mmr_vaccination_e2e_with_imported_dose_one( dashboard_page.click_sessions() # Triage step added for MMR - sessions_page.click_session_for_programme_group(schools[0], Programme.MMR) - sessions_page.triage_mmr_patient(child, ConsentOption.MMR_EITHER) + sessions_search_page.click_session_for_programme_group(schools[0], Programme.MMR) + sessions_overview_page.click_triage_tab() + sessions_triage_page.search_child(child) + sessions_patient_page.click_programme_tab(Programme.MMR) + sessions_patient_page.triage_mmr_patient(ConsentOption.MMR_EITHER) dashboard_page.navigate() dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(schools[0], Programme.MMR) - sessions_page.click_set_session_in_progress_for_today() - sessions_page.register_child_as_attending(str(child)) - sessions_page.record_vaccination_for_child( - VaccinationRecord(child, Programme.MMR, mmr_batch_name) - ) + sessions_search_page.click_session_for_programme_group(schools[0], Programme.MMR) + sessions_overview_page.click_set_session_in_progress_for_today() + sessions_overview_page.click_register_tab() + sessions_register_page.register_child_as_attending(str(child)) + sessions_register_page.click_record_vaccinations_tab() + sessions_record_vaccinations_page.search_child(child) + + vaccination_record = VaccinationRecord(child, Programme.MMR, mmr_batch_name) + sessions_patient_page.set_up_vaccination(vaccination_record) + sessions_vaccination_wizard_page.record_vaccination(vaccination_record) dashboard_page.navigate() log_in_page.log_out() diff --git a/tests/test_imms_api_flu.py b/tests/test_imms_api_flu.py index 1cf5519fd93..1adf57946f8 100644 --- a/tests/test_imms_api_flu.py +++ b/tests/test_imms_api_flu.py @@ -32,7 +32,7 @@ def test_create_edit_delete_injected_flu_vaccination_and_verify_imms_api( schools, children, imms_api_helper, - sessions_page, + sessions_patient_page, vaccination_record_page, edit_vaccination_record_page, ): @@ -90,7 +90,7 @@ def test_create_edit_delete_injected_flu_vaccination_and_verify_imms_api( ) # Step 6: Edit outcome to refused - sessions_page.click_vaccination_details(school) + sessions_patient_page.click_vaccination_details(school) vaccination_record_page.expect_vaccination_details( "Synced with NHS England?", "Synced" ) @@ -103,7 +103,7 @@ def test_create_edit_delete_injected_flu_vaccination_and_verify_imms_api( # Step 7: Verify deletion in IMMS API imms_api_helper.check_record_is_not_in_imms_api(Vaccine.SEQUIRUS, child) - sessions_page.click_vaccination_details(school) + sessions_patient_page.click_vaccination_details(school) vaccination_record_page.expect_vaccination_details( "Synced with NHS England?", "Not synced" ) @@ -113,7 +113,7 @@ def test_create_edit_delete_nasal_flu_vaccination_and_verify_imms_api( upload_offline_vaccination_nasal_flu, schools, imms_api_helper, - sessions_page, + sessions_patient_page, vaccination_record_page, edit_vaccination_record_page, children, @@ -173,7 +173,7 @@ def test_create_edit_delete_nasal_flu_vaccination_and_verify_imms_api( ) # Step 6: Edit outcome to refused - sessions_page.click_vaccination_details(school) + sessions_patient_page.click_vaccination_details(school) vaccination_record_page.expect_vaccination_details( "Synced with NHS England?", "Synced" ) @@ -186,7 +186,7 @@ def test_create_edit_delete_nasal_flu_vaccination_and_verify_imms_api( # Step 7: Verify deletion in IMMS API imms_api_helper.check_record_is_not_in_imms_api(Vaccine.FLUENZ, child) - sessions_page.click_vaccination_details(school) + sessions_patient_page.click_vaccination_details(school) vaccination_record_page.expect_vaccination_details( "Synced with NHS England?", "Not synced" ) diff --git a/tests/test_imms_api_hpv.py b/tests/test_imms_api_hpv.py index 659cd38ea6b..6590f4e15fa 100644 --- a/tests/test_imms_api_hpv.py +++ b/tests/test_imms_api_hpv.py @@ -25,7 +25,7 @@ def test_create_edit_delete_hpv_vaccination_and_verify_imms_api( upload_offline_vaccination_hpv, schools, imms_api_helper, - sessions_page, + sessions_patient_page, vaccination_record_page, edit_vaccination_record_page, children, @@ -84,7 +84,7 @@ def test_create_edit_delete_hpv_vaccination_and_verify_imms_api( ) # Step 6: Edit outcome to refused - sessions_page.click_vaccination_details(school) + sessions_patient_page.click_vaccination_details(school) vaccination_record_page.expect_vaccination_details( "Synced with NHS England?", "Synced" ) @@ -97,7 +97,7 @@ def test_create_edit_delete_hpv_vaccination_and_verify_imms_api( # Step 7: Verify deletion in IMMS API imms_api_helper.check_record_is_not_in_imms_api(Vaccine.GARDASIL_9, child) - sessions_page.click_vaccination_details(school) + sessions_patient_page.click_vaccination_details(school) vaccination_record_page.expect_vaccination_details( "Synced with NHS England?", "Not synced" ) diff --git a/tests/test_import_class_lists.py b/tests/test_import_class_lists.py index 3e6b0fd663e..7d111b18791 100644 --- a/tests/test_import_class_lists.py +++ b/tests/test_import_class_lists.py @@ -2,6 +2,7 @@ from mavis.test.data import ClassFileMapping from mavis.test.models import Programme +from mavis.test.utils import get_offset_date @pytest.fixture @@ -9,30 +10,26 @@ def setup_class_list_import( log_in_as_nurse, schools, dashboard_page, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_edit_page, imports_page, import_records_wizard_page, year_groups, ): school = schools[Programme.HPV][0] year_group = year_groups[Programme.HPV] - try: - dashboard_page.click_sessions() - sessions_page.ensure_session_scheduled_for_next_week( - school, Programme.HPV.group - ) - dashboard_page.click_mavis() - dashboard_page.click_import_records() - imports_page.click_import_records() - import_records_wizard_page.navigate_to_class_list_record_import( - str(school), year_group - ) - yield - finally: - dashboard_page.navigate() - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.delete_all_sessions(school) + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) + if not sessions_overview_page.is_date_scheduled(get_offset_date(7)): + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_session(offset_days=7, skip_weekends=False) + dashboard_page.click_mavis() + dashboard_page.click_import_records() + imports_page.click_import_records() + import_records_wizard_page.navigate_to_class_list_record_import( + str(school), year_group + ) @pytest.mark.classlist diff --git a/tests/test_import_offline_vaccinations.py b/tests/test_import_offline_vaccinations.py index 67811cd68a3..bdf1c6fdc2f 100644 --- a/tests/test_import_offline_vaccinations.py +++ b/tests/test_import_offline_vaccinations.py @@ -3,6 +3,7 @@ from mavis.test.annotations import issue from mavis.test.data import ClassFileMapping, VaccsFileMapping from mavis.test.models import Programme +from mavis.test.utils import get_offset_date @pytest.fixture @@ -10,7 +11,9 @@ def setup_vaccs( log_in_as_nurse, schools, dashboard_page, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_edit_page, import_records_wizard_page, imports_page, year_groups, @@ -18,27 +21,24 @@ def setup_vaccs( school = schools[Programme.HPV][0] year_group = year_groups[Programme.HPV] - try: - dashboard_page.click_sessions() - sessions_page.ensure_session_scheduled_for_today(school, Programme.HPV) - sessions_page.click_import_class_lists() - import_records_wizard_page.import_class_list( - ClassFileMapping.RANDOM_CHILD, year_group - ) - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, Programme.HPV) - session_id = sessions_page.get_session_id_from_offline_excel() - dashboard_page.click_mavis() - dashboard_page.click_import_records() - imports_page.click_import_records() - import_records_wizard_page.navigate_to_vaccination_records_import() - yield session_id - finally: - dashboard_page.navigate() - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.delete_all_sessions(school) + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group(school, Programme.HPV.group) + if not sessions_overview_page.is_date_scheduled(get_offset_date(0)): + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_session(offset_days=0, skip_weekends=False) + sessions_overview_page.click_import_class_lists() + import_records_wizard_page.import_class_list( + ClassFileMapping.RANDOM_CHILD, year_group + ) + dashboard_page.click_mavis() + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) + session_id = sessions_overview_page.get_session_id_from_offline_excel() + dashboard_page.click_mavis() + dashboard_page.click_import_records() + imports_page.click_import_records() + import_records_wizard_page.navigate_to_vaccination_records_import() + return session_id @pytest.mark.vaccinations diff --git a/tests/test_nurse_consent.py b/tests/test_nurse_consent.py index 63dfd63cf04..4c448eef11f 100644 --- a/tests/test_nurse_consent.py +++ b/tests/test_nurse_consent.py @@ -3,7 +3,7 @@ from mavis.test.annotations import issue from mavis.test.data import CohortsFileMapping from mavis.test.models import ConsentMethod, DeliverySite, Programme, Vaccine -from mavis.test.utils import MAVIS_NOTE_LENGTH_LIMIT +from mavis.test.utils import MAVIS_NOTE_LENGTH_LIMIT, get_offset_date pytestmark = pytest.mark.consent @@ -13,7 +13,9 @@ def setup_session_with_file_upload( log_in_as_nurse, schools, dashboard_page, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_edit_page, import_records_wizard_page, year_groups, ): @@ -21,22 +23,23 @@ def setup_session_with_file_upload( year_group = year_groups[Programme.HPV] def _setup(class_list_file): - try: - dashboard_page.click_sessions() - sessions_page.ensure_session_scheduled_for_today(school, Programme.HPV) - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, Programme.HPV) - sessions_page.click_import_class_lists() - import_records_wizard_page.import_class_list(class_list_file, year_group) - dashboard_page.click_mavis() - dashboard_page.click_sessions() - yield - finally: - dashboard_page.navigate() - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.delete_all_sessions(school) + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group( + school, Programme.HPV.group + ) + if not sessions_overview_page.is_date_scheduled(get_offset_date(0)): + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_session( + offset_days=0, skip_weekends=False + ) + dashboard_page.click_mavis() + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) + sessions_overview_page.click_import_class_lists() + import_records_wizard_page.import_class_list(class_list_file, year_group) + dashboard_page.click_mavis() + dashboard_page.click_sessions() + yield return _setup @@ -47,7 +50,14 @@ def setup_fixed_child(setup_session_with_file_upload): def test_gillick_competence( - setup_fixed_child, schools, sessions_page, gillick_competence_page, children + setup_fixed_child, + schools, + sessions_search_page, + gillick_competence_page, + children, + sessions_overview_page, + sessions_consent_page, + sessions_patient_page, ): """ Test: Add and edit Gillick competence assessment for a child. @@ -62,17 +72,27 @@ def test_gillick_competence( child = children[Programme.HPV][0] school = schools[Programme.HPV][0] - sessions_page.click_session_for_programme_group(school, Programme.HPV) - sessions_page.navigate_to_gillick_competence(child, Programme.HPV) + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) + sessions_overview_page.click_consent_tab() + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.HPV) + sessions_patient_page.click_assess_gillick_competence() gillick_competence_page.add_gillick_competence(is_competent=True) - sessions_page.click_edit_gillick_competence() + sessions_patient_page.click_edit_gillick_competence() gillick_competence_page.edit_gillick_competence(is_competent=False) @issue("MAV-955") def test_gillick_competence_notes( - setup_fixed_child, schools, sessions_page, gillick_competence_page, children + setup_fixed_child, + schools, + gillick_competence_page, + children, + sessions_search_page, + sessions_overview_page, + sessions_consent_page, + sessions_patient_page, ): """ Test: Validate Gillick competence assessment notes length and update. @@ -90,8 +110,11 @@ def test_gillick_competence_notes( child = children[Programme.HPV][0] school = schools[Programme.HPV][0] - sessions_page.click_session_for_programme_group(school, Programme.HPV) - sessions_page.navigate_to_gillick_competence(child, Programme.HPV) + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) + sessions_overview_page.click_consent_tab() + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.HPV) + sessions_patient_page.click_assess_gillick_competence() gillick_competence_page.answer_gillick_competence_questions(is_competent=True) gillick_competence_page.fill_assessment_notes_with_string_of_length( @@ -103,7 +126,7 @@ def test_gillick_competence_notes( gillick_competence_page.fill_assessment_notes("Gillick competent") gillick_competence_page.click_complete_assessment() - sessions_page.click_edit_gillick_competence() + sessions_patient_page.click_edit_gillick_competence() gillick_competence_page.answer_gillick_competence_questions(is_competent=True) gillick_competence_page.fill_assessment_notes_with_string_of_length( MAVIS_NOTE_LENGTH_LIMIT + 1 @@ -115,7 +138,11 @@ def test_gillick_competence_notes( @pytest.mark.bug def test_invalid_consent( setup_fixed_child, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_consent_page, + sessions_patient_page, + sessions_patient_session_activity_page, schools, nurse_consent_wizard_page, children, @@ -134,35 +161,39 @@ def test_invalid_consent( child = children[Programme.HPV][0] school = schools[Programme.HPV][0] - sessions_page.click_session_for_programme_group(school, Programme.HPV) - sessions_page.click_consent_tab() - sessions_page.select_no_response() - sessions_page.navigate_to_consent_response(child, Programme.HPV) + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) + sessions_overview_page.click_consent_tab() + sessions_consent_page.select_no_response() + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.HPV) + sessions_patient_page.click_record_a_new_consent_response() nurse_consent_wizard_page.select_parent(child.parents[0]) nurse_consent_wizard_page.select_consent_method(ConsentMethod.IN_PERSON) nurse_consent_wizard_page.record_parent_no_response() - sessions_page.select_no_response() + sessions_consent_page.select_no_response() - sessions_page.navigate_to_consent_response(child, Programme.HPV) + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.HPV) + sessions_patient_page.click_record_a_new_consent_response() nurse_consent_wizard_page.select_parent(child.parents[1]) nurse_consent_wizard_page.select_consent_method(ConsentMethod.IN_PERSON) nurse_consent_wizard_page.record_parent_refuse_consent() - sessions_page.select_consent_refused() - sessions_page.click_child(child) - sessions_page.click_programme_tab(Programme.HPV) - sessions_page.invalidate_parent_refusal(child.parents[1]) - sessions_page.click_session_activity_and_notes() + sessions_consent_page.select_consent_refused() + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.HPV) + sessions_patient_page.invalidate_parent_refusal(child.parents[1]) + sessions_patient_page.click_session_activity_and_notes() - sessions_page.check_session_activity_entry( + sessions_patient_session_activity_page.check_session_activity_entry( f"Consent from {child.parents[1].full_name} invalidated", ) - sessions_page.check_session_activity_entry( + sessions_patient_session_activity_page.check_session_activity_entry( f"Consent refused by {child.parents[1].name_and_relationship}", ) - sessions_page.check_session_activity_entry( + sessions_patient_session_activity_page.check_session_activity_entry( f"Consent not_provided by {child.parents[0].name_and_relationship}", ) @@ -170,7 +201,12 @@ def test_invalid_consent( @pytest.mark.bug def test_parent_provides_consent_twice( setup_fixed_child, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_consent_page, + sessions_patient_page, + sessions_patient_session_activity_page, + sessions_vaccination_wizard_page, schools, nurse_consent_wizard_page, children, @@ -191,38 +227,40 @@ def test_parent_provides_consent_twice( child = children[Programme.HPV][0] school = schools[Programme.HPV][0] - sessions_page.click_session_for_programme_group(school, Programme.HPV) - sessions_page.click_consent_tab() - sessions_page.select_no_response() + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) + sessions_overview_page.click_consent_tab() + sessions_consent_page.select_no_response() - sessions_page.navigate_to_consent_response(child, Programme.HPV) + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.HPV) + sessions_patient_page.click_record_a_new_consent_response() nurse_consent_wizard_page.select_parent(child.parents[0]) nurse_consent_wizard_page.select_consent_method(ConsentMethod.PAPER) nurse_consent_wizard_page.record_parent_positive_consent( yes_to_health_questions=True ) - sessions_page.select_consent_given_filters_for_programme(Programme.HPV) - - sessions_page.navigate_to_update_triage_outcome(child, Programme.HPV) - nurse_consent_wizard_page.update_triage_outcome_positive() - - sessions_page.click_record_a_new_consent_response() + sessions_consent_page.select_consent_given_filters_for_programme(Programme.HPV) + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.HPV) + sessions_patient_page.click_record_a_new_consent_response() nurse_consent_wizard_page.select_parent(child.parents[0]) nurse_consent_wizard_page.select_consent_method(ConsentMethod.IN_PERSON) nurse_consent_wizard_page.record_parent_refuse_consent() - sessions_page.select_consent_refused() + sessions_consent_page.select_consent_refused() - sessions_page.click_child(child) - sessions_page.click_programme_tab(Programme.HPV) - sessions_page.expect_consent_refused_text(child.parents[0]) - sessions_page.click_session_activity_and_notes() - sessions_page.check_session_activity_entry( + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.HPV) + sessions_vaccination_wizard_page.expect_consent_refused_text(child.parents[0]) + sessions_patient_page.click_session_activity_and_notes() + sessions_patient_session_activity_page.check_session_activity_entry( f"Consent refused by {child.parents[0].name_and_relationship}", ) - sessions_page.check_session_activity_entry("Triaged decision: Safe to vaccinate") - sessions_page.check_session_activity_entry( + sessions_patient_session_activity_page.check_session_activity_entry( + "Triaged decision: Safe to vaccinate" + ) + sessions_patient_session_activity_page.check_session_activity_entry( f"Consent given by {child.parents[0].name_and_relationship}", ) @@ -230,7 +268,11 @@ def test_parent_provides_consent_twice( @pytest.mark.bug def test_conflicting_consent_with_gillick_consent( setup_fixed_child, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_consent_page, + sessions_patient_page, + sessions_patient_session_activity_page, schools, nurse_consent_wizard_page, gillick_competence_page, @@ -254,42 +296,46 @@ def test_conflicting_consent_with_gillick_consent( child = children[Programme.HPV][0] school = schools[Programme.HPV][0] - sessions_page.click_session_for_programme_group(school, Programme.HPV) - sessions_page.click_consent_tab() - sessions_page.select_no_response() - sessions_page.navigate_to_consent_response(child, Programme.HPV) + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) + sessions_overview_page.click_consent_tab() + sessions_consent_page.select_no_response() + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.HPV) + sessions_patient_page.click_record_a_new_consent_response() nurse_consent_wizard_page.select_parent(child.parents[0]) nurse_consent_wizard_page.select_consent_method(ConsentMethod.IN_PERSON) nurse_consent_wizard_page.record_parent_positive_consent() - sessions_page.select_consent_given_filters_for_programme(Programme.HPV) - sessions_page.navigate_to_consent_response(child, Programme.HPV) + sessions_consent_page.select_consent_given_filters_for_programme(Programme.HPV) + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.HPV) + sessions_patient_page.click_record_a_new_consent_response() nurse_consent_wizard_page.select_parent(child.parents[1]) nurse_consent_wizard_page.select_consent_method(ConsentMethod.IN_PERSON) nurse_consent_wizard_page.record_parent_refuse_consent() - sessions_page.select_conflicting_consent() + sessions_consent_page.select_conflicting_consent() - sessions_page.click_child(child) - sessions_page.click_programme_tab(Programme.HPV) - sessions_page.expect_consent_status(Programme.HPV, "Conflicting consent") - sessions_page.expect_conflicting_consent_text() - sessions_page.click_assess_gillick_competence() + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.HPV) + sessions_patient_page.expect_consent_status(Programme.HPV, "Conflicting consent") + sessions_patient_page.expect_conflicting_consent_text() + sessions_patient_page.click_assess_gillick_competence() gillick_competence_page.add_gillick_competence(is_competent=True) - sessions_page.click_record_a_new_consent_response() + sessions_patient_page.click_record_a_new_consent_response() nurse_consent_wizard_page.select_gillick_competent_child() nurse_consent_wizard_page.record_child_positive_consent() nurse_consent_wizard_page.expect_text_in_alert(f"Consent recorded for {child!s}") - sessions_page.select_consent_given_filters_for_programme(Programme.HPV) - sessions_page.click_child(child) - sessions_page.click_programme_tab(Programme.HPV) - sessions_page.expect_consent_status(Programme.HPV, "Consent given") - sessions_page.click_session_activity_and_notes() - sessions_page.check_session_activity_entry( + sessions_consent_page.select_consent_given_filters_for_programme(Programme.HPV) + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.HPV) + sessions_patient_page.expect_consent_status(Programme.HPV, "Consent given") + sessions_patient_page.click_session_activity_and_notes() + sessions_patient_session_activity_page.check_session_activity_entry( f"Consent given by {child!s} (Child (Gillick competent))", ) @@ -298,7 +344,13 @@ def test_conflicting_consent_with_gillick_consent( def test_accessibility( setup_fixed_child, add_vaccine_batch, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_consent_page, + sessions_patient_page, + sessions_register_page, + sessions_record_vaccinations_page, + sessions_vaccination_wizard_page, schools, nurse_consent_wizard_page, children, @@ -311,11 +363,13 @@ def test_accessibility( dashboard_page.navigate() dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, Programme.HPV) - sessions_page.click_consent_tab() - sessions_page.select_no_response() + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) + sessions_overview_page.click_consent_tab() + sessions_consent_page.select_no_response() - sessions_page.navigate_to_consent_response(child, Programme.HPV) + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.HPV) + sessions_patient_page.click_record_a_new_consent_response() accessibility_helper.check_accessibility() nurse_consent_wizard_page.click_radio_button(child.parents[0].name_and_relationship) @@ -342,25 +396,26 @@ def test_accessibility( nurse_consent_wizard_page.click_confirm() accessibility_helper.check_accessibility() - sessions_page.register_child_as_attending(child) - sessions_page.click_record_vaccinations_tab() + sessions_overview_page.click_register_tab() + sessions_register_page.register_child_as_attending(str(child)) + sessions_register_page.click_record_vaccinations_tab() accessibility_helper.check_accessibility() - sessions_page.click_child(child) + sessions_record_vaccinations_page.click_child(child) accessibility_helper.check_accessibility() - sessions_page.confirm_pre_screening_checks(Programme.HPV) - sessions_page.select_identity_confirmed_by_child(child) - sessions_page.select_ready_for_vaccination() - sessions_page.select_delivery_site(DeliverySite.LEFT_ARM_UPPER) - sessions_page.click_continue_button() + sessions_patient_page.confirm_pre_screening_checks(Programme.HPV) + sessions_patient_page.select_identity_confirmed_by_child(child) + sessions_patient_page.select_ready_for_vaccination() + sessions_patient_page.select_delivery_site(DeliverySite.LEFT_ARM_UPPER) + sessions_vaccination_wizard_page.click_continue_button() accessibility_helper.check_accessibility() - sessions_page.choose_batch(batch_name) + sessions_vaccination_wizard_page.choose_batch(batch_name) accessibility_helper.check_accessibility() - sessions_page.click_confirm_button() + sessions_vaccination_wizard_page.click_confirm_button() accessibility_helper.check_accessibility() - sessions_page.click_vaccination_details(school) + sessions_patient_page.click_vaccination_details(school) accessibility_helper.check_accessibility() diff --git a/tests/test_online_consent_flu.py b/tests/test_online_consent_flu.py index 7895b7c813d..6465a18b559 100644 --- a/tests/test_online_consent_flu.py +++ b/tests/test_online_consent_flu.py @@ -27,7 +27,8 @@ def setup_session_with_file_upload( log_in_as_nurse, schools, dashboard_page, - sessions_page, + sessions_search_page, + sessions_overview_page, import_records_wizard_page, year_groups, ): @@ -36,8 +37,8 @@ def setup_session_with_file_upload( dashboard_page.click_mavis() dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, Programme.FLU) - sessions_page.click_import_class_lists() + sessions_search_page.click_session_for_programme_group(school, Programme.FLU) + sessions_overview_page.click_import_class_lists() import_records_wizard_page.import_class_list( CohortsFileMapping.FIXED_CHILD, year_group, @@ -184,7 +185,9 @@ def test_flu_consent_method_displayed_correctly( children, consents, start_page, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_consent_page, dashboard_page, ): """ @@ -245,16 +248,18 @@ def test_flu_consent_method_displayed_correctly( dashboard_page.navigate() dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(schools[0], Programme.FLU) - sessions_page.click_consent_tab() - sessions_page.select_consent_given_for_nasal_spray() - sessions_page.select_consent_given_for_injected_vaccine() + sessions_search_page.click_session_for_programme_group(schools[0], Programme.FLU) + sessions_overview_page.click_consent_tab() + sessions_consent_page.select_consent_given_for_nasal_spray() + sessions_consent_page.select_consent_given_for_injected_vaccine() - sessions_page.search_for(str(child)) - sessions_page.verify_child_shows_correct_flu_consent_method(child, consents[2]) + sessions_consent_page.search_for(str(child)) + sessions_consent_page.verify_child_shows_correct_flu_consent_method( + child, consents[2] + ) # Verify in session download dashboard_page.navigate() dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(schools[0], Programme.FLU) - sessions_page.verify_consent_message_in_excel() + sessions_search_page.click_session_for_programme_group(schools[0], Programme.FLU) + sessions_overview_page.verify_consent_message_in_excel() diff --git a/tests/test_online_consent_school_moves.py b/tests/test_online_consent_school_moves.py index ebe88dab4f1..30ca444b7dc 100644 --- a/tests/test_online_consent_school_moves.py +++ b/tests/test_online_consent_school_moves.py @@ -26,7 +26,8 @@ def setup_session_with_file_upload( log_in_as_nurse, schools, dashboard_page, - sessions_page, + sessions_search_page, + sessions_overview_page, import_records_wizard_page, year_groups, ): @@ -35,8 +36,8 @@ def setup_session_with_file_upload( dashboard_page.click_mavis() dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, Programme.FLU) - sessions_page.click_import_class_lists() + sessions_search_page.click_session_for_programme_group(school, Programme.FLU) + sessions_overview_page.click_import_class_lists() import_records_wizard_page.import_class_list( CohortsFileMapping.FIXED_CHILD, year_group, @@ -51,7 +52,9 @@ def test_online_consent_school_moves_with_existing_patient( online_consent_page, schools, children, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_consent_page, dashboard_page, school_moves_page, review_school_move_page, @@ -100,13 +103,13 @@ def test_online_consent_school_moves_with_existing_patient( dashboard_page.navigate() dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(schools[1], Programme.FLU) + sessions_search_page.click_session_for_programme_group(schools[1], Programme.FLU) - sessions_page.click_consent_tab() - sessions_page.select_consent_given_for_nasal_spray() - sessions_page.select_consent_given_for_injected_vaccine() - sessions_page.search_for(str(child)) - sessions_page.verify_child_shows_correct_flu_consent_method( + sessions_overview_page.click_consent_tab() + sessions_consent_page.select_consent_given_for_nasal_spray() + sessions_consent_page.select_consent_given_for_injected_vaccine() + sessions_consent_page.search_for(str(child)) + sessions_consent_page.verify_child_shows_correct_flu_consent_method( child, ConsentOption.NASAL_SPRAY_OR_INJECTION ) @@ -116,7 +119,9 @@ def test_online_consent_school_moves_with_new_patient( online_consent_page, schools, children, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_consent_page, dashboard_page, unmatched_consent_responses_page, consent_response_page, @@ -172,13 +177,13 @@ def test_online_consent_school_moves_with_new_patient( dashboard_page.navigate() dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(schools[1], Programme.FLU) + sessions_search_page.click_session_for_programme_group(schools[1], Programme.FLU) - sessions_page.click_consent_tab() - sessions_page.select_consent_given_for_nasal_spray() - sessions_page.select_consent_given_for_injected_vaccine() - sessions_page.search_for(str(child)) - sessions_page.verify_child_shows_correct_flu_consent_method( + sessions_overview_page.click_consent_tab() + sessions_consent_page.select_consent_given_for_nasal_spray() + sessions_consent_page.select_consent_given_for_injected_vaccine() + sessions_consent_page.search_for(str(child)) + sessions_consent_page.verify_child_shows_correct_flu_consent_method( child, ConsentOption.NASAL_SPRAY_OR_INJECTION ) diff --git a/tests/test_psd.py b/tests/test_psd.py index 6db1f837c67..02371e64c10 100644 --- a/tests/test_psd.py +++ b/tests/test_psd.py @@ -8,6 +8,7 @@ VaccinationRecord, Vaccine, ) +from mavis.test.utils import get_offset_date @pytest.fixture @@ -15,7 +16,9 @@ def setup_session_with_file_upload( log_in_as_prescriber, schools, dashboard_page, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_edit_page, import_records_wizard_page, year_groups, add_vaccine_batch, @@ -25,27 +28,28 @@ def _factory( ) -> str: school = schools[Programme.FLU][0] year_group = year_groups[Programme.FLU] - try: - batch_name = add_vaccine_batch(Vaccine.FLUENZ) - dashboard_page.click_mavis() - dashboard_page.click_sessions() - if schedule_session_for_today: - sessions_page.ensure_session_scheduled_for_today(school, Programme.FLU) - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, Programme.FLU) - sessions_page.click_import_class_lists() - import_records_wizard_page.import_class_list( - class_file_mapping, year_group, Programme.FLU.group + batch_name = add_vaccine_batch(Vaccine.FLUENZ) + dashboard_page.click_mavis() + dashboard_page.click_sessions() + if schedule_session_for_today: + sessions_search_page.click_session_for_programme_group( + school, Programme.FLU.group ) - dashboard_page.click_mavis() - dashboard_page.click_sessions() - return batch_name - finally: - dashboard_page.navigate() - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.delete_all_sessions(school) + if not sessions_overview_page.is_date_scheduled(get_offset_date(0)): + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_session( + offset_days=0, skip_weekends=False + ) + dashboard_page.click_mavis() + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group(school, Programme.FLU) + sessions_overview_page.click_import_class_lists() + import_records_wizard_page.import_class_list( + class_file_mapping, year_group, Programme.FLU.group + ) + dashboard_page.click_mavis() + dashboard_page.click_sessions() + return batch_name return _factory @@ -75,7 +79,15 @@ def flu_consent_url(schedule_session_and_get_consent_url, schools): def test_delivering_vaccination_after_psd( setup_session_with_one_child, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_edit_page, + sessions_consent_page, + sessions_psd_page, + sessions_patient_page, + sessions_register_page, + sessions_vaccination_wizard_page, + sessions_record_vaccinations_page, schools, nurse_consent_wizard_page, children, @@ -99,17 +111,17 @@ def test_delivering_vaccination_after_psd( school = schools[Programme.FLU][0] fluenz_batch_name = setup_session_with_one_child - sessions_page.click_session_for_programme_group(school, Programme.FLU) - sessions_page.click_edit_session() - sessions_page.click_change_psd() - sessions_page.answer_whether_psd_should_be_enabled("Yes") - sessions_page.click_continue_button() - sessions_page.click_save_changes() - - sessions_page.click_consent_tab() - sessions_page.search_child(child) - sessions_page.click_programme_tab(Programme.FLU) - sessions_page.click_record_a_new_consent_response() + sessions_search_page.click_session_for_programme_group(school, Programme.FLU) + sessions_overview_page.click_edit_session() + sessions_edit_page.click_change_psd() + sessions_edit_page.answer_whether_psd_should_be_enabled("Yes") + sessions_edit_page.click_continue_button() + sessions_edit_page.click_save_changes() + + sessions_overview_page.click_consent_tab() + sessions_consent_page.search_child(child) + sessions_patient_page.click_programme_tab(Programme.FLU) + sessions_patient_page.click_record_a_new_consent_response() nurse_consent_wizard_page.select_parent(child.parents[0]) nurse_consent_wizard_page.select_consent_method(ConsentMethod.IN_PERSON) nurse_consent_wizard_page.record_parent_positive_consent( @@ -118,9 +130,9 @@ def test_delivering_vaccination_after_psd( psd_option=True, yes_to_health_questions=True, ) - sessions_page.click_psds_tab() - sessions_page.search_for(str(child)) - sessions_page.check_child_has_psd(child) + sessions_overview_page.click_psds_tab() + sessions_psd_page.search_for(str(child)) + sessions_psd_page.check_child_has_psd(child) log_in_page.log_out() log_in_page.navigate() @@ -128,23 +140,29 @@ def test_delivering_vaccination_after_psd( dashboard_page.click_mavis() dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, Programme.FLU) - sessions_page.register_child_as_attending(str(child)) - sessions_page.record_vaccination_for_child( - VaccinationRecord( - child, - Programme.FLU, - fluenz_batch_name, - ConsentOption.NASAL_SPRAY_OR_INJECTION, - ), - psd_option=True, + sessions_search_page.click_session_for_programme_group(school, Programme.FLU) + sessions_overview_page.click_register_tab() + sessions_register_page.register_child_as_attending(str(child)) + sessions_register_page.click_record_vaccinations_tab() + sessions_record_vaccinations_page.search_child(child) + + vaccination_record = VaccinationRecord( + child, Programme.FLU, fluenz_batch_name, ConsentOption.NASAL_SPRAY_OR_INJECTION + ) + sessions_patient_page.set_up_vaccination(vaccination_record) + sessions_vaccination_wizard_page.record_vaccination( + vaccination_record, psd_option=True ) def test_bulk_adding_psd( flu_consent_url, setup_session_with_two_children, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_edit_page, + sessions_consent_page, + sessions_psd_page, schools, children, dashboard_page, @@ -190,39 +208,43 @@ def test_bulk_adding_psd( dashboard_page.navigate() dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, Programme.FLU) - sessions_page.click_edit_session() - sessions_page.click_change_psd() - sessions_page.answer_whether_psd_should_be_enabled("Yes") - sessions_page.click_continue_button() - sessions_page.click_save_changes() + sessions_search_page.click_session_for_programme_group(school, Programme.FLU) + sessions_overview_page.click_edit_session() + sessions_edit_page.click_change_psd() + sessions_edit_page.answer_whether_psd_should_be_enabled("Yes") + sessions_edit_page.click_continue_button() + sessions_edit_page.click_save_changes() - sessions_page.click_consent_tab() + sessions_overview_page.click_consent_tab() for child in children[Programme.FLU]: - sessions_page.get_flu_consent_status_locator_from_search(child) + sessions_consent_page.get_flu_consent_status_locator_from_search(child) - sessions_page.click_psds_tab() + sessions_consent_page.click_psds_tab() for child in children[Programme.FLU]: - sessions_page.search_for(str(child)) - sessions_page.check_child_does_not_have_psd(child) + sessions_psd_page.search_for(str(child)) + sessions_psd_page.check_child_does_not_have_psd(child) - sessions_page.verify_psd_banner_has_patients(2) + sessions_psd_page.verify_psd_banner_has_patients(2) - sessions_page.click_add_new_psds() - sessions_page.click_yes_add_psds() + sessions_psd_page.click_add_new_psds() + sessions_psd_page.click_yes_add_psds() - sessions_page.verify_psd_banner_has_patients(0) + sessions_psd_page.verify_psd_banner_has_patients(0) for child in children[Programme.FLU]: - sessions_page.search_for(str(child)) - sessions_page.check_child_has_psd(child) + sessions_psd_page.search_for(str(child)) + sessions_psd_page.check_child_has_psd(child) @pytest.mark.accessibility def test_accessibility( - sessions_page, - accessibility_helper, setup_session_with_one_child, + sessions_search_page, + sessions_overview_page, + sessions_edit_page, + sessions_consent_page, + sessions_psd_page, + accessibility_helper, dashboard_page, schools, ): @@ -239,19 +261,22 @@ def test_accessibility( dashboard_page.navigate() dashboard_page.click_sessions() - sessions_page.ensure_session_scheduled_for_next_week(school, Programme.FLU.group) - sessions_page.click_edit_session() - sessions_page.click_change_psd() + sessions_search_page.click_session_for_programme_group(school, Programme.HPV.group) + if not sessions_overview_page.is_date_scheduled(get_offset_date(7)): + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_session(offset_days=7, skip_weekends=False) + sessions_overview_page.click_edit_session() + sessions_edit_page.click_change_psd() accessibility_helper.check_accessibility() - sessions_page.answer_whether_psd_should_be_enabled("Yes") - sessions_page.click_continue_button() - sessions_page.click_save_changes() - sessions_page.click_psds_tab() + sessions_edit_page.answer_whether_psd_should_be_enabled("Yes") + sessions_edit_page.click_continue_button() + sessions_edit_page.click_save_changes() + sessions_consent_page.click_psds_tab() accessibility_helper.check_accessibility() - sessions_page.click_add_new_psds() + sessions_psd_page.click_add_new_psds() accessibility_helper.check_accessibility() - sessions_page.click_yes_add_psds() + sessions_psd_page.click_yes_add_psds() accessibility_helper.check_accessibility() diff --git a/tests/test_reset.py b/tests/test_reset.py index f43d8d38799..01bb7d0bc19 100644 --- a/tests/test_reset.py +++ b/tests/test_reset.py @@ -9,7 +9,11 @@ VaccinationRecord, Vaccine, ) -from mavis.test.utils import MAVIS_NOTE_LENGTH_LIMIT, generate_random_string +from mavis.test.utils import ( + MAVIS_NOTE_LENGTH_LIMIT, + generate_random_string, + get_offset_date, +) @pytest.fixture @@ -19,34 +23,35 @@ def setup_all_programmes( schools, dashboard_page, import_records_wizard_page, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_edit_page, children, ): school = schools["doubles"][0] child = children["doubles"][0] - try: - batch_names = { - Programme.HPV: add_vaccine_batch(Vaccine.GARDASIL_9), - Programme.MENACWY: add_vaccine_batch(Vaccine.MENQUADFI), - Programme.TD_IPV: add_vaccine_batch(Vaccine.REVAXIS), - Programme.FLU: add_vaccine_batch(Vaccine.FLUENZ), - } - for programme_group in [Programme.HPV, "doubles", Programme.FLU]: - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.ensure_session_scheduled_for_today(school, programme_group) - sessions_page.click_import_class_lists() - import_records_wizard_page.import_class_list( - ClassFileMapping.FIXED_CHILD, - child.year_group, - "doubles", - ) - yield batch_names - finally: - dashboard_page.navigate() + batch_names = { + Programme.HPV: add_vaccine_batch(Vaccine.GARDASIL_9), + Programme.MENACWY: add_vaccine_batch(Vaccine.MENQUADFI), + Programme.TD_IPV: add_vaccine_batch(Vaccine.REVAXIS), + Programme.FLU: add_vaccine_batch(Vaccine.FLUENZ), + } + for programme_group in [Programme.HPV, "doubles", Programme.FLU]: dashboard_page.click_mavis() dashboard_page.click_sessions() - sessions_page.delete_all_sessions(school) + sessions_search_page.click_session_for_programme_group(school, programme_group) + if not sessions_overview_page.is_date_scheduled(get_offset_date(0)): + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_session( + offset_days=0, skip_weekends=False + ) + sessions_overview_page.click_import_class_lists() + import_records_wizard_page.import_class_list( + ClassFileMapping.FIXED_CHILD, + child.year_group, + "doubles", + ) + return batch_names @issue("MAV-965") @@ -57,7 +62,12 @@ def test_pre_screening_questions_prefilled_for_multiple_vaccinations( setup_all_programmes, schools, dashboard_page, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_register_page, + sessions_consent_page, + sessions_patient_page, + sessions_vaccination_wizard_page, nurse_consent_wizard_page, children, ): @@ -85,11 +95,12 @@ def test_pre_screening_questions_prefilled_for_multiple_vaccinations( for programme_group in [Programme.HPV, "doubles", Programme.FLU]: dashboard_page.click_mavis() dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, programme_group) + sessions_search_page.click_session_for_programme_group(school, programme_group) if programme_group is Programme.HPV: - sessions_page.register_child_as_attending(str(child)) - sessions_page.click_consent_tab() - sessions_page.search_child(child) + sessions_overview_page.click_register_tab() + sessions_register_page.register_child_as_attending(str(child)) + sessions_register_page.click_consent_tab() + sessions_consent_page.search_child(child) programmes = ( [Programme.MENACWY, Programme.TD_IPV] if programme_group == "doubles" @@ -102,20 +113,23 @@ def test_pre_screening_questions_prefilled_for_multiple_vaccinations( else ConsentOption.INJECTION ) - sessions_page.click_programme_tab(programme) - sessions_page.click_record_a_new_consent_response() + sessions_patient_page.click_programme_tab(programme) + sessions_patient_page.click_record_a_new_consent_response() nurse_consent_wizard_page.select_parent(child.parents[0]) nurse_consent_wizard_page.select_consent_method(ConsentMethod.IN_PERSON) nurse_consent_wizard_page.record_parent_positive_consent( programme=programme, consent_option=consent_option, ) - sessions_page.record_vaccination_for_child( - VaccinationRecord( - child, programme, batch_names[programme], consent_option - ), - notes=generate_random_string( - target_length=MAVIS_NOTE_LENGTH_LIMIT + 1, - generate_spaced_words=True, - ), + vaccination_record = VaccinationRecord( + child, programme, batch_names[programme], consent_option + ) + notes = generate_random_string( + target_length=MAVIS_NOTE_LENGTH_LIMIT + 1, + generate_spaced_words=True, + ) + sessions_consent_page.search_child(child) + sessions_patient_page.set_up_vaccination(vaccination_record, notes=notes) + sessions_vaccination_wizard_page.record_vaccination( + vaccination_record, notes=notes ) diff --git a/tests/test_school_moves.py b/tests/test_school_moves.py index b6bbf5e0e88..325180c05f0 100644 --- a/tests/test_school_moves.py +++ b/tests/test_school_moves.py @@ -3,6 +3,7 @@ from mavis.test.data import ClassFileMapping from mavis.test.models import Programme +from mavis.test.utils import get_offset_date pytestmark = pytest.mark.school_moves @@ -13,7 +14,9 @@ def setup_confirm_and_ignore( test_data, schools, dashboard_page, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_edit_page, import_records_wizard_page, year_groups, children_search_page, @@ -30,10 +33,10 @@ def setup_confirm_and_ignore( ) def upload_class_list(): - sessions_page.click_import_class_lists() + sessions_overview_page.click_import_class_lists() import_records_wizard_page.select_year_groups(year_group) - sessions_page.choose_file_child_records(input_file_path) - sessions_page.click_continue_button() + import_records_wizard_page.set_input_file(input_file_path) + import_records_wizard_page.click_continue() import_records_wizard_page.record_upload_time() import_records_wizard_page.click_uploaded_file_datetime() import_records_wizard_page.wait_for_processed() @@ -41,40 +44,32 @@ def upload_class_list(): import_records_wizard_page.approve_preview_if_shown() import_records_wizard_page.verify_upload_output(output_file_path) - try: - dashboard_page.click_sessions() - sessions_page.ensure_session_scheduled_for_next_week( - schools[0], Programme.HPV.group - ) - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.ensure_session_scheduled_for_next_week( - schools[1], Programme.HPV.group - ) - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(schools[0], Programme.HPV) - upload_class_list() - children_search_page.click_record_for_child(children[0]) - child_record_page.click_activity_log() - child_activity_log_page.expect_activity_log_header( - f"Added to the session at {schools[0]}" - ) - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(schools[1], Programme.HPV) - upload_class_list() - dashboard_page.click_mavis() - dashboard_page.click_school_moves() - yield - finally: - dashboard_page.navigate() - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.delete_all_sessions(schools[0]) - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.delete_all_sessions(schools[1]) + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group(schools[0], Programme.HPV) + if not sessions_overview_page.is_date_scheduled(get_offset_date(7)): + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_session(offset_days=7, skip_weekends=False) + dashboard_page.click_mavis() + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group(schools[1], Programme.HPV) + if not sessions_overview_page.is_date_scheduled(get_offset_date(7)): + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_session(offset_days=7, skip_weekends=False) + dashboard_page.click_mavis() + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group(schools[0], Programme.HPV) + upload_class_list() + children_search_page.click_record_for_child(children[0]) + child_record_page.click_activity_log() + child_activity_log_page.expect_activity_log_header( + f"Added to the session at {schools[0]}" + ) + dashboard_page.click_mavis() + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group(schools[1], Programme.HPV) + upload_class_list() + dashboard_page.click_mavis() + dashboard_page.click_school_moves() def test_confirm_and_ignore( diff --git a/tests/test_sessions.py b/tests/test_sessions.py index 8af2edfd6e8..05402a8a2e4 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -4,6 +4,7 @@ from mavis.test.annotations import issue from mavis.test.data import ClassFileMapping from mavis.test.models import ConsentMethod, Programme, VaccinationRecord, Vaccine +from mavis.test.utils import get_offset_date pytestmark = pytest.mark.sessions @@ -18,7 +19,9 @@ def setup_session_with_file_upload( setup_tests, schools, dashboard_page, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_edit_page, import_records_wizard_page, year_groups, ): @@ -26,19 +29,20 @@ def setup_session_with_file_upload( year_group = year_groups[Programme.HPV] def _setup(class_list_file): - try: - sessions_page.ensure_session_scheduled_for_today(school, Programme.HPV) - sessions_page.click_import_class_lists() - import_records_wizard_page.import_class_list(class_list_file, year_group) - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, Programme.HPV) - yield - finally: - dashboard_page.navigate() - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.delete_all_sessions(school) + sessions_search_page.click_session_for_programme_group( + school, Programme.HPV.group + ) + if not sessions_overview_page.is_date_scheduled(get_offset_date(0)): + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_session( + offset_days=0, skip_weekends=False + ) + sessions_overview_page.click_import_class_lists() + import_records_wizard_page.import_class_list(class_list_file, year_group) + dashboard_page.click_mavis() + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) + yield return _setup @@ -58,7 +62,14 @@ def setup_fixed_child(setup_session_with_file_upload): yield from setup_session_with_file_upload(ClassFileMapping.FIXED_CHILD) -def test_session_lifecycle(setup_tests, schools, dashboard_page, sessions_page): +def test_session_lifecycle( + setup_tests, + schools, + dashboard_page, + sessions_search_page, + sessions_overview_page, + sessions_edit_page, +): """ Test: Create, edit, and delete a session for a school and verify lifecycle actions. Steps: @@ -71,18 +82,25 @@ def test_session_lifecycle(setup_tests, schools, dashboard_page, sessions_page): """ school = schools[Programme.HPV][0] - sessions_page.click_session_for_programme_group(school, Programme.HPV) - sessions_page.schedule_a_valid_session(offset_days=14) - sessions_page.schedule_a_valid_session(offset_days=1) + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_session(offset_days=14) + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_session(offset_days=1) dashboard_page.click_mavis() dashboard_page.click_sessions() - sessions_page.edit_a_session_to_today(school, Programme.HPV) - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.delete_all_sessions(school) + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) + sessions_overview_page.click_edit_session() + sessions_edit_page.edit_a_session_to_today() -def test_create_invalid_session(setup_tests, schools, sessions_page): +def test_create_invalid_session( + setup_tests, + schools, + sessions_search_page, + sessions_overview_page, + sessions_edit_page, +): """ Test: Attempt to create an invalid session and verify error handling. Steps: @@ -93,16 +111,22 @@ def test_create_invalid_session(setup_tests, schools, sessions_page): - Error is shown or invalid session is not created. """ school = schools[Programme.HPV][0] - sessions_page.create_invalid_session(school, Programme.HPV) + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) + sessions_overview_page.schedule_or_edit_session() - sessions_page.create_session_in_previous_academic_year() + sessions_edit_page.create_invalid_session() - sessions_page.create_session_in_next_academic_year() + sessions_edit_page.create_session_in_previous_academic_year() + + sessions_edit_page.create_session_in_next_academic_year() @pytest.mark.bug def test_attendance_filters_functionality( - setup_positive_upload, sessions_page, year_groups + setup_positive_upload, + sessions_overview_page, + sessions_register_page, + year_groups, ): """ Test: Verify attendance filters on the register tab work as expected. @@ -115,24 +139,26 @@ def test_attendance_filters_functionality( """ year_group = year_groups[Programme.HPV] - sessions_page.click_register_tab() - search_summary = sessions_page.page.get_by_text("Showing 1 to") + sessions_overview_page.click_register_tab() + search_summary = sessions_register_page.page.get_by_text("Showing 1 to") expect(search_summary).not_to_have_text("Showing 1 to 1 of 1 children") - sessions_page.check_year_checkbox(year_group) - sessions_page.click_on_update_results() + sessions_register_page.check_year_checkbox(year_group) + sessions_register_page.click_on_update_results() expect(search_summary).to_contain_text("Showing 1 to") - sessions_page.uncheck_year_checkbox(year_group) - sessions_page.click_advanced_filters() - sessions_page.check_archived_records_checkbox() - sessions_page.click_on_update_results() + sessions_register_page.uncheck_year_checkbox(year_group) + sessions_register_page.click_advanced_filters() + sessions_register_page.check_archived_records_checkbox() + sessions_register_page.click_on_update_results() expect(search_summary).not_to_be_visible() @issue("MAV-1018") @pytest.mark.bug -def test_session_search_functionality(setup_random_child, sessions_page): +def test_session_search_functionality( + setup_random_child, sessions_overview_page, sessions_consent_page +): """ Test: Verify the search functionality within a session. Steps: @@ -141,14 +167,17 @@ def test_session_search_functionality(setup_random_child, sessions_page): Verification: - Search returns expected results for the session. """ - sessions_page.verify_search() + sessions_overview_page.click_consent_tab() + sessions_consent_page.verify_search() @issue("MAV-1381") @pytest.mark.bug def test_consent_filters( setup_fixed_child, - sessions_page, + sessions_overview_page, + sessions_consent_page, + sessions_patient_page, nurse_consent_wizard_page, children, ): @@ -162,24 +191,28 @@ def test_consent_filters( - Consent refused checkbox is checked for the child. """ child = children[Programme.HPV][0] - sessions_page.review_child_with_no_response() - sessions_page.click_child(child) - sessions_page.click_record_a_new_consent_response() + sessions_overview_page.review_child_with_no_response() + sessions_consent_page.click_child(child) + sessions_patient_page.click_record_a_new_consent_response() nurse_consent_wizard_page.select_parent(child.parents[0]) nurse_consent_wizard_page.select_consent_method(ConsentMethod.PAPER) nurse_consent_wizard_page.record_parent_refuse_consent() - sessions_page.click_overview_tab() - sessions_page.click_consent_refused() - sessions_page.expect_consent_refused_checkbox_to_be_checked() + sessions_consent_page.click_overview_tab() + sessions_overview_page.click_consent_refused() + sessions_consent_page.expect_consent_refused_checkbox_to_be_checked() @issue("MAV-1265") def test_session_activity_notes_order( setup_fixed_child, dashboard_page, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_consent_page, + sessions_patient_page, + sessions_patient_session_activity_page, schools, children, ): @@ -198,27 +231,30 @@ def test_session_activity_notes_order( note_1 = "Note 1" note_2 = "Note 2" - sessions_page.click_consent_tab() - sessions_page.search_child(child) - sessions_page.click_session_activity_and_notes() - sessions_page.add_note(note_1) - sessions_page.add_note(note_2) + sessions_overview_page.click_consent_tab() + sessions_consent_page.search_child(child) + sessions_patient_page.click_session_activity_and_notes() + sessions_patient_session_activity_page.add_note(note_1) + sessions_patient_session_activity_page.add_note(note_2) dashboard_page.click_mavis() dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, Programme.HPV) - sessions_page.click_consent_tab() - sessions_page.search_for(str(child)) - sessions_page.check_note_appears_in_search(child, note_2) - sessions_page.click_child(child) - sessions_page.click_session_activity_and_notes() - sessions_page.check_notes_appear_in_order([note_2, note_1]) + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) + sessions_overview_page.click_consent_tab() + sessions_consent_page.search_for(str(child)) + sessions_consent_page.check_note_appears_in_search(child, note_2) + sessions_consent_page.click_child(child) + sessions_patient_page.click_session_activity_and_notes() + sessions_patient_session_activity_page.check_notes_appear_in_order([note_2, note_1]) @pytest.mark.rav def test_triage_consent_given_and_triage_outcome( setup_fixed_child, schools, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_consent_page, + sessions_patient_page, dashboard_page, nurse_consent_wizard_page, children, @@ -235,8 +271,10 @@ def test_triage_consent_given_and_triage_outcome( child = children[Programme.HPV][0] school = schools[Programme.HPV][0] - sessions_page.click_consent_tab() - sessions_page.navigate_to_consent_response(child, Programme.HPV) + sessions_overview_page.click_consent_tab() + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.HPV) + sessions_patient_page.click_record_a_new_consent_response() nurse_consent_wizard_page.select_parent(child.parents[0]) nurse_consent_wizard_page.select_consent_method(ConsentMethod.PHONE) @@ -247,19 +285,24 @@ def test_triage_consent_given_and_triage_outcome( dashboard_page.click_mavis() dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, Programme.HPV) + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) - sessions_page.click_register_tab() - sessions_page.navigate_to_update_triage_outcome(child, Programme.HPV) - sessions_page.select_yes_safe_to_vaccinate() - sessions_page.click_save_triage() - sessions_page.verify_triage_updated_for_child() + sessions_overview_page.click_register_tab() + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.HPV) + sessions_patient_page.click_update_triage_outcome() + sessions_patient_page.select_yes_safe_to_vaccinate() + sessions_patient_page.click_save_triage() + sessions_patient_page.verify_triage_updated_for_child() @pytest.mark.rav def test_consent_refused_and_activity_log( setup_fixed_child, - sessions_page, + sessions_overview_page, + sessions_consent_page, + sessions_patient_page, + sessions_patient_session_activity_page, nurse_consent_wizard_page, children, ): @@ -274,18 +317,20 @@ def test_consent_refused_and_activity_log( """ child = children[Programme.HPV][0] - sessions_page.click_consent_tab() - sessions_page.navigate_to_consent_response(child, Programme.HPV) + sessions_overview_page.click_consent_tab() + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.HPV) + sessions_patient_page.click_record_a_new_consent_response() nurse_consent_wizard_page.select_parent(child.parents[0]) nurse_consent_wizard_page.select_consent_method(ConsentMethod.PAPER) nurse_consent_wizard_page.record_parent_refuse_consent() nurse_consent_wizard_page.expect_text_in_alert(str(child)) - sessions_page.select_consent_refused() - sessions_page.click_child(child) - sessions_page.click_session_activity_and_notes() - sessions_page.check_session_activity_entry( + sessions_consent_page.select_consent_refused() + sessions_consent_page.click_child(child) + sessions_patient_page.click_session_activity_and_notes() + sessions_patient_session_activity_page.check_session_activity_entry( f"Consent refused by {child.parents[0].name_and_relationship}", ) @@ -299,7 +344,13 @@ def test_verify_excel_export_and_clinic_invitation( clinics, children_search_page, child_record_page, - sessions_page, + sessions_edit_page, + sessions_search_page, + sessions_overview_page, + sessions_patient_page, + sessions_register_page, + sessions_vaccination_wizard_page, + sessions_record_vaccinations_page, dashboard_page, nurse_consent_wizard_page, children, @@ -321,10 +372,12 @@ def test_verify_excel_export_and_clinic_invitation( dashboard_page.click_mavis() dashboard_page.click_sessions() - sessions_page.ensure_session_scheduled_for_today( - "Community clinic", - Programme.HPV, + sessions_search_page.click_session_for_programme_group( + "Community clinic", Programme.HPV.group ) + if not sessions_overview_page.is_date_scheduled(get_offset_date(0)): + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_session(offset_days=0, skip_weekends=False) dashboard_page.click_mavis() dashboard_page.click_children() @@ -336,29 +389,34 @@ def test_verify_excel_export_and_clinic_invitation( Programme.HPV, check_date=True, ) - sessions_page.click_record_a_new_consent_response() + sessions_patient_page.click_record_a_new_consent_response() nurse_consent_wizard_page.select_parent(child.parents[0]) nurse_consent_wizard_page.select_consent_method(ConsentMethod.IN_PERSON) nurse_consent_wizard_page.record_parent_positive_consent() - sessions_page.register_child_as_attending(child) - sessions_page.record_vaccination_for_child( - VaccinationRecord(child, Programme.HPV, batch_name), - at_school=False, + sessions_overview_page.click_register_tab() + sessions_register_page.register_child_as_attending(str(child)) + sessions_register_page.click_record_vaccinations_tab() + sessions_record_vaccinations_page.search_child(child) + vaccination_record = VaccinationRecord(child, Programme.HPV, batch_name) + sessions_patient_page.set_up_vaccination(vaccination_record) + sessions_vaccination_wizard_page.record_vaccination( + vaccination_record, at_school=False ) - sessions_page.check_location_radio(clinics[0]) - sessions_page.click_continue_button() - sessions_page.click_confirm_button() - sessions_page.expect_alert_text("Vaccination outcome recorded for HPV") + + sessions_vaccination_wizard_page.check_location_radio(clinics[0]) + sessions_vaccination_wizard_page.click_continue_button() + sessions_vaccination_wizard_page.click_confirm_button() + sessions_patient_page.expect_alert_text("Vaccination outcome recorded for HPV") dashboard_page.click_mavis() dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, Programme.HPV) - assert sessions_page.get_session_id_from_offline_excel() + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) + assert sessions_overview_page.get_session_id_from_offline_excel() @issue("MAV-2023") def test_session_verify_consent_reminders_and_pdf_downloads( setup_fixed_child, - sessions_page, + sessions_overview_page, schools, ): """ @@ -373,11 +431,18 @@ def test_session_verify_consent_reminders_and_pdf_downloads( """ school = schools[Programme.HPV][0] - sessions_page.click_send_reminders(school) - sessions_page.download_consent_form(Programme.HPV) + sessions_overview_page.click_send_reminders(school) + sessions_overview_page.download_consent_form(Programme.HPV) -def test_editing_session_programmes(setup_fixed_child, sessions_page, children): +def test_editing_session_programmes( + setup_fixed_child, + children, + sessions_overview_page, + sessions_edit_page, + sessions_consent_page, + sessions_patient_page, +): """ Test: Edit the programmes of an existing session and verify changes. Steps: @@ -390,16 +455,16 @@ def test_editing_session_programmes(setup_fixed_child, sessions_page, children): """ child = children[Programme.HPV][0] - sessions_page.click_edit_session() - sessions_page.click_change_programmes() - sessions_page.add_programme(Programme.FLU) - sessions_page.click_continue_button() - sessions_page.expect_details("Programmes", "Flu HPV") - sessions_page.click_save_changes() - sessions_page.expect_session_to_have_programmes([Programme.FLU, Programme.HPV]) - sessions_page.click_consent_tab() - sessions_page.click_child(child) - sessions_page.click_programme_tab(Programme.FLU) + sessions_overview_page.click_edit_session() + sessions_edit_page.click_change_programmes() + sessions_edit_page.add_programme(Programme.FLU) + sessions_edit_page.click_continue_button() + sessions_edit_page.expect_details("Programmes", "Flu HPV") + sessions_edit_page.click_save_changes() + sessions_edit_page.expect_session_to_have_programmes([Programme.FLU, Programme.HPV]) + sessions_overview_page.click_consent_tab() + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.FLU) @pytest.mark.accessibility @@ -407,7 +472,14 @@ def test_accessibility( setup_fixed_child, dashboard_page, accessibility_helper, - sessions_page, + sessions_search_page, + sessions_overview_page, + sessions_edit_page, + sessions_consent_page, + sessions_patient_page, + sessions_children_page, + sessions_triage_page, + sessions_register_page, schools, children, ): @@ -426,32 +498,32 @@ def test_accessibility( dashboard_page.click_sessions() accessibility_helper.check_accessibility() - sessions_page.click_session_for_programme_group(school, Programme.HPV) + sessions_search_page.click_session_for_programme_group(school, Programme.HPV) accessibility_helper.check_accessibility() - sessions_page.click_edit_session() + sessions_overview_page.click_edit_session() accessibility_helper.check_accessibility() - sessions_page.click_change_session_dates() + sessions_edit_page.click_change_session_dates() accessibility_helper.check_accessibility() - sessions_page.click_back() - sessions_page.click_save_changes() + sessions_edit_page.click_back() + sessions_edit_page.click_save_changes() - sessions_page.click_children_tab() + sessions_overview_page.click_children_tab() accessibility_helper.check_accessibility() - sessions_page.click_consent_tab() + sessions_children_page.click_consent_tab() accessibility_helper.check_accessibility() - sessions_page.click_triage_tab() + sessions_consent_page.click_triage_tab() accessibility_helper.check_accessibility() - sessions_page.click_register_tab() + sessions_triage_page.click_register_tab() accessibility_helper.check_accessibility() - sessions_page.click_child(child) + sessions_register_page.click_child(child) accessibility_helper.check_accessibility() - sessions_page.click_session_activity_and_notes() + sessions_patient_page.click_session_activity_and_notes() accessibility_helper.check_accessibility() diff --git a/tests/test_tallying.py b/tests/test_tallying.py index 121e25d063c..c21428754fe 100644 --- a/tests/test_tallying.py +++ b/tests/test_tallying.py @@ -11,6 +11,7 @@ VaccinationRecord, Vaccine, ) +from mavis.test.utils import get_offset_date pytestmark = pytest.mark.tallying @@ -26,7 +27,9 @@ def setup_session_with_file_upload( add_vaccine_batch, schools, dashboard_page, - sessions_page, + sessions_edit_page, + sessions_search_page, + sessions_overview_page, import_records_wizard_page, year_groups, ): @@ -34,27 +37,28 @@ def setup_session_with_file_upload( year_group = year_groups[Programme.FLU] def _setup(class_list_file): - try: - batch_names = { - vaccine: add_vaccine_batch(vaccine) - for vaccine in [Vaccine.SEQUIRUS, Vaccine.FLUENZ] - } - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.ensure_session_scheduled_for_today(school, Programme.FLU) - sessions_page.click_import_class_lists() - import_records_wizard_page.import_class_list( - class_list_file, year_group, Programme.FLU.group + batch_names = { + vaccine: add_vaccine_batch(vaccine) + for vaccine in [Vaccine.SEQUIRUS, Vaccine.FLUENZ] + } + dashboard_page.click_mavis() + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group( + school, Programme.FLU.group + ) + if not sessions_overview_page.is_date_scheduled(get_offset_date(0)): + sessions_overview_page.schedule_or_edit_session() + sessions_edit_page.schedule_a_valid_session( + offset_days=0, skip_weekends=False ) - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.click_session_for_programme_group(school, Programme.FLU) - yield batch_names - finally: - dashboard_page.navigate() - dashboard_page.click_mavis() - dashboard_page.click_sessions() - sessions_page.delete_all_sessions(school) + sessions_overview_page.click_import_class_lists() + import_records_wizard_page.import_class_list( + class_list_file, year_group, Programme.FLU.group + ) + dashboard_page.click_mavis() + dashboard_page.click_sessions() + sessions_search_page.click_session_for_programme_group(school, Programme.FLU) + yield batch_names return _setup @@ -66,9 +70,14 @@ def setup_fixed_child(setup_session_with_file_upload): @issue("MAV-1669") @pytest.mark.bug -def test_tallying( +def test_tallying( # noqa: PLR0915 setup_fixed_child, - sessions_page, + sessions_overview_page, + sessions_patient_page, + sessions_register_page, + sessions_consent_page, + sessions_vaccination_wizard_page, + sessions_record_vaccinations_page, nurse_consent_wizard_page, children, schools, @@ -86,11 +95,13 @@ def test_tallying( batch_name = setup_fixed_child[Vaccine.FLUENZ] school = schools[Programme.FLU][0] - tally_totals = sessions_page.get_all_totals(Programme.FLU) + tally_totals = sessions_overview_page.get_all_totals(Programme.FLU) assert tally_totals[TallyCategory.NO_RESPONSE] > 0 - sessions_page.click_consent_tab() - sessions_page.navigate_to_consent_response(child, Programme.FLU) + sessions_overview_page.click_consent_tab() + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.FLU) + sessions_patient_page.click_record_a_new_consent_response() nurse_consent_wizard_page.select_parent(child.parents[0]) nurse_consent_wizard_page.select_consent_method(ConsentMethod.PHONE) nurse_consent_wizard_page.record_parent_positive_consent( @@ -99,35 +110,37 @@ def test_tallying( tally_totals[TallyCategory.NO_RESPONSE] -= 1 tally_totals[TallyCategory.CONSENT_GIVEN_FOR_INJECTION] += 1 - sessions_page.check_all_totals(tally_totals) + sessions_overview_page.check_all_totals(tally_totals) - sessions_page.click_consent_tab() - sessions_page.click_child(child) - sessions_page.click_response_from_parent(child.parents[0]) - sessions_page.click_withdraw_consent() + sessions_overview_page.click_consent_tab() + sessions_consent_page.click_child(child) + sessions_patient_page.click_response_from_parent(child.parents[0]) + sessions_patient_page.click_withdraw_consent() nurse_consent_wizard_page.click_consent_refusal_reason( ConsentRefusalReason.PERSONAL_CHOICE ) nurse_consent_wizard_page.give_withdraw_consent_notes("notes") nurse_consent_wizard_page.click_withdraw_consent() - sessions_page.click_back() - sessions_page.go_back_to_session_for_school(school) + sessions_patient_page.click_back() + sessions_patient_page.go_back_to_session_for_school(school) tally_totals[TallyCategory.CONSENT_GIVEN_FOR_INJECTION] -= 1 tally_totals[TallyCategory.CONSENT_REFUSED] += 1 - sessions_page.check_all_totals(tally_totals) + sessions_overview_page.check_all_totals(tally_totals) - sessions_page.click_consent_tab() - sessions_page.click_child(child) - sessions_page.invalidate_parent_refusal(child.parents[0]) - sessions_page.go_back_to_session_for_school(school) + sessions_overview_page.click_consent_tab() + sessions_consent_page.click_child(child) + sessions_patient_page.invalidate_parent_refusal(child.parents[0]) + sessions_patient_page.go_back_to_session_for_school(school) tally_totals[TallyCategory.CONSENT_REFUSED] -= 1 tally_totals[TallyCategory.NO_RESPONSE] += 1 - sessions_page.check_all_totals(tally_totals) + sessions_overview_page.check_all_totals(tally_totals) - sessions_page.click_consent_tab() - sessions_page.navigate_to_consent_response(child, Programme.FLU) + sessions_overview_page.click_consent_tab() + sessions_consent_page.click_child(child) + sessions_patient_page.click_programme_tab(Programme.FLU) + sessions_patient_page.click_record_a_new_consent_response() nurse_consent_wizard_page.select_parent(child.parents[1]) nurse_consent_wizard_page.select_consent_method(ConsentMethod.PHONE) nurse_consent_wizard_page.record_parent_positive_consent( @@ -138,16 +151,20 @@ def test_tallying( tally_totals[TallyCategory.NO_RESPONSE] -= 1 tally_totals[TallyCategory.CONSENT_GIVEN_FOR_NASAL_SPRAY] += 1 - sessions_page.check_all_totals(tally_totals) + sessions_overview_page.check_all_totals(tally_totals) - sessions_page.register_child_as_attending(str(child)) - sessions_page.record_vaccination_for_child( - VaccinationRecord( - child, Programme.FLU, batch_name, ConsentOption.NASAL_SPRAY_OR_INJECTION - ) + sessions_overview_page.click_register_tab() + sessions_register_page.register_child_as_attending(str(child)) + sessions_register_page.click_record_vaccinations_tab() + sessions_record_vaccinations_page.search_child(child) + + vaccination_record = VaccinationRecord( + child, Programme.FLU, batch_name, ConsentOption.NASAL_SPRAY ) - sessions_page.go_back_to_session_for_school(school) + sessions_patient_page.set_up_vaccination(vaccination_record) + sessions_vaccination_wizard_page.record_vaccination(vaccination_record) + sessions_patient_page.go_back_to_session_for_school(school) tally_totals[TallyCategory.CONSENT_GIVEN_FOR_NASAL_SPRAY] -= 1 tally_totals[TallyCategory.VACCINATED] += 1 - sessions_page.check_all_totals(tally_totals) + sessions_overview_page.check_all_totals(tally_totals)