Best Python code snippet using SeleniumBase
base_case.py
Source:base_case.py
...97 self.click_link_text(selector, timeout=timeout)98 return99 element = page_actions.wait_for_element_visible(100 self.driver, selector, by, timeout=timeout)101 self.__demo_mode_highlight_if_active(selector, by)102 if not self.demo_mode:103 self.__scroll_to_element(element)104 pre_action_url = self.driver.current_url105 try:106 if self.browser == 'ie' and by == By.LINK_TEXT:107 # An issue with clicking Link Text on IE means using jquery108 self.__jquery_click(selector, by=by)109 else:110 # Normal click111 element.click()112 except (StaleElementReferenceException, ENI_Exception):113 self.wait_for_ready_state_complete()114 time.sleep(0.05)115 element = page_actions.wait_for_element_visible(116 self.driver, selector, by, timeout=timeout)117 element.click()118 except (WebDriverException, MoveTargetOutOfBoundsException):119 self.wait_for_ready_state_complete()120 try:121 self.__js_click(selector, by=by)122 except Exception:123 try:124 self.__jquery_click(selector, by=by)125 except Exception:126 # One more attempt to click on the element127 element = page_actions.wait_for_element_visible(128 self.driver, selector, by, timeout=timeout)129 element.click()130 if settings.WAIT_FOR_RSC_ON_CLICKS:131 self.wait_for_ready_state_complete()132 if self.demo_mode:133 if self.driver.current_url != pre_action_url:134 self.__demo_mode_pause_if_active()135 else:136 self.__demo_mode_pause_if_active(tiny=True)137 def double_click(self, selector, by=By.CSS_SELECTOR,138 timeout=settings.SMALL_TIMEOUT):139 from selenium.webdriver import ActionChains140 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:141 timeout = self.__get_new_timeout(timeout)142 if page_utils.is_xpath_selector(selector):143 by = By.XPATH144 element = page_actions.wait_for_element_visible(145 self.driver, selector, by, timeout=timeout)146 self.__demo_mode_highlight_if_active(selector, by)147 if not self.demo_mode:148 self.__scroll_to_element(element)149 pre_action_url = self.driver.current_url150 try:151 actions = ActionChains(self.driver)152 actions.move_to_element(element)153 actions.double_click(element)154 actions.perform()155 except (StaleElementReferenceException, ENI_Exception):156 self.wait_for_ready_state_complete()157 time.sleep(0.05)158 element = page_actions.wait_for_element_visible(159 self.driver, selector, by, timeout=timeout)160 actions = ActionChains(self.driver)161 actions.move_to_element(element)162 actions.double_click(element)163 actions.perform()164 if settings.WAIT_FOR_RSC_ON_CLICKS:165 self.wait_for_ready_state_complete()166 if self.demo_mode:167 if self.driver.current_url != pre_action_url:168 self.__demo_mode_pause_if_active()169 else:170 self.__demo_mode_pause_if_active(tiny=True)171 def click_chain(self, selectors_list, by=By.CSS_SELECTOR,172 timeout=settings.SMALL_TIMEOUT, spacing=0):173 """ This method clicks on a list of elements in succession.174 'spacing' is the amount of time to wait between clicks. (sec) """175 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:176 timeout = self.__get_new_timeout(timeout)177 for selector in selectors_list:178 self.click(selector, by=by, timeout=timeout)179 if spacing > 0:180 time.sleep(spacing)181 def is_link_text_present(self, link_text):182 """ Returns True if the link text appears in the HTML of the page.183 The element doesn't need to be visible,184 such as elements hidden inside a dropdown selection. """185 self.wait_for_ready_state_complete()186 source = self.get_page_source()187 soup = BeautifulSoup(source, "html.parser")188 html_links = soup.find_all('a')189 for html_link in html_links:190 if html_link.text.strip() == link_text.strip():191 return True192 return False193 def get_link_attribute(self, link_text, attribute, hard_fail=True):194 """ Finds a link by link text and then returns the attribute's value.195 If the link text or attribute cannot be found, an exception will196 get raised if hard_fail is True (otherwise None is returned). """197 self.wait_for_ready_state_complete()198 source = self.get_page_source()199 soup = BeautifulSoup(source, "html.parser")200 html_links = soup.find_all('a')201 for html_link in html_links:202 if html_link.text.strip() == link_text.strip():203 if html_link.has_attr(attribute):204 attribute_value = html_link.get(attribute)205 return attribute_value206 if hard_fail:207 raise Exception(208 'Unable to find attribute {%s} from link text {%s}!'209 % (attribute, link_text))210 else:211 return None212 if hard_fail:213 raise Exception("Link text {%s} was not found!" % link_text)214 else:215 return None216 def wait_for_link_text_present(self, link_text,217 timeout=settings.SMALL_TIMEOUT):218 start_ms = time.time() * 1000.0219 stop_ms = start_ms + (timeout * 1000.0)220 for x in range(int(timeout * 5)):221 try:222 if not self.is_link_text_present(link_text):223 raise Exception(224 "Link text {%s} was not found!" % link_text)225 return226 except Exception:227 now_ms = time.time() * 1000.0228 if now_ms >= stop_ms:229 break230 time.sleep(0.2)231 raise Exception(232 "Link text {%s} was not present after %s seconds!" % (233 link_text, timeout))234 def click_link_text(self, link_text, timeout=settings.SMALL_TIMEOUT):235 """ This method clicks link text on a page """236 # If using phantomjs, might need to extract and open the link directly237 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:238 timeout = self.__get_new_timeout(timeout)239 if self.browser == 'phantomjs':240 if self.is_link_text_visible(link_text):241 element = self.wait_for_link_text_visible(link_text)242 element.click()243 return244 self.open(self.__get_href_from_link_text(link_text))245 return246 if not self.is_link_text_present(link_text):247 self.wait_for_link_text_present(link_text)248 pre_action_url = self.get_current_url()249 try:250 element = self.wait_for_link_text_visible(251 link_text, timeout=0.2)252 self.__demo_mode_highlight_if_active(link_text, by=By.LINK_TEXT)253 try:254 element.click()255 except (StaleElementReferenceException, ENI_Exception):256 self.wait_for_ready_state_complete()257 time.sleep(0.05)258 element = self.wait_for_link_text_visible(259 link_text, timeout=timeout)260 element.click()261 except Exception:262 found_css = False263 text_id = self.get_link_attribute(link_text, "id", False)264 if text_id:265 link_css = '[id="%s"]' % link_text266 found_css = True267 if not found_css:268 href = self.__get_href_from_link_text(link_text, False)269 if href:270 if href.startswith('/') or page_utils.is_valid_url(href):271 link_css = '[href="%s"]' % href272 found_css = True273 if not found_css:274 ngclick = self.get_link_attribute(link_text, "ng-click", False)275 if ngclick:276 link_css = '[ng-click="%s"]' % ngclick277 found_css = True278 if not found_css:279 onclick = self.get_link_attribute(link_text, "onclick", False)280 if onclick:281 link_css = '[onclick="%s"]' % onclick282 found_css = True283 success = False284 if found_css:285 if self.is_element_visible(link_css):286 self.click(link_css)287 success = True288 else:289 # The link text might be hidden under a dropdown menu290 success = self.__click_dropdown_link_text(291 link_text, link_css)292 if not success:293 element = self.wait_for_link_text_visible(294 link_text, timeout=settings.MINI_TIMEOUT)295 element.click()296 if settings.WAIT_FOR_RSC_ON_CLICKS:297 self.wait_for_ready_state_complete()298 if self.demo_mode:299 if self.driver.current_url != pre_action_url:300 self.__demo_mode_pause_if_active()301 else:302 self.__demo_mode_pause_if_active(tiny=True)303 def click_link(self, link_text, timeout=settings.SMALL_TIMEOUT):304 """ Same as self.click_link_text() """305 self.click_link_text(link_text, timeout=timeout)306 def click_partial_link_text(self, partial_link_text,307 timeout=settings.SMALL_TIMEOUT):308 """ This method clicks the partial link text on a page. """309 # If using phantomjs, might need to extract and open the link directly310 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:311 timeout = self.__get_new_timeout(timeout)312 if self.browser == 'phantomjs':313 if self.is_partial_link_text_visible(partial_link_text):314 element = self.wait_for_partial_link_text(partial_link_text)315 element.click()316 return317 source = self.get_page_source()318 soup = BeautifulSoup(source, "html.parser")319 html_links = soup.fetch('a')320 for html_link in html_links:321 if partial_link_text in html_link.text:322 for html_attribute in html_link.attrs:323 if html_attribute[0] == 'href':324 href = html_attribute[1]325 if href.startswith('//'):326 link = "http:" + href327 elif href.startswith('/'):328 url = self.driver.current_url329 domain_url = self.get_domain_url(url)330 link = domain_url + href331 else:332 link = href333 self.open(link)334 return335 raise Exception(336 'Could not parse link from partial link_text '337 '{%s}' % partial_link_text)338 raise Exception(339 "Partial link text {%s} was not found!" % partial_link_text)340 # Not using phantomjs341 element = self.wait_for_partial_link_text(342 partial_link_text, timeout=timeout)343 self.__demo_mode_highlight_if_active(344 partial_link_text, by=By.PARTIAL_LINK_TEXT)345 pre_action_url = self.driver.current_url346 try:347 element.click()348 except (StaleElementReferenceException, ENI_Exception):349 self.wait_for_ready_state_complete()350 time.sleep(0.05)351 element = self.wait_for_partial_link_text(352 partial_link_text, timeout=timeout)353 element.click()354 if settings.WAIT_FOR_RSC_ON_CLICKS:355 self.wait_for_ready_state_complete()356 if self.demo_mode:357 if self.driver.current_url != pre_action_url:358 self.__demo_mode_pause_if_active()359 else:360 self.__demo_mode_pause_if_active(tiny=True)361 def get_text(self, selector, by=By.CSS_SELECTOR,362 timeout=settings.SMALL_TIMEOUT):363 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:364 timeout = self.__get_new_timeout(timeout)365 if page_utils.is_xpath_selector(selector):366 by = By.XPATH367 self.wait_for_ready_state_complete()368 time.sleep(0.01)369 element = page_actions.wait_for_element_visible(370 self.driver, selector, by, timeout)371 try:372 element_text = element.text373 except (StaleElementReferenceException, ENI_Exception):374 self.wait_for_ready_state_complete()375 time.sleep(0.06)376 element = page_actions.wait_for_element_visible(377 self.driver, selector, by, timeout)378 element_text = element.text379 return element_text380 def get_attribute(self, selector, attribute, by=By.CSS_SELECTOR,381 timeout=settings.SMALL_TIMEOUT):382 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:383 timeout = self.__get_new_timeout(timeout)384 if page_utils.is_xpath_selector(selector):385 by = By.XPATH386 if page_utils.is_link_text_selector(selector):387 selector = page_utils.get_link_text_from_selector(selector)388 by = By.LINK_TEXT389 self.wait_for_ready_state_complete()390 time.sleep(0.01)391 element = page_actions.wait_for_element_present(392 self.driver, selector, by, timeout)393 try:394 attribute_value = element.get_attribute(attribute)395 except (StaleElementReferenceException, ENI_Exception):396 self.wait_for_ready_state_complete()397 time.sleep(0.06)398 element = page_actions.wait_for_element_present(399 self.driver, selector, by, timeout)400 attribute_value = element.get_attribute(attribute)401 if attribute_value is not None:402 return attribute_value403 else:404 raise Exception("Element {%s} has no attribute {%s}!" % (405 selector, attribute))406 def refresh_page(self):407 self.__last_page_load_url = None408 self.driver.refresh()409 self.wait_for_ready_state_complete()410 def refresh(self):411 """ The shorter version of self.refresh_page() """412 self.refresh_page()413 def get_current_url(self):414 return self.driver.current_url415 def get_page_source(self):416 return self.driver.page_source417 def get_page_title(self):418 return self.driver.title419 def get_title(self):420 """ The shorter version of self.get_page_title() """421 return self.driver.title422 def go_back(self):423 self.__last_page_load_url = None424 self.driver.back()425 self.wait_for_ready_state_complete()426 def go_forward(self):427 self.__last_page_load_url = None428 self.driver.forward()429 self.wait_for_ready_state_complete()430 def get_image_url(self, selector, by=By.CSS_SELECTOR,431 timeout=settings.SMALL_TIMEOUT):432 """ Extracts the URL from an image element on the page. """433 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:434 timeout = self.__get_new_timeout(timeout)435 return self.get_attribute(selector,436 attribute='src', by=by, timeout=timeout)437 def add_text(self, selector, new_value, by=By.CSS_SELECTOR,438 timeout=settings.LARGE_TIMEOUT):439 """ The more-reliable version of driver.send_keys()440 Similar to update_text(), but won't clear the text field first. """441 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:442 timeout = self.__get_new_timeout(timeout)443 if page_utils.is_xpath_selector(selector):444 by = By.XPATH445 element = self.wait_for_element_visible(446 selector, by=by, timeout=timeout)447 self.__demo_mode_highlight_if_active(selector, by)448 if not self.demo_mode:449 self.__scroll_to_element(element)450 pre_action_url = self.driver.current_url451 try:452 if not new_value.endswith('\n'):453 element.send_keys(new_value)454 else:455 new_value = new_value[:-1]456 element.send_keys(new_value)457 element.send_keys(Keys.RETURN)458 if settings.WAIT_FOR_RSC_ON_PAGE_LOADS:459 self.wait_for_ready_state_complete()460 except (StaleElementReferenceException, ENI_Exception):461 self.wait_for_ready_state_complete()462 time.sleep(0.06)463 element = self.wait_for_element_visible(464 selector, by=by, timeout=timeout)465 if not new_value.endswith('\n'):466 element.send_keys(new_value)467 else:468 new_value = new_value[:-1]469 element.send_keys(new_value)470 element.send_keys(Keys.RETURN)471 if settings.WAIT_FOR_RSC_ON_PAGE_LOADS:472 self.wait_for_ready_state_complete()473 except Exception:474 exc_message = self.__get_improved_exception_message()475 raise Exception(exc_message)476 if self.demo_mode:477 if self.driver.current_url != pre_action_url:478 self.__demo_mode_pause_if_active()479 else:480 self.__demo_mode_pause_if_active(tiny=True)481 def send_keys(self, selector, new_value, by=By.CSS_SELECTOR,482 timeout=settings.LARGE_TIMEOUT):483 """ Same as add_text() -> more reliable, but less name confusion. """484 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:485 timeout = self.__get_new_timeout(timeout)486 if page_utils.is_xpath_selector(selector):487 by = By.XPATH488 self.add_text(selector, new_value, by=by, timeout=timeout)489 def update_text_value(self, selector, new_value, by=By.CSS_SELECTOR,490 timeout=settings.LARGE_TIMEOUT, retry=False):491 """ This method updates an element's text value with a new value.492 @Params493 selector - the selector with the value to update494 new_value - the new value for setting the text field495 by - the type of selector to search by (Default: CSS)496 timeout - how long to wait for the selector to be visible497 retry - if True, use JS if the selenium text update fails498 """499 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:500 timeout = self.__get_new_timeout(timeout)501 if page_utils.is_xpath_selector(selector):502 by = By.XPATH503 element = self.wait_for_element_visible(504 selector, by=by, timeout=timeout)505 self.__demo_mode_highlight_if_active(selector, by)506 if not self.demo_mode:507 self.__scroll_to_element(element)508 try:509 element.clear()510 except (StaleElementReferenceException, ENI_Exception):511 self.wait_for_ready_state_complete()512 time.sleep(0.06)513 element = self.wait_for_element_visible(514 selector, by=by, timeout=timeout)515 element.clear()516 except Exception:517 pass # Clearing the text field first isn't critical518 self.__demo_mode_pause_if_active(tiny=True)519 pre_action_url = self.driver.current_url520 try:521 if not new_value.endswith('\n'):522 element.send_keys(new_value)523 if settings.WAIT_FOR_RSC_ON_PAGE_LOADS:524 self.wait_for_ready_state_complete()525 else:526 new_value = new_value[:-1]527 element.send_keys(new_value)528 element.send_keys(Keys.RETURN)529 if settings.WAIT_FOR_RSC_ON_PAGE_LOADS:530 self.wait_for_ready_state_complete()531 except (StaleElementReferenceException, ENI_Exception):532 self.wait_for_ready_state_complete()533 time.sleep(0.06)534 element = self.wait_for_element_visible(535 selector, by=by, timeout=timeout)536 element.clear()537 if not new_value.endswith('\n'):538 element.send_keys(new_value)539 else:540 new_value = new_value[:-1]541 element.send_keys(new_value)542 element.send_keys(Keys.RETURN)543 if settings.WAIT_FOR_RSC_ON_PAGE_LOADS:544 self.wait_for_ready_state_complete()545 except Exception:546 exc_message = self.__get_improved_exception_message()547 raise Exception(exc_message)548 if (retry and element.get_attribute('value') != new_value and (549 not new_value.endswith('\n'))):550 logging.debug('update_text() is falling back to JavaScript!')551 self.set_value(selector, new_value, by=by)552 if self.demo_mode:553 if self.driver.current_url != pre_action_url:554 self.__demo_mode_pause_if_active()555 else:556 self.__demo_mode_pause_if_active(tiny=True)557 def update_text(self, selector, new_value, by=By.CSS_SELECTOR,558 timeout=settings.LARGE_TIMEOUT, retry=False):559 """ The shorter version of update_text_value(), which560 clears existing text and adds new text into the text field.561 We want to keep the old version for backward compatibility. """562 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:563 timeout = self.__get_new_timeout(timeout)564 if page_utils.is_xpath_selector(selector):565 by = By.XPATH566 self.update_text_value(selector, new_value, by=by,567 timeout=timeout, retry=retry)568 def is_element_present(self, selector, by=By.CSS_SELECTOR):569 if page_utils.is_xpath_selector(selector):570 by = By.XPATH571 if page_utils.is_link_text_selector(selector):572 selector = page_utils.get_link_text_from_selector(selector)573 by = By.LINK_TEXT574 return page_actions.is_element_present(self.driver, selector, by)575 def is_element_visible(self, selector, by=By.CSS_SELECTOR):576 if page_utils.is_xpath_selector(selector):577 by = By.XPATH578 if page_utils.is_link_text_selector(selector):579 selector = page_utils.get_link_text_from_selector(selector)580 by = By.LINK_TEXT581 return page_actions.is_element_visible(self.driver, selector, by)582 def is_link_text_visible(self, link_text):583 self.wait_for_ready_state_complete()584 time.sleep(0.01)585 return page_actions.is_element_visible(self.driver, link_text,586 by=By.LINK_TEXT)587 def is_partial_link_text_visible(self, partial_link_text):588 self.wait_for_ready_state_complete()589 time.sleep(0.01)590 return page_actions.is_element_visible(self.driver, partial_link_text,591 by=By.PARTIAL_LINK_TEXT)592 def is_text_visible(self, text, selector, by=By.CSS_SELECTOR):593 self.wait_for_ready_state_complete()594 time.sleep(0.01)595 if page_utils.is_xpath_selector(selector):596 by = By.XPATH597 if page_utils.is_link_text_selector(selector):598 selector = page_utils.get_link_text_from_selector(selector)599 by = By.LINK_TEXT600 return page_actions.is_text_visible(self.driver, text, selector, by)601 def find_elements(self, selector, by=By.CSS_SELECTOR):602 """ Returns a list of matching WebElements. """603 self.wait_for_ready_state_complete()604 if page_utils.is_xpath_selector(selector):605 by = By.XPATH606 if page_utils.is_link_text_selector(selector):607 selector = page_utils.get_link_text_from_selector(selector)608 by = By.LINK_TEXT609 return self.driver.find_elements(by=by, value=selector)610 def find_visible_elements(self, selector, by=By.CSS_SELECTOR):611 """ Returns a list of matching WebElements that are visible. """612 self.wait_for_ready_state_complete()613 if page_utils.is_xpath_selector(selector):614 by = By.XPATH615 if page_utils.is_link_text_selector(selector):616 selector = page_utils.get_link_text_from_selector(selector)617 by = By.LINK_TEXT618 return page_actions.find_visible_elements(self.driver, selector, by)619 def is_element_in_an_iframe(self, selector, by=By.CSS_SELECTOR):620 """ Returns True if the selector's element is located in an iframe.621 Otherwise returns False. """622 selector, by = self.__recalculate_selector(selector, by)623 if self.is_element_present(selector, by=by):624 return False625 source = self.get_page_source()626 soup = BeautifulSoup(source, "html.parser")627 iframe_list = soup.select('iframe')628 for iframe in iframe_list:629 iframe_identifier = None630 if iframe.has_attr('name') and len(iframe['name']) > 0:631 iframe_identifier = iframe['name']632 elif iframe.has_attr('id') and len(iframe['id']) > 0:633 iframe_identifier = iframe['id']634 else:635 continue636 self.switch_to_frame(iframe_identifier)637 if self.is_element_present(selector, by=by):638 self.switch_to_default_content()639 return True640 self.switch_to_default_content()641 return False642 def switch_to_frame_of_element(self, selector, by=By.CSS_SELECTOR):643 """ Set driver control to the iframe of the element (assuming the644 element is in a single-nested iframe) and returns the iframe name.645 If element is not in an iframe, returns None, and nothing happens.646 May not work if multiple iframes are nested within each other. """647 selector, by = self.__recalculate_selector(selector, by)648 if self.is_element_present(selector, by=by):649 return None650 source = self.get_page_source()651 soup = BeautifulSoup(source, "html.parser")652 iframe_list = soup.select('iframe')653 for iframe in iframe_list:654 iframe_identifier = None655 if iframe.has_attr('name') and len(iframe['name']) > 0:656 iframe_identifier = iframe['name']657 elif iframe.has_attr('id') and len(iframe['id']) > 0:658 iframe_identifier = iframe['id']659 else:660 continue661 self.switch_to_frame(iframe_identifier)662 if self.is_element_present(selector, by=by):663 return iframe_identifier664 self.switch_to_default_content()665 return None666 def execute_script(self, script):667 return self.driver.execute_script(script)668 def execute_async_script(self, script, timeout=settings.EXTREME_TIMEOUT):669 return js_utils.execute_async_script(self.driver, script, timeout)670 def set_window_size(self, width, height):671 self.driver.set_window_size(width, height)672 self.__demo_mode_pause_if_active()673 def maximize_window(self):674 self.driver.maximize_window()675 self.__demo_mode_pause_if_active()676 def add_css_link(self, css_link):677 js_utils.add_css_link(self.driver, css_link)678 def add_js_link(self, js_link):679 js_utils.add_js_link(self.driver, js_link)680 def add_css_style(self, css_style):681 js_utils.add_css_style(self.driver, css_style)682 def add_js_code_from_link(self, js_link):683 js_utils.add_js_code_from_link(self.driver, js_link)684 def add_meta_tag(self, http_equiv=None, content=None):685 js_utils.add_meta_tag(686 self.driver, http_equiv=http_equiv, content=content)687 def activate_jquery(self):688 """ If "jQuery is not defined", use this method to activate it for use.689 This happens because jQuery is not always defined on web sites. """690 js_utils.activate_jquery(self.driver)691 def __are_quotes_escaped(self, string):692 return js_utils.are_quotes_escaped(string)693 def __escape_quotes_if_needed(self, string):694 return js_utils.escape_quotes_if_needed(string)695 def create_tour(self, name=None, theme=None):696 """ Creates a tour for a website. By default, the Shepherd Javascript697 Library is used with the Shepherd "Light" / "Arrows" theme.698 @Params699 name - If creating multiple tours at the same time,700 use this to select the tour you wish to add steps to.701 theme - Sets the default theme for the tour.702 Choose from "light"/"arrows", "dark", "default", "square",703 and "square-dark". ("arrows" is used if None is selected.)704 Alternatively, you may use a different Javascript Library705 as the theme. Those include "IntroJS", "Bootstrap", and706 "Hopscotch".707 """708 if not name:709 name = "default"710 if theme:711 if theme.lower() == "bootstrap":712 self.create_bootstrap_tour(name)713 return714 elif theme.lower() == "hopscotch":715 self.create_hopscotch_tour(name)716 return717 elif theme.lower() == "intro":718 self.create_introjs_tour(name)719 return720 elif theme.lower() == "introjs":721 self.create_introjs_tour(name)722 return723 elif theme.lower() == "shepherd":724 self.create_shepherd_tour(name, theme="light")725 return726 else:727 self.create_shepherd_tour(name, theme)728 else:729 self.create_shepherd_tour(name, theme="light")730 def create_shepherd_tour(self, name=None, theme=None):731 """ Creates a Shepherd JS website tour.732 @Params733 name - If creating multiple tours at the same time,734 use this to select the tour you wish to add steps to.735 theme - Sets the default theme for the tour.736 Choose from "light"/"arrows", "dark", "default", "square",737 and "square-dark". ("light" is used if None is selected.)738 """739 shepherd_theme = "shepherd-theme-arrows"740 if theme:741 if theme.lower() == "default":742 shepherd_theme = "shepherd-theme-default"743 elif theme.lower() == "dark":744 shepherd_theme = "shepherd-theme-dark"745 elif theme.lower() == "light":746 shepherd_theme = "shepherd-theme-arrows"747 elif theme.lower() == "arrows":748 shepherd_theme = "shepherd-theme-arrows"749 elif theme.lower() == "square":750 shepherd_theme = "shepherd-theme-square"751 elif theme.lower() == "square-dark":752 shepherd_theme = "shepherd-theme-square-dark"753 if not name:754 name = "default"755 new_tour = (756 """757 // Shepherd Tour758 var tour = new Shepherd.Tour({759 defaults: {760 classes: '%s',761 scrollTo: true762 }763 });764 var allButtons = {765 skip: {766 text: "Skip",767 action: tour.cancel,768 classes: 'shepherd-button-secondary tour-button-left'769 },770 back: {771 text: "Back",772 action: tour.back,773 classes: 'shepherd-button-secondary'774 },775 next: {776 text: "Next",777 action: tour.next,778 classes: 'shepherd-button-primary tour-button-right'779 },780 };781 var firstStepButtons = [allButtons.skip, allButtons.next];782 var midTourButtons = [allButtons.back, allButtons.next];783 """ % shepherd_theme)784 self._tour_steps[name] = []785 self._tour_steps[name].append(new_tour)786 def create_bootstrap_tour(self, name=None):787 """ Creates a Bootstrap tour for a website.788 @Params789 name - If creating multiple tours at the same time,790 use this to select the tour you wish to add steps to.791 """792 if not name:793 name = "default"794 new_tour = (795 """796 // Bootstrap Tour797 var tour = new Tour({798 });799 tour.addSteps([800 """)801 self._tour_steps[name] = []802 self._tour_steps[name].append(new_tour)803 def create_hopscotch_tour(self, name=None):804 """ Creates an Hopscotch tour for a website.805 @Params806 name - If creating multiple tours at the same time,807 use this to select the tour you wish to add steps to.808 """809 if not name:810 name = "default"811 new_tour = (812 """813 // Hopscotch Tour814 var tour = {815 id: "hopscotch_tour",816 steps: [817 """)818 self._tour_steps[name] = []819 self._tour_steps[name].append(new_tour)820 def create_introjs_tour(self, name=None):821 """ Creates an IntroJS tour for a website.822 @Params823 name - If creating multiple tours at the same time,824 use this to select the tour you wish to add steps to.825 """826 if not name:827 name = "default"828 new_tour = (829 """830 // IntroJS Tour831 function startIntro(){832 var intro = introJs();833 intro.setOptions({834 steps: [835 """)836 self._tour_steps[name] = []837 self._tour_steps[name].append(new_tour)838 def add_tour_step(self, message, selector=None, name=None,839 title=None, theme=None, alignment=None, duration=None):840 """ Allows the user to add tour steps for a website.841 @Params842 message - The message to display.843 selector - The CSS Selector of the Element to attach to.844 name - If creating multiple tours at the same time,845 use this to select the tour you wish to add steps to.846 title - Additional header text that appears above the message.847 theme - (NON-Bootstrap Tours ONLY) The styling of the tour step.848 Choose from "light"/"arrows", "dark", "default", "square",849 and "square-dark". ("arrows" is used if None is selected.)850 alignment - Choose from "top", "bottom", "left", and "right".851 ("top" is the default alignment).852 duration - (Bootstrap Tours ONLY) The amount of time, in seconds,853 before automatically advancing to the next tour step.854 """855 if not selector:856 selector = "html"857 if page_utils.is_xpath_selector(selector):858 selector = self.convert_to_css_selector(selector, By.XPATH)859 selector = self.__escape_quotes_if_needed(selector)860 if not name:861 name = "default"862 if name not in self._tour_steps:863 # By default, will create an IntroJS tour if no tours exist864 self.create_tour(name=name, theme="introjs")865 if not title:866 title = ""867 title = self.__escape_quotes_if_needed(title)868 if message:869 message = self.__escape_quotes_if_needed(message)870 else:871 message = ""872 if not alignment or (873 alignment not in ["top", "bottom", "left", "right"]):874 if "Hopscotch" not in self._tour_steps[name][0]:875 alignment = "top"876 else:877 alignment = "bottom"878 if "Bootstrap" in self._tour_steps[name][0]:879 self.__add_bootstrap_tour_step(880 message, selector=selector, name=name, title=title,881 alignment=alignment, duration=duration)882 elif "Hopscotch" in self._tour_steps[name][0]:883 self.__add_hopscotch_tour_step(884 message, selector=selector, name=name, title=title,885 alignment=alignment)886 elif "IntroJS" in self._tour_steps[name][0]:887 self.__add_introjs_tour_step(888 message, selector=selector, name=name, title=title,889 alignment=alignment)890 else:891 self.__add_shepherd_tour_step(892 message, selector=selector, name=name, title=title,893 theme=theme, alignment=alignment)894 def __add_shepherd_tour_step(self, message, selector=None, name=None,895 title=None, theme=None, alignment=None):896 """ Allows the user to add tour steps for a website.897 @Params898 message - The message to display.899 selector - The CSS Selector of the Element to attach to.900 name - If creating multiple tours at the same time,901 use this to select the tour you wish to add steps to.902 title - Additional header text that appears above the message.903 theme - (NON-Bootstrap Tours ONLY) The styling of the tour step.904 Choose from "light"/"arrows", "dark", "default", "square",905 and "square-dark". ("arrows" is used if None is selected.)906 alignment - Choose from "top", "bottom", "left", and "right".907 ("top" is the default alignment).908 """909 if theme == "default":910 shepherd_theme = "shepherd-theme-default"911 elif theme == "dark":912 shepherd_theme = "shepherd-theme-dark"913 elif theme == "light":914 shepherd_theme = "shepherd-theme-arrows"915 elif theme == "arrows":916 shepherd_theme = "shepherd-theme-arrows"917 elif theme == "square":918 shepherd_theme = "shepherd-theme-square"919 elif theme == "square-dark":920 shepherd_theme = "shepherd-theme-square-dark"921 else:922 shepherd_base_theme = re.search(923 r"[\S\s]+classes: '([\S\s]+)',[\S\s]+",924 self._tour_steps[name][0]).group(1)925 shepherd_theme = shepherd_base_theme926 shepherd_classes = shepherd_theme927 if selector == "html":928 shepherd_classes += " shepherd-orphan"929 buttons = "firstStepButtons"930 if len(self._tour_steps[name]) > 1:931 buttons = "midTourButtons"932 step = ("""933 tour.addStep('%s', {934 title: '%s',935 classes: '%s',936 text: '%s',937 attachTo: {element: '%s', on: '%s'},938 buttons: %s,939 advanceOn: '.docs-link click'940 });""" % (941 name, title, shepherd_classes, message, selector, alignment,942 buttons))943 self._tour_steps[name].append(step)944 def __add_bootstrap_tour_step(self, message, selector=None, name=None,945 title=None, alignment=None, duration=None):946 """ Allows the user to add tour steps for a website.947 @Params948 message - The message to display.949 selector - The CSS Selector of the Element to attach to.950 name - If creating multiple tours at the same time,951 use this to select the tour you wish to add steps to.952 title - Additional header text that appears above the message.953 alignment - Choose from "top", "bottom", "left", and "right".954 ("top" is the default alignment).955 duration - (Bootstrap Tours ONLY) The amount of time, in seconds,956 before automatically advancing to the next tour step.957 """958 if selector != "html":959 selector = self.__make_css_match_first_element_only(selector)960 element_row = "element: '%s'," % selector961 else:962 element_row = ""963 if not duration:964 duration = "0"965 else:966 duration = str(float(duration) * 1000.0)967 step = ("""{968 %s969 title: '%s',970 content: '%s',971 orphan: true,972 placement: 'auto %s',973 smartPlacement: true,974 duration: %s,975 },""" % (element_row, title, message, alignment, duration))976 self._tour_steps[name].append(step)977 def __add_hopscotch_tour_step(self, message, selector=None, name=None,978 title=None, alignment=None):979 """ Allows the user to add tour steps for a website.980 @Params981 message - The message to display.982 selector - The CSS Selector of the Element to attach to.983 name - If creating multiple tours at the same time,984 use this to select the tour you wish to add steps to.985 title - Additional header text that appears above the message.986 alignment - Choose from "top", "bottom", "left", and "right".987 ("bottom" is the default alignment).988 """989 arrow_offset_row = None990 if not selector or selector == "html":991 selector = "head"992 alignment = "bottom"993 arrow_offset_row = "arrowOffset: '200',"994 else:995 arrow_offset_row = ""996 step = ("""{997 target: '%s',998 title: '%s',999 content: '%s',1000 %s1001 showPrevButton: 'true',1002 scrollDuration: '550',1003 placement: '%s'},1004 """ % (selector, title, message, arrow_offset_row, alignment))1005 self._tour_steps[name].append(step)1006 def __add_introjs_tour_step(self, message, selector=None, name=None,1007 title=None, alignment=None):1008 """ Allows the user to add tour steps for a website.1009 @Params1010 message - The message to display.1011 selector - The CSS Selector of the Element to attach to.1012 name - If creating multiple tours at the same time,1013 use this to select the tour you wish to add steps to.1014 title - Additional header text that appears above the message.1015 alignment - Choose from "top", "bottom", "left", and "right".1016 ("top" is the default alignment).1017 """1018 if selector != "html":1019 element_row = "element: '%s'," % selector1020 else:1021 element_row = ""1022 if title:1023 message = "<center><b>" + title + "</b></center><hr>" + message1024 message = '<font size=\"3\" color=\"#33475B\">' + message + '</font>'1025 step = ("""{%s1026 intro: '%s',1027 position: '%s'},1028 """ % (element_row, message, alignment))1029 self._tour_steps[name].append(step)1030 def play_tour(self, name=None, interval=0):1031 """ Plays a tour on the current website.1032 @Params1033 name - If creating multiple tours at the same time,1034 use this to select the tour you wish to add steps to.1035 interval - The delay time between autoplaying tour steps.1036 If set to 0 (default), the tour is fully manual control.1037 """1038 if self.headless:1039 return # Tours should not run in headless mode.1040 if not name:1041 name = "default"1042 if name not in self._tour_steps:1043 raise Exception("Tour {%s} does not exist!" % name)1044 if "Bootstrap" in self._tour_steps[name][0]:1045 tour_helper.play_bootstrap_tour(1046 self.driver, self._tour_steps, self.browser,1047 self.message_duration, name=name, interval=interval)1048 elif "Hopscotch" in self._tour_steps[name][0]:1049 tour_helper.play_hopscotch_tour(1050 self.driver, self._tour_steps, self.browser,1051 self.message_duration, name=name, interval=interval)1052 elif "IntroJS" in self._tour_steps[name][0]:1053 tour_helper.play_introjs_tour(1054 self.driver, self._tour_steps, self.browser,1055 self.message_duration, name=name, interval=interval)1056 else:1057 # "Shepherd"1058 tour_helper.play_shepherd_tour(1059 self.driver, self._tour_steps,1060 self.message_duration, name=name, interval=interval)1061 def export_tour(self, name=None, filename="my_tour.js"):1062 """ Exports a tour as a JS file.1063 You can call self.export_tour() anywhere where you could1064 normally use self.play_tour()1065 It will include necessary resources as well, such as jQuery.1066 You'll be able to copy the tour directly into the Console of1067 any web browser to play the tour outside of SeleniumBase runs.1068 @Params1069 name - If creating multiple tours at the same time,1070 use this to select the tour you wish to add steps to.1071 filename - The name of the javascript file that you wish to1072 save the tour to. """1073 tour_helper.export_tour(self._tour_steps, name=name, filename=filename)1074 def activate_jquery_confirm(self):1075 """ See https://craftpip.github.io/jquery-confirm/ for usage. """1076 js_utils.activate_jquery_confirm(self.driver)1077 def activate_messenger(self):1078 js_utils.activate_messenger(self.driver)1079 def set_messenger_theme(self, theme="default", location="default",1080 max_messages="default"):1081 js_utils.set_messenger_theme(1082 self.driver, theme=theme,1083 location=location, max_messages=max_messages)1084 def post_message(self, message, style="info", duration=None):1085 """ Post a message on the screen with Messenger.1086 Arguments:1087 message: The message to display.1088 style: "info", "success", or "error".1089 duration: The time until the message vanishes.1090 You can also post messages by using =>1091 self.execute_script('Messenger().post("My Message")') """1092 js_utils.post_message(1093 self.driver, message, self.message_duration,1094 style=style, duration=duration)1095 def get_property_value(self, selector, property, by=By.CSS_SELECTOR,1096 timeout=settings.SMALL_TIMEOUT):1097 """ Returns the property value of a page element's computed style.1098 Example:1099 opacity = self.get_property_value("html body a", "opacity")1100 self.assertTrue(float(opacity) > 0, "Element not visible!") """1101 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1102 timeout = self.__get_new_timeout(timeout)1103 if page_utils.is_xpath_selector(selector):1104 by = By.XPATH1105 if page_utils.is_link_text_selector(selector):1106 selector = page_utils.get_link_text_from_selector(selector)1107 by = By.LINK_TEXT1108 self.wait_for_ready_state_complete()1109 page_actions.wait_for_element_present(1110 self.driver, selector, by, timeout)1111 try:1112 selector = self.convert_to_css_selector(selector, by=by)1113 except Exception:1114 # Don't run action if can't convert to CSS_Selector for JavaScript1115 raise Exception(1116 "Exception: Could not convert {%s}(by=%s) to CSS_SELECTOR!" % (1117 selector, by))1118 selector = re.escape(selector)1119 selector = self.__escape_quotes_if_needed(selector)1120 script = ("""var $elm = document.querySelector('%s');1121 $val = window.getComputedStyle($elm).getPropertyValue('%s');1122 return $val;"""1123 % (selector, property))1124 value = self.execute_script(script)1125 if value is not None:1126 return value1127 else:1128 return "" # Return an empty string if the property doesn't exist1129 def bring_to_front(self, selector, by=By.CSS_SELECTOR):1130 """ Updates the Z-index of a page element to bring it into view.1131 Useful when getting a WebDriverException, such as the one below:1132 { Element is not clickable at point (#, #).1133 Other element would receive the click: ... } """1134 if page_utils.is_xpath_selector(selector):1135 by = By.XPATH1136 self.find_element(selector, by=by, timeout=settings.SMALL_TIMEOUT)1137 try:1138 selector = self.convert_to_css_selector(selector, by=by)1139 except Exception:1140 # Don't run action if can't convert to CSS_Selector for JavaScript1141 return1142 selector = re.escape(selector)1143 selector = self.__escape_quotes_if_needed(selector)1144 script = ("""document.querySelector('%s').style.zIndex = '9999';"""1145 % selector)1146 self.execute_script(script)1147 def highlight_click(self, selector, by=By.CSS_SELECTOR,1148 loops=3, scroll=True):1149 if not self.demo_mode:1150 self.highlight(selector, by=by, loops=loops, scroll=scroll)1151 self.click(selector, by=by)1152 def highlight_update_text(self, selector, new_value, by=By.CSS_SELECTOR,1153 loops=3, scroll=True):1154 if not self.demo_mode:1155 self.highlight(selector, by=by, loops=loops, scroll=scroll)1156 self.update_text(selector, new_value, by=by)1157 def highlight(self, selector, by=By.CSS_SELECTOR,1158 loops=settings.HIGHLIGHTS, scroll=True):1159 """ This method uses fancy JavaScript to highlight an element.1160 Used during demo_mode.1161 @Params1162 selector - the selector of the element to find1163 by - the type of selector to search by (Default: CSS)1164 loops - # of times to repeat the highlight animation1165 (Default: 4. Each loop lasts for about 0.18s)1166 scroll - the option to scroll to the element first (Default: True)1167 """1168 selector, by = self.__recalculate_selector(selector, by)1169 element = self.find_element(1170 selector, by=by, timeout=settings.SMALL_TIMEOUT)1171 if scroll:1172 self.__slow_scroll_to_element(element)1173 try:1174 selector = self.convert_to_css_selector(selector, by=by)1175 except Exception:1176 # Don't highlight if can't convert to CSS_SELECTOR1177 return1178 if self.highlights:1179 loops = self.highlights1180 if self.browser == 'ie':1181 loops = 1 # Override previous setting because IE is slow1182 loops = int(loops)1183 o_bs = '' # original_box_shadow1184 style = element.get_attribute('style')1185 if style:1186 if 'box-shadow: ' in style:1187 box_start = style.find('box-shadow: ')1188 box_end = style.find(';', box_start) + 11189 original_box_shadow = style[box_start:box_end]1190 o_bs = original_box_shadow1191 if ":contains" not in selector and ":first" not in selector:1192 selector = re.escape(selector)1193 selector = self.__escape_quotes_if_needed(selector)1194 self.__highlight_with_js(selector, loops, o_bs)1195 else:1196 selector = self.__make_css_match_first_element_only(selector)1197 selector = re.escape(selector)1198 selector = self.__escape_quotes_if_needed(selector)1199 try:1200 self.__highlight_with_jquery(selector, loops, o_bs)1201 except Exception:1202 pass # JQuery probably couldn't load. Skip highlighting.1203 time.sleep(0.065)1204 def __highlight_with_js(self, selector, loops, o_bs):1205 js_utils.highlight_with_js(self.driver, selector, loops, o_bs)1206 def __highlight_with_jquery(self, selector, loops, o_bs):1207 js_utils.highlight_with_jquery(self.driver, selector, loops, o_bs)1208 def scroll_to(self, selector, by=By.CSS_SELECTOR,1209 timeout=settings.SMALL_TIMEOUT):1210 ''' Fast scroll to destination '''1211 if self.demo_mode:1212 self.slow_scroll_to(selector, by=by, timeout=timeout)1213 return1214 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1215 timeout = self.__get_new_timeout(timeout)1216 element = self.wait_for_element_visible(1217 selector, by=by, timeout=timeout)1218 try:1219 self.__scroll_to_element(element)1220 except (StaleElementReferenceException, ENI_Exception):1221 self.wait_for_ready_state_complete()1222 time.sleep(0.05)1223 element = self.wait_for_element_visible(1224 selector, by=by, timeout=timeout)1225 self.__scroll_to_element(element)1226 def slow_scroll_to(self, selector, by=By.CSS_SELECTOR,1227 timeout=settings.SMALL_TIMEOUT):1228 ''' Slow motion scroll to destination '''1229 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1230 timeout = self.__get_new_timeout(timeout)1231 element = self.wait_for_element_visible(1232 selector, by=by, timeout=timeout)1233 self.__slow_scroll_to_element(element)1234 def scroll_click(self, selector, by=By.CSS_SELECTOR):1235 # DEPRECATED - self.click() now scrolls to the element before clicking1236 # self.scroll_to(selector, by=by)1237 self.click(selector, by=by)1238 def click_xpath(self, xpath):1239 self.click(xpath, by=By.XPATH)1240 def js_click(self, selector, by=By.CSS_SELECTOR):1241 """ Clicks an element using pure JS. Does not use jQuery. """1242 selector, by = self.__recalculate_selector(selector, by)1243 if by == By.LINK_TEXT:1244 message = (1245 "Pure JavaScript doesn't support clicking by Link Text. "1246 "You may want to use self.jquery_click() instead, which "1247 "allows this with :contains(), assuming jQuery isn't blocked. "1248 "For now, self.js_click() will use a regular WebDriver click.")1249 logging.debug(message)1250 self.click(selector, by=by)1251 return1252 element = self.wait_for_element_present(1253 selector, by=by, timeout=settings.SMALL_TIMEOUT)1254 if self.is_element_visible(selector, by=by):1255 self.__demo_mode_highlight_if_active(selector, by)1256 if not self.demo_mode:1257 self.__scroll_to_element(element)1258 css_selector = self.convert_to_css_selector(selector, by=by)1259 css_selector = re.escape(css_selector)1260 css_selector = self.__escape_quotes_if_needed(css_selector)1261 self.__js_click(selector, by=by) # The real "magic" happens here1262 self.__demo_mode_pause_if_active()1263 def jquery_click(self, selector, by=By.CSS_SELECTOR):1264 """ Clicks an element using jQuery. Different from using pure JS. """1265 selector, by = self.__recalculate_selector(selector, by)1266 self.wait_for_element_present(1267 selector, by=by, timeout=settings.SMALL_TIMEOUT)1268 if self.is_element_visible(selector, by=by):1269 self.__demo_mode_highlight_if_active(selector, by)1270 selector = self.convert_to_css_selector(selector, by=by)1271 selector = self.__make_css_match_first_element_only(selector)1272 click_script = """jQuery('%s')[0].click()""" % selector1273 self.safe_execute_script(click_script)1274 self.__demo_mode_pause_if_active()1275 def hide_element(self, selector, by=By.CSS_SELECTOR):1276 """ Hide the first element on the page that matches the selector. """1277 selector, by = self.__recalculate_selector(selector, by)1278 selector = self.convert_to_css_selector(selector, by=by)1279 selector = self.__make_css_match_first_element_only(selector)1280 hide_script = """jQuery('%s').hide()""" % selector1281 self.safe_execute_script(hide_script)1282 def hide_elements(self, selector, by=By.CSS_SELECTOR):1283 """ Hide all elements on the page that match the selector. """1284 selector, by = self.__recalculate_selector(selector, by)1285 selector = self.convert_to_css_selector(selector, by=by)1286 hide_script = """jQuery('%s').hide()""" % selector1287 self.safe_execute_script(hide_script)1288 def show_element(self, selector, by=By.CSS_SELECTOR):1289 """ Show the first element on the page that matches the selector. """1290 selector, by = self.__recalculate_selector(selector, by)1291 selector = self.convert_to_css_selector(selector, by=by)1292 selector = self.__make_css_match_first_element_only(selector)1293 show_script = """jQuery('%s').show(0)""" % selector1294 self.safe_execute_script(show_script)1295 def show_elements(self, selector, by=By.CSS_SELECTOR):1296 """ Show all elements on the page that match the selector. """1297 selector, by = self.__recalculate_selector(selector, by)1298 selector = self.convert_to_css_selector(selector, by=by)1299 show_script = """jQuery('%s').show(0)""" % selector1300 self.safe_execute_script(show_script)1301 def remove_element(self, selector, by=By.CSS_SELECTOR):1302 """ Remove the first element on the page that matches the selector. """1303 selector, by = self.__recalculate_selector(selector, by)1304 selector = self.convert_to_css_selector(selector, by=by)1305 selector = self.__make_css_match_first_element_only(selector)1306 remove_script = """jQuery('%s').remove()""" % selector1307 self.safe_execute_script(remove_script)1308 def remove_elements(self, selector, by=By.CSS_SELECTOR):1309 """ Remove all elements on the page that match the selector. """1310 selector, by = self.__recalculate_selector(selector, by)1311 selector = self.convert_to_css_selector(selector, by=by)1312 remove_script = """jQuery('%s').remove()""" % selector1313 self.safe_execute_script(remove_script)1314 def ad_block(self):1315 from seleniumbase.config import ad_block_list1316 for css_selector in ad_block_list.AD_BLOCK_LIST:1317 css_selector = re.escape(css_selector)1318 css_selector = self.__escape_quotes_if_needed(css_selector)1319 script = ("""var $elements = document.querySelectorAll('%s');1320 var index = 0, length = $elements.length;1321 for(; index < length; index++){1322 $elements[index].remove();}"""1323 % css_selector)1324 try:1325 self.execute_script(script)1326 except Exception:1327 pass # Don't fail test if ad_blocking fails1328 def jq_format(self, code):1329 # DEPRECATED - Use re.escape() instead, which does the action you want.1330 return js_utils._jq_format(code)1331 def get_domain_url(self, url):1332 return page_utils.get_domain_url(url)1333 def safe_execute_script(self, script):1334 """ When executing a script that contains a jQuery command,1335 it's important that the jQuery library has been loaded first.1336 This method will load jQuery if it wasn't already loaded. """1337 try:1338 self.execute_script(script)1339 except Exception:1340 # The likely reason this fails is because: "jQuery is not defined"1341 self.activate_jquery() # It's a good thing we can define it here1342 self.execute_script(script)1343 def download_file(self, file_url, destination_folder=None):1344 """ Downloads the file from the url to the destination folder.1345 If no destination folder is specified, the default one is used.1346 (The default downloads folder = "./downloaded_files") """1347 if not destination_folder:1348 destination_folder = constants.Files.DOWNLOADS_FOLDER1349 page_utils._download_file_to(file_url, destination_folder)1350 def save_file_as(self, file_url, new_file_name, destination_folder=None):1351 """ Similar to self.download_file(), except that you get to rename the1352 file being downloaded to whatever you want. """1353 if not destination_folder:1354 destination_folder = constants.Files.DOWNLOADS_FOLDER1355 page_utils._download_file_to(1356 file_url, destination_folder, new_file_name)1357 def save_data_as(self, data, file_name, destination_folder=None):1358 """ Saves the data specified to a file of the name specified.1359 If no destination folder is specified, the default one is used.1360 (The default downloads folder = "./downloaded_files") """1361 if not destination_folder:1362 destination_folder = constants.Files.DOWNLOADS_FOLDER1363 page_utils._save_data_as(data, destination_folder, file_name)1364 def get_downloads_folder(self):1365 """ Returns the OS path of the Downloads Folder.1366 (Works with Chrome and Firefox only, for now.) """1367 return download_helper.get_downloads_folder()1368 def get_path_of_downloaded_file(self, file):1369 """ Returns the OS path of the downloaded file. """1370 return os.path.join(self.get_downloads_folder(), file)1371 def is_downloaded_file_present(self, file):1372 """ Checks if the file exists in the Downloads Folder. """1373 return os.path.exists(self.get_path_of_downloaded_file(file))1374 def assert_downloaded_file(self, file):1375 """ Asserts that the file exists in the Downloads Folder. """1376 assert os.path.exists(self.get_path_of_downloaded_file(file))1377 def get_google_auth_password(self, totp_key=None):1378 """ Returns a time-based one-time password based on the1379 Google Authenticator password algorithm. Works with Authy.1380 If "totp_key" is not specified, defaults to using the one1381 provided in seleniumbase/config/settings.py1382 Google Auth passwords expire and change at 30-second intervals.1383 If the fetched password expires in the next 1.5 seconds, waits1384 for a new one before returning it (may take up to 1.5 seconds).1385 See https://pyotp.readthedocs.io/en/latest/ for details. """1386 import pyotp1387 if not totp_key:1388 totp_key = settings.TOTP_KEY1389 epoch_interval = time.time() / 30.01390 cycle_lifespan = float(epoch_interval) - int(epoch_interval)1391 if float(cycle_lifespan) > 0.95:1392 # Password expires in the next 1.5 seconds. Wait for a new one.1393 for i in range(30):1394 time.sleep(0.05)1395 epoch_interval = time.time() / 30.01396 cycle_lifespan = float(epoch_interval) - int(epoch_interval)1397 if not float(cycle_lifespan) > 0.95:1398 # The new password cycle has begun1399 break1400 totp = pyotp.TOTP(totp_key)1401 return str(totp.now())1402 def convert_xpath_to_css(self, xpath):1403 return xpath_to_css.convert_xpath_to_css(xpath)1404 def convert_to_css_selector(self, selector, by):1405 """ This method converts a selector to a CSS_SELECTOR.1406 jQuery commands require a CSS_SELECTOR for finding elements.1407 This method should only be used for jQuery/JavaScript actions.1408 Pure JavaScript doesn't support using a:contains("LINK_TEXT"). """1409 if by == By.CSS_SELECTOR:1410 return selector1411 elif by == By.ID:1412 return '#%s' % selector1413 elif by == By.CLASS_NAME:1414 return '.%s' % selector1415 elif by == By.NAME:1416 return '[name="%s"]' % selector1417 elif by == By.TAG_NAME:1418 return selector1419 elif by == By.XPATH:1420 return self.convert_xpath_to_css(selector)1421 elif by == By.LINK_TEXT:1422 return 'a:contains("%s")' % selector1423 elif by == By.PARTIAL_LINK_TEXT:1424 return 'a:contains("%s")' % selector1425 else:1426 raise Exception(1427 "Exception: Could not convert {%s}(by=%s) to CSS_SELECTOR!" % (1428 selector, by))1429 def set_value(self, selector, new_value, by=By.CSS_SELECTOR,1430 timeout=settings.LARGE_TIMEOUT):1431 """ This method uses JavaScript to update a text field. """1432 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1433 timeout = self.__get_new_timeout(timeout)1434 if page_utils.is_xpath_selector(selector):1435 by = By.XPATH1436 orginal_selector = selector1437 css_selector = self.convert_to_css_selector(selector, by=by)1438 self.__demo_mode_highlight_if_active(orginal_selector, by)1439 if not self.demo_mode:1440 self.scroll_to(orginal_selector, by=by, timeout=timeout)1441 value = re.escape(new_value)1442 value = self.__escape_quotes_if_needed(value)1443 css_selector = re.escape(css_selector)1444 css_selector = self.__escape_quotes_if_needed(css_selector)1445 script = ("""document.querySelector('%s').value='%s';"""1446 % (css_selector, value))1447 self.execute_script(script)1448 if new_value.endswith('\n'):1449 element = self.wait_for_element_present(1450 orginal_selector, by=by, timeout=timeout)1451 element.send_keys(Keys.RETURN)1452 if settings.WAIT_FOR_RSC_ON_PAGE_LOADS:1453 self.wait_for_ready_state_complete()1454 self.__demo_mode_pause_if_active()1455 def js_update_text(self, selector, new_value, by=By.CSS_SELECTOR,1456 timeout=settings.LARGE_TIMEOUT):1457 """ Same as self.set_value() """1458 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1459 timeout = self.__get_new_timeout(timeout)1460 self.set_value(1461 selector, new_value, by=by, timeout=timeout)1462 def jquery_update_text_value(self, selector, new_value, by=By.CSS_SELECTOR,1463 timeout=settings.LARGE_TIMEOUT):1464 """ This method uses jQuery to update a text field.1465 If the new_value string ends with the newline character,1466 WebDriver will finish the call, which simulates pressing1467 {Enter/Return} after the text is entered. """1468 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1469 timeout = self.__get_new_timeout(timeout)1470 if page_utils.is_xpath_selector(selector):1471 by = By.XPATH1472 element = self.wait_for_element_visible(1473 selector, by=by, timeout=timeout)1474 self.__demo_mode_highlight_if_active(selector, by)1475 self.scroll_to(selector, by=by)1476 selector = self.convert_to_css_selector(selector, by=by)1477 selector = self.__make_css_match_first_element_only(selector)1478 selector = self.__escape_quotes_if_needed(selector)1479 new_value = re.escape(new_value)1480 new_value = self.__escape_quotes_if_needed(new_value)1481 update_text_script = """jQuery('%s').val('%s')""" % (1482 selector, new_value)1483 self.safe_execute_script(update_text_script)1484 if new_value.endswith('\n'):1485 element.send_keys('\n')1486 self.__demo_mode_pause_if_active()1487 def jquery_update_text(self, selector, new_value, by=By.CSS_SELECTOR,1488 timeout=settings.LARGE_TIMEOUT):1489 """ The shorter version of self.jquery_update_text_value()1490 (The longer version remains for backwards compatibility.) """1491 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1492 timeout = self.__get_new_timeout(timeout)1493 self.jquery_update_text_value(1494 selector, new_value, by=by, timeout=timeout)1495 def hover_on_element(self, selector, by=By.CSS_SELECTOR):1496 if page_utils.is_xpath_selector(selector):1497 selector = self.convert_to_css_selector(selector, By.XPATH)1498 by = By.CSS_SELECTOR1499 if page_utils.is_link_text_selector(selector):1500 selector = page_utils.get_link_text_from_selector(selector)1501 by = By.LINK_TEXT1502 self.wait_for_element_visible(1503 selector, by=by, timeout=settings.SMALL_TIMEOUT)1504 self.__demo_mode_highlight_if_active(selector, by)1505 self.scroll_to(selector, by=by)1506 time.sleep(0.05) # Settle down from scrolling before hovering1507 return page_actions.hover_on_element(self.driver, selector)1508 def hover_and_click(self, hover_selector, click_selector,1509 hover_by=By.CSS_SELECTOR, click_by=By.CSS_SELECTOR,1510 timeout=settings.SMALL_TIMEOUT):1511 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1512 timeout = self.__get_new_timeout(timeout)1513 if page_utils.is_xpath_selector(hover_selector):1514 hover_selector = self.convert_to_css_selector(1515 hover_selector, By.XPATH)1516 hover_by = By.CSS_SELECTOR1517 if page_utils.is_xpath_selector(click_selector):1518 click_by = By.XPATH1519 if page_utils.is_link_text_selector(hover_selector):1520 hover_selector = page_utils.get_link_text_from_selector(1521 hover_selector)1522 hover_by = By.LINK_TEXT1523 if page_utils.is_link_text_selector(click_selector):1524 click_selector = page_utils.get_link_text_from_selector(1525 click_selector)1526 click_by = By.LINK_TEXT1527 self.wait_for_element_visible(1528 hover_selector, by=hover_by, timeout=timeout)1529 self.__demo_mode_highlight_if_active(hover_selector, hover_by)1530 self.scroll_to(hover_selector, by=hover_by)1531 pre_action_url = self.driver.current_url1532 element = page_actions.hover_and_click(1533 self.driver, hover_selector, click_selector,1534 hover_by, click_by, timeout)1535 if self.demo_mode:1536 if self.driver.current_url != pre_action_url:1537 self.__demo_mode_pause_if_active()1538 else:1539 self.__demo_mode_pause_if_active(tiny=True)1540 return element1541 def __select_option(self, dropdown_selector, option,1542 dropdown_by=By.CSS_SELECTOR, option_by="text",1543 timeout=settings.SMALL_TIMEOUT):1544 """ Selects an HTML <select> option by specification.1545 Option specifications are by "text", "index", or "value".1546 Defaults to "text" if option_by is unspecified or unknown. """1547 if page_utils.is_xpath_selector(dropdown_selector):1548 dropdown_by = By.XPATH1549 element = self.find_element(1550 dropdown_selector, by=dropdown_by, timeout=timeout)1551 self.__demo_mode_highlight_if_active(dropdown_selector, dropdown_by)1552 pre_action_url = self.driver.current_url1553 try:1554 if option_by == "index":1555 Select(element).select_by_index(option)1556 elif option_by == "value":1557 Select(element).select_by_value(option)1558 else:1559 Select(element).select_by_visible_text(option)1560 except (StaleElementReferenceException, ENI_Exception):1561 self.wait_for_ready_state_complete()1562 time.sleep(0.05)1563 element = self.find_element(1564 dropdown_selector, by=dropdown_by, timeout=timeout)1565 if option_by == "index":1566 Select(element).select_by_index(option)1567 elif option_by == "value":1568 Select(element).select_by_value(option)1569 else:1570 Select(element).select_by_visible_text(option)1571 if settings.WAIT_FOR_RSC_ON_CLICKS:1572 self.wait_for_ready_state_complete()1573 if self.demo_mode:1574 if self.driver.current_url != pre_action_url:1575 self.__demo_mode_pause_if_active()1576 else:1577 self.__demo_mode_pause_if_active(tiny=True)1578 def select_option_by_text(self, dropdown_selector, option,1579 dropdown_by=By.CSS_SELECTOR,1580 timeout=settings.SMALL_TIMEOUT):1581 """ Selects an HTML <select> option by option text.1582 @Params1583 dropdown_selector - the <select> selector1584 option - the text of the option """1585 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1586 timeout = self.__get_new_timeout(timeout)1587 self.__select_option(dropdown_selector, option,1588 dropdown_by=dropdown_by, option_by="text",1589 timeout=timeout)1590 def select_option_by_index(self, dropdown_selector, option,1591 dropdown_by=By.CSS_SELECTOR,1592 timeout=settings.SMALL_TIMEOUT):1593 """ Selects an HTML <select> option by option index.1594 @Params1595 dropdown_selector - the <select> selector1596 option - the index number of the option """1597 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1598 timeout = self.__get_new_timeout(timeout)1599 self.__select_option(dropdown_selector, option,1600 dropdown_by=dropdown_by, option_by="index",1601 timeout=timeout)1602 def select_option_by_value(self, dropdown_selector, option,1603 dropdown_by=By.CSS_SELECTOR,1604 timeout=settings.SMALL_TIMEOUT):1605 """ Selects an HTML <select> option by option value.1606 @Params1607 dropdown_selector - the <select> selector1608 option - the value property of the option """1609 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1610 timeout = self.__get_new_timeout(timeout)1611 self.__select_option(dropdown_selector, option,1612 dropdown_by=dropdown_by, option_by="value",1613 timeout=timeout)1614 @decorators.deprecated("Use self.select_option_by_text() instead!")1615 def pick_select_option_by_text(self, dropdown_selector, option,1616 dropdown_by=By.CSS_SELECTOR,1617 timeout=settings.SMALL_TIMEOUT):1618 """ Selects an HTML <select> option by option text. """1619 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1620 timeout = self.__get_new_timeout(timeout)1621 self.__select_option(dropdown_selector, option,1622 dropdown_by=dropdown_by, option_by="text",1623 timeout=timeout)1624 @decorators.deprecated("Use self.select_option_by_index() instead!")1625 def pick_select_option_by_index(self, dropdown_selector, option,1626 dropdown_by=By.CSS_SELECTOR,1627 timeout=settings.SMALL_TIMEOUT):1628 """ Selects an HTML <select> option by option index. """1629 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1630 timeout = self.__get_new_timeout(timeout)1631 self.__select_option(dropdown_selector, option,1632 dropdown_by=dropdown_by, option_by="index",1633 timeout=timeout)1634 @decorators.deprecated("Use self.select_option_by_value() instead!")1635 def pick_select_option_by_value(self, dropdown_selector, option,1636 dropdown_by=By.CSS_SELECTOR,1637 timeout=settings.SMALL_TIMEOUT):1638 """ Selects an HTML <select> option by option value. """1639 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1640 timeout = self.__get_new_timeout(timeout)1641 self.__select_option(dropdown_selector, option,1642 dropdown_by=dropdown_by, option_by="value",1643 timeout=timeout)1644 ############1645 def generate_referral(self, start_page, destination_page):1646 """ This method opens the start_page, creates a referral link there,1647 and clicks on that link, which goes to the destination_page.1648 (This generates real traffic for testing analytics software.) """1649 if not page_utils.is_valid_url(destination_page):1650 raise Exception(1651 "Exception: destination_page {%s} is not a valid URL!"1652 % destination_page)1653 if start_page:1654 if not page_utils.is_valid_url(start_page):1655 raise Exception(1656 "Exception: start_page {%s} is not a valid URL! "1657 "(Use an empty string or None to start from current page.)"1658 % start_page)1659 self.open(start_page)1660 time.sleep(0.08)1661 referral_link = ('''<a class='analytics referral test' href='%s' '''1662 '''style='font-family: Arial,sans-serif; '''1663 '''font-size: 30px; color: #18a2cd'>'''1664 '''Magic Link Button</a>''' % destination_page)1665 self.execute_script(1666 '''document.body.innerHTML = \"%s\"''' % referral_link)1667 time.sleep(0.1)1668 self.click("a.analytics.referral.test") # Clicks the generated button1669 time.sleep(0.15)1670 try:1671 self.click("html")1672 time.sleep(0.08)1673 except Exception:1674 pass1675 def generate_traffic(self, start_page, destination_page, loops=1):1676 """ Similar to generate_referral(), but can do multiple loops. """1677 for loop in range(loops):1678 self.generate_referral(start_page, destination_page)1679 time.sleep(0.05)1680 def generate_referral_chain(self, pages):1681 """ Use this method to chain the action of creating button links on1682 one website page that will take you to the next page.1683 (When you want to create a referral to a website for traffic1684 generation without increasing the bounce rate, you'll want to visit1685 at least one additional page on that site with a button click.) """1686 if not type(pages) is tuple and not type(pages) is list:1687 raise Exception(1688 "Exception: Expecting a list of website pages for chaining!")1689 if len(pages) < 2:1690 raise Exception(1691 "Exception: At least two website pages required for chaining!")1692 for page in pages:1693 # Find out if any of the web pages are invalid before continuing1694 if not page_utils.is_valid_url(page):1695 raise Exception(1696 "Exception: Website page {%s} is not a valid URL!" % page)1697 for page in pages:1698 self.generate_referral(None, page)1699 def generate_traffic_chain(self, pages, loops=1):1700 """ Similar to generate_referral_chain(), but for multiple loops. """1701 for loop in range(loops):1702 self.generate_referral_chain(pages)1703 time.sleep(0.05)1704 ############1705 def wait_for_element_present(self, selector, by=By.CSS_SELECTOR,1706 timeout=settings.LARGE_TIMEOUT):1707 """ Waits for an element to appear in the HTML of a page.1708 The element does not need be visible (it may be hidden). """1709 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1710 timeout = self.__get_new_timeout(timeout)1711 if page_utils.is_xpath_selector(selector):1712 by = By.XPATH1713 if page_utils.is_link_text_selector(selector):1714 selector = page_utils.get_link_text_from_selector(selector)1715 by = By.LINK_TEXT1716 return page_actions.wait_for_element_present(1717 self.driver, selector, by, timeout)1718 def assert_element_present(self, selector, by=By.CSS_SELECTOR,1719 timeout=settings.SMALL_TIMEOUT):1720 """ Similar to wait_for_element_present(), but returns nothing.1721 Waits for an element to appear in the HTML of a page.1722 The element does not need be visible (it may be hidden).1723 Returns True if successful. Default timeout = SMALL_TIMEOUT. """1724 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1725 timeout = self.__get_new_timeout(timeout)1726 self.wait_for_element_present(selector, by=by, timeout=timeout)1727 return True1728 # For backwards compatibility, earlier method names of the next1729 # four methods have remained even though they do the same thing,1730 # with the exception of assert_*, which won't return the element,1731 # but like the others, will raise an exception if the call fails.1732 def wait_for_element_visible(self, selector, by=By.CSS_SELECTOR,1733 timeout=settings.LARGE_TIMEOUT):1734 """ Waits for an element to appear in the HTML of a page.1735 The element must be visible (it cannot be hidden). """1736 if page_utils.is_xpath_selector(selector):1737 by = By.XPATH1738 if page_utils.is_link_text_selector(selector):1739 selector = page_utils.get_link_text_from_selector(selector)1740 by = By.LINK_TEXT1741 return page_actions.wait_for_element_visible(1742 self.driver, selector, by, timeout)1743 def wait_for_element(self, selector, by=By.CSS_SELECTOR,1744 timeout=settings.LARGE_TIMEOUT):1745 """ The shorter version of wait_for_element_visible() """1746 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1747 timeout = self.__get_new_timeout(timeout)1748 return self.wait_for_element_visible(selector, by=by, timeout=timeout)1749 def find_element(self, selector, by=By.CSS_SELECTOR,1750 timeout=settings.LARGE_TIMEOUT):1751 """ Same as wait_for_element_visible() - returns the element """1752 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1753 timeout = self.__get_new_timeout(timeout)1754 return self.wait_for_element_visible(selector, by=by, timeout=timeout)1755 def assert_element(self, selector, by=By.CSS_SELECTOR,1756 timeout=settings.SMALL_TIMEOUT):1757 """ Similar to wait_for_element_visible(), but returns nothing.1758 As above, will raise an exception if nothing can be found.1759 Returns True if successful. Default timeout = SMALL_TIMEOUT. """1760 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1761 timeout = self.__get_new_timeout(timeout)1762 self.wait_for_element_visible(selector, by=by, timeout=timeout)1763 if self.demo_mode:1764 if page_utils.is_xpath_selector(selector):1765 by = By.XPATH1766 if page_utils.is_link_text_selector(selector):1767 selector = page_utils.get_link_text_from_selector(selector)1768 by = By.LINK_TEXT1769 messenger_post = "ASSERT %s: %s" % (by, selector)1770 self.__highlight_with_assert_success(messenger_post, selector, by)1771 return True1772 # For backwards compatibility, earlier method names of the next1773 # four methods have remained even though they do the same thing,1774 # with the exception of assert_*, which won't return the element,1775 # but like the others, will raise an exception if the call fails.1776 def wait_for_text_visible(self, text, selector, by=By.CSS_SELECTOR,1777 timeout=settings.LARGE_TIMEOUT):1778 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1779 timeout = self.__get_new_timeout(timeout)1780 if page_utils.is_xpath_selector(selector):1781 by = By.XPATH1782 if page_utils.is_link_text_selector(selector):1783 selector = page_utils.get_link_text_from_selector(selector)1784 by = By.LINK_TEXT1785 return page_actions.wait_for_text_visible(1786 self.driver, text, selector, by, timeout)1787 def wait_for_text(self, text, selector, by=By.CSS_SELECTOR,1788 timeout=settings.LARGE_TIMEOUT):1789 """ The shorter version of wait_for_text_visible() """1790 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1791 timeout = self.__get_new_timeout(timeout)1792 return self.wait_for_text_visible(1793 text, selector, by=by, timeout=timeout)1794 def find_text(self, text, selector, by=By.CSS_SELECTOR,1795 timeout=settings.LARGE_TIMEOUT):1796 """ Same as wait_for_text_visible() - returns the element """1797 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1798 timeout = self.__get_new_timeout(timeout)1799 return self.wait_for_text_visible(1800 text, selector, by=by, timeout=timeout)1801 def assert_text_visible(self, text, selector, by=By.CSS_SELECTOR,1802 timeout=settings.SMALL_TIMEOUT):1803 """ Same as assert_text() """1804 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1805 timeout = self.__get_new_timeout(timeout)1806 return self.assert_text(text, selector, by=by, timeout=timeout)1807 def assert_text(self, text, selector, by=By.CSS_SELECTOR,1808 timeout=settings.SMALL_TIMEOUT):1809 """ Similar to wait_for_text_visible()1810 Raises an exception if the element or the text is not found.1811 Returns True if successful. Default timeout = SMALL_TIMEOUT. """1812 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1813 timeout = self.__get_new_timeout(timeout)1814 self.wait_for_text_visible(text, selector, by=by, timeout=timeout)1815 if self.demo_mode:1816 if page_utils.is_xpath_selector(selector):1817 by = By.XPATH1818 if page_utils.is_link_text_selector(selector):1819 selector = page_utils.get_link_text_from_selector(selector)1820 by = By.LINK_TEXT1821 messenger_post = ("ASSERT TEXT {%s} in %s: %s"1822 % (text, by, selector))1823 self.__highlight_with_assert_success(messenger_post, selector, by)1824 return True1825 # For backwards compatibility, earlier method names of the next1826 # four methods have remained even though they do the same thing,1827 # with the exception of assert_*, which won't return the element,1828 # but like the others, will raise an exception if the call fails.1829 def wait_for_link_text_visible(self, link_text,1830 timeout=settings.LARGE_TIMEOUT):1831 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1832 timeout = self.__get_new_timeout(timeout)1833 return self.wait_for_element_visible(1834 link_text, by=By.LINK_TEXT, timeout=timeout)1835 def wait_for_link_text(self, link_text, timeout=settings.LARGE_TIMEOUT):1836 """ The shorter version of wait_for_link_text_visible() """1837 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1838 timeout = self.__get_new_timeout(timeout)1839 return self.wait_for_link_text_visible(link_text, timeout=timeout)1840 def find_link_text(self, link_text, timeout=settings.LARGE_TIMEOUT):1841 """ Same as wait_for_link_text_visible() - returns the element """1842 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1843 timeout = self.__get_new_timeout(timeout)1844 return self.wait_for_link_text_visible(link_text, timeout=timeout)1845 def assert_link_text(self, link_text, timeout=settings.SMALL_TIMEOUT):1846 """ Similar to wait_for_link_text_visible(), but returns nothing.1847 As above, will raise an exception if nothing can be found.1848 Returns True if successful. Default timeout = SMALL_TIMEOUT. """1849 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1850 timeout = self.__get_new_timeout(timeout)1851 self.wait_for_link_text_visible(link_text, timeout=timeout)1852 if self.demo_mode:1853 messenger_post = ("ASSERT LINK TEXT {%s}." % link_text)1854 self.__highlight_with_assert_success(1855 messenger_post, link_text, by=By.LINK_TEXT)1856 return True1857 # For backwards compatibility, earlier method names of the next1858 # four methods have remained even though they do the same thing,1859 # with the exception of assert_*, which won't return the element,1860 # but like the others, will raise an exception if the call fails.1861 def wait_for_partial_link_text(self, partial_link_text,1862 timeout=settings.LARGE_TIMEOUT):1863 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1864 timeout = self.__get_new_timeout(timeout)1865 return self.wait_for_element_visible(1866 partial_link_text, by=By.PARTIAL_LINK_TEXT, timeout=timeout)1867 def find_partial_link_text(self, partial_link_text,1868 timeout=settings.LARGE_TIMEOUT):1869 """ Same as wait_for_partial_link_text() - returns the element """1870 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1871 timeout = self.__get_new_timeout(timeout)1872 return self.wait_for_partial_link_text(1873 partial_link_text, timeout=timeout)1874 def assert_partial_link_text(self, partial_link_text,1875 timeout=settings.SMALL_TIMEOUT):1876 """ Similar to wait_for_partial_link_text(), but returns nothing.1877 As above, will raise an exception if nothing can be found.1878 Returns True if successful. Default timeout = SMALL_TIMEOUT. """1879 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1880 timeout = self.__get_new_timeout(timeout)1881 self.wait_for_partial_link_text(partial_link_text, timeout=timeout)1882 return True1883 ############1884 def wait_for_element_absent(self, selector, by=By.CSS_SELECTOR,1885 timeout=settings.LARGE_TIMEOUT):1886 """ Waits for an element to no longer appear in the HTML of a page.1887 A hidden element still counts as appearing in the page HTML.1888 If an element with "hidden" status is acceptable,1889 use wait_for_element_not_visible() instead. """1890 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1891 timeout = self.__get_new_timeout(timeout)1892 if page_utils.is_xpath_selector(selector):1893 by = By.XPATH1894 return page_actions.wait_for_element_absent(1895 self.driver, selector, by, timeout)1896 def assert_element_absent(self, selector, by=By.CSS_SELECTOR,1897 timeout=settings.SMALL_TIMEOUT):1898 """ Similar to wait_for_element_absent() - returns nothing.1899 As above, will raise an exception if the element stays present.1900 Returns True if successful. Default timeout = SMALL_TIMEOUT. """1901 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1902 timeout = self.__get_new_timeout(timeout)1903 self.wait_for_element_absent(selector, by=by, timeout=timeout)1904 return True1905 ############1906 def wait_for_element_not_visible(self, selector, by=By.CSS_SELECTOR,1907 timeout=settings.LARGE_TIMEOUT):1908 """ Waits for an element to no longer be visible on a page.1909 The element can be non-existant in the HTML or hidden on the page1910 to qualify as not visible. """1911 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1912 timeout = self.__get_new_timeout(timeout)1913 if page_utils.is_xpath_selector(selector):1914 by = By.XPATH1915 if page_utils.is_link_text_selector(selector):1916 selector = page_utils.get_link_text_from_selector(selector)1917 by = By.LINK_TEXT1918 return page_actions.wait_for_element_not_visible(1919 self.driver, selector, by, timeout)1920 def assert_element_not_visible(self, selector, by=By.CSS_SELECTOR,1921 timeout=settings.SMALL_TIMEOUT):1922 """ Similar to wait_for_element_not_visible() - returns nothing.1923 As above, will raise an exception if the element stays visible.1924 Returns True if successful. Default timeout = SMALL_TIMEOUT. """1925 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1926 timeout = self.__get_new_timeout(timeout)1927 self.wait_for_element_not_visible(selector, by=by, timeout=timeout)1928 return True1929 ############1930 def wait_for_ready_state_complete(self, timeout=settings.EXTREME_TIMEOUT):1931 if self.timeout_multiplier and timeout == settings.EXTREME_TIMEOUT:1932 timeout = self.__get_new_timeout(timeout)1933 is_ready = js_utils.wait_for_ready_state_complete(self.driver, timeout)1934 self.wait_for_angularjs(timeout=settings.MINI_TIMEOUT)1935 if self.ad_block_on:1936 # If the ad_block feature is enabled, then block ads for new URLs1937 current_url = self.get_current_url()1938 if not current_url == self.__last_page_load_url:1939 time.sleep(0.02)1940 self.ad_block()1941 time.sleep(0.01)1942 if self.is_element_present("iframe"):1943 time.sleep(0.07) # iframe ads take slightly longer to load1944 self.ad_block() # Do ad_block on slower-loading iframes1945 self.__last_page_load_url = current_url1946 return is_ready1947 def wait_for_angularjs(self, timeout=settings.LARGE_TIMEOUT, **kwargs):1948 js_utils.wait_for_angularjs(self.driver, timeout, **kwargs)1949 def wait_for_and_accept_alert(self, timeout=settings.LARGE_TIMEOUT):1950 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1951 timeout = self.__get_new_timeout(timeout)1952 return page_actions.wait_for_and_accept_alert(self.driver, timeout)1953 def wait_for_and_dismiss_alert(self, timeout=settings.LARGE_TIMEOUT):1954 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1955 timeout = self.__get_new_timeout(timeout)1956 return page_actions.wait_for_and_dismiss_alert(self.driver, timeout)1957 def wait_for_and_switch_to_alert(self, timeout=settings.LARGE_TIMEOUT):1958 if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:1959 timeout = self.__get_new_timeout(timeout)1960 return page_actions.wait_for_and_switch_to_alert(self.driver, timeout)1961 def switch_to_frame(self, frame, timeout=settings.SMALL_TIMEOUT):1962 """ Sets driver control to the specified browser frame. """1963 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1964 timeout = self.__get_new_timeout(timeout)1965 page_actions.switch_to_frame(self.driver, frame, timeout)1966 def switch_to_default_content(self):1967 """ Brings driver control outside the current iframe.1968 (If driver control is inside an iframe, the driver control1969 will be set to one level above the current frame. If the driver1970 control is not currenly in an iframe, nothing will happen.) """1971 self.driver.switch_to.default_content()1972 def open_new_window(self, switch_to=True):1973 """ Opens a new browser tab/window and switches to it by default. """1974 self.driver.execute_script("window.open('');")1975 time.sleep(0.01)1976 if switch_to:1977 self.switch_to_window(len(self.driver.window_handles) - 1)1978 def switch_to_window(self, window, timeout=settings.SMALL_TIMEOUT):1979 if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:1980 timeout = self.__get_new_timeout(timeout)1981 page_actions.switch_to_window(self.driver, window, timeout)1982 def switch_to_default_window(self):1983 self.switch_to_window(0)1984 def save_screenshot(self, name, folder=None):1985 """ The screenshot will be in PNG format. """1986 return page_actions.save_screenshot(self.driver, name, folder)1987 def get_new_driver(self, browser=None, headless=None,1988 servername=None, port=None, proxy=None, switch_to=True):1989 """ This method spins up an extra browser for tests that require1990 more than one. The first browser is already provided by tests1991 that import base_case.BaseCase from seleniumbase. If parameters1992 aren't specified, the method uses the same as the default driver.1993 @Params1994 browser - the browser to use. (Ex: "chrome", "firefox")1995 headless - the option to run webdriver in headless mode1996 servername - if using a Selenium Grid, set the host address here1997 port - if using a Selenium Grid, set the host port here1998 proxy - if using a proxy server, specify the "host:port" combo here1999 switch_to - the option to switch to the new driver (default = True)2000 """2001 if browser is None:2002 browser = self.browser2003 browser_name = browser2004 if headless is None:2005 headless = self.headless2006 if servername is None:2007 servername = self.servername2008 if port is None:2009 port = self.port2010 use_grid = False2011 if servername != "localhost":2012 # Use Selenium Grid (Use "127.0.0.1" for localhost Grid)2013 use_grid = True2014 proxy_string = proxy2015 if proxy_string is None:2016 proxy_string = self.proxy_string2017 valid_browsers = constants.ValidBrowsers.valid_browsers2018 if browser_name not in valid_browsers:2019 raise Exception("Browser: {%s} is not a valid browser option. "2020 "Valid options = {%s}" % (browser, valid_browsers))2021 # Launch a web browser2022 from seleniumbase.core import browser_launcher2023 new_driver = browser_launcher.get_driver(browser_name=browser_name,2024 headless=headless,2025 use_grid=use_grid,2026 servername=servername,2027 port=port,2028 proxy_string=proxy_string)2029 self._drivers_list.append(new_driver)2030 if switch_to:2031 self.driver = new_driver2032 if self.headless:2033 # Make sure the invisible browser window is big enough2034 try:2035 self.set_window_size(1440, 1080)2036 self.wait_for_ready_state_complete()2037 except Exception:2038 # This shouldn't fail, but in case it does,2039 # get safely through setUp() so that2040 # WebDrivers can get closed during tearDown().2041 pass2042 else:2043 if self.browser == 'chrome':2044 try:2045 if settings.START_CHROME_IN_FULL_SCREEN_MODE:2046 self.driver.maximize_window()2047 else:2048 self.driver.set_window_size(1250, 840)2049 self.wait_for_ready_state_complete()2050 except Exception:2051 pass # Keep existing browser resolution2052 return new_driver2053 def switch_to_driver(self, driver):2054 """ Sets self.driver to the specified driver.2055 You may need this if using self.get_new_driver() in your code. """2056 self.driver = driver2057 def switch_to_default_driver(self):2058 """ Sets self.driver to the default/original driver. """2059 self.driver = self._default_driver2060 ############2061 def __get_new_timeout(self, timeout):2062 """ When using --timeout_multiplier=#.# """2063 try:2064 timeout_multiplier = float(self.timeout_multiplier)2065 if timeout_multiplier <= 0.5:2066 timeout_multiplier = 0.52067 timeout = int(math.ceil(timeout_multiplier * timeout))2068 return timeout2069 except Exception:2070 # Wrong data type for timeout_multiplier (expecting int or float)2071 return timeout2072 ############2073 def __get_exception_message(self):2074 """ This method extracts the message from an exception if there2075 was an exception that occurred during the test, assuming2076 that the exception was in a try/except block and not thrown. """2077 exception_info = sys.exc_info()[1]2078 if hasattr(exception_info, 'msg'):2079 exc_message = exception_info.msg2080 elif hasattr(exception_info, 'message'):2081 exc_message = exception_info.message2082 else:2083 exc_message = '(Unknown Exception)'2084 return exc_message2085 def __get_improved_exception_message(self):2086 """2087 If Chromedriver is out-of-date, make it clear!2088 Given the high popularity of the following StackOverflow article:2089 https://stackoverflow.com/questions/49162667/unknown-error-2090 call-function-result-missing-value-for-selenium-send-keys-even2091 ... the original error message was not helpful. Tell people directly.2092 (Only expected when using driver.send_keys() with an old Chromedriver.)2093 """2094 exc_message = self.__get_exception_message()2095 maybe_using_old_chromedriver = False2096 if "unknown error: call function result missing" in exc_message:2097 maybe_using_old_chromedriver = True2098 if self.browser == 'chrome' and maybe_using_old_chromedriver:2099 update = ("Your version of ChromeDriver may be out-of-date! "2100 "Please go to "2101 "https://sites.google.com/a/chromium.org/chromedriver/ "2102 "and download the latest version to your system PATH! "2103 "Or use: ``seleniumbase install chromedriver`` . "2104 "Original Exception Message: %s" % exc_message)2105 exc_message = update2106 return exc_message2107 def __add_delayed_assert_failure(self):2108 """ Add a delayed_assert failure into a list for future processing. """2109 current_url = self.driver.current_url2110 message = self.__get_exception_message()2111 self.__page_check_failures.append(2112 "CHECK #%s: (%s)\n %s" % (2113 self.__page_check_count, current_url, message))2114 def delayed_assert_element(self, selector, by=By.CSS_SELECTOR,2115 timeout=settings.MINI_TIMEOUT):2116 """ A non-terminating assertion for an element on a page.2117 Failures will be saved until the process_delayed_asserts()2118 method is called from inside a test, likely at the end of it. """2119 self.__page_check_count += 12120 try:2121 url = self.get_current_url()2122 if url == self.__last_url_of_delayed_assert:2123 timeout = 12124 else:2125 self.__last_url_of_delayed_assert = url2126 except Exception:2127 pass2128 try:2129 self.wait_for_element_visible(selector, by=by, timeout=timeout)2130 return True2131 except Exception:2132 self.__add_delayed_assert_failure()2133 return False2134 @decorators.deprecated("Use self.delayed_assert_element() instead!")2135 def check_assert_element(self, selector, by=By.CSS_SELECTOR,2136 timeout=settings.MINI_TIMEOUT):2137 """ DEPRECATED - Use self.delayed_assert_element() instead. """2138 return self.delayed_assert_element(selector, by=by, timeout=timeout)2139 def delayed_assert_text(self, text, selector, by=By.CSS_SELECTOR,2140 timeout=settings.MINI_TIMEOUT):2141 """ A non-terminating assertion for text from an element on a page.2142 Failures will be saved until the process_delayed_asserts()2143 method is called from inside a test, likely at the end of it. """2144 self.__page_check_count += 12145 try:2146 url = self.get_current_url()2147 if url == self.__last_url_of_delayed_assert:2148 timeout = 12149 else:2150 self.__last_url_of_delayed_assert = url2151 except Exception:2152 pass2153 try:2154 self.wait_for_text_visible(text, selector, by=by, timeout=timeout)2155 return True2156 except Exception:2157 self.__add_delayed_assert_failure()2158 return False2159 @decorators.deprecated("Use self.delayed_assert_text() instead!")2160 def check_assert_text(self, text, selector, by=By.CSS_SELECTOR,2161 timeout=settings.MINI_TIMEOUT):2162 """ DEPRECATED - Use self.delayed_assert_text() instead. """2163 return self.delayed_assert_text(text, selector, by=by, timeout=timeout)2164 def process_delayed_asserts(self, print_only=False):2165 """ To be used with any test that uses delayed_asserts, which are2166 non-terminating verifications that only raise exceptions2167 after this method is called.2168 This is useful for pages with multiple elements to be checked when2169 you want to find as many bugs as possible in a single test run2170 before having all the exceptions get raised simultaneously.2171 Might be more useful if this method is called after processing all2172 the delayed asserts on a single html page so that the failure2173 screenshot matches the location of the delayed asserts.2174 If "print_only" is set to True, the exception won't get raised. """2175 if self.__page_check_failures:2176 exception_output = ''2177 exception_output += "\n*** DELAYED ASSERTION FAILURES FOR: "2178 exception_output += "%s\n" % self.id()2179 all_failing_checks = self.__page_check_failures2180 self.__page_check_failures = []2181 for tb in all_failing_checks:2182 exception_output += "%s\n" % tb2183 if print_only:2184 print(exception_output)2185 else:2186 raise Exception(exception_output)2187 @decorators.deprecated("Use self.process_delayed_asserts() instead!")2188 def process_checks(self, print_only=False):2189 """ DEPRECATED - Use self.process_delayed_asserts() instead. """2190 self.process_delayed_asserts(print_only=print_only)2191 ############2192 def __js_click(self, selector, by=By.CSS_SELECTOR):2193 """ Clicks an element using pure JS. Does not use jQuery. """2194 selector, by = self.__recalculate_selector(selector, by)2195 css_selector = self.convert_to_css_selector(selector, by=by)2196 css_selector = re.escape(css_selector)2197 css_selector = self.__escape_quotes_if_needed(css_selector)2198 script = ("""var simulateClick = function (elem) {2199 var evt = new MouseEvent('click', {2200 bubbles: true,2201 cancelable: true,2202 view: window2203 });2204 var canceled = !elem.dispatchEvent(evt);2205 };2206 var someLink = document.querySelector('%s');2207 simulateClick(someLink);"""2208 % css_selector)2209 self.execute_script(script)2210 def __jquery_click(self, selector, by=By.CSS_SELECTOR):2211 """ Clicks an element using jQuery. Different from using pure JS. """2212 selector, by = self.__recalculate_selector(selector, by)2213 self.wait_for_element_present(2214 selector, by=by, timeout=settings.SMALL_TIMEOUT)2215 if self.is_element_visible(selector, by=by):2216 self.__demo_mode_highlight_if_active(selector, by)2217 selector = self.convert_to_css_selector(selector, by=by)2218 selector = self.__make_css_match_first_element_only(selector)2219 click_script = """jQuery('%s')[0].click()""" % selector2220 self.safe_execute_script(click_script)2221 def __get_href_from_link_text(self, link_text, hard_fail=True):2222 href = self.get_link_attribute(link_text, "href", hard_fail)2223 if not href:2224 return None2225 if href.startswith('//'):2226 link = "http:" + href2227 elif href.startswith('/'):2228 url = self.driver.current_url2229 domain_url = self.get_domain_url(url)2230 link = domain_url + href2231 else:2232 link = href2233 return link2234 def __click_dropdown_link_text(self, link_text, link_css):2235 """ When a link may be hidden under a dropdown menu, use this. """2236 source = self.get_page_source()2237 soup = BeautifulSoup(source, "html.parser")2238 drop_down_list = soup.select('[class*=dropdown]')2239 csstype = link_css.split('[')[1].split('=')[0]2240 for item in drop_down_list:2241 if link_text in item.text.split('\n') and csstype in item.decode():2242 dropdown_css = ""2243 for css_class in item['class']:2244 dropdown_css += '.'2245 dropdown_css += css_class2246 dropdown_css = item.name + dropdown_css2247 matching_dropdowns = self.find_visible_elements(dropdown_css)2248 for dropdown in matching_dropdowns:2249 # The same class names might be used for multiple dropdowns2250 try:2251 page_actions.hover_element_and_click(2252 self.driver, dropdown, link_text,2253 click_by=By.LINK_TEXT, timeout=0.1)2254 return True2255 except Exception:2256 pass2257 return False2258 def __recalculate_selector(self, selector, by):2259 # Try to determine the type of selector automatically2260 if page_utils.is_xpath_selector(selector):2261 by = By.XPATH2262 if page_utils.is_link_text_selector(selector):2263 selector = page_utils.get_link_text_from_selector(selector)2264 by = By.LINK_TEXT2265 return (selector, by)2266 def __make_css_match_first_element_only(self, selector):2267 # Only get the first match2268 return page_utils.make_css_match_first_element_only(selector)2269 def __demo_mode_pause_if_active(self, tiny=False):2270 if self.demo_mode:2271 if self.demo_sleep:2272 wait_time = float(self.demo_sleep)2273 else:2274 wait_time = settings.DEFAULT_DEMO_MODE_TIMEOUT2275 if not tiny:2276 time.sleep(wait_time)2277 else:2278 time.sleep(wait_time / 3.4)2279 def __demo_mode_scroll_if_active(self, selector, by):2280 if self.demo_mode:2281 self.slow_scroll_to(selector, by=by)2282 def __demo_mode_highlight_if_active(self, selector, by):2283 if self.demo_mode:2284 # Includes self.slow_scroll_to(selector, by=by) by default2285 self.highlight(selector, by=by)2286 def __scroll_to_element(self, element):2287 js_utils.scroll_to_element(self.driver, element)2288 self.__demo_mode_pause_if_active(tiny=True)2289 def __slow_scroll_to_element(self, element):2290 js_utils.slow_scroll_to_element(self.driver, element, self.browser)2291 def __post_messenger_success_message(self, message, duration=None):2292 js_utils.post_messenger_success_message(2293 self.driver, message, self.message_duration, duration=duration)2294 def __post_messenger_error_message(self, message, duration=None):2295 js_utils.post_messenger_error_message(2296 self.driver, message, self.message_duration, duration=duration)...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!