11import re
22from playwright .sync_api import Page , expect , Locator
33from pages .base_page import BasePage
4- from enum import StrEnum
4+ from enum import Enum , StrEnum
55from utils .oracle .oracle_specific_functions import (
66 get_investigation_dataset_polyp_category ,
77 get_investigation_dataset_polyp_algorithm_size ,
88)
9- from typing import Optional
9+ from typing import Optional , Any , Union , List
1010import logging
11+ import sys
1112
1213
1314class InvestigationDatasetsPage (BasePage ):
@@ -80,6 +81,11 @@ def __init__(self, page: Page):
8081 self .visible_ui_results_string = 'select[id^="UI_RESULTS_"]:visible'
8182 self .sections = self .page .locator (".DatasetSection" )
8283
84+ # Repeat strings:
85+ self .bowel_preparation_administered_string = "Bowel Preparation Administered"
86+ self .antibiotics_administered_string = "Antibiotics Administered"
87+ self .other_drugs_administered_string = "Other Drugs Administered"
88+
8389 def select_site_lookup_option (self , option : str ) -> None :
8490 """
8591 This method is designed to select a site from the site lookup options.
@@ -750,11 +756,13 @@ def assert_drug_type_text(
750756 locator = self .get_drug_type_locator (drug_type , drug_number )
751757 actual_text = locator .input_value ().strip ()
752758 logging .info (
753- f"Drug type text for drug { drug_number } : '{ actual_text } ' (expected: '{ expected_text } ')"
759+ f"Drug type text for drug { drug_number } : "
760+ f"'{ to_enum_name_or_value (actual_text )} ' "
761+ f"(expected: '{ to_enum_name_or_value (expected_text )} ')"
754762 )
755763 assert (
756764 actual_text == expected_text
757- ), f"Expected drug type text '{ expected_text } ' but found '{ actual_text } '"
765+ ), f"Expected drug type text '{ to_enum_name_or_value ( expected_text ) } ' but found '{ to_enum_name_or_value ( actual_text ) } '"
758766
759767 def assert_drug_dose_text (
760768 self , drug_type : str , drug_number : int , expected_text : str
@@ -784,11 +792,11 @@ def get_drug_type_locator(self, drug_type: str, drug_number: int) -> Locator:
784792 drug_type (str): The drug type to check
785793 drug_number (int): The number of the drug to check
786794 """
787- if drug_type == "Bowel Preparation Administered" :
795+ if drug_type == self . bowel_preparation_administered_string :
788796 locator_prefix = "#UI_BOWEL_PREP_DRUG"
789- elif drug_type == "Antibiotics Administered" :
797+ elif drug_type == self . antibiotics_administered_string :
790798 locator_prefix = "#UI_ANTIBIOTIC"
791- elif drug_type == "Other Drugs Administered" :
799+ elif drug_type == self . other_drugs_administered_string :
792800 locator_prefix = "#UI_DRUG"
793801 return self .page .locator (f"{ locator_prefix } { drug_number } " )
794802
@@ -799,11 +807,11 @@ def get_drug_dose_locator(self, drug_type: str, drug_number: int) -> Locator:
799807 drug_type (str): The drug type to check
800808 drug_number (int): The number of the drug to check
801809 """
802- if drug_type . lower () == "bowel preparation administered" :
810+ if drug_type == self . bowel_preparation_administered_string :
803811 locator_prefix = "#UI_BOWEL_PREP_DRUG_DOSE"
804- elif drug_type . lower () == "antibiotics administered" :
812+ elif drug_type == self . antibiotics_administered_string :
805813 locator_prefix = "#UI_ANTIBIOTIC_DOSE"
806- elif drug_type . lower () == "other drugs administered" :
814+ elif drug_type == self . other_drugs_administered_string :
807815 locator_prefix = "#UI_DOSE"
808816 return self .page .locator (f"{ locator_prefix } { drug_number } " )
809817
@@ -847,7 +855,11 @@ def assert_all_drug_information(
847855 drug_numbers = [
848856 int (match .group (1 ))
849857 for key in drug_information
850- if (match := re .match (r"drug_(?:dose|type)(\d+)" , key ))
858+ if (
859+ match := re .match (
860+ r"(?:drug|other_drug|antibiotic_drug)_(?:dose|type)(\d+)" , key
861+ )
862+ )
851863 ]
852864
853865 if not drug_numbers :
@@ -857,8 +869,16 @@ def assert_all_drug_information(
857869 max_drug_number = max (drug_numbers )
858870
859871 for drug_index in range (1 , max_drug_number + 1 ):
860- drug_type = drug_information .get (f"drug_type{ drug_index } " )
861- drug_dose = drug_information .get (f"drug_dose{ drug_index } " )
872+ drug_type = (
873+ drug_information .get (f"drug_type{ drug_index } " )
874+ or drug_information .get (f"other_drug_type{ drug_index } " )
875+ or drug_information .get (f"antibiotic_drug_type{ drug_index } " )
876+ )
877+ drug_dose = (
878+ drug_information .get (f"drug_dose{ drug_index } " )
879+ or drug_information .get (f"other_drug_dose{ drug_index } " )
880+ or drug_information .get (f"antibiotic_drug_dose{ drug_index } " )
881+ )
862882
863883 if drug_type is not None :
864884 self .assert_drug_type_text (drug_type_label , drug_index , drug_type )
@@ -891,8 +911,25 @@ def assert_all_drug_information(
891911 | DrugTypeOptions .FLEET_PHOSPHO_SODA
892912 ):
893913 expected_unit = "Mls Solution"
894- case DrugTypeOptions .OTHER :
914+ case (
915+ DrugTypeOptions .OTHER
916+ | AntibioticsAdministeredDrugTypeOptions .OTHER_ANTIBIOTIC
917+ ):
895918 expected_unit = ""
919+ case (
920+ AntibioticsAdministeredDrugTypeOptions .AMOXYCILLIN
921+ | AntibioticsAdministeredDrugTypeOptions .CEFOTAXIME
922+ | AntibioticsAdministeredDrugTypeOptions .VANCOMYCIN
923+ ):
924+ expected_unit = "g"
925+ case (
926+ AntibioticsAdministeredDrugTypeOptions .CIPROFLAXACIN
927+ | AntibioticsAdministeredDrugTypeOptions .CO_AMOXICLAV
928+ | AntibioticsAdministeredDrugTypeOptions .GENTAMICIN
929+ | AntibioticsAdministeredDrugTypeOptions .METRONIDAZOLE
930+ | AntibioticsAdministeredDrugTypeOptions .TEICOPLANIN
931+ ):
932+ expected_unit = "mg"
896933 case _:
897934 expected_unit = None
898935
@@ -911,11 +948,11 @@ def get_drug_dose_unit_locator(self, drug_type: str, drug_number: int) -> Locato
911948 drug_type (str): The drug type to check
912949 drug_number (int): The number of the drug to check
913950 """
914- if drug_type . lower () == "bowel preparation administered" :
951+ if drug_type == self . bowel_preparation_administered_string :
915952 locator_prefix = "#spanBowelPrepDrugDosageUnit"
916- elif drug_type . lower () == "antibiotics administered" :
953+ elif drug_type == self . antibiotics_administered_string :
917954 locator_prefix = "#spanAntibioticDosageUnit"
918- elif drug_type . lower () == "other drugs administered" :
955+ elif drug_type == self . other_drugs_administered_string :
919956 locator_prefix = "#spanDosageUnit"
920957 return self .page .locator (f"{ locator_prefix } { drug_number } " )
921958
@@ -940,6 +977,46 @@ def assert_drug_dose_unit_text(
940977 actual_text == expected_text
941978 ), f"Expected drug unit dose text '{ expected_text } ' but found '{ actual_text } '"
942979
980+ def assert_drug_dosage_unit_text (
981+ self , drug_type : str , drug_number : int , expected_text : str
982+ ) -> None :
983+ """
984+ Asserts that the drug dosage unit contains the expected text.
985+
986+ Args:
987+ drug_type (str): The drug type to check
988+ drug_number (int): The number of the drug dosage unit cell to check.
989+ expected_text (str): The expected text content of the cell.
990+
991+ Raises:
992+ AssertionError: If the actual text does not match the expected text.
993+ """
994+ locator = self .get_drug_dosage_text_locator (drug_type , drug_number )
995+ actual_text = locator .inner_text ().strip ()
996+
997+ logging .info (
998+ f"Drug dosage unit text for drug { drug_number } : "
999+ f"'{ actual_text } ' (expected: '{ expected_text } ')"
1000+ )
1001+
1002+ assert actual_text == expected_text , (
1003+ f"Expected drug dosage unit text '{ expected_text } ' "
1004+ f"but found '{ actual_text } '"
1005+ )
1006+
1007+ def get_drug_dosage_text_locator (self , drug_type : str , drug_number : int ) -> Locator :
1008+ """
1009+ Returns the drug dosage text locator for the matching drug type and number
1010+ Args:
1011+ drug_type (str): The drug type to check
1012+ drug_number (int): The number of the drug to check
1013+ """
1014+ if drug_type == self .bowel_preparation_administered_string :
1015+ locator_prefix = "#HILITE_spanBowelPrepDrugDosageUnit"
1016+ elif drug_type == self .antibiotics_administered_string :
1017+ locator_prefix = "#HILITE_spanAntibioticDosageUnit"
1018+ return self .page .locator (f"{ locator_prefix } { drug_number } " )
1019+
9431020
9441021def normalize_label (text : str ) -> str :
9451022 """
@@ -1276,3 +1353,62 @@ class PolypReasonLeftInSituOptions(StrEnum):
12761353 REQUIRES_SURGICAL_RESECTION = "200558"
12771354 CANNOT_FIND_POLYP_ON_WITHDRAWAL = "200559"
12781355 CLINICAL_DECISION_NOT_TO_EXCISE = "203082"
1356+
1357+
1358+ class AntibioticsAdministeredDrugTypeOptions (StrEnum ):
1359+ """Enum for antobiotics administered drug type options"""
1360+
1361+ AMOXYCILLIN = "17941~g"
1362+ CEFOTAXIME = "17950~g"
1363+ CIPROFLAXACIN = "17945~mg"
1364+ CO_AMOXICLAV = "17951~mg"
1365+ GENTAMICIN = "17942~mg"
1366+ METRONIDAZOLE = "17949~mg"
1367+ TEICOPLANIN = "17944~mg"
1368+ VANCOMYCIN = "17943~g"
1369+ OTHER_ANTIBIOTIC = "305493"
1370+
1371+
1372+ # Registry of all known Enums to search when matching string values
1373+ ALL_ENUMS : List [type [Enum ]] = [
1374+ obj
1375+ for obj in globals ().values ()
1376+ if (
1377+ isinstance (obj , type )
1378+ and issubclass (obj , Enum )
1379+ and obj is not Enum
1380+ and obj is not StrEnum # Exclude only the base classes, not subclasses
1381+ )
1382+ ]
1383+
1384+
1385+ def to_enum_name_or_value (val : Any ) -> Union [str , Any ]:
1386+ """
1387+ Convert an Enum member or matching string value to its Enum name.
1388+
1389+ If the input is:
1390+ - An Enum member → returns the `.name` (e.g., "KLEAN_PREP")
1391+ - A string matching any Enum value in ALL_ENUMS → returns that member's `.name`
1392+ - Anything else → returns the value unchanged
1393+
1394+ Args:
1395+ val (Any): The value to convert. Can be an Enum member, a string,
1396+ or any other type.
1397+
1398+ Returns:
1399+ Union[str, Any]: The Enum name (string) if matched, otherwise the original value.
1400+ """
1401+ # Directly handle Enum instances
1402+ if isinstance (val , Enum ):
1403+ return val .name
1404+
1405+ # Handle strings that match known Enum values
1406+ if isinstance (val , str ):
1407+ for enum_cls in ALL_ENUMS :
1408+ try :
1409+ return enum_cls (val ).name
1410+ except ValueError :
1411+ continue
1412+
1413+ # Fallback: return unchanged
1414+ return val
0 commit comments