Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 1 addition & 10 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def start_playwright():
yield _playwright


@pytest.fixture()
@pytest.fixture(scope="session")
def start_mavis(start_exe_session, start_playwright):
_browser, _context = start_browser(pw=start_playwright, browser_or_device=ce.current_browser_name)
ce.browser = _browser
Expand All @@ -35,15 +35,6 @@ def start_mavis(start_exe_session, start_playwright):
close_browser(browser=_browser, page=ce.page)


# @pytest.fixture
# def start_consent_workflow(start_exe_session, start_playwright):
# _browser, _context = start_browser(pw=start_playwright, browser_or_device=ce.current_browser_name)
# ce.page = _context.new_page()
# ce.page.goto(url=ce.parental_consent_url)
# yield
# close_browser(browser=_browser, page=ce.page)


@pytest.fixture
def start_consent_workflow(start_exe_session, start_playwright):
_browser, _context = start_browser(pw=start_playwright, browser_or_device=ce.current_browser_name)
Expand Down
2 changes: 1 addition & 1 deletion libs/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class playwright_roles:


class wait_time:
MIN: Final[str] = "3s"
MIN: Final[str] = "1s"
MED: Final[str] = "10s"
MAX: Final[str] = "30s"

Expand Down
53 changes: 40 additions & 13 deletions libs/playwright_ops.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import re

from libs import CurrentExecution
from libs.constants import (
Expand All @@ -7,6 +8,7 @@
object_properties,
playwright_roles,
screenshot_types,
wait_time,
)
from libs.wrappers import *

Expand All @@ -26,37 +28,55 @@ def capture_screenshot(self, identifier: str, action: str) -> None:
# self.ce.page.set_viewport_size({"width": 1500, "height": 1500})
self.ce.page.screenshot(path=_ss_path, type=screenshot_types.JPEG)

def verify(self, locator: str, property: str, value: str, exact: bool = False, by_test_id: bool = False) -> None:
def verify(
self,
locator: str,
property: str,
value: str,
exact: bool = False,
by_test_id: bool = False,
chain_locator: bool = False,
) -> None:
current_value = self.get_object_property(
locator=locator, property=property, by_test_id=by_test_id, chain_locator=chain_locator
)
match property.lower():
case object_properties.TEXT:
text = self.get_object_property(locator=locator, property=property, by_test_id=by_test_id)
if exact:
if value == text:
if value == current_value:
self.capture_screenshot(identifier=locator, action="verify_text_passed")
else:
self.capture_screenshot(identifier=locator, action="verify_text_failed")
assert value == text, f"Exact match failed. Expected: '{value}' but actual: '{text}'."
assert (
value == current_value
), f"Exact match failed. Expected: '{value}' but actual: '{current_value}'."
else:
if clean_text(text=value) in clean_text(text=text):
if clean_text(text=value) in clean_text(text=current_value):
self.capture_screenshot(identifier=locator, action="verify_text_passed")
else:
self.capture_screenshot(identifier=locator, action="verify_text_failed")
assert clean_text(text=value) in clean_text(text=text), f"Text '{value}' not found in '{text}'."
assert clean_text(text=value) in clean_text(
text=current_value
), f"Text '{value}' not found in '{current_value}'."
case object_properties.VISIBILITY:
current_state = self.get_object_property(locator=locator, property=property, by_test_id=by_test_id)
if current_state == value:
if current_value == value:
self.capture_screenshot(identifier=locator, action="verify_visibility_passed")
else:
self.capture_screenshot(identifier=locator, action="verify_visibility_failed")
assert value == current_state, f"{locator} is not visible."
assert value == current_value, f"{locator} is not visible."

def get_object_property(self, locator: str, property: str, by_test_id: bool = False) -> str:
def get_object_property(
self, locator: str, property: str, by_test_id: bool = False, chain_locator: bool = False
) -> str:
match property:
case object_properties.TEXT:
if by_test_id:
elem = self.ce.page.get_by_test_id(locator)
else:
elem = self.ce.page.get_by_role(locator).nth(0)
if chain_locator:
elem = eval(f"self.ce.page.{locator}")
else:
elem = self.ce.page.get_by_role(locator).nth(0)
elem.scroll_into_view_if_needed()
return "".join(elem.all_text_contents()).strip()
case object_properties.VISIBILITY:
Expand All @@ -65,10 +85,17 @@ def get_object_property(self, locator: str, property: str, by_test_id: bool = Fa
_locator = locator.split(escape_characters.SEPARATOR)[1]
elem = self.ce.page.get_by_role(_location, name=_locator).nth(0)
else:
elem = self.ce.page.get_by_role(locator).nth(0)
if chain_locator:
wait(timeout=wait_time.MIN)
elem = eval(f"self.ce.page.{locator}")
else:
elem = self.ce.page.get_by_role(locator).nth(0)
return elem.is_visible()
case object_properties.HREF:
elem = self.ce.page.get_by_role("link", name=locator).nth(0)
if chain_locator:
elem = eval(f"self.ce.page.{locator}")
else:
elem = self.ce.page.get_by_role("link", name=locator).nth(0)
return elem.get_attribute(object_properties.HREF)

def perform_action(self, locator, action, value=None, exact: bool = False) -> None:
Expand Down
2 changes: 1 addition & 1 deletion pages/pg_login.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def perform_valid_login(self):
self.verify_login_successful()

def perform_invalid_login(self, user: str, pwd: str, expected_message: str) -> str:
self.click_start()
# self.click_start()
self.enter_username(username=user)
self.enter_password(password=pwd)
self.click_login()
Expand Down
37 changes: 20 additions & 17 deletions pages/pg_sessions.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
import re
from pickle import TRUE

from playwright.sync_api import expect

from libs import CurrentExecution, file_ops, playwright_ops, testdata_ops
from libs.constants import actions, object_properties, wait_time
from libs.wrappers import *
Expand Down Expand Up @@ -63,6 +58,7 @@ class pg_sessions:
BTN_UPDATE_GILLICK_ASSESSMENT = "Update your assessment"
LNK_CONSENT_FORM = "View parental consent form ("
LNK_COULD_NOT_VACCINATE = "Could not vaccinate"
LNK_CONSENT_REFUSED = "Consent refused"

def __get_display_formatted_date(self, date_to_format: str) -> str:
_parsed_date = datetime.strptime(date_to_format, "%Y%m%d")
Expand Down Expand Up @@ -139,6 +135,9 @@ def click_edit_gillick_competence(self):
def click_could_not_vaccinate(self):
self.po.perform_action(locator=self.LNK_COULD_NOT_VACCINATE, action=actions.CLICK_LINK)

def click_consent_refused(self):
self.po.perform_action(locator=self.LNK_CONSENT_REFUSED, action=actions.CLICK_LINK)

def add_gillick_competence(self, is_competent: bool, competence_details: str) -> None:
self.__set_gillick_consent(is_add=True, is_competent=is_competent, competence_details=competence_details)

Expand Down Expand Up @@ -227,12 +226,14 @@ def __delete_sessions(self):
self.po.perform_action(locator=self.BTN_DELETE, action=actions.CLICK_BUTTON)
self.po.perform_action(locator=self.LNK_BACK, action=actions.CLICK_LINK)
self.po.perform_action(locator=self.LNK_CONTINUE, action=actions.CLICK_LINK)
# FIXME: Use the common verify function
expect(
self.ce.page.locator("div")
.filter(has_text=re.compile(r"^Session datesNot provided$"))
.get_by_role("definition")
).to_be_visible()
self.po.verify(
locator="locator('div').filter(has_text=re.compile(r'^Session datesNot provided$')).get_by_role('definition')",
property=object_properties.VISIBILITY,
value=True,
exact=False,
by_test_id=False,
chain_locator=True,
)

def verify_triage_updated(self):
self.po.verify(
Expand All @@ -243,6 +244,7 @@ def verify_triage_updated(self):
)

def verify_activity_log_entry(self, consent_given: bool):
wait(wait_time.MIN)
if consent_given:
self.po.verify(
locator=self.LBL_MAIN,
Expand Down Expand Up @@ -317,12 +319,13 @@ def update_triage_outcome_consent_refused(self, file_paths):
self.click_child_full_name()
self.click_get_consent_responses()
self.consent_page.service_refuse_consent()
self.dashboard_page.go_to_dashboard()
self.dashboard_page.click_sessions()
self.click_scheduled()
self.click_school1()
self.click_record_vaccinations()
self.click_could_not_vaccinate()
# self.dashboard_page.go_to_dashboard()
# self.dashboard_page.click_sessions()
# self.click_scheduled()
# self.click_school1()
# self.click_record_vaccinations()
# self.click_could_not_vaccinate()
self.click_consent_refused()
self.click_child_full_name()
self.click_activity_log()
self.verify_activity_log_entry(consent_given=False)
Expand Down
15 changes: 13 additions & 2 deletions tests/test_01_login.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ class Test_Regression_Login:
login_page = pg_login.pg_login()
dashboard_page = pg_dashboard.pg_dashboard()

@pytest.fixture(scope="class", autouse=True)
def test_setup(self, start_mavis):
yield

@pytest.fixture(scope="class")
def reset_navigation(self):
self.login_page.click_start()
yield

test_parameters = [
("invalid_user", "invalid_password", "Invalid Email or password."),
("invalid_user", "", "Invalid Email or password."),
Expand All @@ -17,12 +26,14 @@ class Test_Regression_Login:
@pytest.mark.mobile
@pytest.mark.order(101)
@pytest.mark.parametrize("user,pwd,expected_message", test_parameters)
def test_reg_invalid_login(self, start_mavis, user, pwd, expected_message):
def test_reg_invalid_login(self, reset_navigation, user, pwd, expected_message):
self.login_page.perform_invalid_login(user=user, pwd=pwd, expected_message=expected_message)

@pytest.mark.login
@pytest.mark.mobile
@pytest.mark.order(102)
def test_reg_home_page_links(self, start_mavis):
def test_reg_home_page_links(self):
self.login_page.go_to_login_page()
self.login_page.perform_valid_login()
self.dashboard_page.verify_all_expected_links()
self.login_page.perform_logout()
17 changes: 12 additions & 5 deletions tests/test_02_sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,31 @@ class Test_Regression_Sessions:
dashboard_page = pg_dashboard.pg_dashboard()
sessions_page = pg_sessions.pg_sessions()

@pytest.fixture
@pytest.fixture(scope="class", autouse=True)
def test_setup(self, start_mavis):
self.login_page.perform_valid_login()
self.dashboard_page.click_sessions()
yield
self.login_page.perform_logout()

@pytest.fixture(scope="function", autouse=True)
def reset_navigation(self):
self.dashboard_page.go_to_dashboard()
self.dashboard_page.click_sessions()
yield
self.dashboard_page.go_to_dashboard()
self.dashboard_page.click_sessions()

@pytest.mark.sessions
@pytest.mark.order(201)
def test_reg_create_valid_session(self, test_setup):
def test_reg_create_valid_session(self):
self.sessions_page.schedule_a_valid_session()

@pytest.mark.sessions
@pytest.mark.order(202)
def test_reg_delete_all_sessions(self, test_setup):
def test_reg_delete_all_sessions(self):
self.sessions_page.delete_all_sessions()

@pytest.mark.sessions
@pytest.mark.order(203)
def test_reg_create_invalid_session(self, test_setup):
def test_reg_create_invalid_session(self):
self.sessions_page.create_invalid_session()
19 changes: 12 additions & 7 deletions tests/test_03_class_list_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,44 @@ class Test_Regression_Class_List_Upload:
dashboard_page = pg_dashboard.pg_dashboard()
sessions_page = pg_sessions.pg_sessions()

@pytest.fixture()
@pytest.fixture(scope="class", autouse=True)
def test_setup(self, start_mavis: None):
self.login_page.perform_valid_login()
self.dashboard_page.click_sessions()
self.sessions_page.schedule_a_valid_session()
yield
self.sessions_page.delete_all_sessions()
self.login_page.perform_logout()

@pytest.fixture(scope="function", autouse=True)
def reset_navigation(self):
self.dashboard_page.go_to_dashboard()
self.dashboard_page.click_sessions()
yield
self.dashboard_page.go_to_dashboard()
self.dashboard_page.click_sessions()
self.sessions_page.delete_all_sessions()

@pytest.mark.classlist
@pytest.mark.order(301)
def test_reg_class_list_file_upload_positive(self, test_setup: None):
def test_reg_class_list_file_upload_positive(self):
self.sessions_page.upload_class_list(file_paths=test_data_file_paths.CLASS_POSITIVE)

@pytest.mark.classlist
@pytest.mark.order(302)
def test_reg_class_list_file_upload_negative(self, test_setup: None):
def test_reg_class_list_file_upload_negative(self):
self.sessions_page.upload_class_list(file_paths=test_data_file_paths.CLASS_NEGATIVE)

@pytest.mark.classlist
@pytest.mark.order(303)
def test_reg_class_list_file_structure(self, test_setup: None):
def test_reg_class_list_file_structure(self):
self.sessions_page.upload_invalid_class_list_records(file_paths=test_data_file_paths.CLASS_INVALID_STRUCTURE)

@pytest.mark.classlist
@pytest.mark.order(304)
def test_reg_class_list_no_record(self, test_setup: None):
def test_reg_class_list_no_record(self):
self.sessions_page.upload_invalid_class_list_records(file_paths=test_data_file_paths.CLASS_HEADER_ONLY)

@pytest.mark.classlist
@pytest.mark.order(305)
def test_reg_class_list_empty_file(self, test_setup: None):
def test_reg_class_list_empty_file(self):
self.sessions_page.upload_invalid_class_list_records(file_paths=test_data_file_paths.CLASS_EMPTY_FILE)
20 changes: 14 additions & 6 deletions tests/test_04_cohorts.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,42 @@ class Test_Regression_Cohorts:
dashboard_page = pg_dashboard.pg_dashboard()
programmes_page = pg_programmes.pg_programmes()

@pytest.fixture()
@pytest.fixture(scope="class", autouse=True)
def test_setup(self, start_mavis: None):
self.login_page.perform_valid_login()
self.dashboard_page.click_programmes()
yield
self.login_page.perform_logout()

@pytest.fixture(scope="function", autouse=True)
def reset_navigation(self):
self.dashboard_page.go_to_dashboard()
self.dashboard_page.click_programmes()
yield
self.dashboard_page.go_to_dashboard()
self.dashboard_page.click_programmes()

@pytest.mark.cohorts
@pytest.mark.order(401)
def test_reg_cohort_upload_positive(self, test_setup):
def test_reg_cohort_upload_positive(self):
self.programmes_page.upload_cohorts(file_paths=test_data_file_paths.COHORTS_POSITIVE)

@pytest.mark.cohorts
@pytest.mark.order(402)
def test_reg_cohort_upload_negative(self, test_setup):
def test_reg_cohort_upload_negative(self):
self.programmes_page.upload_cohorts(file_paths=test_data_file_paths.COHORTS_NEGATIVE)

@pytest.mark.cohorts
@pytest.mark.order(403)
def test_reg_cohorts_file_structure(self, test_setup):
def test_reg_cohorts_file_structure(self):
self.programmes_page.upload_invalid_cohorts(file_paths=test_data_file_paths.COHORTS_INVALID_STRUCTURE)

@pytest.mark.cohorts
@pytest.mark.order(404)
def test_reg_cohorts_no_record(self, test_setup):
def test_reg_cohorts_no_record(self):
self.programmes_page.upload_invalid_cohorts(file_paths=test_data_file_paths.COHORTS_HEADER_ONLY)

@pytest.mark.cohorts
@pytest.mark.order(405)
def test_reg_cohorts_empty_file(self, test_setup):
def test_reg_cohorts_empty_file(self):
self.programmes_page.upload_invalid_cohorts(file_paths=test_data_file_paths.COHORTS_EMPTY_FILE)
Loading
Loading