# Subject/Title: LDT -2280 Patient Vitals - SW - 02 - Q&R - 15: SIT - Software Integration Tests - Squish Qt # # Functionalities: Testing all functionalities of Patient Vitals in the main treatment screen # # Steps: # 1 Patient Vitals: # - Verify the Systolic minimum,mid and maximum values in Vital Popup # - Verify the Diastolic minimum ,mid and maximum values in Vital Popup # - Verify the Heart Rate minimum,mid and maximum values in Vital Popup # - Verify the time intervals in the vital interval Popup # - Verify the vitals popup is opened automatically once the BPM interval time is elapsed when the rejection reason is 1 # - Verify the confirm button is disabled when user enters out of range values in the systolic, diastolic and heart rate parameters # - Verify the vitals interval time with current system time # Python import os import can # plugin specific from leahi_dialin.common.msg_defs import MsgIds, MsgFieldPositions from leahi_dialin.protocols import CAN from leahi_dialin.utils import conversions import names import time import builtins from leahi_dialin.ui import utils from configuration import utility from configuration import config from leahi_dialin.ui.td_messaging import TD_Messaging from leahi_dialin.common.td_defs import TDOpModes,TDTreatmentStates from datetime import datetime import squish td =TD_Messaging() can_interface = td.can_interface def keyboard_object_map_helper(text): """ Method for setting custom object property's for keyboard keys @return: required object property's for keys """ if text is not None: names.keyboard_input["text"] = text return names.keyboard_input else: test.log("Invalid ",text," for object.") names.o_keyboard_input["text"] = "Q" def verify_valid_vitals_through_keypad(title_name,input_field_obj,expected_value, actual_value): """ Tests verifies valid patient id set through application keyboard setup . @return: N/A """ input_field = waitForObject(input_field_obj) mouseClick(input_field) #check the title title = waitForObjectExists(utility.setObjectText(text = title_name,obj =names.o_title_Text)) test.compare(title_name, title.text, "Title text should be -> "+ str(title_name)) for text in expected_value: keyboard_value = keyboard_object_map_helper(text) utils.waitForGUI(0.2) mouseClick(waitForObjectExists(keyboard_value)) utils.waitForGUI(0.2) test.compare(actual_value, (input_field.text), "Value should be -> "+ str(actual_value)) test.log("User successfully authenticated through patient id -> " + expected_value + "using keypad.") def verify_vitals_pop_up_is_opened_automatically_after_an_interval(interval): """ Method to verify the vitals pop up is opened automatically once the BPM interval time is elapsed @param interval - (int) interval in min """ test.startSection("Verify the vitals pop up opened automatically after interval time is elapsed") sec = interval*60 start_time = time.time() sec_count = 0 while not(object.exists(names.o_vitals_close_btn)): sec_count += 1 end_time = time.time() if sec_count in range(295, 301): test.log("Dialog close button be visible after {}".format(sec)) close_btn = waitForObject(names.o_vitals_close_btn) total_elapsed_time = end_time - start_time test.log("Total elapsed time : {}".format(total_elapsed_time)) test.compare(close_btn.visible, config.VISIBLE, "Popup close option is visible after the vitals pop up is opened automatically") reason_text = waitForObjectExists(utility.setObjectText(text = "Rejected Reason: [1] Request is not allowed in the current operating mode",obj =names.o_title_Text)) test.compare(reason_text.text, "Rejected Reason: [1] Request is not allowed in the current operating mode", "Rejection reason text should be"+str("Rejected Reason: [1] Request is not allowed in the current operating mode")) test.endSection() def verify_last_read_time(interval): test.startSection("Verify the last read time") sec = interval*60 start_time = time.time() sec_count = 0 while not(object.exists(names.o_vitals_close_btn)): sec_count += 1 end_time = time.time() if sec_count in range(295, 301): test.log("Dialog close button be visible after {}".format(sec)) total_elapsed_time = end_time - start_time def erase_entered_value(input_field): """ Method to erase the entered value @param input_field - (obj) object of input field """ test.startSection("Erasing value") input_field= squish.waitForObject(input_field) entered_value = str(input_field.text) if len(entered_value) != 0: for value in range(len(entered_value)+1): squish.mouseClick(squish.waitForObjectExists(names.o_back_space_key)) test.compare(str(input_field.text), "", "Input field should be empty") test.endSection() def clear_BP_and_HR_settings(): #clearing systolic field #Add start section and end section mouseClick(waitForObject(names.o_vitalsButton_VitalsButton)) systolic = waitForObject(names.o_bloodPressureSystolic_TextEntry) mouseClick(systolic) erase_entered_value(input_field=systolic) #clear diastolic field diastolic = waitForObject(names.o_bloodPressureDiastolic_TextEntry) mouseClick(diastolic) erase_entered_value(diastolic) #Clearing HR field hr = waitForObject(names.o_heartRate_TextEntry) mouseClick(hr) erase_entered_value(hr) def verify_the_popup_with_rejectionReason(): """ Method to check the popup is opened automatically after time interval """ vitalsrequest = False # mouseClick(waitForObject(names.o_treatmentHome_editButton_IconButton)) test.startSection("Verify popup is opened automatically after time interval") mouseClick(waitForObject(names.o_vitalsButton_VitalsButton)) td.td_vitals( systolic = 70, diastolic = 50, heartRate = 120 ) td.td_vitals_adjustment_response(vRejectionReason=1) verify_vitals_pop_up_is_opened_automatically_after_an_interval(interval=5) test.verify(waitFor("'vitalsrequest == True'", 1000), "UI Sending the request to FW") test.endSection() def validate_time_interval(vital_interval_obj, int_min): """ vm_time_obj: Object name/path that displays VM time (HH:MM) vitals interval_obj: Object name/path that displays remaining time (MM:SS) interval_minutes: Integer (ex: 5, 10, 15 ...) """ vm_time_str = str(utility.get_current_date_and_time(date_format='%H:%M:%S')).strip() try: hh, mm, ss = vm_time_str.split(":") print(f"current time: {vm_time_str}") except Exception as e: test.fail(f"Invalid VM time format: {vm_time_str}, error={e}") # Compute interval start time # Example: interval=5, vm=09:01 -> start = 09:05 - 5 = 09:00 interval_seconds =int_min *60 # Expected remaining seconds elapsed =(builtins.int(mm) * 60)% interval_seconds + builtins.int(ss) remaining_seconds = interval_seconds - elapsed # If negative, clamp to zero if remaining_seconds < 0: remaining_seconds = 0 # Convert to MM:SS expected_mm = remaining_seconds // 60 expected_ss = remaining_seconds % 60 expected_str = f"{expected_mm:02d}:{expected_ss:02d}" #Read UI displayed remaining time (MM:SS) utils.waitForGUI(2) #After changing the time interval to update the value in UI ui_str = str(waitForObject(vital_interval_obj,1000).text).strip() fmt = "%M:%S" expected_time = datetime.strptime(expected_str, fmt) actual_time = datetime.strptime(ui_str, fmt) diff = abs((actual_time - expected_time).total_seconds()) if diff <= 2: test.log(f"Remaining time is correct: {ui_str}") else: test.fail(f"Remaining time incorrect. Expected {expected_str}, got {ui_str}") # handler for messages from UI to FW def handle_patient_vitals_request( message): """ Called when the user requests to firmware from UI @return: None """ message = message['message'] index = MsgFieldPositions.START_POS_FIELD_1 index = conversions.bytearray_to_integer( message, index) global vitalsrequest vitalsrequest = True def verify_automatic_vitals_noRejection_Reason(): global vitalsrequest vitalsrequest = False MAX_WAIT = 5 * 60 # 5 minutes in seconds POLL_INTERVAL = 5 # check every 5 seconds mouseClick(waitForObject(names.o_vitalsButton_VitalsButton)) mouseClick(names.o_measureVitalsButton_TouchRect) td.td_vitals( systolic = 70, diastolic = 50, heartRate = 120 ) test.verify(waitFor("'vitalsrequest == True'", 1000), "UI Sending the request to FW") td.td_vitals_adjustment_response(vRejectionReason=0) start_time = time.time() while time.time() - start_time < MAX_WAIT: if vitalsrequest: td.td_vitals(systolic = 80, diastolic = 60, heartRate = 140 ) break time.sleep(POLL_INTERVAL) else: test.log("Condition not satisfied within 5 minutes. Exiting loop.") blood_pressure = waitForObjectExists(names.o_treatmentHome_bloodPressure_LabelValue).topText test.compare("70"+"/"+"50", blood_pressure,"Blood pressure value should be ->"+str("80"+"/"+"60")) heart_rate = waitForObjectExists(names.o_treatmentHome_heartBeat_LabelValue).topText test.compare("120", heart_rate,"Heart Rate value should be ->"+str(120)) def main(): utils.tstStart(__file__) if can_interface is not None: channel_id = CAN.DenaliChannels.ui_to_td_ch_id message_id = MsgIds.MSG_ID_UI_BLOOD_PRESSURE_REQUEST.value can_interface.register_receiving_publication_function(channel_id, message_id, handle_patient_vitals_request) startApplication(config.AUT_NAME) td.td_operation_mode(TDOpModes.MODE_STAN.value) # verify Standby screen test.verify(waitForObjectExists(names.o_standByScreen_MainHome), "In Standby") mouseClick(waitForObject(names.o_createTreatmentRect_TouchRect)) td.td_operation_mode(TDOpModes.MODE_PRET.value, 0) test.startSection("Create the pretreatment values") utility.verify_create_treatment_parameters() test.endSection() test.startSection("Verify the minimum values in the vitals popup") # td.td_operation_mode(TDOpModes.MODE_TREA.value, 0) td.td_tx_state(TDTreatmentStates.TREATMENT_DIALYSIS_STATE.value , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0) mouseClick(waitForObject(names.o_vitalsButton_VitalsButton)) verify_valid_vitals_through_keypad(config.SYSTOLIC,names.o_bloodPressureSystolic_TextEntry,config.MIN_SYSTOLIC,config.MIN_SYSTOLIC) verify_valid_vitals_through_keypad(config.DIASTOLIC,names.o_bloodPressureDiastolic_TextEntry,config.MIN_DIASTOLIC,config.MIN_DIASTOLIC) verify_valid_vitals_through_keypad(config.HEARTRATE, names.o_heartRate_TextEntry, config.MIN_HEARTRATE, config.MIN_HEARTRATE) mouseClick(waitForObject(names.o_confirm_button)) blood_pressure = waitForObjectExists(names.o_treatmentHome_bloodPressure_LabelValue).topText test.compare(config.MIN_SYSTOLIC+"/"+config.MIN_DIASTOLIC, blood_pressure,"Blood pressure value should be ->"+str(config.MIN_SYSTOLIC+"/"+config.MIN_DIASTOLIC)) heart_rate = waitForObjectExists(names.o_treatmentHome_heartBeat_LabelValue).topText test.compare(config.MIN_HEARTRATE, heart_rate,"Heart Rate value should be ->"+str(config.MIN_HEARTRATE)) test.endSection() test.startSection("Verify the maximum values in the vitals popup") mouseClick(waitForObject(names.o_vitalsButton_VitalsButton)) verify_valid_vitals_through_keypad(config.SYSTOLIC,names.o_bloodPressureSystolic_TextEntry,config.MAX_SYSTOLIC,config.MAX_SYSTOLIC) verify_valid_vitals_through_keypad(config.DIASTOLIC,names.o_bloodPressureDiastolic_TextEntry,config.MAX_DIASTOLIC,config.MAX_DIASTOLIC) verify_valid_vitals_through_keypad(config.HEARTRATE, names.o_heartRate_TextEntry, config.MAX_HEARTRATE, config.MAX_HEARTRATE) mouseClick(waitForObject(names.o_confirm_button)) blood_pressure = waitForObjectExists(names.o_treatmentHome_bloodPressure_LabelValue).topText test.compare(config.MAX_SYSTOLIC+"/"+config.MAX_DIASTOLIC, blood_pressure,"Blood pressure value should be ->"+str(config.MAX_SYSTOLIC+"/"+config.MAX_DIASTOLIC)) heart_rate = waitForObjectExists(names.o_treatmentHome_heartBeat_LabelValue).topText test.compare(config.MAX_HEARTRATE, heart_rate,"Heart Rate value should be ->"+str(config.MAX_HEARTRATE)) test.endSection() test.startSection("Verify the confirm button is disabled when user enter invalid values") mouseClick(waitForObject(names.o_vitalsButton_VitalsButton)) verify_valid_vitals_through_keypad(config.SYSTOLIC,names.o_bloodPressureSystolic_TextEntry,config.SYSTOLIC_251,config.SYSTOLIC_251) verify_valid_vitals_through_keypad(config.DIASTOLIC,names.o_bloodPressureDiastolic_TextEntry,config.DIASTOLIC_201,config.DIASTOLIC_201) verify_valid_vitals_through_keypad(config.HEARTRATE, names.o_heartRate_TextEntry, config.HEARTRATE_181, config.HEARTRATE_181) confirm_button =waitForObjectExists(names.o_confirm_button) test.verify(not confirm_button.enabled, "Confirm button is not enabled") mouseClick(waitForObject(names.o_vitals_close_btn)) test.endSection() test.startSection("Verify the vitals interval popup") mouseClick(waitForObject(names.o_treatmentHome_editButton_IconButton)) #check the title text in the popup vitals_titleText = waitForObjectExists(names.o_vitals_Interval_TitleText).text test.compare("Vitals Interval", vitals_titleText, "Vitals Interval popup text should be ->"+str("Vitals Interval")) utility.set_value_based_on_target(names.o_bpMeasurementIntervalControl_ValueAdjusterCustom, 5) mouseClick(waitForObject(names.o_vitals_close_btn)) test.endSection() test.startSection("Verify the vitals data send automatically populate on popup") verify_automatic_vitals_noRejection_Reason() #With rejection reason verify_the_popup_with_rejectionReason() test.endSection() test.startSection("Verify the last read time in the UI") mouseClick(waitForObject(names.o_vitalsButton_VitalsButton)) verify_valid_vitals_through_keypad(config.SYSTOLIC,names.o_bloodPressureSystolic_TextEntry,config.MIN_SYSTOLIC,config.MIN_SYSTOLIC) verify_valid_vitals_through_keypad(config.DIASTOLIC,names.o_bloodPressureDiastolic_TextEntry,config.MIN_DIASTOLIC,config.MIN_DIASTOLIC) verify_valid_vitals_through_keypad(config.HEARTRATE, names.o_heartRate_TextEntry,config.MIN_HEARTRATE,config.MIN_HEARTRATE) mouseClick(waitForObject(names.o_confirm_button)) sys_time = utility.get_current_date_and_time(date_format="%Y/%b/%d - %H:%M:%S") last_read = waitForObjectExists(names.o_last_read).text lastdatetime = str(last_read).split(" ")[3] systime = sys_time.split("-")[1].strip() test.compare(lastdatetime, systime, "Last read time is updated properly") test.endSection() test.startSection("Check the vitals in main treatment screen") mouseClick(waitForObject(names.o_treatmentHome_editButton_IconButton)) utility.set_value_based_on_target(names.o_bpMeasurementIntervalControl_ValueAdjusterCustom, 5) mouseClick(waitForObject(names.o_confirm_button,1000)) validate_time_interval(names.o_vitalCountdown_Text,30) mouseClick(waitForObject(names.o_treatmentHome_editButton_IconButton)) utility.set_value_based_on_target(names.o_bpMeasurementIntervalControl_ValueAdjusterCustom, 10) mouseClick(waitForObject(names.o_confirm_button,1000)) validate_time_interval(names.o_vitalCountdown_Text,5) test.endSection() utils.tstDone()