class ConsentFormView(view.View): post_url = 'consent-form' def load(self, expectedInfo=None, editMode=False): try: WDW(self.driver, 20).until_not(EC.presence_of_element_located((By.CLASS_NAME, 'overlay'))) self.util = UtilityFunctions(self.driver) self.menu = menu.Menu(self.driver) self.header = header.AuthHeader(self.driver) # print('0') # Verify consent form is in expected mode (normal or edit) if self.edit_mode() != editMode: print('ConsentForm: Incorrect mode. Expected editMode ' + str(editMode)) return False self.form = self.driver.find_elements_by_tag_name('form')[1] # print('1') try: self.facility_name = self.form.find_elements_by_class_name('font-weight-bold')[1].text except NoSuchElementException: # Facility name is not required field on previous page (for now) self.facility_name = None # print('2') self.load_preferences() # print('3') self.other_input = self.form.find_element_by_id('other_value') # print('4') # Patient Info self.first_name = self.form.find_element_by_id('patient_firstName') self.last_name = self.form.find_element_by_id('patient_lastName') self.rep_first_name = self.form.find_element_by_id('representative_firstName') self.rep_last_name = self.form.find_element_by_id('representative_lastName') self.date_input = self.form.find_element_by_id('dateField') # print('5') # Portal Info self.load_portal_login_info(editMode) # print('6') # Order is not same as displayed on page (float right) self.buttons = self.form.find_elements_by_class_name('green-hvr-bounce-to-top') self.agree_button = self.buttons[0] self.do_not_agree_button = self.buttons[1] self.print_button = self.buttons[2] self.back_button = self.buttons[3] # print('7') return self.validate(expectedInfo) except (NoSuchElementException, StaleElementReferenceException, IndexError) as e: return False def edit_mode(self): # Is consent form in edit mode? try: # Look for edit button for Portal Login Information el = self.driver.find_element_by_class_name('info-edit') return True except NoSuchElementException: return False def load_portal_login_info(self, editMode): self.edit_login_info_button = self.try_load_edit_login_info_button() if editMode and self.login_info_mode() == 'noneditable': # No inputs. Load text as values vals = self.driver.find_elements_by_class_name('account-val') self.username = self.util.get_text(vals[0]) self.password = self.util.get_text(vals[1]) self.url = self.util.get_text(vals[2]) else: # Editable. Load input elements self.username = self.form.find_element_by_id('portal_username') self.password = self.form.find_element_by_id('portal_password') self.url = self.form.find_element_by_id('portal_url') def try_load_edit_login_info_button(self): # Button for entering edit mode for 'Patient Portal Login Information' # Only exists when editing consent form try: return self.driver.find_element_by_class_name('info-edit') except NoSuchElementException: return None def login_info_mode(self): # Is login information editable? try: # Look for non-editable fields els = self.driver.find_elements_by_class_name('account-val') if len(els) == 3: return 'noneditable' except NoSuchElementException: return 'editable' def validate(self, expectedInfo): failures = [] if len(self.buttons) != 4: failure.append('ConsentForm: Unexpected number of form buttons. Loaded ' + str(len(self.buttons))) if len(self.preference_inputs) != 12: failure.append('ConsentForm: Unexpected number of preference inputs. Loaded ' + str(len(self.preference_inputs))) if expectedInfo: # Validate facilities pass if len(failures) > 0: for failure in failures: print(failure) return False return True def load_preferences(self): self.preference_inputs = self.form.find_elements_by_class_name('checkbox-custom') self.preferences = {} for inputEl in self.preference_inputs: inputId = inputEl.get_attribute('id') self.preferences[inputId] = inputEl # 'access_all_records' # 'lab_reports' # 'history' # 'admission' # 'medication' # 'xray' # 'paperwork' # 'consult' # 'mental' # 'alcohol' # 'hiv' # 'other' def set_preferences(self, info, other_comment=None): for key in self.preferences: if key in info: # Make sure it's selected if not self.preferences[key].is_selected(): self.util.click_el(self.preferences[key]) else: # Make sure it's de-selected if self.preferences[key].is_selected(): self.util.click_el(self.preferences[key]) if other_comment: self.util.set_input(self.other_input, other_comment) def get_preferences(self): selected_preferences = [] for inputEl in self.preference_inputs: if inputEl.is_selected(): selected_preferences.append(inputEl.get_attribute('id')) return selected_preferences def set_patient_info(self, info, inputMethod='typed'): # Patient if 'first name' in info: self.util.set_input(self.first_name, info['first name']) if 'last name' in info: self.util.set_input(self.last_name, info['last name']) # Representative (optional) if 'rep first name' in info: self.util.set_input(self.rep_first_name, info['rep first name']) if 'rep last name' in info: self.util.set_input(self.rep_last_name, info['rep last name']) # Date if 'date' in info: self.set_date(info['date'], inputMethod) def get_patient_info(self, current_date=True): patient_info = {} patient_info['first name'] = self.first_name.get_attribute('value') patient_info['last name'] = self.last_name.get_attribute('value') patient_info['rep first name'] = self.rep_first_name.get_attribute('value') patient_info['rep last name'] = self.rep_last_name.get_attribute('value') if current_date: # Return 'current' if date is today's date self.util.click_el(self.date_input) self.picker = singleDatePicker.SingleDatePicker(self.driver) patient_info['date'] = self.picker.has_current_date() else: patient_info['date'] = self.date_input.get_attribute('value') return patient_info def set_date(self, date, inputMethod='typed'): if inputMethod == 'typed': self.util.set_input(self.date_input, date) # Typing value via selenium won't update date displayed on picker. Need to press enter self.date_input.send_keys(Keys.RETURN) elif inputMethod == 'picker': self.util.click_el(self.date_input) self.picker = singleDatePicker.SingleDatePicker(self.driver) self.picker.set_date(date) def compare_date(self, date, date_source='input'): # Compare given date w/ value of (input) or (picker) if date_source == 'input': now = datetime.datetime.now() curDate = now.strftime("%m/%d/%Y") return curDate == self.date_input.get_attribute('value') elif date_source == 'picker': self.util.click_el(self.date_input) self.picker = singleDatePicker.SingleDatePicker(self.driver) picker_date = self.picker.get_date() print(str(picker_date['date']) + ' == ' + str(date)) return date == picker_date['date'] def set_portal_info(self, info): if self.edit_mode() and self.login_info_mode() == 'uneditable': self.util.click_el(self.edit_login_info_button) time.sleep(.4) self.load() if info.get('username', None): self.util.set_input(self.username, info['username']) if info.get('password', None): self.util.set_input(self.password, info['password']) if info.get('url', None): self.util.set_input(self.url, info['url']) def get_portal_info(self): portal_info = {} editMode = self.edit_mode() portalInfoMode = self.login_info_mode() if editMode and portalInfoMode == 'noneditable': # Info is not editable. Password will be replaced w/ * characters portal_info['username'] = self.username portal_info['password'] = self.password portal_info['url'] = self.url else: portal_info['username'] = self.username.get_attribute('value') portal_info['password'] = self.password.get_attribute('value') portal_info['url'] = self.url.get_attribute('value') return portal_info def action(self, action='submit'): if action == 'submit': self.util.click_el(self.agree_button) elif action == 'back': self.util.click_el(self.back_button) elif action == 'do not agree': self.util.click_el(self.do_not_agree_button)
class EditTreatmentPopup(): def __init__(self, driver): self.driver = driver self.util = UtilityFunctions(self.driver) def load(self, expectedValues=None): WDW(self.driver, 10).until_not(EC.presence_of_element_located((By.CLASS_NAME, 'overlay'))) self.container = self.driver.find_element_by_class_name('editroll') # Should only 1 on T&O view self.buttons = self.container.find_elements_by_class_name('green-hvr-bounce-to-top') return self.validate(expectedValues) def validate(self, expectedValues): self.failures = [] # Basic validation if len(self.buttons) != 2: self.failures.append('editTreatmentPopup: Expected 2 buttons, loaded ' + str(len(self.buttons))) if self.util.get_text(self.buttons[0]) != 'CANCEL': self.failures.append('editTreatmentPopup: Unexpected text on cancel button: ' + self.util.get_text(self.buttons[0])) if self.util.get_text(self.buttons[1]) != 'SAVE': self.failures.append('editTreatmentPopup: Unexpected text on save button: ' + self.util.get_text(self.buttons[1])) if expectedValues: print('editTreatmentPopup: Need to validate expectedValues') if len(self.failures) > 0: for failure in self.failures: print(failure) return False return True def parse_select_all(self, questionInfo, questionCont): done = False count = 0 while not done and count < 5: try: # Select options in specified in optionInfo # De-selecting options not contained in optionInfo name_checker = ['Severity of the side effects', 'Cost of the treatment', 'Too much travel'] radios = questionCont.find_elements_by_class_name('radio') suboption_filter = [] # Add index of any suboptions radio buttons to this list. Skip over them for i, radio in enumerate(radios): if i not in suboption_filter: inputs = radio.find_elements_by_tag_name('input') spans = radio.find_elements_by_tag_name('span') if len(inputs) == 0: print('EditTreatmentForm: radio option has no inputElements?') elif len(spans) == 0: print('EditTreatmentForm: radio option has no spanElements?') optionName = self.util.get_text(spans[0]) print('optionName: ' + optionName) optionInput = inputs[0] optionInfo = questionInfo.get(optionName, False) # raw_input('optionInfo: ' + str(optionInfo)) subOptions = False if optionInfo != False: # select input, enter comment, check for subquestions if not optionInput.is_selected(): self.util.click_radio(optionInput) self.util.set_input(radio, optionInfo.get('comment', '')) # Check for suboptions or select-all subOptions = optionInfo.get('options', False) if not subOptions: subOptions = optionInfo.get('select-all', False) else: # De-select, clear comment, update inputs (might have hidden subquestions) if optionInput.is_selected(): self.util.click_radio(optionInput) self.util.set_input(radio, '') inputs = radio.find_elements_by_tag_name('input') # Don't iterate over suboptions if len(inputs) > 1: for inputIndex, inputEl in enumerate(inputs): if inputIndex > 0: print('skipping ' + str(i + inputIndex)) suboption_filter.append(i + inputIndex) if subOptions: self.parse_select_all(subOptions, radio) done = True except StaleElementReferenceException: print('failed to parse select-all: ' + str(count)) count += 1 time.sleep(.2) if count == 5: print('EditTreatmentPopup: failed to parse select-all') def parse_complex(self, complexInfo, questionCont): # For questions w/ multiple sections (sideEffects, chemotherapy drugs, medications added/removed) # Loop through complexInfo and select given options for each category # De-select options not contained in complexInfo # Wait for categories to show up categories = None loaded = False count = 0 while not loaded and count < 5: # Doesn't immediately load categories = questionCont.find_elements_by_class_name('col-md-6') if categories: loaded = True else: time.sleep(.2) count += 1 question = {} for i, category in enumerate(categories): # Has issues loading category name sometimes. # Make sure it's loaded before looking for options loadedCategoryName = False count = 0 while not loadedCategoryName and count < 5: try: categoryName = self.util.get_text(category.find_element_by_class_name('treatment-group')) loadedCategoryName = True except NoSuchElementException: categoryName = None if categoryName: # Loaded name! Parse through category options categoryOptions = complexInfo.get(categoryName, False) options = {} for radio in category.find_elements_by_class_name('radio'): inputs = radio.find_elements_by_tag_name('input') labels = radio.find_elements_by_tag_name('label') label = labels[0] optionName = self.util.get_text(label) optionInput = label.find_element_by_tag_name('input') optionInfo = False if categoryOptions: optionInfo = categoryOptions.get(optionName, False) if optionInfo != False: # select input, enter comment/intensity if not optionInput.is_selected(): self.util.click_radio(optionInput) self.util.set_input(radio, optionInfo.get('comment', '')) self.set_intensity(radio, optionInfo.get('intensity', None)) else: # De-select, clear comment, update inputs (might have hidden subquestions) if optionInput.is_selected(): self.util.click_radio(optionInput) self.util.set_input(radio, '') inputs = radio.find_elements_by_tag_name('input') else: # Failed to find categoryName count += 1 time.sleep(.2) if complexInfo.get('date', None): print('complex question has date. Need to set it') def set_intensity(self, container, value): try: sliderEl = container.find_element_by_class_name('rc-slider-handle') except NoSuchElementException: print('SideEffectsForm: failed to load sliderEl') curValue = sliderEl.get_attribute('aria-valuenow') # Need to change intensity value? if value != curValue: xOffset = None # Every time offset doesn't work, increase by 5 and try again additionalOffset = 0 while str(curValue) != str(value) and additionalOffset < 50: if curValue != 1: # reset to base position AC(self.driver).drag_and_drop_by_offset(sliderEl, -200, 0).perform() # Calculate offset # Note: monitor and window sizes affect this. if xOffset != None: # First offset wasn't correct. Increment amount of offset additionalOffset += 4 xOffset = 11*(value - 1) + additionalOffset AC(self.driver).drag_and_drop_by_offset(sliderEl, xOffset, 0).perform() curValue = sliderEl.get_attribute('aria-valuenow') def set_input(self, container, value): # Return if able to set value into textarea or input in container. try: textareaEl = container.find_element_by_tag_name('textarea') textareaEl.clear() textareaEl.send_keys(value) return True except NoSuchElementException: try: inputEl = container.find_element_by_tag_name('input') if inputEl.get_attribute('type') == 'text': inputEl.clear() inputEl.send_keys(value) return True except NoSuchElementException: return False def edit_treatment(self, newInfo, popupType, action='save'): # Submit info if popupType == 'side effects': self.parse_complex(newInfo['options'], self.container) elif popupType == 'outcomes': self.parse_select_all(newInfo['options'], self.container) # Save or cancel if action == 'save': self.util.click_el(self.buttons[1]) elif action == 'cancel': self.util.click_el(self.buttons[0]) WDW(self.driver, 15).until_not(EC.presence_of_element_located((By.CLASS_NAME, 'overlay'))) return True