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(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(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(self): try: # Make sure on map page WDW(self.driver, 10).until(lambda x: EC.element_to_be_clickable( (By.ID, 'busName')) and self.try_click('busName')) 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(self): try: self.nav = NavigationFunctions(self.driver) anchors = self.driver.find_elements_by_tag_name('a') if len(anchors) == 2: self.browserButton = anchors[0] self.appButton = anchors[1] else: raw_input(len(anchors)) return True except (NoSuchElementException, StaleElementReferenceException, IndexError) as e: return False
def load(self): #raw_input('loading lobby page') try: self.nav = NavigationFunctions(self.driver) self.load_body() self.menu = menu.SideMenu(self.driver, True) self.header = header.PrivateHeader(self.driver) return True except (NoSuchElementException, StaleElementReferenceException, IndexError) as e: #print('Exception: ' + str(e)) pass return False
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
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)
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
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
def load(self): try: WDW(self.driver, 10).until( lambda x: EC.presence_of_element_located( (By.CLASS_NAME, 'sm-employee-table')) or EC. presence_of_element_located((By.CLASS_NAME, 'employeeDiv'))) self.nav = NavigationFunctions(self.driver) self.load_body() if EmployeePage.debug: raw_input('1') self.header = header.PrivateHeader(self.driver) if EmployeePage.debug: raw_input('2') self.menu = menu.SideMenu(self.driver, True) return True except (NoSuchElementException, StaleElementReferenceException, IndexError) as e: return False
def load(self, expectedTab='send'): self.expected_tab = expectedTab self.nav = NavigationFunctions(self.driver) try: self.load_body() self.menu = menu.SideMenu(self.driver, True) self.header = header.PrivateHeader(self.driver) return True except (NoSuchElementException, StaleElementReferenceException, IndexError) as e: return False
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)
class InvitePreScreenPage(Page): def load(self): try: self.nav = NavigationFunctions(self.driver) anchors = self.driver.find_elements_by_tag_name('a') if len(anchors) == 2: self.browserButton = anchors[0] self.appButton = anchors[1] else: raw_input(len(anchors)) return True except (NoSuchElementException, StaleElementReferenceException, IndexError) as e: return False def click(self, button='browser'): if button == 'browser': self.nav.click_el(self.browserButton) elif button == 'app': self.nav.click_el(self.appButton) else: raw_input('InvitePreScreenPage: Wrong button')
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()
class LobbyPage(Page): url_tail = 'settings/employer/' dynamic = True def load(self): #raw_input('loading lobby page') try: self.nav = NavigationFunctions(self.driver) self.load_body() self.menu = menu.SideMenu(self.driver, True) self.header = header.PrivateHeader(self.driver) return True except (NoSuchElementException, StaleElementReferenceException, IndexError) as e: #print('Exception: ' + str(e)) pass return False def load_body(self): self.load_invitations_card() #print('loaded invite card') self.load_pending_elections_card() #print("loaded pening card") self.load_employees_card() #print('loaded emp card') self.cards = [ self.invitations_card, self.pending_elections_card, self.employees_card ] self.learn_more = [ self.invitations_lm, self.pending_elections_lm, self.employees_lm ] # Probably not on lobby page if there isn't at least 1 card card_exists = False for card in self.cards: if card is not None: card_exists = True if not card_exists: raise NoSuchElementException('No cards found on Lobby page') def load_invitations_card(self): find_by = self.driver.find_elements_by_class_name try: self.invitations_card = find_by('card')[0] self.invitations_lm = find_by('invitations_card')[0] except (NoSuchElementException, IndexError) as e: self.invitations_card = None self.invitations_lm = None def load_pending_elections_card(self): find_by = self.driver.find_elements_by_class_name try: self.pending_elections_card = find_by('card')[1] self.pending_elections_lm = find_by('payelections_card')[0] except (NoSuchElementException, IndexError) as e: self.pending_elections_card = None self.pending_elections_lm = None def load_employees_card(self): find_by = self.driver.find_elements_by_class_name try: self.employees_card = find_by('card')[2] self.employees_lm = find_by('employees_card')[0] except (NoSuchElementException, IndexError) as e: self.employees_card = None self.employees_lm = None def click_link(self, link_type='card', index=0): """link_type: 'card', or 'learn_more'. Index: 0, 1, 2""" # card or learn more link? if link_type.lower() == 'card': l = self.cards else: l = self.learn_more try: el = l[int(index)] except IndexError: raise Exception('Invalid card index') # make sure element is in view if not main.is_desktop(): el_bottom = self.get_el_location(el, 'bottom') window_height = self.get_window_height() scroll_distance = el_bottom - window_height self.move('down', scroll_distance) # make sure menu is closed on desktop if not main.is_desktop(): self.menu.close() self.nav.click_el(el)
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
def __init__(self, driver): self.driver = driver self.nav = NavigationFunctions(self.driver) self.load()
class Disclosure(Component): def __init__(self, driver): self.driver = driver self.nav = NavigationFunctions(self.driver) self.load() def load(self): self.container = self.driver.find_element_by_class_name('sendForm') # see code snippets for results # num_divs = len(self.form.find_elements_by_tag_name('div')) # for i in xrange(num_divs): # text = self.form.find_elements_by_tag_name('div')[i].text self.name = self.read_name() self.load_table() self.exchange_rate = self.try_load_exchange_rate() self.total_to_recipient = self.try_load_total_to_recipient() self.load_disclosure_statements() self.continue_button = self.container.find_element_by_id( 'send_conf_button') def read_name(self): # Ignore stuff before name (Send payroll from Dunkin' Donuts to Jose Ortega) text = self.container.find_elements_by_tag_name('div')[2].text index = text.find(' to ') + 4 return text[index - len(text):] def load_table(self): """Table containing transfer amount, fees, and total""" self.table_rows = self.container.find_elements_by_tag_name('tr') # returns amount only (in USD) self.transfer_amount = self.nav.get_text( self.table_rows[0].find_elements_by_tag_name('td')[0]) # Transfer fee row contains "+ " and " 1.00" (desktop chrome) self.transfer_fee = ( self.table_rows[1].find_elements_by_tag_name('td')[0].text[2:]) self.transfer_total = self.nav.get_text( self.table_rows[2].find_elements_by_tag_name('td')[0]) def try_load_exchange_rate(self): """Amount in MXN. Only exists when sending to MX""" try: return self.container.find_element_by_id('exchangeRateDiv') except NoSuchElementException: return None def try_load_total_to_recipient(self): """Amount in MXN, only exists when sending to MX""" try: return self.container.find_element_by_id('totalRecipDiv') except NoSuchElementException: return None def load_disclosure_statements(self): """Up to 3 disclosure statements""" self.disclosure_30 = self.try_load_d_30() self.disclosure_less = self.try_load_d_less() self.disclosure_notify = self.try_load_d_notify() def try_load_d_30(self): """You have 30 minutes to cancel this transfer...""" try: return self.container.find_element_by_id('disclose30MinDiv') except NoSuchElementException: return None def try_load_d_less(self): """Recipient may receive less due to fees charged by...""" try: return self.container.find_element_by_id('discloseLessDiv') except NoSuchElementException: return None def try_load_d_notify(self): """You'll be notified when the transfer is complete.""" try: return self.container.find_element_by_id('discloseNotifyDiv') except NoSuchElementException: return None def has_d_30(self): return self.disclosure_30 is not None def has_d_less(self): return self.disclosure_less is not None def has_d_notify(self): return self.disclosure_notify is not None def get_exchange_rate(self): if self.exchange_rate is not None: return self.exchange_rate.text return None def get_name(self): return self.name def get_transfer_amount(self): return self.transfer_amount.replace(',', '') def get_transfer_fee(self): return self.transfer_fee.strip() def get_transfer_total(self): return self.transfer_total.replace(',', '') def get_total_to_recipient(self): return self.total_to_recipient.text def num_disclosures(self): return len(self.statements) def click_continue(self): self.nav.click_el(self.continue_button) def has_error(self): try: self.error = self.driver.find_element_by_class_name('alert-danger') self.error_button = self.error.find_element_by_tag_name('button') return True except NoSuchElementException: self.error = None self.error_button = None return False def has_upper_limit_error(self): if self.has_error(): try: error_p = self.error.find_element_by_tag_name('div') # raw_input(self.nav.get_text(error_p)) if 'exceed your deposit limit of USD $999 per day' in self.nav.get_text( error_p): return True except NoSuchElementException: pass return False def try_clear_error(self): if self.has_error(): # error not visible on mobile if not main.is_desktop(): self.scroll_to_bottom() self.nav.click_el(self.error_button) time.sleep(.6)
class TransferDetailsPage(Page): url_tail = '/sent' #i.e. 'transfer/15717205387' dynamic = True def load(self, hasPin=False): try: self.menu = menu.SideMenu(self.driver) self.header = header.PrivateHeader(self.driver) self.nav = NavigationFunctions(self.driver) self.load_body(hasPin) return True except (NoSuchElementException, StaleElementReferenceException) as e: return False def load_body(self, hasPin): # w/in 30 minute window only self.send_now_button = self.try_load_send_now() self.cancel_button = self.try_load_cancel() self.pin = self.try_load_pin(hasPin) # always self.continue_button = self.driver.find_element_by_id( 'transfer_ok_button') self.icon_type = self.read_transaction_icon() self.recipient_link = self.driver.find_element_by_id('recipientLink') self.noRecip_dialog = self.try_load_no_recip_dialog() self.delay_disclosure = self.try_load_delay_disclosure() def try_load_pin(self, hasPin): if hasPin: # Force pin to load. Fail loading if it's not there return self.driver.find_element_by_class_name('bbva_pin') else: try: return self.driver.find_element_by_class_name('bbva_pin') except NoSuchElementException: return None def try_load_send_now(self): try: return self.driver.find_element_by_id('send_now_button') except NoSuchElementException: return None def try_load_cancel(self): try: return self.driver.find_element_by_id('cancel_transfer_button') except NoSuchElementException: return None def try_load_delay_disclosure(self): # Appears when MX transfers get delayed by STP # Test server: All non-STP clabes get delayed (never sent) try: container = self.driver.find_element_by_class_name('alert-gray') cancel_button = container.find_element_by_tag_name('a') return {'container': container, 'cancel_button': cancel_button} except NoSuchElementException: return None def try_load_refund_dialog(self): try: container = self.driver.find_element_by_class_name('sendmiDlg') buttons = container.find_elements_by_tag_name('button') if buttons and len(buttons) == 2: return { 'container': container, 'noButton': buttons[0], # Do not refund, close popup 'refundButton': buttons[1], # Cancel and Refund transfer } else: print('TD: loaded cancel dialog cont, but no/wrong# buttons') return None except NoSuchElementException: return None def read_transaction_icon(self): """Interpret length of img src to determine image""" img = self.driver.find_elements_by_tag_name('img')[0] return self.interpret_image(len(img.get_attribute('src'))) def interpret_image(self, img_src_length): """Given length of img_src, determine which icon is used""" if img_src_length == 1302: return 'clock' elif img_src_length == 1314: return 'check' elif img_src_length == 1274: return 'x' else: return None def get_pin(self): if self.pin: return self.pin.text def click_continue(self): self.nav.click_el(self.continue_button) def send_now(self, action='send'): if self.send_now_button is not None: self.nav.click_el(self.send_now_button) time.sleep(.4) return self.send_now_dialog(action) def send_now_dialog(self, action): # True: 'send now' was successful. Should be back on acct page # False: unsuccessful or took more than 20 seconds try: dialog = self.driver.find_element_by_class_name('sendmiDlg') if action is not None: buttons = dialog.find_elements_by_tag_name('button') if action == 'send': self.nav.click_el(buttons[1]) WDW(self.driver, 20).until_not( EC.presence_of_element_located( (By.ID, 'send_now_button'))) elif action == 'cancel': self.nav.click_el(buttons[0]) # will spin until we hear back from bankaool (~8 seconds) # Goes back to acct page when done. # Look for element for 20 seconds or until page changes '''timeout = time.time() + 25 while time.time() < timeout: try: text = self.send_now_button.text # sometimes get stale exception # sometimes get webdriverException 'unknown server-side error' except (WebDriverException, StaleElementReferenceException) as e: # probably successful and not on td page anymore return True if time.time() > timeout: # took too long. return False else: time.sleep(.5)''' #Clicked cancel or not on td page anymore return True except NoSuchElementException: pass # had issues loading/navigating dialog or performing desired action return False def refund_transaction(self, action='refund'): if self.delay_disclosure: self.nav.click_el(self.delay_disclosure['cancel_button']) refund_dialog = self.try_load_refund_dialog() if refund_dialog: if action == 'refund': # Cancel and refund transfer self.nav.click_el(refund_dialog['refundButton']) time.sleep(3) # Wait for refund to go through else: # Do nothing, Close dialog self.nav.click_el(refund_dialog['noButton']) def cancel_transaction(self, action='cancel transfer'): if self.cancel_button is not None: self.nav.click_el(self.cancel_button) time.sleep(.4) self.cancel_dialog(action) def cancel_dialog(self, action): try: dialog = self.driver.find_element_by_class_name('sendmiDlg') if action is not None: buttons = dialog.find_elements_by_tag_name('button') if action == 'cancel transfer': self.nav.click_el(buttons[1]) WDW(self.driver, 10).until( EC.presence_of_element_located( (By.ID, 'send_money_button'))) elif action == 'cancel': self.nav.click_el(buttons[0]) except NoSuchElementException: pass def has_noRecip_dialog(self): try: el = self.driver.find_element_by_id('noRecipDialog') return True except NoSuchElementException: return False def try_load_no_recip_dialog(self): if self.has_noRecip_dialog(): res = {} res['cont'] = self.find_element('id', 'noRecipDialog') res['button'] = self.find_element('id', 'confirmOkButton', res['cont']) return res else: return None def click_recip_link(self): self.nav.click_el(self.recipient_link) def find_element(self, find_by, identifier, cont='driver', single=True): res = None if find_by and identifier: action = None if find_by == 'id': if single: if cont == 'driver': action = self.driver.find_element_by_id else: action = cont.find_element_by_id else: if cont == 'driver': action = self.driver.find_elements_by_id else: action = cont.find_elements_by_id elif find_by == 'class': if single: if cont == 'driver': action = self.driver.find_element_by_class_name else: action = cont.find_element_by_class_name else: if cont == 'driver': action = self.driver.find_elements_by_class_name else: action = cont.find_elements_by_class_name if action: try: res = action(identifier) except NoSuchElementException: pass return res
class AddBusinessPage(Page): url_tail = 'add-business' dynamic = False def load(self): try: # Make sure on map page WDW(self.driver, 10).until(lambda x: EC.element_to_be_clickable( (By.ID, 'busName')) and self.try_click('busName')) 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): by_class = self.driver.find_element_by_class_name self.location_input = self.driver.find_element_by_id('busName') self.cant_find_button = by_class('sm-skip-button') def add(self, location, option=0, expectedFailure=False): if self.select_location(location, option): timer = 10 if expectedFailure: # Don't want to wait full 10 seconds when adding non-US business timer = 2 try: WDW(self.driver, timer).until( EC.presence_of_element_located((By.ID, 'agreed'))) return True except Exception as e: print('failed to add business') return False def select_location(self, location, option=0): self.type_location(location) self.try_hide_keyboard() unsetOption = True count = 0 while count < 5: try: if self.options is not None: self.nav.click_el(self.options[option]) # self.options[option].click() try: WDW(self.driver, 5).until( EC.element_to_be_clickable( (By.CLASS_NAME, 'sm-continue-button'))) self.click_continue() return True except TimeoutException: # no continue button (i.e. adding non-us business) pass return False except StaleElementReferenceException: # Page might have reloaded print('Failed to click location option.') count += 1 return False def type_location(self, location): self.location_input.clear() self.location_input.send_keys(location) if main.is_ios(): self.location_input.click() # Wait a couple seconds. Sometimes options change as you type time.sleep(2) # wait up to 5 seconds for options to show up presence = EC.presence_of_all_elements_located try: self.options = WDW(self.driver, 10).until( presence((By.CLASS_NAME, 'sm-place-menuitem'))) except TimeoutException: self.options = None def num_results(self): self.options = ( self.driver.find_elements_by_class_name("sm-place-menuitem")) return len(self.options) def click_continue(self): try: # need to grab <button> for ios web find_by = self.driver.find_element_by_class_name self.continue_button = find_by('sm-continue-button') self.continue_button.click() WDW(self.driver, 10).until_not( EC.presence_of_element_located( (By.CLASS_NAME, 'sm-continue-button'))) except (NoSuchElementException, ElementNotVisibleException, WebDriverException) as e: pass def click_cant_find(self): self.cant_find_button.click() time.sleep(.2) def click_skip(self): self.skip_button.click() def has_error(self): # page has non-US business error message try: error_div = self.driver.find_element_by_class_name('alert-danger') text = 'sendmi is only available to businesses in the United States.' return text == error_div.text except NoSuchElementException: return False
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)
class SendForm(Component): def __init__(self, driver): self.driver = driver self.nav = NavigationFunctions(self.driver) self.load() def load(self): self.form = self.driver.find_element_by_class_name('sendForm') self.type = self.load_destination_type() if self.type == 'atm': self.try_load_bbva_picker() else: self.usd_div = self.form.find_element_by_id('sourceAmountInput') self.usd_amount = ( self.form.find_element_by_id('sourceAmountInput_number')) self.usd_input = self.form.find_element_by_id( 'sourceAmountInput_hide') self.mxn_div = self.try_load_mxn_div() self.mxn_amount = self.try_load_mxn_amount() self.mxn_input = self.try_load_mxn_input() # BBVA doesn't have a speed option for MX accounts # self.try_load_delivery_speed() self.account_balance = ( self.form.find_element_by_id('accountBalanceDiv')) self.exchange_rate = self.try_load_exchange_rate() # self.destination = self.form.find_element_by_tag_name('a') self.continue_button = self.form.find_element_by_id('send_cont_button') def load_destination_type(self): # Destination types... # 'atm': has currency picker # 'bank': has id=sourceAmountInput # 'cashout': not implemented yet try: bbvaAmount = self.form.find_element_by_class_name( 'picker-item-selected') return 'atm' except NoSuchElementException: return 'bank' def try_load_bbva_picker(self): try: if main.is_desktop(): self.pickerUp = self.form.find_element_by_id('currencyUp') self.pickerDown = self.form.find_element_by_id('currencyDown') else: self.pickerUp = None self.pickerDown = None self.pickerOptions = self.form.find_elements_by_class_name( 'picker-item') self.bbvaAmount = (self.form.find_element_by_class_name( 'picker-item-selected').text.replace(",", "")) self.bbvaUSDAmount = ( self.form.find_element_by_class_name('usd_amount').text) except NoSuchElementException: self.pickerUp = None self.pickerDown = None self.pickerOptions = None self.bbvaAmount = None self.bbvaUSDAmount = None print('failed to load bbva picker') def try_load_mxn_div(self): # only there when sending to MX. Element you click on try: return self.form.find_element_by_id('destAmountInput') except NoSuchElementException: return None def try_load_mxn_amount(self): # only there when sending to MX. Element that has amount as text try: return self.form.find_element_by_id( 'destAmountInput_number') #_number except NoSuchElementException: return None def try_load_mxn_input(self): # hidden input element. Send keys to this el on desktop try: return self.form.find_element_by_id('destAmountInput_hide') except NoSuchElementException: return None def try_load_exchange_rate(self): # only there when sending to MX try: self.exchange_cont = ( self.form.find_element_by_id('exchangeRateDiv')) return self.exchange_cont.find_element_by_tag_name('span') except NoSuchElementException: return None def try_load_delivery_speed(self): """Look for delivery speed stuff if sending to MX""" if self.mxn_div is not None: if 'SORIANA' not in self.destination.text: if self.toggle_or_radio() == 'radio': cont = self.form.find_element_by_id('radio_speed') inputs = cont.find_elements_by_tag_name('input') self.radio_fast = inputs[0] self.radio_instant = inputs[1] # self.radio_fast = ( # self.form.find_element_by_id('fastRadioButton')) # self.radio_instant = ( # self.form.find_element_by_id('instantRadioButton')) else: self.toggle = self.form.find_element_by_id('instantToggle') else: self.toggle = None ####################### BBVA functions ######################## def get_picker_item(self, mxnAmount): # Return picker-item that corresponds to desired mxnAmount # amount must be multiple of 100 for i, option in enumerate(self.pickerOptions): text = option.text.replace(",", "") # print(text) if text == mxnAmount: return self.pickerOptions[i] return None def get_picker_index(self): # return index of currently selected item for i, option in enumerate(self.pickerOptions): classes = option.get_attribute('class') if 'picker-item-selected' in classes: return i return None def get_direction(self, desired_amount): # is current bbva amount clickable? If not, which direction does picker need to move? current_amount = self.form.find_element_by_class_name( 'picker-item-selected').text current_amount = current_amount.replace( ",", "") # Strip out commas for Decimal functions difference = Decimal(desired_amount) - Decimal(current_amount) if (difference >= -200) and (difference <= 200): # Desired amount is w/in 200 of current amount. Desired amount should be clickable return 'click' elif difference > 200: # Element not visible. Scroll down return 'down' else: return 'up' def move_picker(self, direction): if main.is_desktop(): if direction == 'down': self.nav.click_el(self.pickerDown) else: self.nav.click_el(self.pickerUp) else: if direction == 'down': self.nav.click_el(self.pickerOptions[self.get_picker_index() + 2]) else: self.nav.click_el(self.pickerOptions[self.get_picker_index() - 2]) def set_bbva_amount(self, mxnAmount): # move up or down until amount is clickable # amount must be in multiples of 100 if self.type == 'atm' and mxnAmount != self.bbvaAmount: # env_type = main.get_env() while mxnAmount != self.bbvaAmount: direction = self.get_direction(mxnAmount) if direction == 'click': item = self.get_picker_item(mxnAmount) self.nav.click_el(item) else: self.move_picker(direction) time.sleep(.4) clsName = 'picker-item-selected' self.bbvaAmount = ( self.form.find_element_by_class_name(clsName).text.replace( ",", "")) self.bbvaUSDAmount = ( self.form.find_element_by_class_name('usd_amount').text) def get_bbva_amount(self): if self.type == 'atm': return self.bbvaAmount def toggle_or_radio(self): """Is UI set to radio buttons or toggle switch?""" try: el = self.form.find_element_by_id('instantToggle') return 'toggle' except NoSuchElementException: return 'radio' def set_speed(self, speed='fast'): """Set toggle/radio to given speed""" if self.toggle_or_radio() == 'radio': self.set_speed_radio(speed) else: # toggle self.set_speed_toggle(speed) def get_speed(self, speed='toggle'): """Return speed indicated by radio/toggle""" if self.toggle_or_radio() == 'radio': return self.get_speed_radio() else: # default (toggle) return self.get_speed_toggle() def set_speed_radio(self, speed): # has issues clicking 'invisible' elements on Safari desktop if speed == 'instant': self.click_el(self.radio_instant) else: # default (fast) self.click_el(self.radio_fast) def get_speed_radio(self): """Which radio button is selected? Instant or Fast (default)?""" if self.radio_instant.get_attribute('checked'): return 'instant' else: return 'fast' def set_speed_toggle(self, speed): if self.get_speed_toggle() != speed: if main.is_ios(): el = self.toggle.find_element_by_tag_name('input') self.nav.click_el(el) else: self.move_to_el(self.toggle) def get_speed_toggle(self): el = self.toggle.find_element_by_tag_name('input') if el.get_attribute('checked'): return 'instant' else: # default (fast) return 'fast' def get_balance(self): return self.account_balance.text def get_exchange_rate(self): if self.exchange_rate is not None: return self.exchange_rate.text return None def clear_currency_input(self, currency_type): """Clear out amount of given currency_type""" # set focus on input el = None amount = '' if currency_type.lower() == 'usd': el = self.usd_amount amount = self.get_usd() elif currency_type.lower() == 'mxn': el = self.mxn_amount amount = self.get_mxn() if el: self.nav.click_el(el) # Desktop: hit backspace enough times to clear out current amount # Mobile: hit backspace (on custom keyboard) enough times to clear if main.is_desktop(): for i in xrange(len(amount)): AC(self.driver).send_keys(Keys.BACKSPACE).perform() else: # Mobile: hit backspace on custom keyboard self.clear_currency(amount) def set_usd(self, amount): # clear current amount and enter given amount self.clear_currency_input('usd') if main.is_desktop(): self.usd_input.send_keys(str(amount)) # self.usd_div.send_keys(amount) else: self.enter_currency(amount) def set_mxn(self, amount): # clear current amount and enter given amount self.clear_currency_input('mxn') if main.is_desktop(): self.mxn_input.send_keys(str(amount)) # self.mxn_div.send_keys(amount) else: self.enter_currency(amount) def get_usd(self): if self.type == 'atm': return self.bbvaUSDAmount else: amount = (self.usd_amount.text).replace(',', '') return amount def get_mxn(self): return self.mxn_amount.text def has_error(self): try: self.error = self.form.find_element_by_class_name('alert-danger') self.error_button = self.error.find_element_by_tag_name('button') return True except NoSuchElementException: self.error = None self.error_button = None return False def has_balance_error(self): """Return if page has 'You have no money to send.' msg""" # This text is difficult to parse (react crap and weird ascii chars). # Seems to change sometimes. Last updated 11/29 if self.has_error(): try: error_p = self.error.find_element_by_tag_name('div') if self.nav.get_text(error_p) == 'You have no money to send.': return True except NoSuchElementException: pass return False def has_upper_limit_error(self): if self.has_error(): try: error_p = self.error.find_element_by_tag_name('div') raw_input(self.nav.get_text(error_p)) if 'exceed your deposit limit of USD $999 per day' in self.nav.get_text( error_p): return True except NoSuchElementException: pass return False def try_clear_error(self): if self.has_error(): # error not visible on mobile if not main.is_desktop(): self.scroll_to_bottom() self.nav.click_el(self.error_button) time.sleep(.6) def click_account(self): self.nav.click_el(self.destination) time.sleep(1) def get_account_info(self): # get div w/ text els. return bank name and clabe text acct_div = self.destination.find_elements_by_tag_name('div')[1] account_info = { 'bank': acct_div.find_elements_by_tag_name('div')[0].text, 'clabe': acct_div.find_elements_by_tag_name('div')[1].text } return account_info ################## Custom Currency Keyboard ########################## def enter_currency(self, amount): """Enter given amount using custom keyboard then close keyboard Mobile ONLY Requires input is focused and custom keyboard is open""" try: self.keyboard = ( self.driver.find_element_by_class_name('custom_keyboard')) for i in xrange(len(amount)): # raw_input('typing index:' + str(i) + ' char:' + str(amount[i])) self.click_custom_key(amount[i]) self.close_custom_keyboard() return True # pass in el w/ amount and return it matches amount? except NoSuchElementException: return False def clear_currency(self, amount): """Given amount (as text), press backspace enough to clear. Input needs to be selected and custom keyboard open""" if amount != '': for i in xrange(len(amount)): self.click_custom_key('backspace') def close_custom_keyboard(self): """If open, close custom keyboard""" try: el = self.driver.find_element_by_id('accountBalanceDiv') self.nav.click_el(el) except NoSuchElementException: print('SendForm: Could not find acct balance to close keyboard') def click_custom_key(self, character): """Given valid character, press correct key on custom keyboard""" key_el = self.get_custom_key(character) if key_el is not None: self.nav.click_el(key_el) def get_custom_key(self, character): """return custom keyboard element corresponding to given character""" keys = { '0': 'key_0', '1': 'key_1', '2': 'key_2', '3': 'key_3', '4': 'key_4', '5': 'key_5', '6': 'key_6', '7': 'key_7', '8': 'key_8', '9': 'key_9', '.': 'key_dot', 'backspace': 'key_back' } try: return self.driver.find_element_by_class_name(keys[character]) except NoSuchElementException: print('could not find key w/ class ' + keys[character]) return None def is_form_enabled(self): return self.continue_button.is_enabled() def click_continue(self): self.continue_button = self.form.find_element_by_id('send_cont_button') try: WDW(self.driver, 10).until( EC.element_to_be_clickable((By.ID, 'send_cont_button'))) except TimeoutException: raise TimeoutException("Send page: Continue button not enabled.") self.nav.click_el(self.continue_button) try: WDW(self.driver, 10).until( EC.presence_of_element_located((By.ID, 'send_conf_button'))) except TimeoutException: raise TimeoutException( "Send Page: Could not find element on next page.")
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
class EmployeePage(Page): url_tail = 'employees' dynamic = False debug = False #################################### Loading ################################## def load(self): try: WDW(self.driver, 10).until( lambda x: EC.presence_of_element_located( (By.CLASS_NAME, 'sm-employee-table')) or EC. presence_of_element_located((By.CLASS_NAME, 'employeeDiv'))) self.nav = NavigationFunctions(self.driver) self.load_body() if EmployeePage.debug: raw_input('1') self.header = header.PrivateHeader(self.driver) if EmployeePage.debug: raw_input('2') self.menu = menu.SideMenu(self.driver, True) return True except (NoSuchElementException, StaleElementReferenceException, IndexError) as e: return False def load_body(self): # employees, add button, filter toggle, search input # this line might fail if you're actually on account page (IndexError) # Other inputs exist if filter options are visible self.search_input = self.driver.find_elements_by_tag_name('input')[0] find_by = self.driver.find_element_by_class_name if EmployeePage.debug: raw_input('3') self.employees = self.load_employees() if EmployeePage.debug: raw_input('4') self.add_button = self.driver.find_element_by_id('fab_button') self.filter_button = ( self.driver.find_element_by_class_name('filter_toggle')) if EmployeePage.debug: raw_input('5') self.filter_pane = self.driver.find_element_by_class_name( 'ReactCollapse--collapse') if EmployeePage.debug: raw_input('6') self.try_load_filter_opts() if EmployeePage.debug: raw_input('7') self.try_load_sort_opts() if EmployeePage.debug: raw_input('8') def load_employees(self): # Should always be at least 1 entry in table. # Fail to load page if cant find any if main.is_desktop(): # return table row elements find_by = self.driver.find_element_by_class_name css = 'sm-employee-table' table = find_by(css) employees = table.find_elements_by_tag_name('tr')[1:] else: # return employee entry elements employees = self.driver.find_elements_by_class_name('employeeDiv') if len(employees) == 0: raise NoSuchElementException("Couldn't find employees in table.") return employees def try_load_filter_opts(self): """Only visible when filter button is toggled""" opts = [None] * 5 if self.filters_open(): try: # possibly need to grab child of each opt for ios opts[0] = self.driver.find_element_by_id('filter_invited') opts[1] = self.driver.find_element_by_id('filter_inactive') opts[2] = self.driver.find_element_by_id('filter_active') opts[3] = self.driver.find_element_by_id('filter_removed') opts[4] = self.driver.find_element_by_id('filter_terminated') except NoSuchElementException: pass self.filter_opts = opts def try_load_sort_opts(self): # desktop: grab <th> els from first table # mobile: page inputs (if visible) opts = [None] * 5 if main.is_desktop(): t = self.driver.find_elements_by_class_name('sm-employee-table') opts = t[0].find_elements_by_tag_name('th') elif self.filters_open(): # Mobile: only there when filters are open opts[0] = self.driver.find_element_by_id('sort_first_name') opts[1] = self.driver.find_element_by_id('sort_employee_id') opts[2] = self.driver.find_element_by_id('sort_state') opts[3] = self.driver.find_element_by_id('sort_elect_amount') opts[4] = self.driver.find_element_by_id('sort_modified') self.sort_opts = opts def load_participate_dialog(self): try: buttons = self.driver.find_elements_by_tag_name('button') self.participate = buttons[-2] self.skip = buttons[-1] # IDs not pushed to test server yet. # self.participate = self.driver.find_element_by_id("newBus_participate") # self.skip = self.driver.find_elements_by_id("newBus_skip") return True except NoSuchElementException: self.participate = None self.skip = None return False def handle_participate_dialog(self, action='skip'): self.load_participate_dialog() if self.participate is not None: if action == 'participate': self.participate.click() else: self.skip.click() time.sleep(1) else: print('No participate dialog found') ########################### Employee/Table functions ########################## def num_employees(self): return len(self.employees) def get_employee(self, find_by, identifier, get_info=True): """ find_by: 'index', 'name', 'id' identifier: string get_info: True=return employee data, False=return employee element """ emp = None if find_by == 'index': emp = self.employees[int(identifier)] elif find_by == 'name': emp = self.get_emp_by_name(identifier) elif find_by == 'id': emp = self.get_emp_by_id(identifier) if emp is None: return None elif get_info: return self.get_emp_data(emp) else: return emp def get_emp_by_name(self, name): for employee in self.employees: find_by = employee.find_elements_by_tag_name if main.is_desktop(): text = find_by('td')[0].text else: text = find_by('div')[2].text # raw_input(text) if text == name: #print('found employee: ' + name) return employee return None def get_emp_by_id(self, emp_id): for employee in self.employees: find_by = employee.find_elements_by_tag_name # print(employee.text) tds = find_by('td') # raw_input('# tds: ' + str(len(tds))) if main.is_desktop(): el = find_by('td')[1] text = el.text else: el = find_by('div')[3] text = str(el.text)[13:] if text == emp_id: return employee return None def get_emp_data(self, employee): """ given employee div, parse text and return employee dict """ emp = None find_by = employee.find_elements_by_tag_name if str(type(employee)) != "<type 'NoneType'>" and main.is_desktop(): # columns = employee.find_elements_by_tag_name("td") emp = { 'name': find_by('td')[0].text, 'id': find_by('td')[1].text, 'status': find_by('td')[2].text, 'election': find_by('td')[3].text, 'date_changed': find_by('td')[4].text } elif str(type(employee)) != "<type 'NoneType'>": emp = { 'name': find_by('div')[2].text, 'id': find_by('div')[3].text[13:], 'status': find_by('div')[4].text[8:], #Fail 4:20p, StaleEl 'election': find_by('div')[5].text[17:], #Fail 4:15p, StaleEl 'date_changed': find_by('div')[6].text[14:] } # raw_input(str(emp)) return emp def employee_menu(self, find_by, identifier, command_text='click'): """Find employee, 'click': just open menu, 'reinvite', 'remove' """ emp = self.get_employee(find_by, identifier, False) try: emp_menu = emp.find_element_by_tag_name('button') # move to emp. click toast (if visible) self.nav.click_el(emp_menu) # AC(self.driver).move_to_element(emp).perform() time.sleep(.2) self.click_toast() time.sleep(.2) # open emp menu, click action matching command_text self.move_to_el(emp_menu) time.sleep(.4) if command_text != 'click': class_name = "{command}_employee".format( command=command_text.lower()) option = self.driver.find_element_by_class_name(class_name) option.click() WDW(self.driver, 10).until( EC.presence_of_element_located( (By.CLASS_NAME, 'confirm_remove'))) if command_text.lower() == 'remove': self.load_remove_form() except NoSuchElementException: print('something went wrong in employee_menu()') def load_reinvite_form(self): # shouldn't have invites in table anymore pass # self.reinvite_cancel_button = ( # self.driver.find_element_by_xpath("//span[text() = 'Cancel']") # ) # self.reinvite_ok_button = ( # self.driver.find_element_by_xpath("//span[text() = 'OK']") # ) def cancel_reinvite(self): self.reinvite_cancel_button.click() def reinvite(self): self.reinvite_ok_button.click() time.sleep(1) def load_remove_form(self): self.remove_select_cont = self.driver.find_element_by_id( 'remove_select') self.remove_select = ( self.remove_select_cont.find_elements_by_tag_name('div')[2]) self.remove_cancel_button = ( self.driver.find_element_by_class_name('cancel_remove')) self.remove_remove_button = ( self.driver.find_element_by_class_name('confirm_remove')) def select_remove_new_status(self, new_status): self.remove_select.click() time.sleep(1) action = AC(self.driver) action.send_keys(new_status) action.send_keys(Keys.ENTER) action.perform() def remove_employee(self, find_by, identifier, remove=True): self.employee_menu(find_by, identifier, 'Remove') time.sleep(.2) self.remove_remove_button.click() # Table redraws after removing someone. Wait for first employee to go stale try: WDW(self.driver, 10).until(EC.staleness_of(self.employees[0])) except (WebDriverException, NoSuchElementException, StaleElementReferenceException) as e: # employee element probably already gone pass # Wait for table to redraw if main.is_desktop(): WDW(self.driver, 10).until( EC.presence_of_element_located( (By.CLASS_NAME, 'sm-employee-table'))) else: WDW(self.driver, 10).until( EC.presence_of_element_located((By.CLASS_NAME, 'employeeDiv'))) # Should be good to go. Load page self.load() def click_employee(self, find_by, identifier): emp = self.get_employee(find_by, identifier, False) if emp is None: print('no employee found') return False else: if main.is_ios(): # ios needs to click a child div (not menu div) emp = emp.find_elements_by_tag_name('div')[3] #elif main.is_desktop(): # emp = emp.find_elements_by_tag_name('td')[1] self.click_toast() # move_to_el handles navigating to employee and clicking self.move_to_el(emp) # emp.click() time.sleep(.4) return True ############################ Add Employee Functions ########################### def click_plus(self): self.add_button.click() time.sleep(.4) try: find_by = self.driver.find_element_by_id self.add_employee_button = find_by('add_employee') # only has multiple employees option on desktop if main.is_desktop(): self.add_multiple_employees = find_by('add_employees') except NoSuchElementException: fail = 1 + '2' # problem if these elements don't exist def click_add_employee(self): self.add_employee_button.click() def click_add_multiple_employees(self): self.add_multiple_employees.click() ################################## Filter Functions ########################### def filters_open(self): # are filter options visible on page? return self.filter_pane.size['height'] != 0 # Filters always drawn on page, tucked in zero-height el when not shown. # BUG: May return True, where should be False, if filter options pane is closing, but not closed. def filter_is_active(self, index): # self.filter_opts[index].find_element_by_xpath("parent::*") prop = 'background-color' color = 'rgba(56, 217, 244, 1)' el = self.filter_opts[index].find_elements_by_tag_name('div')[0] # raw_input('bg: ' + el.value_of_css_property(prop)) return el.value_of_css_property(prop) == color def toggle_filter(self): """Click element to hide/show filter options""" #print('toggling filter') self.filter_button.click() #WDW(self.driver, 10).until(EC.presence_of_element_located((By.ID, 'filter_terminated'))) time.sleep(1) # update filter/sort options self.try_load_filter_opts() if not main.is_desktop(): self.try_load_sort_opts() #raw_input('what happening?') time.sleep(1) def set_filter(self, pattern): """toggle individual filter (int), or apply pattern (list)""" # make sure filter options visible if not self.filters_open(): self.toggle_filter() if type(pattern) is int: self.filter_opts[pattern].click() elif type(pattern) is list: current_filter = self.get_filters() for i in xrange(len(pattern)): if (pattern[i] != current_filter[i]): self.filter_opts[i].click() time.sleep(.4) time.sleep(1) #Can't get a WDW condition to load correctly. WDW(self.driver, 20).until(lambda x: EC.visibility_of_element_located( (By.TAG_NAME, 'tr')) or EC.visibility_of_all_elements_located( (By.CLASS_NAME, 'employeeDiv'))) self.load() def get_filters(self): filters = [None] * 5 for i, filt in enumerate(self.filter_opts): if self.filter_is_active(i): filters[i] = 1 else: filters[i] = 0 return filters ################################ Sort Functions ############################### def get_active_sort(self): if main.is_desktop(): return self.get_active_desktop_sort() else: return self.get_active_web_sort() def get_active_desktop_sort(self): """return index in self.sort_opts that is currently active""" # non-active options have opacity of 0.2 for i in xrange(5): # raw_input(str(i)) arrow_el = (self.sort_opts[i].find_element_by_tag_name("svg")) opacity = arrow_el.value_of_css_property("opacity") if opacity != "0.2": return i return None def get_active_web_sort(self): """Return index in self.sort_opts that is currently active""" # ensure sort options are visible if not main.is_desktop() and not self.filters_open(): #if main.is_desktop() is not True and self.filters_open() is False: self.toggle_filter() # return index of sort opt that has active color for i, opt in enumerate(self.sort_opts): prop = 'background-color' color = 'rgba(56, 217, 244, 1)' if opt.value_of_css_property(prop) == color: return i def get_sort_direction(self): """Determine index of current sort setting. return True if sort is normal, False if reverse""" direction = True if main.is_desktop(): active_index = self.get_active_desktop_sort() arrow_el = ( self.sort_opts[active_index].find_element_by_tag_name("path")) path = arrow_el.get_attribute('d') if path == "M7 14l5-5 5 5z": # vs "M7 10l5 5 5-5z" for normal direction = False else: direction = self.get_mobile_sort_direction() return direction def get_mobile_sort_direction(self): """Return opposite of reverse order checkbox selected status""" if not self.filters_open(): self.toggle_filter() # should be 2 inputs. Search, reverse checkbox reverse_order_checkbox = ( self.driver.find_elements_by_tag_name('input')[1]) return not reverse_order_checkbox.is_selected() def get_sort(self): column = self.get_active_sort() direction = self.get_sort_direction() return [column, direction] def click_sort(self, index): self.sort_opts[index].click() time.sleep(.2) def get_first_emp(self): self.load() return self.get_employee('index', 0) def set_sort(self, index, direction=True): # open sort options if not visible (always vis on desktop) # Index: 0=name, 1=ID, 2=Status, 3=election 4=date changed if not main.is_desktop() and not self.filters_open(): self.toggle_filter() cur_sort = self.get_sort() old_first_emp = self.get_first_emp() #first_emp = self.get_employee('index', 0) if cur_sort[0] != int(index) or cur_sort[1] != direction: if cur_sort[0] != int(index): self.click_sort(index) cur_sort = self.get_sort() if cur_sort[1] != direction: self.reverse_sort(cur_sort[0]) #raw_input('waiting on...?') #giving time for page to update. WDW until old_first_el != first_el and first_el is not None? time.sleep(2) '''WDW(self.driver, 10).until(lambda x: EC.presence_of_element_located((By.TAG_NAME , 'tr')) or EC.visibility_of_element_located((By.CLASS_NAME ,'employeeDiv')) )''' # lambda x : old_first_emp != self.get_first_emp() and self.get_first_emp() is not None # ) self.load() def reverse_sort(self, index): """Desktop: Toggle current sort. Web: Click sort toggle button""" if main.is_desktop(): self.click_sort(index) else: self.click_sort_toggle() def click_sort_toggle(self): reverse_order_checkbox = ( self.driver.find_elements_by_tag_name('input')[1]) reverse_order_checkbox.click() ############################### Toast Functions ############################### def get_secret_urls(self): WDW(self.driver, 10).until(EC.presence_of_element_located((By.ID, 'testSnackId'))) self.load() elem = self.driver.find_elements_by_class_name("sm-secret-code") try: email_string = elem[0].text try: email_url = email_string[0:email_string.index(' => ')] except ValueError: pass email = email_string[email_string.index('email:') + 6:] except NoSuchElementException: email = None email_url = None try: phone_string = elem[1].text phone = phone_string[phone_string.index('phone:') + 6:] phone_url = phone_string[0:phone_string.index(' => ')] except IndexError: phone = None phone_url = None return { 'email': email, 'phone': phone, 'email_url': email_url, 'phone_url': phone_url } def click_toast(self): if self.has_toast(): self.toast.click() time.sleep(.4) def has_toast(self): # is toast visible on page? try: self.toast = self.driver.find_element_by_id('testSnackId') return True except NoSuchElementException: return False
class PubHeader(Component): """load content of element id='sendmi_public_appbar'""" def __init__(self, driver): self.driver = driver self.nav = NavigationFunctions(self.driver) self.load() def load(self): self.cont = self.load_cont() find_by = self.cont.find_element_by_id # Todo: Load Logo, language dd # ID nightmare... # self.logo = find_by('public_logo_sm') self.logo = find_by('public_logo') # self.language_dd = find_by('locale_dropdown') self.pre_signed_in = self.load_pre_sign_in() # desktop only if main.is_desktop(): # signin dropdown only on desktop when not signed in # never on signin or signin/code # Contents of dropdown do not exist when dropdown is closed try: self.sign_in_button = ( self.cont.find_element_by_id('signin_dropdown')) except NoSuchElementException: self.sign_in_button = None # forgot pw form loads when 'forgot' link clicked self.for_employers = self.load_employers_link() self.for_employees = self.load_employees_link() # mobile web only self.hamburger = self.try_load_hamburger() def load_cont(self): # IDs are a nightmare # look for sendmi_public_appbar or sendmi_appbar try: cont = self.driver.find_element_by_id('sendmi_appbar') return cont except NoSuchElementException: try: cont = self.driver.find_element_by_id('sendmi_public_appbar') return cont except NoSuchElementException: print('Failed to load appbar container') raise NoSuchElementException('Failed to load appbar container') def load_pre_sign_in(self): # Desktop: item in header # Mobile: option in header action menu try: return self.cont.find_element_by_id("signin_myaccount") except NoSuchElementException: return None def load_employers_link(self): """Desktop only. Pages: homepage, contact us, about""" # Note: Is same id for option in action menu try: return self.cont.find_element_by_id('public_enroll_employers') except NoSuchElementException: return None def load_employees_link(self): """Desktop only. Pages: enroll, contact us, about""" # Note: Is same id for option in action menu try: return self.cont.find_element_by_id('public_enroll_employees') except NoSuchElementException: return None def try_load_hamburger(self): # Only on mobile. Menu contents only visible when open try: return self.driver.find_element_by_id('nav_toggle') except NoSuchElementException: return None # header functions def click_logo(self): """click visible header logo""" logo = self.logo if main.is_desktop() and not self.logo.is_displayed(): # scrolled to top on desktop and we need to load other logo logo = self.cont.find_element_by_id('public_logo') self.nav.click_el(logo) def click_for_employers(self): if self.for_employers != None: self.for_employers.click() WDW(self.driver, 10).until(EC.presence_of_element_located( (By.ID, 'demo_email'))) def click_for_employees(self): if main.is_desktop(): if self.for_employees != None: self.for_employees.click() WDW(self.driver, 10).until( EC.presence_of_element_located((By.ID, 'contactEmail2'))) else: self.select_action('employees') def select_action(self, text): # text: 'emp' (employers or employees), 'sign in', or 'signed in' if self.hamburger != None: if not self.action_menu_open(): self.nav.click_el(self.hamburger) WDW(self.driver, 10).until(lambda x: EC.element_to_be_clickable(( By.ID, 'public_enroll')) or EC.element_to_be_clickable( (By.ID, 'signin_myaccount'))) time.sleep(.4) elId = None if text.lower() == 'employers': elId = 'public_enroll_employers' elif text.lower() == 'employees': elId = 'public_enroll_employees' elif text.lower() == 'sign in': elId = 'public_enroll' elif text.lower() == 'signed in': elId = 'signin_myaccount' if elId: try: el = self.driver.find_element_by_id(elId) except NoSuchElementException: print('unable to find element w/ id: ' + str(elId)) if el: self.nav.click_el(el) return True return False def action_menu_open(self): # Does action menu exist (web only) and is it open? find_by = self.driver.find_element_by_class_name if (self.hamburger != None): try: el = find_by('MuiDrawer-paperAnchorTop-069') return el.is_displayed() except NoSuchElementException: pass return False def sign_in_submit(self, email='', password='', submit=True): # No sign in dropdown on mobile if main.is_desktop(): # Make sure dropdown is visible (won't have dropdown on signin page) if self.sign_in_button: if not self.sign_in_open(): self.nav.click_el(self.sign_in_button) self.signInForm = SignInForm(self.driver) WDW(self.driver, 10).until(lambda x: self.signInForm.load()) self.signInForm.submit(email, password, submit) def forgot_password_submit(self, email='', submit=True): # No forgor password dropdown on mobile if main.is_desktop(): # Neither dropdowns are visible if not self.forgot_password_open() and not self.sign_in_open(): self.nav.click_el(self.sign_in_button) self.signInForm = SignInForm(self.driver) # Sign In form is visible if self.sign_in_open(): WDW(self.driver, 10).until(lambda x: self.signInForm.load()) self.signInForm.forgot_password() # Should be on forgotPWForm self.forgotPWForm = ForgotPasswordForm(self.driver) WDW(self.driver, 10).until(lambda x: self.forgotPWForm.load()) self.forgotPWForm.submit(email, submit) def sign_in_open(self): # is signin dropdown open? if main.is_desktop() and self.sign_in_button: try: el = self.driver.find_element_by_id('forgot_password') if el.is_displayed(): return True except NoSuchElementException: pass return False def forgot_password_open(self): # Is forgot password form visible? if main.is_desktop() and self.sign_in_button: try: resetPWform = self.driver.find_element_by_class_name( 'resetPWForm') if resetPWform.is_displayed(): return True except NoSuchElementException: pass return False def signed_in(self): # is user signed in? # Used to tell which item we should expect in header/action dd return self.pre_signed_in is not None def sign_in(self): if self.signed_in(): if main.is_desktop(): self.move_to_el(self.pre_signed_in) else: self.select_action('signed in')
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
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