コード例 #1
0
class InvitePage(Page):
    url_tail = "/i/"  # i.e. https://ppay11.herokuapp.com/i/9acb52f3/934464476
    dynamic = True

    def load(self):
        try:
            self.nav = NavigationFunctions(self.driver)
            self.header = header.PubHeader(self.driver)
            self.h2 = self.driver.find_element_by_tag_name('h2')
            # load continue button if normal, signin button if link is expired
            if self.h2.text == 'Oops!':
                self.load_expired_link()
            else:
                self.load_body()
            return True
        except (NoSuchElementException, StaleElementReferenceException,
                WebDriverException) as e:
            return False

    def load_expired_link(self):
        """Invite has expired. Or error"""
        self.signin_button = self.driver.find_element_by_id('signin_button')

    def load_body(self):
        self.form = self.driver.find_element_by_tag_name('form')
        self.email_input = self.form.find_element_by_tag_name('input')
        self.continue_button = (
            self.form.find_element_by_class_name('primaryButton'))
        self.why_button = self.form.find_element_by_tag_name('a')

    def set_email(self, email):
        self.nav.set_input(self.email_input, email)

    def enter_email(self, email):
        self.set_email(email)
        self.click_continue()

    def get_email(self):
        return self.email_input.get_attribute('value')

    def click_why(self):
        self.nav.move_to_el(self.why_button)

    def click_continue(self):
        if self.h2.text == 'Oops!':  # (expired link)
            self.nav.move_to_el(self.signin_button)
        else:  # (normal link)
            self.nav.move_to_el(self.continue_button)

    def is_expired(self):
        """Return True if signin_button visible"""
        try:
            return self.signin_button.is_displayed()
        except Exception:
            return False
コード例 #2
0
class AddEmployeePage(Page):
    url_tail = 'add-employee'
    dynamic = False

    def load(self):
        try:
            self.nav = NavigationFunctions(self.driver)
            self.load_body()
            self.menu = menu.SideMenu(self.driver)
            self.header = header.PrivateHeader(self.driver)
            return True
        except (NoSuchElementException, StaleElementReferenceException,
                IndexError) as e:
            return False

    def load_body(self):
        self.form = self.driver.find_element_by_tag_name('form')
        find_by = self.form.find_elements_by_tag_name

        self.add_button = find_by('button')[0]
        self.inputs = {
            'first_name': find_by('input')[0],
            'last_name': find_by('input')[1],
            'employee_id': find_by('input')[2],
            'dob': find_by('input')[3],
            'zip_code': find_by('input')[4],
            'email': find_by('input')[5],
            'phone': find_by('input')[6],
        }

    def set_value(self, input_id, value):
        try:
            form_input = self.inputs[input_id]
            self.nav.set_input(form_input, value)
            # form_input.clear()
            # form_input.send_keys(value)
        except IndexError:
            raise Exception("Add Employee form: incorrect input index")

    def get_value(self, input_id):
        try:
            form_input = self.inputs[input_id]
            return form_input.get_attribute('value')
        except IndexError:
            raise Exception('Add Employee form: incorrect input index')

    def click_continue(self):
        self.nav.click_el(self.add_button)
        time.sleep(.4)
コード例 #3
0
class SignInForm(Component):
    def __init__(self, driver):
        self.driver = driver
        self.nav = NavigationFunctions(self.driver)

    def load(self):
        WDW(self.driver,
            10).until(EC.presence_of_element_located(
                (By.ID, 'signin_form_id')))
        self.form = self.driver.find_element_by_id('signin_form_id')
        self.email_input = self.form.find_element_by_id('signin_form_user')
        self.password_input = self.form.find_element_by_id('signin_form_pw')
        self.show_password_button = self.form.find_element_by_id(
            'show_password')
        self.forgot_password_button = self.form.find_element_by_id(
            'forgot_password')  # (link to reset password)
        self.continue_button = self.form.find_element_by_id('submit_si_button')
        # self.nav.print_source()
        # raw_input('source?')
        return True

    def submit(self, email, password, submit):
        if email or email == '':
            self.set_email(email)
        if password or password == '':
            self.set_password(password)
        if submit:
            self.nav.click_el(self.continue_button)

    def set_email(self, email):
        self.nav.set_input(self.email_input, email)

    def set_password(self, password):
        self.nav.set_input(self.password_input, password)

    def toggle_password(self):
        self.nav.click_el(self.show_password_button)

    def forgot_password(self):
        self.nav.dismiss_keyboard(
        )  # Android web needs to close keyboard. Native not tested.
        self.nav.click_el(self.forgot_password_button)
コード例 #4
0
class ForgotPasswordForm(Component):
    def __init__(self, driver):
        self.driver = driver
        self.nav = NavigationFunctions(self.driver)

    def load(self):
        WDW(self.driver, 10).until(
            EC.presence_of_element_located((By.CLASS_NAME, 'resetPWForm')))
        self.form = self.driver.find_element_by_class_name('resetPWForm')
        self.email_input = self.form.find_element_by_id('login')
        self.continue_button = self.form.find_element_by_id('submit_button')
        return True

    def submit(self, email, submit):
        if email or email == '':
            self.set_email(email)
        if submit:
            self.nav.click_el(self.continue_button)

    def set_email(self, email):
        self.nav.set_input(self.email_input, email)
コード例 #5
0
class BusinessDetailsPage(Page):
    url_tail = 'add-business/detail'
    dynamic = False

    def load(self):
        try:
            self.nav = NavigationFunctions(self.driver)
            self.load_body()
            self.menu = menu.SideMenu(self.driver)
            self.header = header.PrivateHeader(self.driver)
            return True
        except (NoSuchElementException, StaleElementReferenceException) as e:
            return False

    def load_body(self):
        self.form = self.driver.find_element_by_class_name('form-horizontal')
        find_by = self.form.find_elements_by_tag_name
        find_by_id = self.form.find_element_by_id
        self.ein_input = find_by('input')[0]
        self.hr_email_input = find_by('input')[1]
        self.business_name_input = find_by('input')[2]
        self.dba_input = find_by('input')[3]

        self.line1_input = find_by_id('recipient_line1')
        self.line2_input = find_by_id('recipient_line2')
        self.city_input = find_by_id('recipient_city')

        # not sure which el we need to click
        self.state_cont = self.form.find_element_by_class_name(
            'state_dropdown')
        self.state_dd = self.state_cont.find_elements_by_tag_name('div')[3]
        self.postal_code_input = find_by_id('recipient_code')
        self.phone_input = find_by('input')[9]
        self.website_input = find_by('input')[10]
        self.continue_button = self.form.find_element_by_class_name(
            'primaryButton')

        self.load_agree_checkbox()

    def load_agree_checkbox(self):
        # cont = self.form.find_element_by_id('agreed')
        # self.agree_checkbox = cont.find_element_by_tag_name('input')
        self.agree_checkbox = self.form.find_element_by_id('agreed')

    # def toggle_agree(self):
    # 	self.scroll_to_bottom()
    # 	self.agree_checkbox.click()
    # 	time.sleep(.4)
    # 	self.load_body()

    def toggle_agree(self):
        # agree_checkbox is touchy.
        # Think you need to reload form after clicking checkbox or submitting form
        # (only need to reload form after submission if you toggle checkbox afterwards)
        self.nav.dismiss_keyboard()
        self.scroll_to_bottom()
        selected = self.agreed()
        if main.get_browser() == 'safari':
            self.nav.click_el(self.agree_cont)
        else:
            self.nav.click_el(self.agree_checkbox)
        if selected is self.agreed():
            print('checkbox not altered!')
        time.sleep(.4)

    def agreed(self):
        try:
            return self.agree_checkbox.is_selected()
        except (StaleElementReferenceException, WebDriverException) as e:
            self.load()
            return self.agree_checkbox.is_selected()

    def get_el(self, name):
        """Return input element given name. None if invalid name"""
        if name == 'business_name':
            return self.business_name_input
        elif name == 'dba':
            return self.dba_input
        elif name == 'ein':
            return self.ein_input
        elif name == 'hr_email':
            return self.hr_email_input
        elif name == 'line1':
            return self.line1_input
        elif name == 'line2':
            return self.line2_input
        elif name == 'city':
            return self.city_input
        elif name == 'postal_code':
            return self.postal_code_input
        elif name == 'phone':
            return self.phone_input
        elif name == 'website':
            return self.website_input
        elif name == 'state':
            if main.is_ios():  # click doesn't regester on self.state_cont
                return self.state_dd
            return self.state_cont
        else:
            return None

    def get(self, name):
        """Return the text of the element with the given name"""
        el = self.get_el(name)
        if el is not None:
            if name == 'state':
                # ignore text in label
                if not main.is_ios():  # ios: el is already the child
                    el = el.find_elements_by_tag_name('div')[0]
                return el.text
            return el.get_attribute('value')
        return None

    def set(self, name, value):
        """Pass in name of el and desired value. Don't use for setting state"""
        el = self.get_el(name)
        if el is not None:
            if name == 'state':
                time.sleep(.4)
                self.nav.dismiss_keyboard()
                self.nav.move_to_el(el)
                self.set_state(value)
            else:
                self.nav.set_input(el, value)

                # ios: Inputs dont seem to update unless you click after setting value
                # i.e. 'Required' errors won't show up just for sending keys.
                # if main.is_ios():
                # 	self.nav.click_el(el)

    def set_state(self, state_text):
        WDW(self.driver, 10).until(
            EC.presence_of_element_located(
                (By.CLASS_NAME, 'sm-state-menuitem')))
        try:
            self.states = self.driver.find_elements_by_class_name(
                'sm-state-menuitem')
            for i, state in enumerate(self.states):
                text = self.states[i].text
                if text == state_text:
                    self.nav.click_el(self.states[i])
                    break
        except NoSuchElementException:
            # couldn't find state. De-select dropdown
            AC(self.driver).send_keys(Keys.ESC).perform()
        WDW(self.driver, 10).until_not(
            EC.presence_of_element_located(
                (By.CLASS_NAME, 'sm-state-menuitem')))

    # select state by typing keys, then selecting state by pressing enter
    # Not used, doesn't work. Issues using AC functions. Use nav functions
    def type_state(self, state):
        self.move_to_el(self.state_dd)
        time.sleep(1.4)  # need decent wait before sending keys
        AC(self.driver).send_keys(state).perform()
        time.sleep(.4)
        AC(self.driver).send_keys(Keys.ENTER).perform()
        time.sleep(.4)

    def click_continue(self):
        self.scroll_to_bottom()
        time.sleep(.2)
        self.continue_button.click()

        try:
            WDW(self.driver,
                2).until_not(EC.presence_of_element_located((By.ID, 'agreed')))
            # not on details page anymore
        except TimeoutException:
            # still on page. Need to reload
            self.load()
コード例 #6
0
class ForEmployersPage(Page):
    url_tail = 'enroll-business'  # Now home page. '' will work
    dynamic = False

    def load(self):
        try:
            WDW(self.driver, 10).until(
                EC.element_to_be_clickable((By.CLASS_NAME, 'form-control')))
            self.nav = NavigationFunctions(self.driver)
            self.load_body()
            self.header = header.PubHeader(self.driver)
            self.footer = footer.PubFooter(self.driver)
            return True
        except (NoSuchElementException, StaleElementReferenceException) as e:
            return False

    def load_body(self):
        find_by = self.driver.find_element_by_class_name
        self.learn_more_button = find_by('learnMoreButton')
        self.load_employer_enroll_form()  # form towards top of page
        self.load_demo_request_form()  # form towards bottom of page
        self.load_page_buttons()

    def load_employer_enroll_form(self):
        self.employer_enroll_form = (
            self.driver.find_element_by_class_name('emp_enroll'))

        find_by = self.employer_enroll_form.find_element_by_tag_name
        self.employer_enroll_input = find_by('input')
        self.employer_enroll_button = find_by('button')

    def load_demo_request_form(self):
        self.demo_request_form = (
            self.driver.find_element_by_class_name('enrollCont'))

        find_by = self.demo_request_form.find_element_by_tag_name
        self.demo_request_input = find_by('input')
        self.demo_request_button = find_by('button')

    def load_page_buttons(self):
        """3 buttons that redirect to employers page, 2 go to about page"""
        find_by = self.driver.find_elements_by_class_name
        # redirects to homepage
        self.employee_button = find_by('employerButton')[0]
        # scrolls up to 1st contact form
        self.enroll_now_button = find_by('employerButton')[1]
        # redirects to about page
        self.about_our_mission_button = find_by('employerButton')[2]

    def click_page_button(self, buttton_num):
        """given num (1,2,3) move to and select appropriate button"""
        el = None
        if button_num == 1:
            el = self.employee_button
        elif button_num == 2:
            el = self.enroll_now_button
        elif button_num == 3:
            el = self.about_our_mission_button

        if el is not None:
            self.nav.click_el(el)
            # AC(self.driver).move_to_element(el).perform()
            # el.click()

    def set_employer_email(self, email):
        self.nav.set_input(self.employer_enroll_input, email)
        # AC(self.driver).move_to_element(self.employer_enroll_input).perform()
        # self.employer_enroll_input.clear()
        # self.employer_enroll_input.send_keys(email)

    def get_employer_email(self):
        return self.employer_enroll_input.get_attribute('value')

    def click_employer_enroll_continue(self):
        self.nav.click_el(self.employer_enroll_button)
        # AC(self.driver).move_to_element(self.employer_enroll_button).perform()
        # self.employer_enroll_button.click()

        # Wait until no longer on page
        try:
            WDW(self.driver, 5).until(
                EC.invisibility_of_element_located(
                    (By.CLASS_NAME, 'form-control')))
        except TimeoutException:
            print(
                "Expected to go to enroll-business/code, still on for employers page"
            )

    def enter_employer_email(self, email):
        self.set_employer_email(email)
        self.click_employer_enroll_continue()

    def set_demo_request_email(self, email):
        self.nav.set_input(self.demo_request_input, email)
        # AC(self.driver).move_to_element(self.demo_request_input).perform()
        # self.demo_request_input.clear()
        # self.demo_request_input.send_keys(email)

    def get_demo_request_email(self):
        return self.demo_request_input.get_attribute('value')

    def click_demo_request_continue(self):
        self.nav.click_el(self.demo_request_button)
        # AC(self.driver).move_to_element(self.demo_request_button).perform()
        # self.demo_request_button.click()

    def enter_demo_request_email(self, email):
        self.set_demo_request_email(email)
        self.click_demo_request_continue()

    def clear_demo_request_popup(self):
        try:
            el = self.driver.find_element_by_class_name('logout_cancel')
            el.click()
            #time.sleep(.4)
            #WDW(self.driver, 10).until(EC.element_to_be_clickable((By.ID, 'demo_email')))
            return True
        except NoSuchElementException:
            return False
コード例 #7
0
class DOBPage(Page):
    url_tail = "/i/"
    dynamic = True

    def load(self):
        try:
            self.nav = NavigationFunctions(self.driver)
            self.h1 = self.try_load_expired_header()
            # load continue button if normal, signin button if link is expired
            if self.h1 and self.h1.text == 'Oops!':
                self.load_expired_link()
            else:
                self.header = header.PubHeader(self.driver)
                self.load_body()

            return True
        except (NoSuchElementException, StaleElementReferenceException,
                IndexError) as e:
            return False

    def try_load_expired_header(self):
        # expired link has <h1> element w/ text 'Oops!'
        try:
            return self.driver.find_element_by_tag_name('h1')
        except NoSuchElementException:
            return None

    def load_expired_link(self):
        """Invite has expired. Or error"""
        self.signin_button = self.driver.find_element_by_id('signin_button')

    def load_body(self):
        self.form = self.driver.find_element_by_tag_name('form')
        self.dob_input = self.form.find_element_by_id('dob')
        self.zip_input = self.form.find_element_by_id('zip')
        self.continue_button = (
            self.form.find_element_by_class_name('primaryButton'))

    def set_dob(self, dob):
        self.nav.set_input(self.dob_input, dob)

    def set_zip(self, zipcode):
        self.nav.set_input(self.zip_input, zipcode)

    def get_dob(self):
        return self.dob_input.get_attribute('value')

    def get_zip(self):
        return self.zip_input.get_attribute('value')

    def click_continue(self):
        if self.is_expired():  # (expired link)
            self.nav.move_to_el(self.signin_button)
        else:  # (normal link)
            self.nav.move_to_el(self.continue_button)

    def is_expired(self):
        """Return True if signin_button visible"""
        try:
            return self.signin_button.is_displayed()
        except Exception:
            return False
コード例 #8
0
class BusinessSettingsPage(Page):
    url_tail = 'business-settings'
    dynamic = False

    def load(self):
        try:
            self.nav = NavigationFunctions(self.driver)
            self.load_body()
            self.header = header.PrivateHeader(self.driver)
            self.menu = menu.SideMenu(self.driver)
            if main.is_web() and main.is_ios():
                self.clear_ios_footer()
            return True
        except (NoSuchElementException, StaleElementReferenceException) as e:
            return False

    def load_body(self):
        self.form = self.driver.find_element_by_tag_name('form')
        self.load_business_name()
        self.load_dba()
        self.load_ein()
        self.load_hr()
        self.load_phone()
        self.load_website()

        self.load_address()
        self.remove_button = (
            self.driver.find_element_by_class_name('removeButton'))

    def load_business_name(self):
        cont = self.driver.find_element_by_id('busName_cont')
        # Android native: grab parent of input
        # else: grab input
        # if main.is_android() and not main.is_web():
        # 	self.business_name_input = cont.find_elements_by_tag_name('div')[1]
        # else:
        self.business_name_input = cont.find_element_by_tag_name('input')

    def load_dba(self):
        cont = self.driver.find_element_by_id('dba_cont')
        # if main.is_android() and not main.is_web():
        # 	self.dba_input = cont.find_elements_by_tag_name('div')[1]
        # else:
        self.dba_input = cont.find_element_by_tag_name('input')

    def load_ein(self):
        cont = self.driver.find_element_by_id('ein_cont')
        # if main.is_android() and not main.is_web():
        # 	self.ein_input = cont.find_elements_by_tag_name('div')[1]
        # else:
        self.ein_input = cont.find_element_by_tag_name('input')

    def load_hr(self):
        cont = self.driver.find_element_by_id('hr_cont')
        # if main.is_android() and not main.is_web():
        # 	self.hr_email_input = cont.find_elements_by_tag_name('div')[1]
        # else:
        self.hr_email_input = cont.find_element_by_tag_name('input')

    def load_phone(self):
        cont = self.driver.find_element_by_id('phone_cont')
        # if main.is_android() and not main.is_web():
        # 	self.phone_input = cont.find_elements_by_tag_name('div')[1]
        # else:
        self.phone_input = cont.find_element_by_tag_name('input')

    def load_website(self):
        cont = self.driver.find_element_by_id('website_cont')
        # if main.is_android() and not main.is_web():
        # 	self.website_input = cont.find_elements_by_tag_name('div')[1]
        # else:
        self.website_input = cont.find_element_by_tag_name('input')

    def load_address(self):
        find_by_id = self.form.find_element_by_id
        # line1, line2, city, state, zip
        self.line1_input = find_by_id('recipient_line1')
        self.line2_input = find_by_id('recipient_line2')
        self.city_input = find_by_id('recipient_city')
        self.state_cont = self.form.find_element_by_class_name(
            'state_dropdown')
        self.state_dd = self.state_cont.find_elements_by_tag_name('div')[3]
        self.postal_code_input = find_by_id('recipient_code')

        # cont = self.driver.find_element_by_id('zip_cont')
        # if main.is_android() and not main.is_web():
        # 	self.postal_code_input = cont.find_elements_by_tag_name('div')[1]
        # else:
        # 	self.postal_code_input = cont.find_element_by_tag_name('input')

    def clear_ios_footer(self):
        # scroll down a little bit to lose ios browser footer. Scroll back to top
        self.ios_scroll('down', 100)
        self.scroll_to_top()
        time.sleep(1)

    def set_state(self, state):
        if self.state_dd.tag_name != 'input':
            self.nav.click_el(self.state_dd)
            time.sleep(1)
            ActionChains(self.driver).send_keys(state).perform()
            ActionChains(self.driver).send_keys(Keys.ENTER).perform()
            time.sleep(1)
        else:
            self.state_dd.clear()
            self.state_dd.send_keys(state)

    # select state by typing keys, then selecting state by pressing enter
    def type_state(self, state):
        ActionChains(self.driver).move_to_element(self.state_dd).perform()
        self.nav.click_el(self.state_dd)
        time.sleep(1.4)  # wait before sending keys
        ActionChains(self.driver).send_keys(state).perform()
        time.sleep(.4)
        ActionChains(self.driver).send_keys(Keys.ENTER).perform()

    def set(self, name, value):
        """Set text of input element with given name"""
        # don't use for setting state. Use type_state() or set_state()
        el = self.get_el(name)
        # AC(self.driver).move_to_element(el).perform()
        # time.sleep(.6)
        # autosave causes issues if you don't use clear_input() instead of clear()
        # self.clear_input(el)
        self.nav.set_input(el, value)

    def get_el(self, name):
        """Return input element given name. None if invalid name"""
        if name == 'business_name':
            return self.business_name_input
        elif name == 'dba':
            return self.dba_input
        elif name == 'ein':
            return self.ein_input
        elif name == 'hr_email':
            return self.hr_email_input
        elif name == 'line1':
            return self.line1_input
        elif name == 'line2':
            return self.line2_input
        elif name == 'city':
            return self.city_input
        elif name == 'postal_code':
            return self.postal_code_input
        elif name == 'phone':
            return self.phone_input
        elif name == 'website':
            return self.website_input
        elif name == 'state':
            return self.state_cont
        else:
            return None

    def get(self, name):
        """Given name, return the value of element"""
        el = self.get_el(name)
        if el is not None:
            # State: return text (not label text) Else: return input value
            if name == 'state':
                div = el.find_elements_by_tag_name('div')[0]
                return div.text
            return el.get_attribute('value')
        return None

    def remove_business(self, code):
        self.click_remove()
        self.set_remove_code(code)
        self.click_confirm_remove()

    def click_remove(self):
        """Click 'remove' button, then load elements in confirmation popup"""
        self.nav.dismiss_keyboard(
        )  # Hide keyboard first. Otherwise you won't be at bottom of page
        self.scroll_to_bottom()
        self.remove_button = (
            self.driver.find_element_by_class_name('removeButton'))
        self.nav.click_el(self.remove_button, True)
        time.sleep(1)
        self.try_load_remove_popup()

    def try_load_remove_popup(self):
        try:
            self.confirm_code_input = (
                self.driver.find_element_by_id('removeBusCode'))
            buttons = self.driver.find_elements_by_tag_name('button')
            self.cancel_remove_button = (
                self.driver.find_element_by_class_name(
                    'remove_business_cancel'))
            self.confirm_remove_button = (
                self.driver.find_element_by_class_name('remove_business_ok'))
        except NoSuchElementException:
            self.confirm_code_input = None
            self.cancel_remove_button = None
            self.confirm_remove_button = None

    def click_cancel_remove(self):
        self.nav.click_el(self.cancel_remove_button)

    def click_confirm_remove(self):
        if main.is_android():
            self.try_hide_keyboard()
            time.sleep(.4)
        self.move_to_el(self.confirm_remove_button)
        time.sleep(2)

    def set_remove_code(self, code):
        self.confirm_code_input.clear()
        self.confirm_code_input.send_keys(code)
        if main.is_ios():  # send_keys doesn't seem to update react component.
            self.confirm_code_input.send_keys('')

    def confirm_remove_button_enabled(self):
        """Does confirm remove button exist and is it enabled?"""
        if self.confirm_remove_button is None:
            return False
        return self.confirm_remove_button.is_enabled()

    def saved(self):
        """Determines if the form is valid"""
        try:
            WebDriverWait(self.driver, 6).until_not(
                lambda x: x.find_element_by_class_name('uil-ring-css'))
            return True
        except TimeoutException:
            return False
コード例 #9
0
class BusinessPrefilledPage(Page):
	url_tail = 'add-business/prefilled'
	dynamic = False

	def load(self):
		try:
			self.nav = NavigationFunctions(self.driver)
			self.load_body()
			self.menu = menu.SideMenu(self.driver)
			self.header = header.PrivateHeader(self.driver)
			return True
		except (NoSuchElementException, StaleElementReferenceException) as e:
			return False

	def load_body(self):
		self.form = self.driver.find_element_by_class_name('form-horizontal')
		find_by = self.form.find_elements_by_tag_name
		self.ein_input = self.form.find_element_by_id('ein')
		self.hr_email_input = self.form.find_element_by_id('hr_email')
		self.details_button = find_by('button')[0]
		self.load_agree_checkbox()

		self.continue_button = self.form.find_element_by_class_name('primaryButton')
		self.load_details() # for when you add address and details auto opens

	def load_agree_checkbox(self):
		if main.is_desktop() and main.get_browser() == 'safari':
			# Safari doesn't like clicking the input element
			labels = self.driver.find_elements_by_tag_name('label')
			self.agree_checkbox = labels[-1]
		else:
			self.agree_checkbox = self.form.find_element_by_id('agreed')

	def click_details(self):
		if main.is_android(): # may need to close keyboard
			self.try_hide_keyboard()
		self.scroll_to_top()
		self.details_button.click()
		self.load_details()
		time.sleep(1)

	def load_details(self):
		try:
			find_by = self.form.find_element_by_id
			self.business_name_input = find_by('title')
			self.dba_input = find_by('dba')
			self.line1_input = find_by('recipient_line1')
			self.line2_input = find_by('recipient_line2')
			self.city_input = find_by('recipient_city')

			# Container div
			self.state_cont = self.form.find_element_by_class_name('state_dropdown')
			# Div w/ value as text
			self.state_dd = self.state_cont.find_elements_by_tag_name('div')[3]

			self.postal_code_input = find_by('recipient_code')
			self.phone_input = find_by('phone')
			self.website_input = find_by('website')
			return True
		except (NoSuchElementException, IndexError) as e:
			return False
		time.sleep(1)

	def get_el(self, name):
		"""Return input element given name. None if invalid name"""
		if name == 'business_name':
			return self.business_name_input
		elif name == 'dba':
			return self.dba_input
		elif name == 'ein':
			return self.ein_input
		elif name == 'hr_email':
			return self.hr_email_input
		elif name == 'line1':
			return self.line1_input
		elif name == 'line2':
			return self.line2_input
		elif name == 'city':
			return self.city_input
		elif name == 'postal_code':
			return self.postal_code_input
		elif name == 'phone':
			return self.phone_input
		elif name == 'website':
			return self.website_input
		elif name == 'state':
			return self.state_dd
		else:
			return None

	def get(self, name):
		count = 0
		done = False
		while not done and count < 5:
			try:
				el = self.get_el(name)
				if el is not None:
					if name == 'state':
						return el.text
					return el.get_attribute('value')
				return None
			except StaleElementReferenceException:
				count += 1

		if count == 5:
			print('Failed to find value: ' + str(name))

	def set(self, name, value):
		"""Given name of el, set desired value"""
		# don't use for setting state. Use type_state() or set_state()
		el = self.get_el(name)
		self.nav.set_input(el, value)
		return True
		# hasNewValue = False
		# if el is not None:
		# 	AC(self.driver).move_to_element(el).perform()
		# 	if name == 'state':
		# 		time.sleep(.4)
		# 		self.set_state(value)
		# 		hasNewValue = True
		# 	else:
		# 		# Sometimes has issues setting value (component redraws?).
		# 		# Loop until it actually sets it
		# 		el.clear()

		# 		timeout = time.time() + 5
		# 		while hasNewValue is False:
		# 			el.send_keys(value)
		# 			if self.get(name) == value:
		# 				hasNewValue = True
		# 			elif time.time() > timeout:
		# 				break
		# 			else:
		# 				time.sleep(.5)
		# return hasNewValue

	def set_state(self, state):
		#raw_input(self.state_dd.text)
		self.move_to_el(self.state_dd)
		WDW(self.driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'sm-state-menuitem')))
		states = self.driver.find_elements_by_class_name('sm-state-menuitem')
		for i, st in enumerate(states):
			text = states[i].text
			if state in text:
				states[i].click()
				break
		WDW(self.driver, 10).until_not(EC.presence_of_element_located((By.CLASS_NAME, 'sm-state-menuitem')))

	# select state by typing keys, then selecting state by pressing enter
	def type_state(self,state):
		# move to input below state (so add button doesn't cover on mobile)
		AC(self.driver).move_to_element(self.postal_code_input).perform()
		self.state_dd.click()
		time.sleep(2) # need decent wait before sending keys
		AC(self.driver).send_keys(state).perform()
		time.sleep(1)
		AC(self.driver).send_keys(Keys.ENTER).perform()
		time.sleep(1)

	def toggle_agree(self):
		# agree_checkbox is touchy.
		# Think you need to reload form after clicking checkbox or submitting form
		# (only need to reload form after submission if you toggle checkbox afterwards)
		self.nav.dismiss_keyboard()
		self.scroll_to_bottom()
		selected = self.agreed()
		if main.get_browser() == 'safari':
			self.nav.click_el(self.agree_cont)
		else:
			self.nav.click_el(self.agree_checkbox)
		if selected is self.agreed():
			print('checkbox not altered!')
		time.sleep(.4)

	def agreed(self):
		# Is agree checkbox selected or not?
		checkbox = self.agree_checkbox
		if main.is_desktop() and main.get_browser() == 'safari':
			checkbox = self.form.find_element_by_id('agreed')
		try:
			return checkbox.is_selected()
		except (StaleElementReferenceException, WebDriverException) as e:
			# Reload page and check again
			self.load()
			checkbox = self.form.find_element_by_id('agreed')
			return checkbox.is_selected()

	def click_continue(self):
		self.scroll_to_bottom()
		time.sleep(.2)
		self.continue_button.click()

		# Have had issues trying to load lobby page after clicking continue
		# Try to verify not on prefilled page anymore
		try:
			WDW(self.driver, 2).until_not(
				EC.presence_of_element_located((By.ID, 'agreed')))
			return True
		except TimeoutException:
			# still on page. Need to reload
			self.load()
			return False