class MyelomaLabsView(view.View):
    post_url = 'myeloma-labs'

    def load(self, labInfo=None):
        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)
            self.form = self.driver.find_element_by_id('page-content-wrapper')
            buttons = self.form.find_elements_by_tag_name('button')
            inputs = self.form.find_elements_by_tag_name('input')

            self.add_new_labs = buttons[0]
            self.get_my_labs = buttons[1]  # Is this here all the time?

            # Lab Values Chart
            chart_cont = self.driver.find_element_by_class_name(
                'myeloma-labs-custom')
            self.lab_values_dropdown = chart_cont.find_element_by_tag_name(
                'button')

            # Date range options
            range_cont = self.driver.find_element_by_class_name('datenfilter')
            date_buttons = range_cont.find_elements_by_tag_name('button')
            self.three_month_button = date_buttons[0]
            self.six_month_button = date_buttons[1]
            self.year_to_date_button = date_buttons[2]
            self.one_year_button = date_buttons[3]
            self.two_year_button = date_buttons[4]
            self.five_year_button = date_buttons[5]
            self.ten_year_button = date_buttons[6]
            self.all_button = date_buttons[7]

            # Custom date range
            inputs = range_cont.find_elements_by_tag_name('input')
            self.from_date_input = inputs[0]
            self.to_date_input = inputs[1]

            # Lab Values Table
            self.load_table()

            self.continue_button = buttons[10]

            # self.validate(labInfo)
            return True
        except (NoSuchElementException, StaleElementReferenceException,
                IndexError) as e:
            return False

    def validate(self, labInfo):
        failures = []
        lInfo = self.clinical_tables[-1]
        if lInfo:
            if labInfo:
                if lInfo['dobd'] != labInfo['dobd']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['dobd']) + '"' + ' expected ' +
                                    '"' + str(labInfo['dobd']) + '"')

                # 1: Clinical Trials
                if lInfo['monoclonal'] != labInfo['monoclonal']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['monoclonal']) + '"' +
                                    ' expected ' + '"' +
                                    str(labInfo['monoclonal']) + '"')
                if lInfo['kappa'] != labInfo['kappa']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['kappa']) + '"' + ' expected ' +
                                    '"' + str(labInfo['kappa']) + '"')
                if lInfo['lambda'] != labInfo['lambda']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['lambda']) + '"' + ' expected ' +
                                    '"' + str(labInfo['lambda']) + '"')
                if lInfo['ratio'] != labInfo['ratio']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['ratio']) + '"' + ' expected ' +
                                    '"' + str(labInfo['ratio']) + '"')
                if lInfo['bone_marrow'] != labInfo['bone_marrow']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['bone_marrow']) + '"' +
                                    ' expected ' + '"' +
                                    str(labInfo['bone_marrow']) + '"')

                if lInfo['creatinine'] != labInfo['creatinine']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['creatinine']) + '"' +
                                    ' expected ' + '"' +
                                    str(labInfo['creatinine']) + '"')
                if lInfo['platelets'] != labInfo['platelets']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['platelets']) + '"' +
                                    ' expected ' + '"' +
                                    str(labInfo['platelets']) + '"')
                if lInfo['neutrophils'] != labInfo['neutrophils']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['neutrophils']) + '"' +
                                    ' expected ' + '"' +
                                    str(labInfo['neutrophili']) + '"')

                # if lInfo['blood'] != labInfo['blood']:
                # 	failures.append('Table value: ' + '"' + str(lInfo['blood']) + '"' + ' expected ' + '"' + str(labInfo['blood']) + '"')

                # 2: Current state
                if lInfo['calcium'] != labInfo['calcium']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['calcium']) + '"' +
                                    ' expected ' + '"' +
                                    str(labInfo['calcium']) + '"')
                if lInfo['blood_cell'] != labInfo['blood_cell']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['blood_cell']) + '"' +
                                    ' expected ' + '"' +
                                    str(labInfo['blood_cell']) + '"')
                if lInfo['hemoglobin'] != labInfo['hemoglobin']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['hemoglobin']) + '"' +
                                    ' expected ' + '"' +
                                    str(labInfo['hemoglobin']) + '"')
                if lInfo['lactate'] != labInfo['lactate']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['lactate']) + '"' +
                                    ' expected ' + '"' +
                                    str(labInfo['lactate']) + '"')
                if lInfo['albumin'] != labInfo['albumin']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['albumin']) + '"' +
                                    ' expected ' + '"' +
                                    str(labInfo['albumin']) + '"')
                if lInfo['immuno_g'] != labInfo['immuno_g']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['immuno_g']) + '"' +
                                    ' expected ' + '"' +
                                    str(labInfo['immuno_g']) + '"')
                if lInfo['immuno_a'] != labInfo['immuno_a']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['immuno_a']) + '"' +
                                    ' expected ' + '"' +
                                    str(labInfo['immuno_a']) + '"')
                if lInfo['immuno_m'] != labInfo['immuno_m']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['immuno_m']) + '"' +
                                    ' expected ' + '"' +
                                    str(labInfo['immuno_m']) + '"')

                if lInfo['platelets'] != labInfo['platelets']:
                    failures.append('Table value: ' + '"' +
                                    str(lInfo['platelets']) + '"' +
                                    ' expected ' + '"' +
                                    str(labInfo['platelets']) + '"')
        if self.add_new_labs.text != 'Add New Labs':
            failures.append('AddLabsView: Unexpected add new labs button text')

        if len(failures) > 0:
            for failure in failures:
                print(failure)
                return False
        return True

    def load_table(self):
        # Table with saved Lab results at bottom of page
        # Read info from each row and return dictionary
        self.clinical_tables = []

        # Table Header
        try:
            table_header = self.form.find_element_by_class_name(
                'sticky-table-header-wrapper')
        except NoSuchElementException:
            # No lab results saved (or table not displayed yet)
            return None
        header_cells = table_header.find_elements_by_class_name(
            'sticky-table-cell')
        header_keys = [
            'actions', 'dobd', 'monoclonal', 'kappa', 'lambda', 'ratio',
            'bone_marrow', 'creatine', 'platelets', 'neutrophils',
            'blood_cell', 'hemoglobin', 'lactate', 'albumin', 'immuno_g',
            'immuno_a', 'immuno_m', 'calcium'
        ]

        # Table Body
        table_body = self.form.find_element_by_class_name(
            'sticky-table-y-wrapper')
        # Actions, Lab date
        stationary_content = table_body.find_element_by_class_name(
            'sticky-table-table')
        stationary_rows = stationary_content.find_elements_by_class_name(
            'sticky-table-row')
        # self.clinical_tables.append({'delete': stationary_rows[0].find_element_by_class_name('delete')})
        # Lab fields
        sliding_content = table_body.find_element_by_class_name(
            'sticky-table-x-wrapper')
        sliding_rows = sliding_content.find_elements_by_class_name(
            'sticky-table-row')

        for rowIndex, row in enumerate(stationary_rows):
            # print(rowIndex)
            rowInfo = {}  # Info for an individual lab result
            stationary_row = row
            rowInfo['edit'] = stationary_row.find_element_by_class_name('edit')
            rowInfo['delete'] = stationary_row.find_element_by_class_name(
                'delete')
            rowInfo['date'] = stationary_row.find_elements_by_class_name(
                'sticky-table-cell')[1].text

            sliding_row = sliding_rows[rowIndex]
            cells = sliding_row.find_elements_by_class_name(
                'sticky-table-cell')
            if rowIndex < 5:
                print(len(cells))
            for cellIndex, cell in enumerate(cells):
                rowInfo[header_keys[cellIndex]] = cell.text.lower()
            if rowInfo:
                self.clinical_tables.append(rowInfo)

    def get_my_labs(self):
        self.add_new_labs.click()
        self.addLabsForm = addLabsForm.AddLabsForm(self.driver)
        WDW(self.driver, 10).until(lambda x: self.addLabsForm.load())
        self.util.click_el(self.addLabsForm.get_my_labs_button
                           )  # Should now be on /my-labs-facilities

    def add_new_lab(self, labInfo, action='save'):
        self.add_new_labs.click()
        self.addLabsForm = addLabsForm.AddLabsForm(self.driver)
        WDW(self.driver, 10).until(lambda x: self.addLabsForm.load())
        self.addLabsForm.submit(labInfo, 'save')
        WDW(self.driver, 3).until_not(
            EC.presence_of_element_located((By.CLASS_NAME, 'modal-dialog')))
        WDW(self.driver, 10).until_not(
            EC.presence_of_element_located((By.CLASS_NAME, 'overlay')))

    def edit_delete_lab(self,
                        testIndex=0,
                        revisedLabInfo=None,
                        action='delete',
                        popUpAction='confirm'):
        try:
            test = self.clinical_tables[testIndex]
        except IndexError:
            print('No test w/ index: ' + str(testIndex))
            return False

        if test:
            if action == 'delete':
                test['delete'].click()
                self.popUpForm = popUpForm.PopUpForm(self.driver)
                WDW(self.driver, 10).until(lambda x: self.popUpForm.load())
                self.popUpForm.confirm(popUpAction)
            else:
                test['edit'].click()
                WDW(self.driver, 10).until(lambda x: self.addLabsForm.load())
                self.addLabsForm.submit(revisedLabInfo, 'save')

            return True

    def delete_all_labs(self):
        while self.clinical_tables:
            self.edit_delete_lab()
            time.sleep(2)
            self.load()
class SingleDatePicker():
    def __init__(self, driver):
        self.driver = driver
        self.util = UtilityFunctions(self.driver)
        self.months = [
            'January', 'February', 'March', 'April', 'May', 'June', 'July',
            'August', 'September', 'October', 'November', 'December'
        ]
        count = 0
        loaded = False
        while not loaded and count < 5:
            loaded = self.load()
            count += 1
            time.sleep(.2)

    def load(self):
        try:
            self.container = self.load_container()
            if self.container:
                self.month = self.container.find_element_by_class_name(
                    'cur-month')
                self.year = self.container.find_element_by_class_name(
                    'cur-year')
                self.day_cont = self.container.find_element_by_class_name(
                    'dayContainer')

                self.today = self.try_load_today()
                self.selected_day = self.try_load_selected_day()
                return True
            else:
                print('singleDatePicker: Could not find an open container')

        except NoSuchElementException:
            print('failed to load datepicker')
        return False

    def load_container(self):
        # For some reason has multiple 'months' of dates loaded. Month actually displayed is in last container
        containers = self.driver.find_elements_by_class_name(
            'flatpickr-calendar')
        container = None
        for i, cont in enumerate(containers):
            classes = cont.get_attribute('class')
            if 'open' in classes:
                container = cont
        return container

    def try_load_today(self):
        # Won't have 'today' if input already has today's date or current month is not selected
        today = None
        try:
            today = self.day_cont.find_element_by_class_name('today')
        except NoSuchElementException:
            pass
        return today

    def try_load_selected_day(self):
        # May not have a day selected on displayed month (or at all)
        selectedEl = None
        try:
            selectedEl = self.day_cont.find_element_by_class_name(
                'selected').text
        except NoSuchElementException:
            pass
        return selectedEl


########################### General ##############################

    def set_date(self, date):
        # Expects 'MM/DD/YYYY' format
        if date == 'current':
            self.set_current_date()
        else:
            self.set_year(date[-4:])
            # raw_input('set year?')
            self.set_month(date[:2])
            # raw_input('set month?')
            self.set_day(date[3:5])
            # raw_input('set day?')
        self.load()

    def set_current_date(self):
        now = datetime.datetime.now()
        self.set_date(now.strftime("%m/%d/%Y"))

    def get_date(self):
        # Return datepicker's value in MM/DD/YYYY format (current selection, not input value)
        # day will be '' if nothing is selected ('MM//YYYY')
        month = self.month_int(self.month.text)
        year = self.year.get_attribute('value')
        day = self.day_int(self.selected_day)

        date = month + '/' + day + '/' + year
        return {'month': month, 'year': year, 'day': day, 'date': date}

    def set_year(self, year):
        print('setting year: ' + str(year))
        current_year = self.year.get_attribute('value')
        count = 0
        while year != current_year and count < 50:
            if current_year > year:  # 2018 > 2017
                year_down = self.container.find_element_by_class_name(
                    'arrowDown')
                self.util.click_el(year_down)
            elif current_year < year:
                year_up = self.container.find_element_by_class_name('arrowUp')
                self.util.click_el(year_up)
            time.sleep(.4)
            self.load()
            current_year = self.year.get_attribute('value')
            count += 1

    def set_month(self, month):
        print('setting month: ' + str(month))
        current_month = self.month_int(self.month.text)
        count = 0
        while current_month != month and count < 12:
            if current_month > month:
                print(str(current_month) + " > " + str(month))
                month_back = self.container.find_element_by_class_name(
                    'flatpickr-prev-month')
                self.util.click_el(month_back)
            elif current_month < month:
                print(str(current_month) + " < " + str(month))
                month_next = self.container.find_element_by_class_name(
                    'flatpickr-next-month')
                self.util.click_el(month_next)
            time.sleep(.4)
            self.load()
            current_month = self.month_int(self.month.text)
            count += 1

    def set_day(self, day):
        print('setting day: ' + str(day))
        errorFree = False
        count = 0
        while not errorFree and count < 10:
            try:
                days = self.day_cont.find_elements_by_class_name(
                    'flatpickr-day')
                for i, dayEl in enumerate(days):
                    classes = dayEl.get_attribute('class')
                    if 'nextMonthDay' not in classes and 'prevMonthDay' not in classes:
                        # print(dayEl.text)
                        if int(dayEl.text) == int(day):
                            # print('clicking ' + dayEl.text)
                            self.util.click_el(dayEl)
                            errorFree = True
            except StaleElementReferenceException:
                print('failed to set day: ' + str(count))
            count += 1

    def validate_month(self, month):
        # Compare 'month' to picker's current month (MM format)
        matches = True
        # print('picker month: ' + str(self.month.text))
        # print('expected raw: ' + str(month))
        # print('expected parsed: ' + self.months[self])
        if self.months[month - 1] != self.month.text:
            matches = False
        return matches

    def validate_day(self, day):
        # Compare 'day' to picker's current day (DD format)
        # Pass in None if not expecting a day selected
        # if self.selected_day:
        #   print('picker day: ' + str(self.selected_day.text))
        # else:
        #   print('picker day: None')
        # print('expected: ' + str(day))
        matches = False
        if day == self.selected_day or day == self.selected_day.text:  # No day selected or values match
            matches = True
        return matches

    def validate_year(self, year):
        # Compare 'year' to picker's current year (YYYY format)
        # print('picker year: ' + str(self.year.get_attribute('value')))
        # print('expected year: ' + str(year))
        matches = True
        if self.year.get_attribute('value') != str(year):
            matches = False
        return matches

    def has_current_date(self):
        # Return 'current' if picker has today's date
        now = datetime.datetime.now()
        currentDate = 'current'
        now.strftime("%m/%d/%Y")

        if int(now.strftime("%Y")) != int(self.year.get_attribute('value')):
            print('Not current year: ' + str(
                now.strftime("%Y") + ', ' +
                str(self.year.get_attribute('value'))))
            currentDate = False
        if self.months[now.month - 1] != self.month.text:
            print('Not current month: ' + self.months[now.month - 1] + ', ' +
                  str(self.month.text))
            currentDate = False
        if int(now.day) != int(self.selected_day):
            print('Not current day: ' + str(now.day) + ', ' +
                  self.selected_day)
            currentDate = False
        return currentDate

    def month_int(self, value):
        # Given name of month, return string of name converted to integer (January = '01')
        return str(self.months.index(value) + 1).zfill(2)

    def day_int(self, value):
        if value:
            return value.zfill(2)
        else:
            return ''
Beispiel #3
0
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 TreatmentsOutcomesView(view.View):
    post_url = 'about-me'

    def load(self, expectedValues=None, expectedState=None):
        try:
            WDW(self.driver, 10).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)
            self.state = self.load_state()
            if expectedState and expectedState != self.state:
                print('Wrong state! Expected ' + str(expectedState) +
                      ', got ' + str(self.state))
                return False
            if self.state == 'fresh':
                self.newAccountPopUpForm = newAccountPopUpForm.NewAccountPopUpForm(
                    self.driver)
                # load new popup
                # todo: need new account to get this state
                pass
            else:
                try:
                    # Only shows up when certain diagnoses are selected on 'Myeloma Diagnosis'
                    self.view_options_button = self.driver.find_element_by_class_name(
                        'treatment_op_btn')
                except NoSuchElementException:
                    self.view_options_button = None
                self.load_add_treatment_button()
                self.saved_tests = self.driver.find_elements_by_class_name(
                    'table_container')
            return self.validate(expectedValues)
        except (NoSuchElementException, StaleElementReferenceException,
                IndexError) as e:
            return False

    def load_state(self):
        # New user gets popup asking whether they have received treatments before (yes/no)
        # Todo: figure out how to load popup

        # Saved treatment?
        try:
            savedTable = self.driver.find_element_by_class_name(
                'outer-mypataient-table')
            return 'saved'
        except NoSuchElementException:
            # normal?
            try:
                buttonCont = self.driver.find_element_by_class_name(
                    'custom1-add-treatment-btn')
                return 'normal'
            except NoSuchElementException:
                return 'fresh'

    def load_add_treatment_button(self):
        buttonCont = self.driver.find_element_by_class_name(
            'custom1-add-treatment-btn')
        self.add_treatments_button = buttonCont.find_elements_by_tag_name(
            'button')[0]

    def validate(self, expectedValues):
        self.failures = []

        if expectedValues:
            print('validating expectedValues')
            meta = expectedValues.get('meta', None)
            if meta:
                for key, value in meta.iteritems():
                    if key == 'num_treatments':
                        if value != len(self.saved_tests):
                            self.failures.append(
                                'Treatments&Outcomes Meta: Expected ' +
                                str(value) + ' treatments. Form has ' +
                                str(len(self.saved_tests)))
                        else:
                            print('correct number of treatents: ' + str(value))

            elif self.state == 'fresh':
                # todo: Validate text on 'fresh' popup
                print('validating fresh')
                pass
            else:
                if self.add_treatments_button and self.util.get_text(
                        self.add_treatments_button) != 'Add Treatments':
                    self.failures.append(
                        'treatmentsOutcomesView: Unexpected text on add treatment button'
                    )
                if self.state == 'saved':
                    print('validating saved')
                    # Verify tests have expected data
                    extraTypes = [
                        'bone strengtheners', 'antibiotics', 'antifungal'
                    ]
                    expectedTests = expectedValues.get('tests', {})
                    for testIndex, test in enumerate(expectedTests):
                        print('T&O: Validating test: ' + str(testIndex))
                        # Test meta data
                        testType = test['testMeta']['type']
                        numQuestions = len(test['questions'])

                        # read data out of test's table
                        # if only validating 1 test, make sure grabbing last loadedTest
                        if len(expectedTests) == 1:
                            testIndex = -1
                        savedTest = self.read_test(testIndex)
                        # raw_input('savedTest: ' + str(savedTest))
                        savedData = savedTest['testData']

                        try:
                            if testType == 'clinical':
                                self.compare_nct(savedData['nct #'], test,
                                                 testType)
                                self.compare_treatments(
                                    savedData['treatment type'], test,
                                    testType)
                            else:
                                # All other treatment types have treatments and therapy type
                                self.compare_therapy_type(
                                    savedData['therapy type'], test, testType)
                                self.compare_treatments(
                                    savedData['treatments'], test, testType)
                            if testType == 'stem cell':
                                self.compare_start_date(
                                    self.convert_date(
                                        savedData['transplant date']), test,
                                    testType)
                            else:
                                self.compare_start_date(
                                    self.convert_date(savedData['start date']),
                                    test, testType)
                                self.compare_end_date(
                                    self.convert_date(savedData['end date']),
                                    test, testType)

                            if testType in extraTypes:  # Bone Strengtheners, Antibiotics, Antifungal
                                self.compare_frequency(savedData['frequency'],
                                                       test, testType)
                            else:  # Chemo, Radiation, Stem Cell
                                self.compare_side_effects(
                                    savedData['side effects'], test, testType)
                                self.compare_outcome(savedData['outcome'],
                                                     test, testType)
                        except KeyError:
                            print(savedData)
                            raw_input('keyerror: ?')

                elif self.state == 'normal':
                    print('validating normal')
                    pass

        if len(self.failures) > 0:
            print('Failures!')
            for failure in self.failures:
                print(failure)
                raise NoSuchElementException(
                    "Failed to load treatmentsOutcomesView")
        else:
            return True

    def read_test(self, testIndex):
        # 'actions': {'treatments': webEl, 'outcomes': webEl, 'sideEffects': webEl, 'delete': webEl}
        # 'testData': {
        # 	'start date': 'Jan 2018',
        # 	'end date': 'Current Treatment',
        # 	'therapy type': 'Maintenance Therapy',
        # 	'treatments': ['melphalan', 'Adriamycin (Removed On: Mar 2018) (Reason: Drug cost)'],
        # 	'side effects': {'blood clots': {'intensity': 9}, 'irregular/rapid heartbeat': {'intensity': 2}}
        # }
        testData = {}
        treatments = []
        sideEffects = {}
        actions = {}

        cont = self.saved_tests[testIndex]
        rows = cont.find_elements_by_tag_name('tr')
        testKeys = [
        ]  # ['start date', 'end date', 'therapy type', 'treatments', 'side effects']
        for rowIndex, row in enumerate(rows):
            # Header values
            if rowIndex == 0:
                tds = row.find_elements_by_tag_name('td')
                for td in tds:
                    testKeys.append(self.util.get_text(td).lower())

            # Test values
            elif rowIndex == 1:
                tds = row.find_elements_by_tag_name('td')
                for tdIndex, td in enumerate(tds):
                    key = testKeys[tdIndex]
                    if tdIndex == len(
                            tds) - 2:  # Treatments List (2nd to last td)
                        items = td.find_elements_by_class_name(
                            'treatments-lbl-span')
                        for treatment in items:
                            treatmentText = self.util.get_text(
                                treatment).lower()
                            treatments.append(treatmentText)
                        # Clinical doesn't have items (just text)
                        if not items:
                            text = self.util.get_text(td)
                            if text:
                                treatments.append(text.lower())
                            else:
                                raw_input('wtf?')
                            # try:
                            # 	treatments.append(self.util.get_text(td)).lower()
                            # except AttributeError:
                            # 	raw_input(str(key) + '?')
                        testData[key] = treatments

                    elif tdIndex == len(
                            tds) - 1:  # Last row: index=4 (3 for stem cell)
                        # Side Effects (chemo, radiation, stem cell)
                        items = td.find_elements_by_class_name(
                            'treatments-lbl-span')
                        if len(items) > 0:
                            for effect in items:
                                # Leave in upper case. Data passed in is in upper case
                                name = self.util.get_text(
                                    effect.find_element_by_tag_name('span'))
                                intensity = int(
                                    self.util.get_text(
                                        effect.find_element_by_tag_name(
                                            'div')))
                                sideEffects[name] = {'intensity': intensity}
                            testData[key] = sideEffects

                        else:  # Frequency (Bone strengtheners, antibiotics, antifungal)
                            # Only bone strengtheners have frequency (otherwise 'N/A')
                            text = self.util.get_text(td).lower()
                            print('text: ' + str(text))
                            if text:
                                testData[key] = text
                            else:  # Might have no side effects (any type of treatment)
                                testData[key] = sideEffects

                    else:  # Start date, end date, therapy type
                        testData[key] = self.util.get_text(td).lower()

            # Outcome (no outcome for bone strengtheners, antibiotics, antifungal. Table only has 3 rows)
            elif rowIndex == 2 and len(rows) == 4:
                td = row.find_elements_by_tag_name('td')[
                    1]  # text is in 2nd td
                testData['outcome'] = self.util.get_text(td).lower()

            # Actions (last row)
            elif (rowIndex + 1) == len(rows):
                anchors = row.find_elements_by_tag_name('a')
                if len(anchors) == 4:
                    actions['treatments'] = anchors[0]
                    actions['outcomes'] = anchors[1]
                    actions['sideEffects'] = anchors[2]
                    actions['delete'] = anchors[3]
                elif len(anchors
                         ) == 2:  # bone strengtheners, antibiotics, antifungal
                    actions['treatments'] = anchors[0]
                    actions['delete'] = anchors[1]

        # print('done loading test: ' + str(testIndex))
        return {
            'actions': actions,
            'testData': testData,
        }

    def convert_date(self, dateStr):
        # Input: 'mmm yyyy', Output; 'mm/yyyy'
        spaceIndex = dateStr.find(' ')  # Should always be 3
        if spaceIndex == 3:
            months = [
                'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep',
                'oct', 'nov', 'dec'
            ]
            monthName = dateStr[:3]
            year = dateStr[4:]

            month = str(months.index(monthName) + 1).zfill(2)
            return month + '/' + str(year)
        else:
            if dateStr != 'current treatment':
                print('Unexpected date format: ' + str(dateStr))
            return dateStr

    def parse_sideEffects(self, info):
        # {'cardiovascular/circulatory system': {
        # 'irregular/rapid heartbeat': {'intensity': 2},
        # 'blood clots': {'intensity': 9}}
        # }
        # converted to...
        # {u'irregular/rapid heartbeat': {'intensity': u'2'},
        # 	u'blood clots': {'intensity': u'9'}
        # }
        sideEffects = {}
        if info:
            for category in info:
                for effect, value in info[category].iteritems():
                    sideEffects[effect] = value
        return sideEffects

    def calc_start_date(self, testType, test):
        # Stem Cell: question[3] unless it's induction therapy (question[2]=yes), then it's 8
        if testType == 'stem cell':
            index = 3
            for key in test['questions'][2]['options']:
                if key.lower() == 'yes':
                    index = 8
            return index

    def compare_start_date(self, savedVal, test, testType):
        questionIndicies = {
            'stem cell': self.calc_start_date(testType, test),
            'radiation': 2,
            'chemo': 1,
            'bone strengtheners': 3,
            'antibiotics': 3,
            'antifungal': 3,
            'clinical': 2,
        }

        # Start Date (universal treatment option)
        questionIndex = questionIndicies[testType]
        expectedVal = test['questions'][questionIndex]['text']
        if savedVal != expectedVal:
            self.failures.append('T&Outcomes: Expected start date ' +
                                 str(expectedVal) + ', loaded ' +
                                 str(savedVal))
        else:
            print('correct start date')

    def compare_end_date(self, savedVal, test, testType):
        if testType == 'radiation':
            expectedVal = test['questions'][3]['text']
        elif testType == 'chemo':
            expectedVal = 'current treatment'
            if test['questions'][3]['type'] == 'date':
                expectedVal = test['questions'][3]['text']
        elif testType == 'clinical':
            expectedVal = 'current treatment'
            if test['questions'][4]['type'] == 'date':
                expectedVal = test['questions'][4]['text']
        else:
            try:
                expectedVal = test['questions'][5][
                    'text']  # If no question[5] it's 'current treatment'
            except (IndexError, KeyError) as e:
                # No end date
                expectedVal = 'current treatment'

        if savedVal != expectedVal:
            self.failures.append('T&Outcomes: Expected end date ' +
                                 str(expectedVal) + ', loaded ' +
                                 str(savedVal))
        else:
            print('correct end date')

    def compare_therapy_type(self, savedVal, test, testType):
        if testType == 'radiation':
            expectedVal = 'radiation'
        elif testType == 'stem cell':
            expectedVal = 'stem cell transplant'
        elif testType == 'chemo':
            # If it's not maintenance therapy, ExpectedVal is option from 1st question
            # Index of maintenance therapy question depends on if treatment is 'current' or not
            expectedVal = 'current treatment'
            maintenanceIndex = 3
            if test['questions'][3]['type'] == 'date':
                # Is a current treatment. Maintenance is index 4
                maintenanceIndex = 4

            isMaintenance = False
            for key in test['questions'][maintenanceIndex]['options']:
                if key.lower() == 'yes':
                    expectedVal = 'maintenance therapy'
                else:
                    # Don't pull from question options. Exact text does not match
                    expectedVal = 'Chemotherapy / Myeloma Therapy'.lower()
        else:
            for key in test['questions'][1]['options']:
                expectedVal = key.lower()

        if savedVal != expectedVal:
            self.failures.append('T&Outcomes: Expected therapyType ' +
                                 str(expectedVal) + ', loaded ' +
                                 str(savedVal))
        else:
            print('correct therapy type')

    def compare_side_effects(self, savedVal, test, testType):
        # Everything has sideEffects except for 'extra' treatments
        index = -1
        if testType == 'stem cell':
            index = -2
        expectedVal = self.parse_sideEffects(
            test['questions'][index]['options'])
        # print('expectedVal: ' + str(expectedVal))
        if savedVal != expectedVal:
            self.failures.append('T&Outcomes: Expected sideEffects ' +
                                 str(expectedVal) + ', loaded ' +
                                 str(savedVal))
        else:
            print('correct side effects')

    def compare_treatments(self, savedVal, test, testType):
        # SavedVal should be a list with all the treatment options
        expectedVal = None
        if testType == 'clinical':
            # Clinical shouldn't have multiple 'options', just text from question 4/5
            # question[4] might be stop date
            if test['questions'][4].get('type', None) == 'input':
                expectedVal = test['questions'][4].get('text', None)
            else:
                expectedVal = test['questions'][5].get('text', None)
            if expectedVal:
                expectedVal = ['clinical trial: ' + expectedVal.lower()]
        else:
            print('Not evaluating treatments for testType: ' + str(testType))

        if expectedVal:
            if savedVal != expectedVal:
                self.failures.append('T&Outcomes: Expected treatment ' +
                                     str(expectedVal) + ', loaded ' +
                                     str(savedVal))
            else:
                print('correct treatment')

    def compare_frequency(self, savedVal, test, testType):
        # Only for Bone strengthener, antibiotics, antifungal
        if testType == 'bone strengtheners':
            for key in test['questions'][-1]['options']:
                expectedVal = key.lower()
        else:
            expectedVal = 'na'

        if savedVal != expectedVal:
            self.failures.append('T&Outcomes: Expected frequency ' +
                                 str(expectedVal) + ', loaded ' +
                                 str(savedVal))
        else:
            print('correct frequency')

    def compare_nct(self, savedVal, test, testType):
        expectedVal = None
        if testType == 'clinical':
            expectedVal = test['questions'][1]['text'].lower()

        if expectedVal and savedVal != expectedVal:
            self.failures.append('T&Outcomes: Expected NCT# ' +
                                 str(expectedVal) + ', loaded ' +
                                 str(savedVal))
        else:
            print('correct nct')

    def compare_outcome(self, savedVal, test, testType):
        # Only for chemo, radiation, stem cell
        expectedOutcomes = []
        index = -2
        if testType == 'stem cell':
            index = -3
        options = test['questions'][index]['options']
        for optionName, value in options.iteritems():
            expectedOutcomes.append(optionName.lower())

        # 'options': {
        # 	'I discontinued this treatment': {
        # 		'type': 'select-all',
        # 		'options': {
        # 			'Too much travel': {},
        # 			'Other': {'comment': 'Discontinued comment: Treatment2'},
        # 		},
        # 	}
        if expectedOutcomes[0] == 'i discontinued this treatment':
            # There's subquestions. Get expected options for subquestion
            suboptions = options['I discontinued this treatment']['options']
            for suboption, value in suboptions.iteritems():
                expectedOutcomes.append(suboption.lower())
                # Get comment if 'other' is selected
                if suboption.lower() == 'other':
                    try:
                        comment = value['comment']
                        expectedOutcomes.append(comment.lower())
                    except AttributeError:
                        print('No comment')

        hasError = False
        for expectedOutcome in expectedOutcomes:
            if not expectedOutcome in savedVal:
                self.failures.append('T&Outcomes: Expected outcome ' +
                                     str(expectedOutcome) + ', loaded ' +
                                     str(savedVal))
                hasError = True

        if not hasError:
            print('correct outcome')

############################ Utility Functions ###############################

    def delete_treatment(self):
        self.popUpForm = popUpForm.PopUpForm(self.driver)
        WDW(self.driver, 20).until(lambda x: self.popUpForm.load())
        self.popUpForm.confirm('confirm')
        WDW(self.driver, 20).until_not(
            EC.presence_of_element_located((By.CLASS_NAME, 'overlay')))

    def edit_treatments(self, editInfo, expectedInfo):
        self.editTreatmentForm = editTreatmentForm.EditTreatmentForm(
            self.driver)
        WDW(self.driver, 20).until(lambda x: self.editTreatmentForm.load())
        if self.editTreatmentForm.edit_treatment(editInfo):
            WDW(self.driver, 20).until(
                lambda x: self.load({'tests': [expectedInfo]}, 'saved'))

    def edit_outcomes(self, editInfo, expectedInfo):
        self.popUpEditor = editTreatmentPopup.EditTreatmentPopup(self.driver)
        WDW(self.driver, 20).until(lambda x: self.popUpEditor.load())
        if self.popUpEditor.edit_treatment(editInfo, 'outcomes'):
            WDW(self.driver, 20).until(
                lambda x: self.load({'tests': [expectedInfo]}, 'saved'))

    def edit_side_effects(self, editInfo, expectedInfo):
        self.popUpEditor = editTreatmentPopup.EditTreatmentPopup(self.driver)
        WDW(self.driver, 20).until(lambda x: self.popUpEditor.load())
        if self.popUpEditor.edit_treatment(editInfo, 'side effects'):
            WDW(self.driver, 20).until(
                lambda x: self.load({'tests': [expectedInfo]}, 'saved'))

    def load_actions(self, tableContainer):
        lastRow = tableContainer.find_elements_by_tag_name('tr')[-1]
        links = lastRow.find_elements_by_tag_name('a')
        if len(links) == 4:
            return {
                'treatments': links[0],
                'outcomes': links[1],
                'side effects': links[2],
                'delete': links[3],
            }
        elif len(links) == 2:  # Bone Strengtheners, Antibiotics, Anti Fungals
            return {
                'treatments': links[0],
                'delete': links[1],
            }

    def click_add_treatment(self):
        # Sometimes thinks there's an element in the way of button
        clicked = False
        count = 0
        while not clicked and count < 5:
            # Has issues clicking for some reason.
            try:
                buttonCont = self.driver.find_element_by_class_name(
                    'custom1-add-treatment-btn')
                button = buttonCont.find_elements_by_tag_name('button')[0]
                self.util.click_el(button)
                clicked = True
            except WebDriverException:
                print('could not click add treatment button: ' + str(count))
                time.sleep(.4)
                pass
            count += 1

        if count == 5:
            print('failed to click add treatment button')

    def get_treatment_type(self, treatmentIndex):
        # Normal: Chemo, Radiation, Stem Cell, Clinical.
        # Extra: Bone strengtheners, antibiotics antifungal
        test = self.read_test(treatmentIndex)
        num_actions = len(test['actions'])
        if num_actions == 2:
            return 'extra'
        elif num_actions == 4:
            return 'normal'
        else:
            print('unexpected number of treatment actions: ' +
                  str(num_actions))
        return False

############################### Test Functions. ####################################

    def add_treatment(self,
                      treatmentInfo,
                      expectedInfo=None,
                      expectedError=None,
                      expectedWarnings=None):
        # ExpectedInfo should be list of expected tests
        if expectedInfo is None:
            expectedInfo = [treatmentInfo]
        try:
            # print(self.state)
            if self.state == 'normal' or self.state == 'saved':
                self.click_add_treatment()
                self.addTreatmentForm = addTreatmentForm.AddTreatmentForm(
                    self.driver)
                WDW(self.driver,
                    10).until(lambda x: self.addTreatmentForm.load())
                if self.addTreatmentForm.add_treatment(treatmentInfo):
                    WDW(self.driver, 10).until(
                        lambda x: self.load({'tests': expectedInfo}, 'saved'))
                else:
                    print('Failed to add treatment')
            else:
                # todo: handle fresh popup
                pass
            return True
        except MsgError:
            # Is add treatment expected to fail?
            errorType = self.error['errorType']
            if expectedError and errorType.lower() == expectedError.lower():
                return True
            print(self.error['errorMsg'])
            if errorType == 'undefined':
                print('Undefined error: ' + self.error['errorText'])
        except WarningError:
            # Is form submission expected to have warning?
            unexpectedWarnings = []
            if expectedWarnings:
                # Go through self.warnings and check each warningType matches an expectedWarning
                # Append warnings that aren't expected to unexpectedWarnings
                for i, warning in enumerate(self.warnings):
                    expected = False
                    warningType = warning['type']
                    for expectedWarning in expectedWarnings:
                        if expectedWarning == warningType:
                            expected = True
                    if not expected:
                        unexpectedWarnings.append(self.warnings[i])

                if unexpectedWarnings:
                    for unexpected in unexpectedWarnings:
                        print(unexpected['msg'])
                        if warningType == 'undefined':
                            print('Undefined warning: ' + unexpected['text'])
                else:
                    return True
        return True

    def edit_treatment(self,
                       treatmentIndex,
                       editType,
                       expectedInfo=None,
                       editInfo=None,
                       popupAction='confirm'):
        if self.state == 'saved':
            actions = self.load_actions(self.saved_tests[treatmentIndex])

            try:
                action = actions[editType]
                self.util.click_el(action)
            except KeyError:
                print(str(editType) + ' Is not a valid treatment option')
                raise KeyError('Not a valid treatment option')

            if editType == 'delete':
                self.delete_treatment()
            else:
                if editType == 'treatments':
                    self.edit_treatments(editInfo, expectedInfo)
                elif editType == 'outcomes':
                    self.edit_outcomes(editInfo, expectedInfo)
                elif editType == 'side effects':
                    self.edit_side_effects(editInfo, expectedInfo)
                # self.clear_alert()
            print('Done editing: ' + str(editType))

    def delete_all_treatments(self):
        if self.state == 'saved':
            num_treatments = len(self.saved_tests)
            for i, saved_test in enumerate(self.saved_tests):
                print('deleting treatment #' + str(i))
                actions = self.load_actions(self.saved_tests[0])
                try:
                    self.util.click_el(actions['delete'])
                except KeyError:
                    print('"delete" Is not a valid treatment option')
                    raise KeyError('Not a valid treatment option')
                self.delete_treatment()
                # Should be 1 less treatment
                WDW(self.driver, 10).until(lambda x: self.load(
                    {'meta': {
                        'num_treatments': num_treatments - (i + 1)
                    }}))

    def view_options(self):
        if self.view_options_button:
            self.util.click_el(self.view_options_button)
            url = self.driver.current_url
            if '/treatment-options' not in url:
                return False
        else:
            print(
                'Treatment & Outcomes view does not have "View Options" button'
            )
            return False
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