How to use __is_shadow_selector method in SeleniumBase

Best Python code snippet using SeleniumBase

webdriver_test.py

Source:webdriver_test.py Github

copy

Full Screen

...3460 Returns the element that contains the attribute if successful.3461 Default timeout = LARGE_TIMEOUT."""3462 self.__check_scope__()3463 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)3464 if self.__is_shadow_selector(selector):3465 return self.__wait_for_shadow_attribute_present(3466 selector, attribute, value=value, timeout=timeout3467 )3468 return page_actions.wait_for_attribute(3469 self.driver,3470 selector,3471 attribute,3472 value=value,3473 by=by,3474 timeout=timeout,3475 )3476 def inspect_html(self):3477 """Inspects the Page HTML with HTML-Inspector.3478 (https://github.com/philipwalton/html-inspector)3479 (https://cdnjs.com/libraries/html-inspector)3480 Prints the results and also returns them."""3481 self._activate_html_inspector()3482 self.wait_for_ready_state_complete()3483 script = """HTMLInspector.inspect();"""3484 try:3485 self.execute_script(script)3486 except Exception:3487 # If unable to load the JavaScript, skip inspection and return.3488 msg = "(Unable to load HTML-Inspector JS! Inspection Skipped!)"3489 print("\n" + msg)3490 return msg3491 time.sleep(0.1)3492 browser_logs = []3493 try:3494 browser_logs = self.driver.get_log("browser")3495 except (ValueError, WebDriverException):3496 # If unable to get browser logs, skip the assert and return.3497 msg = "(Unable to Inspect HTML! -> Only works on Chromium!)"3498 print("\n" + msg)3499 return msg3500 messenger_library = "//cdnjs.cloudflare.com/ajax/libs/messenger"3501 url = self.get_current_url()3502 header = "\n* HTML Inspection Results: %s" % url3503 results = [header]3504 row_count = 03505 for entry in browser_logs:3506 message = entry["message"]3507 if "0:6053 " in message:3508 message = message.split("0:6053")[1]3509 message = message.replace("\\u003C", "<")3510 if message.startswith(' "') and message.count('"') == 2:3511 message = message.split('"')[1]3512 message = "X - " + message3513 if messenger_library not in message:3514 if message not in results:3515 results.append(message)3516 row_count += 13517 if row_count > 0:3518 results.append("* (See the Console output for details!)")3519 else:3520 results.append("* (No issues detected!)")3521 results = "\n".join(results)3522 print(results)3523 return results3524 def is_valid_url(self, url):3525 """ Return True if the url is a valid url. """3526 return page_utils.is_valid_url(url)3527 def get_mfa_code(self, totp_key=None):3528 """Same as get_totp_code() and get_google_auth_password().3529 Returns a time-based one-time password based on the3530 Google Authenticator algorithm for multi-factor authentication.3531 If the "totp_key" is not specified, this method defaults3532 to using the one provided in [seleniumbase/config/settings.py].3533 Google Authenticator codes expire & change at 30-sec intervals.3534 If the fetched password expires in the next 1.5 seconds, waits3535 for a new one before returning it (may take up to 1.5 seconds).3536 See https://pyotp.readthedocs.io/en/latest/ for details."""3537 import pyotp3538 if not totp_key:3539 totp_key = settings.TOTP_KEY3540 epoch_interval = time.time() / 30.03541 cycle_lifespan = float(epoch_interval) - int(epoch_interval)3542 if float(cycle_lifespan) > 0.95:3543 # Password expires in the next 1.5 seconds. Wait for a new one.3544 for i in range(30):3545 time.sleep(0.05)3546 epoch_interval = time.time() / 30.03547 cycle_lifespan = float(epoch_interval) - int(epoch_interval)3548 if not float(cycle_lifespan) > 0.95:3549 # The new password cycle has begun3550 break3551 totp = pyotp.TOTP(totp_key)3552 return str(totp.now())3553 def enter_mfa_code(3554 self, selector, totp_key=None, by=By.CSS_SELECTOR, timeout=None3555 ):3556 """Enters into the field a Multi-Factor Authentication TOTP Code.3557 If the "totp_key" is not specified, this method defaults3558 to using the one provided in [seleniumbase/config/settings.py].3559 The TOTP code is generated by the Google Authenticator Algorithm.3560 This method will automatically press ENTER after typing the code."""3561 self.__check_scope__()3562 if not timeout:3563 timeout = settings.SMALL_TIMEOUT3564 self.wait_for_element_visible(selector, by=by, timeout=timeout)3565 mfa_code = self.get_mfa_code(totp_key)3566 self.update_text(selector, mfa_code + "\n", by=by, timeout=timeout)3567 def convert_css_to_xpath(self, css):3568 return css_to_xpath.convert_css_to_xpath(css)3569 def convert_xpath_to_css(self, xpath):3570 return xpath_to_css.convert_xpath_to_css(xpath)3571 def convert_to_css_selector(self, selector, by):3572 """This method converts a selector to a CSS_SELECTOR.3573 jQuery commands require a CSS_SELECTOR for finding elements.3574 This method should only be used for jQuery/JavaScript actions.3575 Pure JavaScript doesn't support using a:contains("LINK_TEXT")."""3576 if by == By.CSS_SELECTOR:3577 return selector3578 elif by == By.ID:3579 return "#%s" % selector3580 elif by == By.CLASS_NAME:3581 return ".%s" % selector3582 elif by == By.NAME:3583 return '[name="%s"]' % selector3584 elif by == By.TAG_NAME:3585 return selector3586 elif by == By.XPATH:3587 return self.convert_xpath_to_css(selector)3588 elif by == By.LINK_TEXT:3589 return 'a:contains("%s")' % selector3590 elif by == By.PARTIAL_LINK_TEXT:3591 return 'a:contains("%s")' % selector3592 else:3593 raise Exception(3594 "Exception: Could not convert {%s}(by=%s) to CSS_SELECTOR!"3595 % (selector, by)3596 )3597 def set_value(3598 self, selector, text, by=By.CSS_SELECTOR, timeout: =None, scroll=True3599 ):3600 """ This method uses JavaScript to update a text field. """3601 self.__check_scope__()3602 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)3603 self.wait_for_ready_state_complete()3604 self.wait_for_element_present(selector, by=by, timeout=timeout)3605 css_selector = self.convert_to_css_selector(selector, by=by)3606 self.__demo_mode_highlight_if_active(how, selector)3607 if scroll and not self.demo_mode and not self.slow_mode:3608 self.scroll_to(how, selector, timeout)3609 if type(text) is int or type(text) is float:3610 text = str(text)3611 value = re.escape(text)3612 value = shared.escape_quotes_if_needed(value)3613 pre_escape_css_selector = css_selector3614 css_selector = re.escape(css_selector) # Add "\\" to special chars3615 css_selector = shared.escape_quotes_if_needed(css_selector)3616 the_type = None3617 if ":contains\\(" not in css_selector:3618 get_type_script = (3619 """return document.querySelector('%s').getAttribute('type');"""3620 % css_selector3621 )3622 the_type = self.execute_script(get_type_script) # Used later3623 script = """document.querySelector('%s').value='%s';""" % (3624 css_selector,3625 value,3626 )3627 self.execute_script(script)3628 else:3629 script = """jQuery('%s')[0].value='%s';""" % (css_selector, value)3630 self.safe_execute_script(script)3631 if text.endswith("\n"):3632 element = self.wait_for_element_present(3633 orginal_selector, by=by, timeout=timeout3634 )3635 element.send_keys(Keys.RETURN)3636 if settings.WAIT_FOR_RSC_ON_PAGE_LOADS:3637 self.wait_for_ready_state_complete()3638 else:3639 if the_type == "range" and ":contains\\(" not in css_selector:3640 # Some input sliders need a mouse event to trigger listeners.3641 try:3642 mouse_move_script = (3643 """m_elm = document.querySelector('%s');"""3644 """m_evt = new Event('mousemove');"""3645 """m_elm.dispatchEvent(m_evt);"""3646 % css_selector3647 )3648 self.execute_script(mouse_move_script)3649 except Exception:3650 pass3651 self._demo_mode_pause_if_active()3652 def js_update_text(self, selector, text, by=By.CSS_SELECTOR, timeout=None):3653 """JavaScript + send_keys are used to update a text field.3654 Performs self.set_value() and triggers event listeners.3655 If text ends in "\n", set_value() presses RETURN after.3656 Works faster than send_keys() alone due to the JS call.3657 """3658 self.__check_scope__()3659 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)3660 if type(text) is int or type(text) is float:3661 text = str(text)3662 self.set_value(selector, text, by=by, timeout=timeout)3663 if not text.endswith("\n"):3664 try:3665 element = page_actions.wait_for_element_present(3666 self.driver, selector, by, timeout=0.23667 )3668 element.send_keys(" " + Keys.BACK_SPACE)3669 except Exception:3670 pass3671 def js_type(3672 self,3673 text: str | None,3674 how: SeleniumBy,3675 selector: str = Field(..., strict=True, min_length=1),3676 timeout: OptionalInt = None,3677 ):3678 """Same as self.js_update_text()3679 JavaScript + send_keys are used to update a text field.3680 Performs self.set_value() and triggers event listeners.3681 If text ends in "\n", set_value() presses RETURN after.3682 Works faster than send_keys() alone due to the JS call.3683 """3684 self.__check_scope__()3685 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)3686 self.js_update_text(text, selector, how, timeout)3687 def set_text(3688 self,3689 text: str | None,3690 how: SeleniumBy,3691 selector: str = Field(..., strict=True, min_length=1),3692 timeout: OptionalInt = None3693 ):3694 """Same as self.js_update_text()3695 JavaScript + send_keys are used to update a text field.3696 Performs self.set_value() and triggers event listeners.3697 If text ends in "\n", set_value() presses RETURN after.3698 Works faster than send_keys() alone due to the JS call.3699 If not an input or textarea, sets textContent instead."""3700 self.__check_scope__()3701 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)3702 self.wait_for_ready_state_complete()3703 element = element_actions.wait_for_element_present(self.driver, how, selector, timeout)3704 if element.tag_name == "input" or element.tag_name == "textarea":3705 self.js_update_text(text, how, selector, timeout)3706 else:3707 self.set_text_content(text, how, selector, timeout)3708 def set_text_content(3709 self,3710 text: str | None,3711 how: SeleniumBy,3712 selector: str = Field(..., strict=True, min_length=1),3713 timeout: OptionalInt = None,3714 scroll=False3715 ):3716 """This method uses JavaScript to set an element's textContent.3717 If the element is an input or textarea, sets the value instead."""3718 self.__check_scope__()3719 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)3720 self.wait_for_ready_state_complete()3721 element = element_actions.wait_for_element_present(self.driver, how, selector, timeout)3722 if element.tag_name == "input" or element.tag_name == "textarea":3723 self.js_update_text(text, how, selector, timeout=timeout)3724 return3725 css_selector = self.convert_to_css_selector(how, selector)3726 if scroll:3727 self.__demo_mode_highlight_if_active(how, selector)3728 if not self.demo_mode and not self.slow_mode:3729 self.scroll_to(how, selector, timeout=timeout)3730 if type(text) is int or type(text) is float:3731 text = str(text)3732 value = re.escape(text)3733 value = shared.escape_quotes_if_needed(value)3734 css_selector = re.escape(css_selector) # Add "\\" to special chars3735 css_selector = shared.escape_quotes_if_needed(css_selector)3736 if ":contains\\(" not in css_selector:3737 script = """document.querySelector('%s').textContent='%s';""" % (3738 css_selector,3739 value,3740 )3741 self.execute_script(script)3742 else:3743 script = """jQuery('%s')[0].textContent='%s';""" % (3744 css_selector,3745 value,3746 )3747 self.safe_execute_script(script)3748 self._demo_mode_pause_if_active()3749 def jquery_update_text(3750 self,3751 text: str | None,3752 how: SeleniumBy,3753 selector: str = Field(..., strict=True, min_length=1),3754 timeout: OptionalInt = None3755 ):3756 """This method uses jQuery to update a text field.3757 If the text string ends with the newline character,3758 Selenium finishes the call, which simulates pressing3759 {Enter/Return} after the text is entered."""3760 self.__check_scope__()3761 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)3762 element = self.wait_for_element_visible(how, selector, timeout)3763 self.__demo_mode_highlight_if_active(how, selector)3764 self.scroll_to(how, selector)3765 selector = self.convert_to_css_selector(how, selector)3766 selector = self.__make_css_match_first_element_only(selector)3767 selector = shared.escape_quotes_if_needed(selector)3768 text = re.escape(text)3769 text = shared.escape_quotes_if_needed(text)3770 update_text_script = """jQuery('%s').val('%s');""" % (selector, text)3771 self.safe_execute_script(update_text_script)3772 if text.endswith("\n"):3773 element.send_keys("\n")3774 self._demo_mode_pause_if_active()3775 def get_value(3776 self,3777 how: SeleniumBy,3778 selector: str = Field(..., strict=True, min_length=1),3779 timeout: OptionalInt = None3780 ) -> Optional[Any]:3781 """This method uses JavaScript to get the value of an input field.3782 (Works on both input fields and textarea fields.)"""3783 self.__check_scope__()3784 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)3785 self.wait_for_ready_state_complete()3786 self.wait_for_element_present(how, selector, timeout=timeout)3787 orginal_selector = selector3788 css_selector = self.convert_to_css_selector(how, selector)3789 self.__demo_mode_highlight_if_active(how, selector)3790 if not self.demo_mode and not self.slow_mode:3791 self.scroll_to(how, selector, timeout=timeout)3792 css_selector = re.escape(css_selector) # Add "\\" to special chars3793 css_selector = shared.escape_quotes_if_needed(css_selector)3794 if ":contains\\(" not in css_selector:3795 script = """return document.querySelector('%s').value;""" % (3796 css_selector3797 )3798 value = self.execute_script(script)3799 else:3800 script = """return jQuery('%s')[0].value;""" % css_selector3801 value = self.safe_execute_script(script)3802 return value3803 def set_time_limit(self, time_limit):3804 self.__check_scope__()3805 if time_limit:3806 try:3807 sb_config.time_limit = float(time_limit)3808 except Exception:3809 sb_config.time_limit = None3810 else:3811 sb_config.time_limit = None3812 if sb_config.time_limit and sb_config.time_limit > 0:3813 sb_config.time_limit_ms = int(sb_config.time_limit * 1000.0)3814 self.time_limit = sb_config.time_limit3815 else:3816 self.time_limit = None3817 sb_config.time_limit = None3818 sb_config.time_limit_ms = None3819 def set_default_timeout(self, timeout):3820 """This method changes the default timeout values of test methods3821 for the duration of the current test.3822 Effected timeouts: (used by methods that wait for elements)3823 * settings.SMALL_TIMEOUT - (default value: 6 seconds)3824 * settings.LARGE_TIMEOUT - (default value: 10 seconds)3825 The minimum allowable default timeout is: 0.5 seconds.3826 The maximum allowable default timeout is: 60.0 seconds.3827 (Test methods can still override timeouts outside that range.)3828 """3829 self.__check_scope__()3830 if not type(timeout) is int and not type(timeout) is float:3831 raise Exception('Expecting a numeric value for "timeout"!')3832 if timeout < 0:3833 raise Exception('The "timeout" cannot be a negative number!')3834 timeout = float(timeout)3835 # Min default timeout: 0.5 seconds. Max default timeout: 60.0 seconds.3836 min_timeout = 0.53837 max_timeout = 60.03838 if timeout < min_timeout:3839 logging.info("Minimum default timeout = %s" % min_timeout)3840 timeout = min_timeout3841 elif timeout > max_timeout:3842 logging.info("Maximum default timeout = %s" % max_timeout)3843 timeout = max_timeout3844 self.__overrided_default_timeouts = True3845 sb_config._is_timeout_changed = True3846 settings.SMALL_TIMEOUT = timeout3847 settings.LARGE_TIMEOUT = timeout3848 def reset_default_timeout(self):3849 """Reset default timeout values to the original from settings.py3850 This method reverts the changes made by set_default_timeout()"""3851 if self.__overrided_default_timeouts:3852 if sb_config._SMALL_TIMEOUT and sb_config._LARGE_TIMEOUT:3853 settings.SMALL_TIMEOUT = sb_config._SMALL_TIMEOUT3854 settings.LARGE_TIMEOUT = sb_config._LARGE_TIMEOUT3855 sb_config._is_timeout_changed = False3856 self.__overrided_default_timeouts = False3857 def skip(self, reason=""):3858 """ Mark the test as Skipped. """3859 self.__check_scope__()3860 if self.dashboard:3861 test_id = self.__get_test_id_2()3862 if hasattr(self, "_using_sb_fixture"):3863 test_id = sb_config._test_id3864 if (3865 test_id in sb_config._results.keys()3866 and sb_config._results[test_id] == "Passed"3867 ):3868 # Duplicate tearDown() called where test already passed3869 self.__passed_then_skipped = True3870 self.__will_be_skipped = True3871 sb_config._results[test_id] = "Skipped"3872 if hasattr(self, "with_db_reporting") and self.with_db_reporting:3873 self.__skip_reason = reason3874 # Add skip reason to the logs3875 if not hasattr(self, "_using_sb_fixture"):3876 test_id = self.__get_test_id() # Recalculate the test id3877 test_logpath = os.path.join(self.log_path, test_id)3878 self.__create_log_path_as_needed(test_logpath)3879 browser = self.browser3880 if not reason:3881 reason = "No skip reason given"3882 log_helper.log_skipped_test_data(3883 self, test_logpath, self.driver, browser, reason3884 )3885 # Finally skip the test for real3886 self.skipTest(reason)3887 # Application "Local Storage" controls3888 def set_local_storage_item(self, key, value):3889 self.__check_scope__()3890 self.execute_script(3891 "window.localStorage.setItem('{}', '{}');".format(key, value)3892 )3893 def get_local_storage_item(self, key):3894 self.__check_scope__()3895 return self.execute_script(3896 "return window.localStorage.getItem('{}');".format(key)3897 )3898 def remove_local_storage_item(self, key):3899 self.__check_scope__()3900 self.execute_script(3901 "window.localStorage.removeItem('{}');".format(key)3902 )3903 def clear_local_storage(self):3904 self.__check_scope__()3905 self.execute_script("window.localStorage.clear();")3906 def get_local_storage_keys(self):3907 self.__check_scope__()3908 return self.execute_script(3909 "var ls = window.localStorage, keys = []; "3910 "for (var i = 0; i < ls.length; ++i) "3911 " keys[i] = ls.key(i); "3912 "return keys;"3913 )3914 def get_local_storage_items(self):3915 self.__check_scope__()3916 return self.execute_script(3917 r"var ls = window.localStorage, items = {}; "3918 "for (var i = 0, k; i < ls.length; ++i) "3919 " items[k = ls.key(i)] = ls.getItem(k); "3920 "return items;"3921 )3922 # Application "Session Storage" controls3923 def set_session_storage_item(self, key, value):3924 self.__check_scope__()3925 self.execute_script(3926 "window.sessionStorage.setItem('{}', '{}');".format(key, value)3927 )3928 def get_session_storage_item(self, key):3929 self.__check_scope__()3930 return self.execute_script(3931 "return window.sessionStorage.getItem('{}');".format(key)3932 )3933 def remove_session_storage_item(self, key):3934 self.__check_scope__()3935 self.execute_script(3936 "window.sessionStorage.removeItem('{}');".format(key)3937 )3938 def clear_session_storage(self):3939 self.__check_scope__()3940 self.execute_script("window.sessionStorage.clear();")3941 def get_session_storage_keys(self):3942 self.__check_scope__()3943 return self.execute_script(3944 "var ls = window.sessionStorage, keys = []; "3945 "for (var i = 0; i < ls.length; ++i) "3946 " keys[i] = ls.key(i); "3947 "return keys;"3948 )3949 def get_session_storage_items(self):3950 self.__check_scope__()3951 return self.execute_script(3952 r"var ls = window.sessionStorage, items = {}; "3953 "for (var i = 0, k; i < ls.length; ++i) "3954 " items[k = ls.key(i)] = ls.getItem(k); "3955 "return items;"3956 )3957 ############3958 # Duplicates (Avoids name confusion when migrating from other frameworks.)3959 def open_url(self, url):3960 """ Same as self.open() """3961 self.open(url)3962 def visit(self, url):3963 """ Same as self.open() """3964 self.open(url)3965 def visit_url(self, url):3966 """ Same as self.open() """3967 self.open(url)3968 def goto(self, url):3969 """ Same as self.open() """3970 self.open(url)3971 def go_to(self, url):3972 """ Same as self.open() """3973 self.open(url)3974 def reload(self):3975 """ Same as self.refresh_page() """3976 self.refresh_page()3977 def reload_page(self):3978 """ Same as self.refresh_page() """3979 self.refresh_page()3980 def open_new_tab(self, switch_to=True):3981 """ Same as self.open_new_window() """3982 self.open_new_window(switch_to=switch_to)3983 def switch_to_tab(self, tab, timeout=None):3984 """ Same as self.switch_to_window()3985 Switches control of the browser to the specified window.3986 The window can be an integer: 0 -> 1st tab, 1 -> 2nd tab, etc...3987 Or it can be a list item from self.driver.window_handles """3988 self.switch_to_window(window=tab, timeout=timeout)3989 def switch_to_default_tab(self):3990 """ Same as self.switch_to_default_window() """3991 self.switch_to_default_window()3992 def switch_to_newest_tab(self):3993 """ Same as self.switch_to_newest_window() """3994 self.switch_to_newest_window()3995 def input(3996 self, selector, text, by=By.CSS_SELECTOR, timeout=None, retry=False3997 ):3998 """ Same as self.update_text() """3999 self.__check_scope__()4000 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)4001 self.update_text(selector, text, by=by, timeout=timeout, retry=retry)4002 def fill(4003 self, selector, text, by=By.CSS_SELECTOR, timeout=None, retry=False4004 ):4005 """ Same as self.update_text() """4006 self.__check_scope__()4007 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)4008 self.update_text(selector, text, by=by, timeout=timeout, retry=retry)4009 def write(4010 self, selector, text, by=By.CSS_SELECTOR, timeout=None, retry=False4011 ):4012 """ Same as self.update_text() """4013 self.__check_scope__()4014 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)4015 self.update_text(selector, text, by=by, timeout=timeout, retry=retry)4016 def send_keys(self, selector, text, by=By.CSS_SELECTOR, timeout=None):4017 """ Same as self.add_text() """4018 self.__check_scope__()4019 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)4020 self.add_text(selector, text, by=by, timeout=timeout)4021 def click_link(self, link_text, timeout=None):4022 """ Same as self.click_link_text() """4023 self.__check_scope__()4024 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)4025 self.click_link_text(link_text, timeout=timeout)4026 def click_partial_link(self, partial_link_text, timeout=None):4027 """ Same as self.click_partial_link_text() """4028 self.__check_scope__()4029 timeout = self.get_timeout(timeout, constants.SMALL_TIMEOUT)4030 self.click_partial_link_text(partial_link_text, timeout=timeout)4031 def wait_for_element_visible(4032 self, selector, by=By.CSS_SELECTOR, timeout=None4033 ):4034 """ Same as self.wait_for_element() """4035 self.__check_scope__()4036 timeout = self.get_timeout(timeout, constants.SMALL_TIMEOUT)4037 if self._is_shadow_selector(selector):4038 return self._shadow.wait_for_shadow_element_visible(4039 selector, timeout4040 )4041 return element_actions.wait_for_element_visible(self.driver, selector, by, timeout)4042 def wait_for_element_interactable(4043 self, selector, by=By.CSS_SELECTOR, timeout=None4044 ):4045 """ Same as self.wait_for_element() """4046 self.__check_scope__()4047 timeout = self.get_timeout(timeout, constants.SMALL_TIMEOUT)4048 if self._is_shadow_selector(selector):4049 return self._shadow.wait_for_shadow_element_visible(4050 selector, timeout4051 )4052 return element_actions.wait_for_element_interactable(self.driver, selector, by, timeout)4053 def wait_for_element_not_present(4054 self, selector, by=By.CSS_SELECTOR, timeout=None4055 ):4056 """Same as self.wait_for_element_absent()4057 Waits for an element to no longer appear in the HTML of a page.4058 A hidden element still counts as appearing in the page HTML.4059 If waiting for elements to be hidden instead of nonexistent,4060 use wait_for_element_not_visible() instead.4061 """4062 self.__check_scope__()4063 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)4064 selector, by = self.__recalculate_selector(selector, by)4065 return page_actions.wait_for_element_absent(4066 self.driver, selector, by, timeout4067 )4068 def get_google_auth_password(self, totp_key=None):4069 """ Same as self.get_mfa_code() """4070 return self.get_mfa_code(totp_key=totp_key)4071 def get_google_auth_code(self, totp_key=None):4072 """ Same as self.get_mfa_code() """4073 return self.get_mfa_code(totp_key=totp_key)4074 def get_totp_code(self, totp_key=None):4075 """ Same as self.get_mfa_code() """4076 return self.get_mfa_code(totp_key=totp_key)4077 def enter_totp_code(4078 self, selector, totp_key=None, by=By.CSS_SELECTOR, timeout=None4079 ):4080 """ Same as self.enter_mfa_code() """4081 return self.enter_mfa_code(4082 selector=selector, totp_key=totp_key, by=by, timeout=timeout4083 )4084 def _print(self, msg):4085 """Same as Python's print(), but won't print during multithreaded runs4086 because overlapping print() commands may lead to unexpected output.4087 In most cases, the print() command won't print for multithreaded tests,4088 but there are some exceptions, and this will take care of those.4089 Here's an example of running tests multithreaded: "pytest -n=4".4090 To force a print during multithreaded tests, use: "sys.stderr.write()".4091 To print without the new-line character end, use: "sys.stdout.write()".4092 """4093 if not sb_config._multithreaded:4094 print(msg)4095 def start_tour(self, name=None, interval=0):4096 self.play_tour(name=name, interval=interval)4097 ############4098 def add_css_link(self, css_link):4099 self.__check_scope__()4100 self.__check_browser()4101 js_utils.add_css_link(self.driver, css_link)4102 def add_js_link(self, js_link):4103 self.__check_scope__()4104 self.__check_browser__()4105 js_utils.add_js_link(self.driver, js_link)4106 def add_css_style(self, css_style):4107 self.__check_scope__()4108 self.__check_browser__()4109 js_utils.add_css_style(self.driver, css_style)4110 def add_js_code_from_link(self, js_link):4111 self.__check_scope__()4112 self.__check_browser__()4113 js_utils.add_js_code_from_link(self.driver, js_link)4114 def add_js_code(self, js_code):4115 self.__check_scope__()4116 self.__check_browser__()4117 js_utils.add_js_code(self.driver, js_code)4118 def add_meta_tag(self, http_equiv=None, content=None):4119 self.__check_scope__()4120 self.__check_browser__()4121 js_utils.add_meta_tag(4122 self.driver, http_equiv=http_equiv, content=content4123 )4124 ############4125 def create_presentation(4126 self, name=None, theme="default", transition="default"4127 ):4128 """Creates a Reveal-JS presentation that you can add slides to.4129 @Params4130 name - If creating multiple presentations at the same time,4131 use this to specify the name of the current presentation.4132 theme - Set a theme with a unique style for the presentation.4133 Valid themes: "serif" (default), "sky", "white", "black",4134 "simple", "league", "moon", "night",4135 "beige", "blood", and "solarized".4136 transition - Set a transition between slides.4137 Valid transitions: "none" (default), "slide", "fade",4138 "zoom", "convex", and "concave".4139 """4140 if not name:4141 name = "default"4142 if not theme or theme == "default":4143 theme = "serif"4144 valid_themes = [4145 "serif",4146 "white",4147 "black",4148 "beige",4149 "simple",4150 "sky",4151 "league",4152 "moon",4153 "night",4154 "blood",4155 "solarized",4156 ]4157 theme = theme.lower()4158 if theme not in valid_themes:4159 raise Exception(4160 "Theme {%s} not found! Valid themes: %s"4161 % (theme, valid_themes)4162 )4163 if not transition or transition == "default":4164 transition = "none"4165 valid_transitions = [4166 "none",4167 "slide",4168 "fade",4169 "zoom",4170 "convex",4171 "concave",4172 ]4173 transition = transition.lower()4174 if transition not in valid_transitions:4175 raise Exception(4176 "Transition {%s} not found! Valid transitions: %s"4177 % (transition, valid_transitions)4178 )4179 reveal_theme_css = None4180 if theme == "serif":4181 reveal_theme_css = constants.Reveal.SERIF_MIN_CSS4182 elif theme == "sky":4183 reveal_theme_css = constants.Reveal.SKY_MIN_CSS4184 elif theme == "white":4185 reveal_theme_css = constants.Reveal.WHITE_MIN_CSS4186 elif theme == "black":4187 reveal_theme_css = constants.Reveal.BLACK_MIN_CSS4188 elif theme == "simple":4189 reveal_theme_css = constants.Reveal.SIMPLE_MIN_CSS4190 elif theme == "league":4191 reveal_theme_css = constants.Reveal.LEAGUE_MIN_CSS4192 elif theme == "moon":4193 reveal_theme_css = constants.Reveal.MOON_MIN_CSS4194 elif theme == "night":4195 reveal_theme_css = constants.Reveal.NIGHT_MIN_CSS4196 elif theme == "beige":4197 reveal_theme_css = constants.Reveal.BEIGE_MIN_CSS4198 elif theme == "blood":4199 reveal_theme_css = constants.Reveal.BLOOD_MIN_CSS4200 elif theme == "solarized":4201 reveal_theme_css = constants.Reveal.SOLARIZED_MIN_CSS4202 else:4203 # Use the default if unable to determine the theme4204 reveal_theme_css = constants.Reveal.SERIF_MIN_CSS4205 new_presentation = (4206 "<html>\n"4207 "<head>\n"4208 '<meta charset="utf-8">\n'4209 '<meta http-equiv="Content-Type" content="text/html">\n'4210 '<meta name="viewport" content="shrink-to-fit=no">\n'4211 '<link rel="stylesheet" href="%s">\n'4212 '<link rel="stylesheet" href="%s">\n'4213 "<style>\n"4214 "pre{background-color:#fbe8d4;border-radius:8px;}\n"4215 "div[flex_div]{height:68vh;margin:0;align-items:center;"4216 "justify-content:center;}\n"4217 "img[rounded]{border-radius:16px;max-width:64%%;}\n"4218 "</style>\n"4219 "</head>\n\n"4220 "<body>\n"4221 "<!-- Generated by SeleniumBase - https://seleniumbase.io -->\n"4222 '<div class="reveal">\n'4223 '<div class="slides">\n'4224 % (constants.Reveal.MIN_CSS, reveal_theme_css)4225 )4226 self._presentation_slides[name] = []4227 self._presentation_slides[name].append(new_presentation)4228 self._presentation_transition[name] = transition4229 def add_slide(4230 self,4231 content=None,4232 image=None,4233 code=None,4234 iframe=None,4235 content2=None,4236 notes=None,4237 transition=None,4238 name=None,4239 ):4240 """Allows the user to add slides to a presentation.4241 @Params4242 content - The HTML content to display on the presentation slide.4243 image - Attach an image (from a URL link) to the slide.4244 code - Attach code of any programming language to the slide.4245 Language-detection will be used to add syntax formatting.4246 iframe - Attach an iFrame (from a URL link) to the slide.4247 content2 - HTML content to display after adding an image or code.4248 notes - Additional notes to include with the slide.4249 ONLY SEEN if show_notes is set for the presentation.4250 transition - Set a transition between slides. (overrides previous)4251 Valid transitions: "none" (default), "slide", "fade",4252 "zoom", "convex", and "concave".4253 name - If creating multiple presentations at the same time,4254 use this to select the presentation to add slides to.4255 """4256 if not name:4257 name = "default"4258 if name not in self._presentation_slides:4259 # Create a presentation if it doesn't already exist4260 self.create_presentation(name=name)4261 if not content:4262 content = ""4263 if not content2:4264 content2 = ""4265 if not notes:4266 notes = ""4267 if not transition:4268 transition = self._presentation_transition[name]4269 elif transition == "default":4270 transition = "none"4271 valid_transitions = [4272 "none",4273 "slide",4274 "fade",4275 "zoom",4276 "convex",4277 "concave",4278 ]4279 transition = transition.lower()4280 if transition not in valid_transitions:4281 raise Exception(4282 "Transition {%s} not found! Valid transitions: %s"4283 "" % (transition, valid_transitions)4284 )4285 add_line = ""4286 if content.startswith("<"):4287 add_line = "\n"4288 html = '\n<section data-transition="%s">%s%s' % (4289 transition,4290 add_line,4291 content,4292 )4293 if image:4294 html += '\n<div flex_div><img rounded src="%s" /></div>' % image4295 if code:4296 html += "\n<div></div>"4297 html += '\n<pre class="prettyprint">\n%s</pre>' % code4298 if iframe:4299 html += (4300 "\n<div></div>"4301 '\n<iframe src="%s" style="width:92%%;height:550px;" '4302 'title="iframe content"></iframe>' % iframe4303 )4304 add_line = ""4305 if content2.startswith("<"):4306 add_line = "\n"4307 if content2:4308 html += "%s%s" % (add_line, content2)4309 html += '\n<aside class="notes">%s</aside>' % notes4310 html += "\n</section>\n"4311 self._presentation_slides[name].append(html)4312 def save_presentation(4313 self, name=None, filename=None, show_notes=False, interval=04314 ):4315 """Saves a Reveal-JS Presentation to a file for later use.4316 @Params4317 name - If creating multiple presentations at the same time,4318 use this to select the one you wish to use.4319 filename - The name of the HTML file that you wish to4320 save the presentation to. (filename must end in ".html")4321 show_notes - When set to True, the Notes feature becomes enabled,4322 which allows presenters to see notes next to slides.4323 interval - The delay time between autoplaying slides. (in seconds)4324 If set to 0 (default), autoplay is disabled.4325 """4326 if not name:4327 name = "default"4328 if not filename:4329 filename = "my_presentation.html"4330 if name not in self._presentation_slides:4331 raise Exception("Presentation {%s} does not exist!" % name)4332 if not filename.endswith(".html"):4333 raise Exception('Presentation file must end in ".html"!')4334 if not interval:4335 interval = 04336 if interval == 0 and self.interval:4337 interval = float(self.interval)4338 if not type(interval) is int and not type(interval) is float:4339 raise Exception('Expecting a numeric value for "interval"!')4340 if interval < 0:4341 raise Exception('The "interval" cannot be a negative number!')4342 interval_ms = float(interval) * 1000.04343 show_notes_str = "false"4344 if show_notes:4345 show_notes_str = "true"4346 the_html = ""4347 for slide in self._presentation_slides[name]:4348 the_html += slide4349 the_html += (4350 "\n</div>\n"4351 "</div>\n"4352 '<script src="%s"></script>\n'4353 '<script src="%s"></script>\n'4354 "<script>Reveal.initialize("4355 "{showNotes: %s, slideNumber: true, progress: true, hash: false, "4356 "autoSlide: %s,});"4357 "</script>\n"4358 "</body>\n"4359 "</html>\n"4360 % (4361 constants.Reveal.MIN_JS,4362 constants.PrettifyJS.RUN_PRETTIFY_JS,4363 show_notes_str,4364 interval_ms,4365 )4366 )4367 # Remove duplicate ChartMaker library declarations4368 chart_libs = """4369 <script src="%s"></script>4370 <script src="%s"></script>4371 <script src="%s"></script>4372 <script src="%s"></script>4373 """ % (4374 constants.HighCharts.HC_JS,4375 constants.HighCharts.EXPORTING_JS,4376 constants.HighCharts.EXPORT_DATA_JS,4377 constants.HighCharts.ACCESSIBILITY_JS,4378 )4379 if the_html.count(chart_libs) > 1:4380 chart_libs_comment = "<!-- HighCharts Libraries Imported -->"4381 the_html = the_html.replace(chart_libs, chart_libs_comment)4382 # Only need to import the HighCharts libraries once4383 the_html = the_html.replace(chart_libs_comment, chart_libs, 1)4384 saved_presentations_folder = constants.Presentations.SAVED_FOLDER4385 if saved_presentations_folder.endswith("/"):4386 saved_presentations_folder = saved_presentations_folder[:-1]4387 if not os.path.exists(saved_presentations_folder):4388 try:4389 os.makedirs(saved_presentations_folder)4390 except Exception:4391 pass4392 file_path = saved_presentations_folder + "/" + filename4393 out_file = codecs.open(file_path, "w+", encoding="utf-8")4394 out_file.writelines(the_html)4395 out_file.close()4396 print("\n>>> [%s] was saved!\n" % file_path)4397 return file_path4398 def begin_presentation(4399 self, name=None, filename=None, show_notes=False, interval=04400 ):4401 """Begin a Reveal-JS Presentation in the web browser.4402 @Params4403 name - If creating multiple presentations at the same time,4404 use this to select the one you wish to use.4405 filename - The name of the HTML file that you wish to4406 save the presentation to. (filename must end in ".html")4407 show_notes - When set to True, the Notes feature becomes enabled,4408 which allows presenters to see notes next to slides.4409 interval - The delay time between autoplaying slides. (in seconds)4410 If set to 0 (default), autoplay is disabled.4411 """4412 if self.headless or self.xvfb:4413 return # Presentations should not run in headless mode.4414 if not name:4415 name = "default"4416 if not filename:4417 filename = "my_presentation.html"4418 if name not in self._presentation_slides:4419 raise Exception("Presentation {%s} does not exist!" % name)4420 if not filename.endswith(".html"):4421 raise Exception('Presentation file must end in ".html"!')4422 if not interval:4423 interval = 04424 if interval == 0 and self.interval:4425 interval = float(self.interval)4426 if not type(interval) is int and not type(interval) is float:4427 raise Exception('Expecting a numeric value for "interval"!')4428 if interval < 0:4429 raise Exception('The "interval" cannot be a negative number!')4430 end_slide = (4431 '\n<section data-transition="none">\n'4432 '<p class="End_Presentation_Now"> </p>\n</section>\n'4433 )4434 self._presentation_slides[name].append(end_slide)4435 file_path = self.save_presentation(4436 name=name,4437 filename=filename,4438 show_notes=show_notes,4439 interval=interval,4440 )4441 self._presentation_slides[name].pop()4442 self.open_html_file(file_path)4443 presentation_folder = constants.Presentations.SAVED_FOLDER4444 try:4445 while (4446 len(self.driver.window_handles) > 04447 and presentation_folder in self.get_current_url()4448 ):4449 time.sleep(0.05)4450 if self.is_element_visible(4451 "section.present p.End_Presentation_Now"4452 ):4453 break4454 time.sleep(0.05)4455 except Exception:4456 pass4457 ############4458 def activate_jquery_confirm(self):4459 """ See https://craftpip.github.io/jquery-confirm/ for usage. """4460 self.__check_scope__()4461 self.__check_browser__()4462 js_utils.activate_jquery_confirm(self.driver)4463 self.wait_for_ready_state_complete()4464 # def set_jqc_theme(self, theme, color=None, width=None):4465 # """ Sets the default jquery-confirm theme and width (optional).4466 # Available themes: "bootstrap", "modern", "material", "supervan",4467 # "light", "dark", and "seamless".4468 # Available colors: (This sets the BORDER color, NOT the button color.)4469 # "blue", "default", "green", "red", "purple", "orange", "dark".4470 # Width can be set using percent or pixels. Eg: "36.0%", "450px".4471 # """4472 # if not self.__changed_jqc_theme:4473 # self.__jqc_default_theme = constants.JqueryConfirm.DEFAULT_THEME4474 # self.__jqc_default_color = constants.JqueryConfirm.DEFAULT_COLOR4475 # self.__jqc_default_width = constants.JqueryConfirm.DEFAULT_WIDTH4476 # valid_themes = [4477 # "bootstrap",4478 # "modern",4479 # "material",4480 # "supervan",4481 # "light",4482 # "dark",4483 # "seamless",4484 # ]4485 # if theme.lower() not in valid_themes:4486 # raise Exception(4487 # "%s is not a valid jquery-confirm theme! "4488 # "Select from %s" % (theme.lower(), valid_themes)4489 # )4490 # constants.JqueryConfirm.DEFAULT_THEME = theme.lower()4491 # if color:4492 # valid_colors = [4493 # "blue",4494 # "default",4495 # "green",4496 # "red",4497 # "purple",4498 # "orange",4499 # "dark",4500 # ]4501 # if color.lower() not in valid_colors:4502 # raise Exception(4503 # "%s is not a valid jquery-confirm border color! "4504 # "Select from %s" % (color.lower(), valid_colors)4505 # )4506 # constants.JqueryConfirm.DEFAULT_COLOR = color.lower()4507 # if width:4508 # if type(width) is int or type(width) is float:4509 # # Convert to a string if a number is given4510 # width = str(width)4511 # if width.isnumeric():4512 # if int(width) <= 0:4513 # raise Exception("Width must be set to a positive number!")4514 # elif int(width) <= 100:4515 # width = str(width) + "%"4516 # else:4517 # width = str(width) + "px" # Use pixels if width is > 1004518 # if not width.endswith("%") and not width.endswith("px"):4519 # raise Exception(4520 # "jqc width must end with %% for percent or px for pixels!"4521 # )4522 # value = None4523 # if width.endswith("%"):4524 # value = width[:-1]4525 # if width.endswith("px"):4526 # value = width[:-2]4527 # try:4528 # value = float(value)4529 # except Exception:4530 # raise Exception("%s is not a numeric value!" % value)4531 # if value <= 0:4532 # raise Exception("%s is not a positive number!" % value)4533 # constants.JqueryConfirm.DEFAULT_WIDTH = width4534 #4535 # def reset_jqc_theme(self):4536 # """ Resets the jqc theme settings to factory defaults. """4537 # if self.__changed_jqc_theme:4538 # constants.JqueryConfirm.DEFAULT_THEME = self.__jqc_default_theme4539 # constants.JqueryConfirm.DEFAULT_COLOR = self.__jqc_default_color4540 # constants.JqueryConfirm.DEFAULT_WIDTH = self.__jqc_default_width4541 # self.__changed_jqc_theme = False4542 #4543 # def get_jqc_button_input(self, message, buttons, options=None):4544 # """4545 # Pop up a jquery-confirm box and return the text of the button clicked.4546 # If running in headless mode, the last button text is returned.4547 # @Params4548 # message: The message to display in the jquery-confirm dialog.4549 # buttons: A list of tuples for text and color.4550 # Example: [("Yes!", "green"), ("No!", "red")]4551 # Available colors: blue, green, red, orange, purple, default, dark.4552 # A simple text string also works: "My Button". (Uses default color.)4553 # options: A list of tuples for options to set.4554 # Example: [("theme", "bootstrap"), ("width", "450px")]4555 # Available theme options: bootstrap, modern, material, supervan,4556 # light, dark, and seamless.4557 # Available colors: (For the BORDER color, NOT the button color.)4558 # "blue", "default", "green", "red", "purple", "orange", "dark".4559 # Example option for changing the border color: ("color", "default")4560 # Width can be set using percent or pixels. Eg: "36.0%", "450px".4561 # """4562 # from seleniumbase.core import jqc_helper4563 #4564 # if message and type(message) is not str:4565 # raise Exception('Expecting a string for arg: "message"!')4566 # if not type(buttons) is list and not type(buttons) is tuple:4567 # raise Exception('Expecting a list or tuple for arg: "button"!')4568 # if len(buttons) < 1:4569 # raise Exception('List "buttons" requires at least one button!')4570 # new_buttons = []4571 # for button in buttons:4572 # if (4573 # (type(button) is list or type(button) is tuple)4574 # and (len(button) == 1)4575 # ):4576 # new_buttons.append(button[0])4577 # elif (4578 # (type(button) is list or type(button) is tuple)4579 # and (len(button) > 1)4580 # ):4581 # new_buttons.append((button[0], str(button[1]).lower()))4582 # else:4583 # new_buttons.append((str(button), ""))4584 # buttons = new_buttons4585 # if options:4586 # for option in options:4587 # if not type(option) is list and not type(option) is tuple:4588 # raise Exception('"options" should be a list of tuples!')4589 # if self.headless or self.xvfb:4590 # return buttons[-1][0]4591 # jqc_helper.jquery_confirm_button_dialog(4592 # self.driver, message, buttons, options4593 # )4594 # self.sleep(0.02)4595 # jf = "document.querySelector('.jconfirm-box').focus();"4596 # try:4597 # self.execute_script(jf)4598 # except Exception:4599 # pass4600 # waiting_for_response = True4601 # while waiting_for_response:4602 # self.sleep(0.05)4603 # jqc_open = self.execute_script(4604 # "return jconfirm.instances.length"4605 # )4606 # if str(jqc_open) == "0":4607 # break4608 # self.sleep(0.1)4609 # status = None4610 # try:4611 # status = self.execute_script("return $jqc_status")4612 # except Exception:4613 # status = self.execute_script(4614 # "return jconfirm.lastButtonText"4615 # )4616 # return status4617 #4618 # def get_jqc_text_input(self, message, button=None, options=None):4619 # """4620 # Pop up a jquery-confirm box and return the text submitted by the input.4621 # If running in headless mode, the text returned is "" by default.4622 # @Params4623 # message: The message to display in the jquery-confirm dialog.4624 # button: A 2-item list or tuple for text and color. Or just the text.4625 # Example: ["Submit", "blue"] -> (default button if not specified)4626 # Available colors: blue, green, red, orange, purple, default, dark.4627 # A simple text string also works: "My Button". (Uses default color.)4628 # options: A list of tuples for options to set.4629 # Example: [("theme", "bootstrap"), ("width", "450px")]4630 # Available theme options: bootstrap, modern, material, supervan,4631 # light, dark, and seamless.4632 # Available colors: (For the BORDER color, NOT the button color.)4633 # "blue", "default", "green", "red", "purple", "orange", "dark".4634 # Example option for changing the border color: ("color", "default")4635 # Width can be set using percent or pixels. Eg: "36.0%", "450px".4636 # """4637 # from seleniumbase.core import jqc_helper4638 #4639 # if message and type(message) is not str:4640 # raise Exception('Expecting a string for arg: "message"!')4641 # if button:4642 # if (4643 # (type(button) is list or type(button) is tuple)4644 # and (len(button) == 1)4645 # ):4646 # button = (str(button[0]), "")4647 # elif (4648 # (type(button) is list or type(button) is tuple)4649 # and (len(button) > 1)4650 # ):4651 # valid_colors = [4652 # "blue",4653 # "default",4654 # "green",4655 # "red",4656 # "purple",4657 # "orange",4658 # "dark",4659 # ]4660 # detected_color = str(button[1]).lower()4661 # if str(button[1]).lower() not in valid_colors:4662 # raise Exception(4663 # "%s is an invalid jquery-confirm button color!\n"4664 # "Select from %s" % (detected_color, valid_colors)4665 # )4666 # button = (str(button[0]), str(button[1]).lower())4667 # else:4668 # button = (str(button), "")4669 # else:4670 # button = ("Submit", "blue")4671 #4672 # if options:4673 # for option in options:4674 # if not type(option) is list and not type(option) is tuple:4675 # raise Exception('"options" should be a list of tuples!')4676 # if self.headless or self.xvfb:4677 # return ""4678 # jqc_helper.jquery_confirm_text_dialog(4679 # self.driver, message, button, options4680 # )4681 # self.sleep(0.02)4682 # jf = "document.querySelector('.jconfirm-box input.jqc_input').focus();"4683 # try:4684 # self.execute_script(jf)4685 # except Exception:4686 # pass4687 # waiting_for_response = True4688 # while waiting_for_response:4689 # self.sleep(0.05)4690 # jqc_open = self.execute_script(4691 # "return jconfirm.instances.length"4692 # )4693 # if str(jqc_open) == "0":4694 # break4695 # self.sleep(0.1)4696 # status = None4697 # try:4698 # status = self.execute_script("return $jqc_input")4699 # except Exception:4700 # status = self.execute_script(4701 # "return jconfirm.lastInputText"4702 # )4703 # return status4704 #4705 # def get_jqc_form_inputs(self, message, buttons, options=None):4706 # """4707 # Pop up a jquery-confirm box and return the input/button texts as tuple.4708 # If running in headless mode, returns the ("", buttons[-1][0]) tuple.4709 # @Params4710 # message: The message to display in the jquery-confirm dialog.4711 # buttons: A list of tuples for text and color.4712 # Example: [("Yes!", "green"), ("No!", "red")]4713 # Available colors: blue, green, red, orange, purple, default, dark.4714 # A simple text string also works: "My Button". (Uses default color.)4715 # options: A list of tuples for options to set.4716 # Example: [("theme", "bootstrap"), ("width", "450px")]4717 # Available theme options: bootstrap, modern, material, supervan,4718 # light, dark, and seamless.4719 # Available colors: (For the BORDER color, NOT the button color.)4720 # "blue", "default", "green", "red", "purple", "orange", "dark".4721 # Example option for changing the border color: ("color", "default")4722 # Width can be set using percent or pixels. Eg: "36.0%", "450px".4723 # """4724 # from seleniumbase.core import jqc_helper4725 #4726 # if message and type(message) is not str:4727 # raise Exception('Expecting a string for arg: "message"!')4728 # if not type(buttons) is list and not type(buttons) is tuple:4729 # raise Exception('Expecting a list or tuple for arg: "button"!')4730 # if len(buttons) < 1:4731 # raise Exception('List "buttons" requires at least one button!')4732 # new_buttons = []4733 # for button in buttons:4734 # if (4735 # (type(button) is list or type(button) is tuple)4736 # and (len(button) == 1)4737 # ):4738 # new_buttons.append(button[0])4739 # elif (4740 # (type(button) is list or type(button) is tuple)4741 # and (len(button) > 1)4742 # ):4743 # new_buttons.append((button[0], str(button[1]).lower()))4744 # else:4745 # new_buttons.append((str(button), ""))4746 # buttons = new_buttons4747 # if options:4748 # for option in options:4749 # if not type(option) is list and not type(option) is tuple:4750 # raise Exception('"options" should be a list of tuples!')4751 # if self.headless or self.xvfb:4752 # return ("", buttons[-1][0])4753 # jqc_helper.jquery_confirm_full_dialog(4754 # self.driver, message, buttons, options4755 # )4756 # self.sleep(0.02)4757 # jf = "document.querySelector('.jconfirm-box input.jqc_input').focus();"4758 # try:4759 # self.execute_script(jf)4760 # except Exception:4761 # pass4762 # waiting_for_response = True4763 # while waiting_for_response:4764 # self.sleep(0.05)4765 # jqc_open = self.execute_script(4766 # "return jconfirm.instances.length"4767 # )4768 # if str(jqc_open) == "0":4769 # break4770 # self.sleep(0.1)4771 # text_status = None4772 # button_status = None4773 # try:4774 # text_status = self.execute_script("return $jqc_input")4775 # button_status = self.execute_script("return $jqc_status")4776 # except Exception:4777 # text_status = self.execute_script(4778 # "return jconfirm.lastInputText"4779 # )4780 # button_status = self.execute_script(4781 # "return jconfirm.lastButtonText"4782 # )4783 # return (text_status, button_status)4784 ############4785 ############4786 def generate_referral(self, start_page, destination_page, selector=None):4787 """This method opens the start_page, creates a referral link there,4788 and clicks on that link, which goes to the destination_page.4789 If a selector is given, clicks that on the destination_page,4790 which can prevent an artificial rise in website bounce-rate.4791 (This generates real traffic for testing analytics software.)"""4792 self.__check_scope__()4793 if not page_utils.is_valid_url(destination_page):4794 raise Exception(4795 "Exception: destination_page {%s} is not a valid URL!"4796 % destination_page4797 )4798 if start_page:4799 if not page_utils.is_valid_url(start_page):4800 raise Exception(4801 "Exception: start_page {%s} is not a valid URL! "4802 "(Use an empty string or None to start from current page.)"4803 % start_page4804 )4805 self.open(start_page)4806 time.sleep(0.08)4807 self.wait_for_ready_state_complete()4808 referral_link = (4809 """<body>"""4810 """<a class='analytics referral test' href='%s' """4811 """style='font-family: Arial,sans-serif; """4812 """font-size: 30px; color: #18a2cd'>"""4813 """Magic Link Button</a></body>""" % destination_page4814 )4815 self.execute_script(4816 '''document.body.outerHTML = \"%s\"''' % referral_link4817 )4818 # Now click the generated button4819 self.click("a.analytics.referral.test", timeout=2)4820 time.sleep(0.15)4821 if selector:4822 self.click(selector)4823 time.sleep(0.15)4824 def generate_traffic(4825 self, start_page, destination_page, loops=1, selector=None4826 ):4827 """Similar to generate_referral(), but can do multiple loops.4828 If a selector is given, clicks that on the destination_page,4829 which can prevent an artificial rise in website bounce-rate."""4830 self.__check_scope__()4831 for loop in range(loops):4832 self.generate_referral(4833 start_page, destination_page, selector=selector4834 )4835 time.sleep(0.05)4836 def generate_referral_chain(self, pages):4837 """Use this method to chain the action of creating button links on4838 one website page that will take you to the next page.4839 (When you want to create a referral to a website for traffic4840 generation without increasing the bounce rate, you'll want to visit4841 at least one additional page on that site with a button click.)"""4842 self.__check_scope__()4843 if not type(pages) is tuple and not type(pages) is list:4844 raise Exception(4845 "Exception: Expecting a list of website pages for chaining!"4846 )4847 if len(pages) < 2:4848 raise Exception(4849 "Exception: At least two website pages required for chaining!"4850 )4851 for page in pages:4852 # Find out if any of the web pages are invalid before continuing4853 if not page_utils.is_valid_url(page):4854 raise Exception(4855 "Exception: Website page {%s} is not a valid URL!" % page4856 )4857 for page in pages:4858 self.generate_referral(None, page)4859 def generate_traffic_chain(self, pages, loops=1):4860 """ Similar to generate_referral_chain(), but for multiple loops. """4861 self.__check_scope__()4862 for loop in range(loops):4863 self.generate_referral_chain(pages)4864 time.sleep(0.05)4865 ############4866 def wait_for_element_present(4867 self, selector, by=By.CSS_SELECTOR, timeout=None4868 ):4869 """Waits for an element to appear in the HTML of a page.4870 The element does not need be visible (it may be hidden)."""4871 self.__check_scope__()4872 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)4873 selector, by = self.__recalculate_selector(selector, by)4874 if self.__is_shadow_selector(selector):4875 return self.__wait_for_shadow_element_present(4876 selector, timeout4877 )4878 return page_actions.wait_for_element_present(4879 self.driver, selector, by, timeout4880 )4881 def wait_for_element(self, selector, by=By.CSS_SELECTOR, timeout=None):4882 """Waits for an element to appear in the HTML of a page.4883 The element must be visible (it cannot be hidden)."""4884 self.__check_scope__()4885 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)4886 selector, by = self.__recalculate_selector(selector, by)4887 if self.__is_shadow_selector(selector):4888 return self.__wait_for_shadow_element_visible(4889 selector, timeout4890 )4891 return page_actions.wait_for_element_visible(4892 self.driver, selector, by, timeout4893 )4894 def get_element(4895 self,4896 how: SeleniumBy,4897 selector: str = Field(default="", strict=True, min_length=1),4898 timeout: OptionalInt = None,4899 ):4900 """Same as wait_for_element_present() - returns the element.4901 The element does not need be visible (it may be hidden)."""4902 self.__check_scope__()4903 timeout = self.get_timeout(timeout, constants.SMALL_TIMEOUT)4904 return self.wait_for_element_present(how, selector, timeout=timeout)4905 def find_element(self, selector, by=By.CSS_SELECTOR, timeout=None):4906 """ Same as wait_for_element_visible() - returns the element """4907 self.__check_scope__()4908 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)4909 return self.wait_for_element_visible(selector, by=by, timeout=timeout)4910 ############4911 def wait_for_text_visible(4912 self, text, selector="html", by=By.CSS_SELECTOR, timeout=None4913 ):4914 self.__check_scope__()4915 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)4916 selector, by = self.__recalculate_selector(selector, by)4917 if self.__is_shadow_selector(selector):4918 return self.__wait_for_shadow_text_visible(4919 text, selector, timeout4920 )4921 return page_actions.wait_for_text_visible(4922 self.driver, text, selector, by, timeout, self.browser4923 )4924 def wait_for_exact_text_visible(4925 self, text, selector="html", by=By.CSS_SELECTOR, timeout=None4926 ):4927 self.__check_scope__()4928 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)4929 selector, by = self.__recalculate_selector(selector, by)4930 if self.__is_shadow_selector(selector):4931 return self.__wait_for_exact_shadow_text_visible(4932 text, selector, timeout4933 )4934 return page_actions.wait_for_exact_text_visible(4935 self.driver, text, selector, by, timeout, self.browser4936 )4937 def wait_for_text(4938 self, text, selector="html", by=By.CSS_SELECTOR, timeout=None4939 ):4940 """ The shorter version of wait_for_text_visible() """4941 self.__check_scope__()4942 timeout = self.get_timeout(timeout, constants.LARGE_TIMEOUT)4943 return self.wait_for_text_visible(4944 text, selector, by=by, timeout=timeout...

Full Screen

Full Screen

base_case.py

Source:base_case.py Github

copy

Full Screen

...29 original_by = by30 selector, by = self.__recalculate_selector(selector, by)31 if delay and (type(delay) in [int, float]) and delay > 0:32 time.sleep(delay)33 if self.__is_shadow_selector(selector):34 self.__shadow_click(selector)35 return36 element = page_actions.wait_for_element_visible(self.driver, selector, by, timeout=timeout)37 if scroll:38 self.__scroll_to_element(element, selector, by)39 element.click()40 def tap(self, selector, by=MobileBy.ACCESSIBILITY_ID, timeout=None, delay=0):41 self.__check_scope()42 if not timeout:43 timeout = settings.SMALL_TIMEOUT44 selector, by = self.__recalculate_selector(selector, by)45 if delay and (type(delay) in [int, float]) and delay > 0:46 time.sleep(delay)47 element = page_actions.wait_for_element_visible(self.driver, selector, by, timeout=timeout)48 actions = TouchAction(self.driver)49 actions.tap(element).perform()50 def back(self):51 self.driver.back()52 def close(self):53 self.driver.close_app()54 def launch(self):55 self.driver.launch_app()56 def swipe_between_element(self, start_selector, dest_selector, by=MobileBy.ACCESSIBILITY_ID, timeout=None):57 self.__check_scope()58 if not timeout:59 timeout = settings.SMALL_TIMEOUT60 start_selector, by = self.__recalculate_selector(start_selector, by)61 dest_selector, by = self.__recalculate_selector(dest_selector, by)62 start_element = page_actions.wait_for_element_visible(self.driver, start_selector, by, timeout=timeout)63 dest_element = page_actions.wait_for_element_visible(self.driver, dest_selector, by, timeout=timeout)64 self.driver.scroll(start_element,dest_element)65 def swipe_to_element(self, selector, by=MobileBy.ACCESSIBILITY_ID, start_x=100, start_y=100, end_x=0, end_y=0, duration=0, count=10, timeout=None):66 self.__check_scope()67 if not timeout:68 timeout = settings.SMALL_TIMEOUT69 selector, by = self.__recalculate_selector(selector, by)70 for i in range(count):71 try:72 self.is_element_visible(selector,by)73 break74 except Exception as e:75 self.driver.swipe(start_x, start_y, end_x, end_y, duration)76 def tap_by_coordinates(self, x, y):77 self.__check_scope()78 time.sleep(2)79 actions = TouchAction(self.driver)80 actions.tap(x=x, y=y).perform()81 def double_tap(self, selector, by=MobileBy.ACCESSIBILITY_ID, timeout=None, delay=0):82 self.__check_scope()83 if not timeout:84 timeout = settings.SMALL_TIMEOUT85 selector, by = self.__recalculate_selector(selector, by)86 if delay and (type(delay) in [int, float]) and delay > 0:87 time.sleep(delay)88 element = page_actions.wait_for_element_visible(self.driver, selector, by, timeout=timeout)89 actions = TouchAction(self.driver)90 actions.tap(element, count=2).perform()91 def scroll_to_element(self, selector, by=MobileBy.ACCESSIBILITY_ID, timeout=None):92 self.scroll_to(selector, by=by, timeout=timeout)93 def scroll_to(self, selector, by=MobileBy.ACCESSIBILITY_ID, timeout=None):94 """ Fast scroll to destination """95 self.__check_scope()96 if not timeout:97 timeout = settings.SMALL_TIMEOUT98 element = self.wait_for_element_visible(99 selector, by=by, timeout=timeout100 )101 try:102 self.__scroll_to_element(element, selector, by)103 except (StaleElementReferenceException, ENI_Exception):104 time.sleep(0.12)105 element = self.wait_for_element_visible(106 selector, by=by, timeout=timeout107 )108 self.__scroll_to_element(element, selector, by)109 def __recalculate_selector(self, selector, by, xp_ok=True):110 """Use autodetection to return the correct selector with "by" updated.111 If "xp_ok" is False, don't call convert_css_to_xpath(), which is112 used to make the ":contains()" selector valid outside JS calls."""113 _type = type(selector) # First make sure the selector is a string114 not_string = False115 if sys.version_info[0] < 3:116 if _type is not str and _type is not unicode: # noqa: F821117 not_string = True118 else:119 if _type is not str:120 not_string = True121 if not_string:122 msg = "Expecting a selector of type: \"<class 'str'>\" (string)!"123 raise Exception('Invalid selector type: "%s"\n%s' % (_type, msg))124 if page_utils.is_xpath_selector(selector):125 by = MobileBy.XPATH126 if page_utils.is_link_text_selector(selector):127 selector = page_utils.get_link_text_from_selector(selector)128 by = MobileBy.LINK_TEXT129 if page_utils.is_partial_link_text_selector(selector):130 selector = page_utils.get_partial_link_text_from_selector(selector)131 by = MobileBy.PARTIAL_LINK_TEXT132 if page_utils.is_name_selector(selector):133 name = page_utils.get_name_from_selector(selector)134 selector = '[name="%s"]' % name135 by = MobileBy.CSS_SELECTOR136 if page_utils.is_id_selector(selector):137 by = MobileBy.ID138 return (selector, by)139 def __is_shadow_selector(self, selector):140 self.__fail_if_invalid_shadow_selector_usage(selector)141 if "::shadow " in selector:142 return True143 return False144 def __fail_if_invalid_shadow_selector_usage(self, selector):145 if selector.strip().endswith("::shadow"):146 msg = (147 "A Shadow DOM selector cannot end on a shadow root element!"148 " End the selector with an element inside the shadow root!"149 )150 raise Exception(msg)151 def double_click(self, selector, by=MobileBy.ACCESSIBILITY_ID, timeout=None):152 from selenium.webdriver.common.action_chains import ActionChains153 self.__check_scope()154 if not timeout:155 timeout = settings.SMALL_TIMEOUT156 original_selector = selector157 original_by = by158 selector, by = self.__recalculate_selector(selector, by)159 element = page_actions.wait_for_element_visible(160 self.driver, selector, by, timeout=timeout161 )162 # Find the element one more time in case scrolling hid it163 element = page_actions.wait_for_element_visible(164 self.driver, selector, by, timeout=timeout165 )166 actions = ActionChains(self.driver)167 actions.double_click(element).perform()168 def go_back(self):169 self.__check_scope()170 self.__last_page_load_url = None171 self.driver.back()172 def scroll_screen(self, start_x=100, start_y=100, end_x=0, end_y=0, duration=0):173 """Swipe from one point to another point, for an optional duration.174 Args:175 start_x: x-coordinate at which to start176 start_y: y-coordinate at which to start177 end_x: x-coordinate at which to stop178 end_y: y-coordinate at which to stop179 duration: time to take the swipe, in ms.180 """181 self.driver.swipe(start_x, start_y, end_x, end_y, duration)182 def is_checked(self, selector, by=MobileBy.ACCESSIBILITY_ID, timeout=None):183 """Determines if a checkbox or a radio button element is checked.184 Returns True if the element is checked.185 Returns False if the element is not checked.186 If the element is not present on the page, raises an exception.187 If the element is not a checkbox or radio, raises an exception."""188 self.__check_scope()189 if not timeout:190 timeout = settings.SMALL_TIMEOUT191 selector, by = self.__recalculate_selector(selector, by)192 kind = self.get_attribute(selector, "type", by=by, timeout=timeout)193 if kind != "checkbox" and kind != "radio":194 raise Exception("Expecting a checkbox or a radio button element!")195 is_checked = self.get_attribute(196 selector, "checked", by=by, timeout=timeout, hard_fail=False197 )198 if is_checked:199 return True200 else: # (NoneType)201 return False202 def __select_option(203 self,204 dropdown_selector,205 option,206 dropdown_by=MobileBy.ACCESSIBILITY_ID,207 option_by="text",208 timeout=None,209 ):210 """Selects an HTML <select> option by specification.211 Option specifications are by "text", "index", or "value".212 Defaults to "text" if option_by is unspecified or unknown."""213 from selenium.webdriver.support.ui import Select214 self.__check_scope()215 if not timeout:216 timeout = settings.SMALL_TIMEOUT217 dropdown_selector, dropdown_by = self.__recalculate_selector(218 dropdown_selector, dropdown_by219 )220 element = self.wait_for_element_present(221 dropdown_selector, by=dropdown_by, timeout=timeout222 )223 try:224 if option_by == "index":225 Select(element).select_by_index(option)226 elif option_by == "value":227 Select(element).select_by_value(option)228 else:229 Select(element).select_by_visible_text(option)230 except (StaleElementReferenceException, ENI_Exception):231 time.sleep(0.14)232 element = self.wait_for_element_present(233 dropdown_selector, by=dropdown_by, timeout=timeout234 )235 if option_by == "index":236 Select(element).select_by_index(option)237 elif option_by == "value":238 Select(element).select_by_value(option)239 else:240 Select(element).select_by_visible_text(option)241 def select_option_by_text(242 self,243 dropdown_selector,244 option,245 dropdown_by=MobileBy.ACCESSIBILITY_ID,246 timeout=None,247 ):248 """Selects an HTML <select> option by option text.249 @Params250 dropdown_selector - the <select> selector.251 option - the text of the option.252 """253 self.__check_scope()254 if not timeout:255 timeout = settings.SMALL_TIMEOUT256 self.__select_option(257 dropdown_selector,258 option,259 dropdown_by=dropdown_by,260 option_by="text",261 timeout=timeout,262 )263 def select_option_by_index(264 self,265 dropdown_selector,266 option,267 dropdown_by=MobileBy.ACCESSIBILITY_ID,268 timeout=None,269 ):270 """Selects an HTML <select> option by option index.271 @Params272 dropdown_selector - the <select> selector.273 option - the index number of the option.274 """275 self.__check_scope()276 if not timeout:277 timeout = settings.SMALL_TIMEOUT278 self.__select_option(279 dropdown_selector,280 option,281 dropdown_by=dropdown_by,282 option_by="index",283 timeout=timeout,284 )285 def select_option_by_value(286 self,287 dropdown_selector,288 option,289 dropdown_by=MobileBy.ACCESSIBILITY_ID,290 timeout=None,291 ):292 """Selects an HTML <select> option by option value.293 @Params294 dropdown_selector - the <select> selector.295 option - the value property of the option.296 """297 self.__check_scope()298 if not timeout:299 timeout = settings.SMALL_TIMEOUT300 self.__select_option(301 dropdown_selector,302 option,303 dropdown_by=dropdown_by,304 option_by="value",305 timeout=timeout,306 )307 def save_screenshot(self, name, folder=None):308 """Saves a screenshot of the current page.309 If no folder is specified, uses the folder where pytest was called.310 The screenshot will be in PNG format."""311 return page_actions.save_screenshot(self.driver, name, folder)312 def sleep(self, seconds):313 self.__check_scope()314 time.sleep(seconds)315 if seconds <= 0.3:316 time.sleep(seconds)317 else:318 start_ms = time.time() * 1000.0319 stop_ms = start_ms + (seconds * 1000.0)320 for x in range(int(seconds * 5)):321 now_ms = time.time() * 1000.0322 if now_ms >= stop_ms:323 break324 time.sleep(0.2)325 def is_selected(self, selector, by=MobileBy.ACCESSIBILITY_ID, timeout=None):326 """ Same as is_checked() """327 return self.is_checked(selector, by=by, timeout=timeout)328 def check_if_unchecked(self, selector, by=MobileBy.ACCESSIBILITY_ID):329 """ If a checkbox or radio button is not checked, will check it. """330 self.__check_scope()331 selector, by = self.__recalculate_selector(selector, by)332 if not self.is_checked(selector, by=by):333 if self.is_element_visible(selector, by=by):334 self.click(selector, by=by)335 def select_if_unselected(self, selector, by=MobileBy.ACCESSIBILITY_ID):336 """ Same as check_if_unchecked() """337 self.check_if_unchecked(selector, by=by)338 def uncheck_if_checked(self, selector, by=MobileBy.ACCESSIBILITY_ID):339 """ If a checkbox is checked, will uncheck it. """340 self.__check_scope()341 selector, by = self.__recalculate_selector(selector, by)342 if self.is_checked(selector, by=by):343 if self.is_element_visible(selector, by=by):344 self.click(selector, by=by)345 def unselect_if_selected(self, selector, by=MobileBy.ACCESSIBILITY_ID):346 """ Same as uncheck_if_checked() """347 self.uncheck_if_checked(selector, by=by)348 def is_element_visible(self, selector, by=MobileBy.ACCESSIBILITY_ID):349 selector, by = self.__recalculate_selector(selector, by)350 return page_actions.is_element_visible(self.driver, selector, by)351 def get_attribute(352 self,353 selector,354 attribute,355 by=MobileBy.ACCESSIBILITY_ID,356 timeout=None,357 hard_fail=True,358 ):359 """ This method uses JavaScript to get the value of an attribute. """360 self.__check_scope()361 if not timeout:362 timeout = settings.SMALL_TIMEOUT363 selector, by = self.__recalculate_selector(selector, by)364 time.sleep(0.01)365 element = page_actions.wait_for_element_present(366 self.driver, selector, by, timeout367 )368 try:369 attribute_value = element.get_attribute(attribute)370 except (StaleElementReferenceException, ENI_Exception):371 time.sleep(0.14)372 element = page_actions.wait_for_element_present(373 self.driver, selector, by, timeout374 )375 attribute_value = element.get_attribute(attribute)376 if attribute_value is not None:377 return attribute_value378 else:379 if hard_fail:380 raise Exception(381 "Element {%s} has no attribute {%s}!"382 % (selector, attribute)383 )384 else:385 return None386 def __shadow_click(self, selector):387 element = self.__get_shadow_element(selector)388 element.click()389 def __get_shadow_element(self, selector, timeout=None):390 if timeout is None:391 timeout = settings.SMALL_TIMEOUT392 elif timeout == 0:393 timeout = 0.1 # Use for: is_shadow_element_* (* = present/visible)394 self.__fail_if_invalid_shadow_selector_usage(selector)395 if "::shadow " not in selector:396 raise Exception(397 'A Shadow DOM selector must contain at least one "::shadow "!'398 )399 selectors = selector.split("::shadow ")400 element = self.get_element(selectors[0])401 selector_chain = selectors[0]402 for selector_part in selectors[1:]:403 shadow_root = self.execute_script(404 "return arguments[0].shadowRoot", element405 )406 if timeout == 0.1 and not shadow_root:407 raise Exception(408 "Element {%s} has no shadow root!" % selector_chain409 )410 elif not shadow_root:411 time.sleep(2) # Wait two seconds for the shadow root to appear412 shadow_root = self.execute_script(413 "return arguments[0].shadowRoot", element414 )415 if not shadow_root:416 raise Exception(417 "Element {%s} has no shadow root!" % selector_chain418 )419 selector_chain += "::shadow "420 selector_chain += selector_part421 try:422 element = page_actions.wait_for_element_present(423 shadow_root,424 selector_part,425 by=MobileBy.CSS_SELECTOR,426 timeout=timeout,427 )428 except Exception:429 msg = (430 "Shadow DOM Element {%s} was not present after %s seconds!"431 % (selector_chain, timeout)432 )433 page_actions.timeout_exception("NoSuchElementException", msg)434 return element435 def execute_script(self, script, *args, **kwargs):436 self.__check_scope()437 return self.driver.execute_script(script, *args, **kwargs)438 def get_element(self, selector, by=MobileBy.CSS_SELECTOR, timeout=None):439 """Same as wait_for_element_present() - returns the element.440 The element does not need be visible (it may be hidden)."""441 self.__check_scope()442 if not timeout:443 timeout = settings.SMALL_TIMEOUT444 selector, by = self.__recalculate_selector(selector, by)445 return self.wait_for_element_present(selector, by=by, timeout=timeout)446 def wait_for_element_visible(447 self, selector, by=MobileBy.ACCESSIBILITY_ID, timeout=None448 ):449 """ Same as self.wait_for_element() """450 self.__check_scope()451 if not timeout:452 timeout = settings.LARGE_TIMEOUT453 selector, by = self.__recalculate_selector(selector, by)454 if self.__is_shadow_selector(selector):455 return self.__wait_for_shadow_element_visible(selector)456 return page_actions.wait_for_element_visible(457 self.driver, selector, by, timeout458 )459 def wait_for_element_present(460 self, selector, by=MobileBy.ACCESSIBILITY_ID, timeout=None461 ):462 """Waits for an element to appear in the HTML of a page.463 The element does not need be visible (it may be hidden)."""464 self.__check_scope()465 if not timeout:466 timeout = settings.LARGE_TIMEOUT467 selector, by = self.__recalculate_selector(selector, by)468 if self.__is_shadow_selector(selector):469 return self.__wait_for_shadow_element_present(selector)470 return page_actions.wait_for_element_present(471 self.driver, selector, by, timeout472 )473 def wait_for_element(self, selector, by=MobileBy.ACCESSIBILITY_ID, timeout=None):474 """Waits for an element to appear in the HTML of a page.475 The element must be visible (it cannot be hidden)."""476 self.__check_scope()477 if not timeout:478 timeout = settings.LARGE_TIMEOUT479 selector, by = self.__recalculate_selector(selector, by)480 if self.__is_shadow_selector(selector):481 return self.__wait_for_shadow_element_visible(selector)482 return page_actions.wait_for_element_visible(483 self.driver, selector, by, timeout484 )485 def __wait_for_shadow_element_present(self, selector):486 element = self.__get_shadow_element(selector)487 return element488 def __wait_for_shadow_element_visible(self, selector):489 element = self.__get_shadow_element(selector)490 if not element.is_displayed():491 msg = "Shadow DOM Element {%s} was not visible!" % selector492 page_actions.timeout_exception("NoSuchElementException", msg)493 return element494 def __get_shadow_text(self, selector):495 element = self.__get_shadow_element(selector)496 return element.text497 def __wait_for_shadow_text_visible(self, text, selector):498 start_ms = time.time() * 1000.0499 stop_ms = start_ms + (settings.SMALL_TIMEOUT * 1000.0)500 for x in range(int(settings.SMALL_TIMEOUT * 10)):501 try:502 actual_text = self.__get_shadow_text(selector).strip()503 text = text.strip()504 if text not in actual_text:505 msg = (506 "Expected text {%s} in element {%s} was not visible!"507 % (text, selector)508 )509 page_actions.timeout_exception(510 "ElementNotVisibleException", msg511 )512 return True513 except Exception:514 now_ms = time.time() * 1000.0515 if now_ms >= stop_ms:516 break517 time.sleep(0.1)518 actual_text = self.__get_shadow_text(selector).strip()519 text = text.strip()520 if text not in actual_text:521 msg = "Expected text {%s} in element {%s} was not visible!" % (522 text,523 selector,524 )525 page_actions.timeout_exception("ElementNotVisibleException", msg)526 return True527 def find_elements(self, selector, by=MobileBy.ACCESSIBILITY_ID, limit=0):528 """Returns a list of matching WebElements.529 Elements could be either hidden or visible on the page.530 If "limit" is set and > 0, will only return that many elements."""531 selector, by = self.__recalculate_selector(selector, by)532 time.sleep(0.05)533 elements = self.driver.find_elements(by=by, value=selector)534 if limit and limit > 0 and len(elements) > limit:535 elements = elements[:limit]536 return elements537 def wait_for_element_not_present(538 self, selector, by=MobileBy.ACCESSIBILITY_ID, timeout=None539 ):540 """Same as self.wait_for_element_absent()541 Waits for an element to no longer appear in the HTML of a page.542 A hidden element still counts as appearing in the page HTML.543 If waiting for elements to be hidden instead of nonexistent,544 use wait_for_element_not_visible() instead.545 """546 self.__check_scope()547 if not timeout:548 timeout = settings.LARGE_TIMEOUT549 selector, by = self.__recalculate_selector(selector, by)550 return page_actions.wait_for_element_absent(551 self.driver, selector, by, timeout552 )553 def find_visible_elements(self, selector, by=MobileBy.ACCESSIBILITY_ID, limit=0):554 """Returns a list of matching WebElements that are visible.555 If "limit" is set and > 0, will only return that many elements."""556 selector, by = self.__recalculate_selector(selector, by)557 time.sleep(0.05)558 v_elems = page_actions.find_visible_elements(self.driver, selector, by)559 if limit and limit > 0 and len(v_elems) > limit:560 v_elems = v_elems[:limit]561 return v_elems562 def click_visible_elements(563 self, selector, by=MobileBy.ACCESSIBILITY_ID, limit=0, timeout=None564 ):565 """Finds all matching page elements and clicks visible ones in order.566 If a click reloads or opens a new page, the clicking will stop.567 If no matching elements appear, an Exception will be raised.568 If "limit" is set and > 0, will only click that many elements.569 Also clicks elements that become visible from previous clicks.570 Works best for actions such as clicking all checkboxes on a page.571 Example: self.click_visible_elements('input[type="checkbox"]')"""572 self.__check_scope()573 if not timeout:574 timeout = settings.SMALL_TIMEOUT575 selector, by = self.__recalculate_selector(selector, by)576 self.wait_for_element_present(selector, by=by, timeout=timeout)577 elements = self.find_elements(selector, by=by)578 click_count = 0579 for element in elements:580 if limit and limit > 0 and click_count >= limit:581 return582 try:583 if element.is_displayed():584 self.__scroll_to_element(element)585 element.click()586 click_count += 1587 except ECI_Exception:588 continue # ElementClickInterceptedException (Overlay likel)589 except (StaleElementReferenceException, ENI_Exception):590 time.sleep(0.12)591 try:592 if element.is_displayed():593 self.__scroll_to_element(element)594 element.click()595 click_count += 1596 except (StaleElementReferenceException, ENI_Exception):597 return # Probably on new page / Elements are all stale598 def assert_true(self, expr, msg=None):599 """Asserts that the expression is True.600 Will raise an exception if the statement if False."""601 self.assertTrue(expr, msg=msg)602 def assert_false(self, expr, msg=None):603 """Asserts that the expression is False.604 Will raise an exception if the statement if True."""605 self.assertFalse(expr, msg=msg)606 def assert_equal(self, first, second, msg=None):607 """Asserts that the two values are equal.608 Will raise an exception if the values are not equal."""609 self.assertEqual(first, second, msg=msg)610 def assert_not_equal(self, first, second, msg=None):611 """Asserts that the two values are not equal.612 Will raise an exception if the values are equal."""613 self.assertNotEqual(first, second, msg=msg)614 def assert_in(self, first, second, msg=None):615 """Asserts that the first string is in the second string.616 Will raise an exception if the first string is not in the second."""617 self.assertIn(first, second, msg=msg)618 def assert_not_in(self, first, second, msg=None):619 """Asserts that the first string is not in the second string.620 Will raise an exception if the first string is in the second string."""621 self.assertNotIn(first, second, msg=msg)622 def assert_raises(self, *args, **kwargs):623 """Asserts that the following block of code raises an exception.624 Will raise an exception if the block of code has no exception.625 Usage Example =>626 # Verify that the expected exception is raised.627 with self.assert_raises(Exception):628 raise Exception("Expected Exception!")629 """630 return self.assertRaises(*args, **kwargs)631 def click_if_visible(self, selector, by=MobileBy.ACCESSIBILITY_ID):632 """If the page selector exists and is visible, clicks on the element.633 This method only clicks on the first matching element found.634 (Use click_visible_elements() to click all matching elements.)"""635 if self.is_element_visible(selector, by=by):636 self.click(selector, by=by)637 def __check_scope(self):638 if not self.__called_setup:639 self.setup()640 if hasattr(self, "device"): # self.browser stores the type of browser641 return # All good: setUp() already initialized variables in "self"642 else:643 from appiumbase.common.exceptions import OutOfScopeException644 message = (645 "\n It looks like you are trying to call a AppiumBase method"646 "\n from outside the scope of your test class's `self` object,"647 "\n which is initialized by calling BaseCase's setUp() method."648 "\n The `self` object is where all test variables are defined."649 "\n If you created a custom setUp() method (that overrided the"650 "\n the default one), make sure to call super().setUp() in it."651 "\n When using page objects, be sure to pass the `self` object"652 "\n from your test class into your page object methods so that"653 "\n they can call BaseCase class methods with all the required"654 "\n variables, which are initialized during the setUp() method"655 "\n that runs automatically before all tests called by pytest."656 )657 raise OutOfScopeException(message)658 def __scroll_to_element(self, element, selector, by):659 pass660 def slow_scroll_to(self, selector, by=MobileBy.ACCESSIBILITY_ID, timeout=None):661 """ Slow motion scroll to destination """662 self.__check_scope()663 pass664 def slow_scroll_to_element(self, selector, by=MobileBy.ACCESSIBILITY_ID, timeout=None):665 self.slow_scroll_to(selector, by=by, timeout=timeout)666 def set_text(self, selector, text, by=MobileBy.ACCESSIBILITY_ID, timeout=None):667 """Same as self.js_update_text()668 JavaScript + send_keys are used to update a text field.669 Performs self.set_value() and triggers event listeners.670 If text ends in "\n", set_value() presses RETURN after.671 Works faster than send_keys() alone due to the JS call.672 If not an input or textarea, sets textContent instead."""673 self.__check_scope()674 if not timeout:675 timeout = settings.LARGE_TIMEOUT676 selector, by = self.__recalculate_selector(selector, by)677 element = page_actions.wait_for_element_present(678 self.driver, selector, by, timeout679 )680 element.send_keys(text)681 def update_text(682 self, selector, text, by=MobileBy.ACCESSIBILITY_ID, timeout=None, retry=False683 ):684 """This method updates an element's text field with new text.685 Has multiple parts:686 * Waits for the element to be visible.687 * Waits for the element to be interactive.688 * Clears the text field.689 * Types in the new text.690 * Hits Enter/Submit (if the text ends in "\n").691 @Params692 selector - the selector of the text field693 text - the new text to type into the text field694 by - the type of selector to search by (Default: CSS Selector)695 timeout - how long to wait for the selector to be visible696 retry - if True, use JS if the Selenium text update fails697 """698 self.__check_scope()699 if not timeout:700 timeout = settings.LARGE_TIMEOUT701 selector, by = self.__recalculate_selector(selector, by)702 if self.__is_shadow_selector(selector):703 self.__shadow_type(selector, text)704 return705 element = self.wait_for_element_visible(706 selector, by=by, timeout=timeout707 )708 self.__scroll_to_element(element, selector, by)709 try:710 element.clear() # May need https://stackoverflow.com/a/50691625711 backspaces = Keys.BACK_SPACE * 42 # Is the answer to everything712 element.send_keys(backspaces) # In case autocomplete keeps text713 except (StaleElementReferenceException, ENI_Exception):714 time.sleep(0.16)715 element = self.wait_for_element_visible(716 selector, by=by, timeout=timeout...

Full Screen

Full Screen

asserts.py

Source:asserts.py Github

copy

Full Screen

...295 timeout = self.get_timeout(timeout, constants.SMALL_TIMEOUT)296 if type(selector) is list:297 self.assert_elements(selector, by=by, timeout=timeout)298 return True299 if self.__is_shadow_selector(selector):300 self.__assert_shadow_element_visible(selector)301 return True302 self.wait_for_element_visible(selector, by=by, timeout=timeout)303 if self.demo_mode:304 selector, by = self.__recalculate_selector(305 selector, by, xp_ok=False306 )307 a_t = "ASSERT"308 if self._language != "English":309 from seleniumbase.fixtures.words import SD310 a_t = SD.translate_assert(self._language)311 messenger_post = "%s %s: %s" % (a_t, by.upper(), selector)312 self.__highlight_with_assert_success(messenger_post, selector, by)313 return True314 def assert_element_visible(315 self, selector, by=By.CSS_SELECTOR, timeout=None316 ):317 """Same as self.assert_element()318 As above, will raise an exception if nothing can be found."""319 self.__check_scope()320 timeout = self.get_timeout(timeout, constants.SMALL_TIMEOUT)321 self.assert_element(selector, by=by, timeout=timeout)322 return True323 def assert_elements(self, *args, **kwargs):324 """Similar to self.assert_element(), but can assert multiple elements.325 The input is a list of elements.326 Optional kwargs include "by" and "timeout" (used by all selectors).327 Raises an exception if any of the elements are not visible.328 Examples:329 self.assert_elements("h1", "h2", "h3")330 OR331 self.assert_elements(["h1", "h2", "h3"])"""332 self.__check_scope()333 selectors = []334 timeout = None335 by = By.CSS_SELECTOR336 for kwarg in kwargs:337 if kwarg == "timeout":338 timeout = kwargs["timeout"]339 elif kwarg == "by":340 by = kwargs["by"]341 elif kwarg == "selector":342 selector = kwargs["selector"]343 if type(selector) is str:344 selectors.append(selector)345 elif type(selector) is list:346 selectors_list = selector347 for selector in selectors_list:348 if type(selector) is str:349 selectors.append(selector)350 else:351 raise Exception('Unknown kwarg: "%s"!' % kwarg)352 timeout = self.get_timeout(timeout, constants.SMALL_TIMEOUT)353 for arg in args:354 if type(arg) is list:355 for selector in arg:356 if type(selector) is str:357 selectors.append(selector)358 elif type(arg) is str:359 selectors.append(arg)360 for selector in selectors:361 if self.__is_shadow_selector(selector):362 self.__assert_shadow_element_visible(selector)363 continue364 self.wait_for_element_visible(selector, by=by, timeout=timeout)365 if self.demo_mode:366 selector, by = self.__recalculate_selector(selector, by)367 a_t = "ASSERT"368 if self._language != "English":369 from seleniumbase.fixtures.words import SD370 a_t = SD.translate_assert(self._language)371 messenger_post = "%s %s: %s" % (a_t, by.upper(), selector)372 self.__highlight_with_assert_success(373 messenger_post, selector, by374 )375 continue376 return True377 def assert_elements_visible(self, *args, **kwargs):378 """Same as self.assert_elements()379 Raises an exception if any element cannot be found."""380 return self.assert_elements(*args, **kwargs)381 def assert_element_absent(382 self, selector, by=By.CSS_SELECTOR, timeout=None383 ):384 """Similar to wait_for_element_absent()385 As above, will raise an exception if the element stays present.386 A hidden element counts as a present element, which fails this assert.387 If you want to assert that elements are hidden instead of nonexistent,388 use assert_element_not_visible() instead.389 (Note that hidden elements are still present in the HTML of the page.)390 Returns True if successful. Default timeout = SMALL_TIMEOUT."""391 self.__check_scope()392 timeout = self.get_timeout(timeout, constants.SMALL_TIMEOUT)393 self.wait_for_element_absent(selector, by=by, timeout=timeout)394 return True395 def assert_element_not_present(396 self, selector, by=By.CSS_SELECTOR, timeout=None397 ):398 """Same as self.assert_element_absent()399 Will raise an exception if the element stays present.400 A hidden element counts as a present element, which fails this assert.401 If you want to assert that elements are hidden instead of nonexistent,402 use assert_element_not_visible() instead.403 (Note that hidden elements are still present in the HTML of the page.)404 Returns True if successful. Default timeout = SMALL_TIMEOUT."""405 self.__check_scope()406 timeout = self.get_timeout(timeout, constants.SMALL_TIMEOUT)407 self.wait_for_element_absent(selector, by=by, timeout=timeout)408 return True409 def assert_element_not_visible(410 self, selector, by=By.CSS_SELECTOR, timeout=None411 ):412 """Similar to wait_for_element_not_visible()413 As above, will raise an exception if the element stays visible.414 Returns True if successful. Default timeout = SMALL_TIMEOUT."""415 self.__check_scope__()416 timeout = self.get_timeout(timeout, constants.SMALL_TIMEOUT)417 self.wait_for_element_not_visible(selector, by=by, timeout=timeout)418 return True419 def assert_element_present(420 self, selector, by=By.CSS_SELECTOR, timeout=None421 ):422 """Similar to wait_for_element_present(), but returns nothing.423 Waits for an element to appear in the HTML of a page.424 The element does not need be visible (it may be hidden).425 Returns True if successful. Default timeout = SMALL_TIMEOUT."""426 self.__check_scope()427 timeout = self.get_timeout(timeout, constants.SMALL_TIMEOUT)428 if type(selector) is list:429 self.assert_elements_present(selector, by=by, timeout=timeout)430 return True431 if self.__is_shadow_selector(selector):432 self.__assert_shadow_element_present(selector)433 return True434 self.wait_for_element_present(selector, by=by, timeout=timeout)435 return True436 def assert_elements_present(self, *args, **kwargs):437 """Similar to self.assert_element_present(),438 but can assert that multiple elements are present in the HTML.439 The input is a list of elements.440 Optional kwargs include "by" and "timeout" (used by all selectors).441 Raises an exception if any of the elements are not visible.442 Examples:443 self.assert_elements_present("head", "style", "script", "body")444 OR445 self.assert_elements_present(["head", "body", "h1", "h2"])446 """447 self.__check_scope()448 selectors = []449 timeout = None450 by = By.CSS_SELECTOR451 for kwarg in kwargs:452 if kwarg == "timeout":453 timeout = kwargs["timeout"]454 elif kwarg == "by":455 by = kwargs["by"]456 elif kwarg == "selector":457 selector = kwargs["selector"]458 if type(selector) is str:459 selectors.append(selector)460 elif type(selector) is list:461 selectors_list = selector462 for selector in selectors_list:463 if type(selector) is str:464 selectors.append(selector)465 else:466 raise Exception('Unknown kwarg: "%s"!' % kwarg)467 timeout = self.get_timeout(timeout, constants.SMALL_TIMEOUT)468 for arg in args:469 if type(arg) is list:470 for selector in arg:471 if type(selector) is str:472 selectors.append(selector)473 elif type(arg) is str:474 selectors.append(arg)475 for selector in selectors:476 if self.__is_shadow_selector(selector):477 self.__assert_shadow_element_visible(selector)478 continue479 self.wait_for_element_present(selector, by=by, timeout=timeout)480 continue481 return True482 def assert_text_visible(483 self, text, selector="html", by=By.CSS_SELECTOR, timeout=None484 ):485 """ Same as assert_text() """486 self.__check_scope()487 timeout = self.get_timeout(timeout, constants.SMALL_TIMEOUT)488 return self.assert_text(text, selector, by=by, timeout=timeout)489 def assert_text(490 self, text, selector="html", by=By.CSS_SELECTOR, timeout=None491 ):492 """Similar to wait_for_text_visible()493 Raises an exception if the element or the text is not found.494 The text only needs to be a subset within the complete text.495 Returns True if successful. Default timeout = SMALL_TIMEOUT."""496 self.__check_scope()497 timeout = self.get_timeout(timeout, constants.SMALL_TIMEOUT)498 selector, by = self.__recalculate_selector(selector, by)499 if self.__is_shadow_selector(selector):500 self.__assert_shadow_text_visible(text, selector, timeout)501 return True502 self.wait_for_text_visible(text, selector, by=by, timeout=timeout)503 if self.demo_mode:504 a_t = "ASSERT TEXT"505 i_n = "in"506 if self._language != "English":507 from seleniumbase.fixtures.words import SD508 a_t = SD.translate_assert_text(self._language)509 i_n = SD.translate_in(self._language)510 messenger_post = "%s: {%s} %s %s: %s" % (511 a_t,512 text,513 i_n,514 by.upper(),515 selector,516 )517 self.__highlight_with_assert_success(messenger_post, selector, by)518 return True519 def assert_exact_text(520 self, text, selector="html", by=By.CSS_SELECTOR, timeout=None521 ):522 """Similar to assert_text(), but the text must be exact,523 rather than exist as a subset of the full text.524 (Extra whitespace at the beginning or the end doesn't count.)525 Raises an exception if the element or the text is not found.526 Returns True if successful. Default timeout = SMALL_TIMEOUT."""527 self.__check_scope()528 timeout = self.get_timeout(timeout, constants.SMALL_TIMEOUT)529 selector, by = self.__recalculate_selector(selector, by)530 if self.__is_shadow_selector(selector):531 self.__assert_exact_shadow_text_visible(text, selector, timeout)532 return True533 self.wait_for_exact_text_visible(534 text, selector, by=by, timeout=timeout535 )536 if self.demo_mode:537 a_t = "ASSERT EXACT TEXT"538 i_n = "in"539 if self._language != "English":540 from seleniumbase.fixtures.words import SD541 a_t = SD.translate_assert_exact_text(self._language)542 i_n = SD.translate_in(self._language)543 messenger_post = "%s: {%s} %s %s: %s" % (544 a_t,...

Full Screen

Full Screen

Automation Testing Tutorials

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.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run SeleniumBase automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful