From d23b375a43a8232b46c0ab4c5c864df6e1595f1d Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Tue, 14 Nov 2023 20:52:25 -0500 Subject: [PATCH 01/10] Add "driver.uc_switch_to_frame(frame)" --- seleniumbase/core/browser_launcher.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/seleniumbase/core/browser_launcher.py b/seleniumbase/core/browser_launcher.py index 6081ddf6371..c1a7266f273 100644 --- a/seleniumbase/core/browser_launcher.py +++ b/seleniumbase/core/browser_launcher.py @@ -453,6 +453,17 @@ def uc_click( driver.js_click(selector, by=by, timeout=timeout) +def uc_switch_to_frame(driver, frame): + from selenium.webdriver.remote.webelement import WebElement + if isinstance(frame, WebElement): + driver.reconnect(0.15) + driver.switch_to.frame(frame) + else: + iframe = driver.locator(frame) + driver.reconnect(0.15) + driver.switch_to.frame(iframe) + + def edgedriver_on_path(): return os.path.exists(LOCAL_EDGEDRIVER) @@ -3574,6 +3585,11 @@ def get_local_driver( driver.uc_click = lambda *args, **kwargs: uc_click( driver, *args, **kwargs ) + driver.uc_switch_to_frame = ( + lambda *args, **kwargs: uc_switch_to_frame( + driver, *args, **kwargs + ) + ) if mobile_emulator: uc_metrics = {} if ( From 41d8fb21acfd1554e1b3e266972f5b7ae7eb4cef Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Tue, 14 Nov 2023 20:53:05 -0500 Subject: [PATCH 02/10] Do some UC Mode refactoring --- seleniumbase/undetected/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/seleniumbase/undetected/__init__.py b/seleniumbase/undetected/__init__.py index 3fbb1a57239..da76cb768bf 100644 --- a/seleniumbase/undetected/__init__.py +++ b/seleniumbase/undetected/__init__.py @@ -367,6 +367,7 @@ def remove_cdc_props_as_needed(self): cdc_props = self._get_cdc_props() if len(cdc_props) > 0: self._hook_remove_cdc_props(cdc_props) + time.sleep(0.05) def get(self, url): self.remove_cdc_props_as_needed() @@ -438,6 +439,10 @@ def quit(self): try: logger.debug("Terminating the UC browser") os.kill(self.browser_pid, 15) + # Not sure if this is really needed: + os.waitpid(self.browser_pid, 0) + except (AttributeError, ChildProcessError, RuntimeError, OSError): + pass except TimeoutError as e: logger.debug(e, exc_info=True) except Exception: From 97dfc85b4d3225248bf02ac1c08b726fceab0503 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Tue, 14 Nov 2023 20:54:30 -0500 Subject: [PATCH 03/10] Do some refactoring --- seleniumbase/fixtures/base_case.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/seleniumbase/fixtures/base_case.py b/seleniumbase/fixtures/base_case.py index fbad650b0ff..5207af809ad 100644 --- a/seleniumbase/fixtures/base_case.py +++ b/seleniumbase/fixtures/base_case.py @@ -14651,8 +14651,14 @@ def setUp(self, masterqa_mode=False): d_height=self.__device_height, d_p_r=self.__device_pixel_ratio, ) - if self.driver.timeouts.implicit_wait > 0: - self.driver.implicitly_wait(0) + try: + if self.driver.timeouts.implicit_wait > 0: + self.driver.implicitly_wait(0) + except Exception: + try: + self.driver.implicitly_wait(0) + except Exception: + pass self._default_driver = self.driver if self._reuse_session: sb_config.shared_driver = self.driver @@ -14671,10 +14677,13 @@ def setUp(self, masterqa_mode=False): self.set_time_limit(self.time_limit) # Configure the page load timeout - if hasattr(settings, "PAGE_LOAD_TIMEOUT"): - self.driver.set_page_load_timeout(settings.PAGE_LOAD_TIMEOUT) - else: - self.driver.set_page_load_timeout(120) # Selenium uses 300 + try: + if hasattr(settings, "PAGE_LOAD_TIMEOUT"): + self.driver.set_page_load_timeout(settings.PAGE_LOAD_TIMEOUT) + else: + self.driver.set_page_load_timeout(120) # Selenium uses 300 + except Exception: + pass # Set the start time for the test (in ms). # Although the pytest clock starts before setUp() begins, From 28f7643ebc8ad4cc9778aefa3c4e4ff5ed69e07a Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Tue, 14 Nov 2023 20:55:33 -0500 Subject: [PATCH 04/10] Add driver methods --- seleniumbase/core/browser_launcher.py | 2 ++ seleniumbase/core/sb_driver.py | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/seleniumbase/core/browser_launcher.py b/seleniumbase/core/browser_launcher.py index c1a7266f273..2cbfe7a7f95 100644 --- a/seleniumbase/core/browser_launcher.py +++ b/seleniumbase/core/browser_launcher.py @@ -187,8 +187,10 @@ def extend_driver(driver): driver.highlight = DM.highlight driver.highlight_click = DM.highlight_click driver.sleep = time.sleep + driver.get_attribute = DM.get_attribute driver.get_page_source = DM.get_page_source driver.get_title = DM.get_title + driver.switch_to_frame = DM.switch_to_frame if hasattr(driver, "proxy"): driver.set_wire_proxy = DM.set_wire_proxy return driver diff --git a/seleniumbase/core/sb_driver.py b/seleniumbase/core/sb_driver.py index 4e8b8e1e359..265f7d70e2c 100644 --- a/seleniumbase/core/sb_driver.py +++ b/seleniumbase/core/sb_driver.py @@ -1,4 +1,5 @@ """Add new methods to extend the driver""" +from selenium.webdriver.remote.webelement import WebElement from seleniumbase.fixtures import js_utils from seleniumbase.fixtures import page_actions from seleniumbase.fixtures import page_utils @@ -41,6 +42,10 @@ def locator(self, selector, by=None): pass raise Exception('No such Element: {%s} (by="%s")!' % (selector, by)) + def get_attribute(self, selector, attribute, by="css selector"): + element = self.locator(selector, by=by) + return element.get_attribute(attribute) + def get_page_source(self): return self.driver.page_source @@ -158,6 +163,13 @@ def highlight_click(self, *args, **kwargs): kwargs.pop("loops") page_actions.click(self.driver, *args, **kwargs) + def switch_to_frame(self, frame): + if isinstance(frame, WebElement): + self.driver.switch_to.frame(frame) + else: + iframe = self.locator(frame) + self.driver.switch_to.frame(iframe) + def set_wire_proxy(self, string): """Set a proxy server for selenium-wire mode ("--wire") Examples: (ONLY avilable if using selenium-wire mode!) From f7568e01937a72404426f17c444088ad88becf72 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Tue, 14 Nov 2023 20:57:21 -0500 Subject: [PATCH 05/10] Update comments --- seleniumbase/plugins/pytest_plugin.py | 4 ++-- seleniumbase/plugins/selenium_plugin.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/seleniumbase/plugins/pytest_plugin.py b/seleniumbase/plugins/pytest_plugin.py index 3e3c8703351..a5e86a7388b 100644 --- a/seleniumbase/plugins/pytest_plugin.py +++ b/seleniumbase/plugins/pytest_plugin.py @@ -798,8 +798,8 @@ def pytest_addoption(parser): dest="message_duration", default=None, help="""Setting this overrides the default time that - messenger notifications remain visible when reaching - assert statements during Demo Mode.""", + messenger notifications remain visible when + reaching assert statements during Demo Mode.""", ) parser.addoption( "--check_js", diff --git a/seleniumbase/plugins/selenium_plugin.py b/seleniumbase/plugins/selenium_plugin.py index f8c45536ae9..227bb9a1b3c 100644 --- a/seleniumbase/plugins/selenium_plugin.py +++ b/seleniumbase/plugins/selenium_plugin.py @@ -529,8 +529,8 @@ def options(self, parser, env): dest="message_duration", default=None, help="""Setting this overrides the default time that - messenger notifications remain visible when reaching - assert statements during Demo Mode.""", + messenger notifications remain visible when + reaching assert statements during Demo Mode.""", ) parser.addoption( "--check_js", From 1e949977c341dc32eea0562767f254ef063cbdbe Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Tue, 14 Nov 2023 21:10:53 -0500 Subject: [PATCH 06/10] Add option for setting "--host-resolver-rules=RULES" --- examples/raw_parameter_script.py | 1 + seleniumbase/behave/behave_sb.py | 8 ++++++++ seleniumbase/core/browser_launcher.py | 19 +++++++++++++++++++ seleniumbase/fixtures/base_case.py | 7 +++++++ seleniumbase/plugins/driver_manager.py | 11 +++++++++++ seleniumbase/plugins/pytest_plugin.py | 21 +++++++++++++++++++++ seleniumbase/plugins/sb_manager.py | 12 ++++++++++++ seleniumbase/plugins/selenium_plugin.py | 21 +++++++++++++++++++++ 8 files changed, 100 insertions(+) diff --git a/examples/raw_parameter_script.py b/examples/raw_parameter_script.py index ee7db91f9b4..d1436fa5bf1 100644 --- a/examples/raw_parameter_script.py +++ b/examples/raw_parameter_script.py @@ -84,6 +84,7 @@ sb._disable_beforeunload = False sb.save_screenshot_after_test = False sb.no_screenshot_after_test = False + sb.host_resolver_rules = None sb.page_load_strategy = None sb.timeout_multiplier = None sb.pytest_html_report = None diff --git a/seleniumbase/behave/behave_sb.py b/seleniumbase/behave/behave_sb.py index e2830757a93..9dc2a4741e1 100644 --- a/seleniumbase/behave/behave_sb.py +++ b/seleniumbase/behave/behave_sb.py @@ -230,6 +230,7 @@ def get_configured_sb(context): sb.proxy_bypass_list = None sb.proxy_pac_url = None sb.multi_proxy = False + sb.host_resolver_rules = None sb.enable_3d_apis = False sb.swiftshader = False sb.ad_block_on = False @@ -772,6 +773,13 @@ def get_configured_sb(context): if low_key in ["multi-proxy", "multi_proxy"]: sb.multi_proxy = True continue + # Handle: -D host-resolver-rules=RULES / host_resolver_rules=RULES + if low_key in ["host-resolver-rules", "host_resolver_rules"]: + host_resolver_rules = userdata[key] + if host_resolver_rules == "true": + host_resolver_rules = sb.host_resolver_rules + sb.host_resolver_rules = host_resolver_rules + continue # Handle: -D enable-3d-apis / enable_3d_apis if low_key in ["enable-3d-apis", "enable_3d_apis"]: sb.enable_3d_apis = True diff --git a/seleniumbase/core/browser_launcher.py b/seleniumbase/core/browser_launcher.py index 2cbfe7a7f95..d354dff5d72 100644 --- a/seleniumbase/core/browser_launcher.py +++ b/seleniumbase/core/browser_launcher.py @@ -756,6 +756,7 @@ def _set_chrome_options( enable_3d_apis, swiftshader, ad_block_on, + host_resolver_rules, block_images, do_not_track, chromium_arg, @@ -837,6 +838,10 @@ def _set_chrome_options( chrome_options.set_capability( "goog:loggingPrefs", {"performance": "ALL", "browser": "ALL"} ) + if host_resolver_rules: + chrome_options.add_argument( + "--host-resolver-rules=%s" % host_resolver_rules + ) if mobile_emulator and not is_using_uc(undetectable, browser_name): emulator_settings = {} device_metrics = {} @@ -1320,6 +1325,7 @@ def get_driver( enable_3d_apis=False, swiftshader=False, ad_block_on=False, + host_resolver_rules=None, block_images=False, do_not_track=False, chromium_arg=None, @@ -1531,6 +1537,7 @@ def get_driver( enable_3d_apis, swiftshader, ad_block_on, + host_resolver_rules, block_images, do_not_track, chromium_arg, @@ -1585,6 +1592,7 @@ def get_driver( enable_3d_apis, swiftshader, ad_block_on, + host_resolver_rules, block_images, do_not_track, chromium_arg, @@ -1643,6 +1651,7 @@ def get_remote_driver( enable_3d_apis, swiftshader, ad_block_on, + host_resolver_rules, block_images, do_not_track, chromium_arg, @@ -1764,6 +1773,7 @@ def get_remote_driver( enable_3d_apis, swiftshader, ad_block_on, + host_resolver_rules, block_images, do_not_track, chromium_arg, @@ -1928,6 +1938,7 @@ def get_remote_driver( enable_3d_apis, swiftshader, ad_block_on, + host_resolver_rules, block_images, do_not_track, chromium_arg, @@ -2042,6 +2053,7 @@ def get_local_driver( enable_3d_apis, swiftshader, ad_block_on, + host_resolver_rules, block_images, do_not_track, chromium_arg, @@ -2453,6 +2465,10 @@ def get_local_driver( edge_options.set_capability( "ms:loggingPrefs", {"performance": "ALL", "browser": "ALL"} ) + if host_resolver_rules: + edge_options.add_argument( + "--host-resolver-rules=%s" % host_resolver_rules + ) if not enable_sync: edge_options.add_argument("--disable-sync") if ( @@ -2795,6 +2811,7 @@ def get_local_driver( enable_3d_apis, swiftshader, ad_block_on, + host_resolver_rules, block_images, do_not_track, chromium_arg, @@ -3295,6 +3312,7 @@ def get_local_driver( enable_3d_apis, swiftshader, None, # ad_block_on + None, # host_resolver_rules block_images, do_not_track, None, # chromium_arg @@ -3511,6 +3529,7 @@ def get_local_driver( enable_3d_apis, swiftshader, None, # ad_block_on + None, # host_resolver_rules block_images, do_not_track, None, # chromium_arg diff --git a/seleniumbase/fixtures/base_case.py b/seleniumbase/fixtures/base_case.py index 5207af809ad..afcbe0038b9 100644 --- a/seleniumbase/fixtures/base_case.py +++ b/seleniumbase/fixtures/base_case.py @@ -3765,6 +3765,7 @@ def get_new_driver( enable_3d_apis=None, swiftshader=None, ad_block_on=None, + host_resolver_rules=None, block_images=None, do_not_track=None, chromium_arg=None, @@ -3822,6 +3823,7 @@ def get_new_driver( enable_3d_apis - the option to enable WebGL and 3D APIs (Chrome) swiftshader - the option to use Chrome's swiftshader (Chrome-only) ad_block_on - the option to block ads from loading (Chromium-only) + host_resolver_rules - Configure host-resolver-rules (Chromium-only) block_images - the option to block images from loading (Chrome) do_not_track - indicate that websites should not track you (Chrome) chromium_arg - the option to add a Chromium arg to Chrome/Edge @@ -3937,6 +3939,8 @@ def get_new_driver( swiftshader = self._swiftshader if ad_block_on is None: ad_block_on = self.ad_block_on + if host_resolver_rules is None: + host_resolver_rules = self.host_resolver_rules if block_images is None: block_images = self.block_images if do_not_track is None: @@ -4024,6 +4028,7 @@ def get_new_driver( enable_3d_apis=enable_3d_apis, swiftshader=swiftshader, ad_block_on=ad_block_on, + host_resolver_rules=host_resolver_rules, block_images=block_images, do_not_track=do_not_track, chromium_arg=chromium_arg, @@ -14266,6 +14271,7 @@ def setUp(self, masterqa_mode=False): self.message_duration = sb_config.message_duration self.js_checking_on = sb_config.js_checking_on self.ad_block_on = sb_config.ad_block_on + self.host_resolver_rules = sb_config.host_resolver_rules self.block_images = sb_config.block_images self.do_not_track = sb_config.do_not_track self.chromium_arg = sb_config.chromium_arg @@ -14633,6 +14639,7 @@ def setUp(self, masterqa_mode=False): enable_3d_apis=self.enable_3d_apis, swiftshader=self._swiftshader, ad_block_on=self.ad_block_on, + host_resolver_rules=self.host_resolver_rules, block_images=self.block_images, do_not_track=self.do_not_track, chromium_arg=self.chromium_arg, diff --git a/seleniumbase/plugins/driver_manager.py b/seleniumbase/plugins/driver_manager.py index c4921c38cea..122e463de95 100644 --- a/seleniumbase/plugins/driver_manager.py +++ b/seleniumbase/plugins/driver_manager.py @@ -99,6 +99,7 @@ def Driver( enable_3d_apis=None, # Enable WebGL and 3D APIs. swiftshader=None, # Chrome: --use-gl=angle / --use-angle=swiftshader-webgl ad_block_on=None, # Block some types of display ads from loading. + host_resolver_rules=None, # Set host-resolver-rules, comma-separated. block_images=None, # Block images from loading during tests. do_not_track=None, # Tell websites that you don't want to be tracked. chromium_arg=None, # "ARG=N,ARG2" (Set Chromium args, ","-separated.) @@ -436,6 +437,15 @@ def Driver( ad_block_on = True else: ad_block_on = False + if host_resolver_rules is None: + if '--host-resolver-rules="' in arg_join: + host_resolver_rules = ( + arg_join.split('--host-resolver-rules="')[1].split('"')[0] + ) + elif '--host_resolver_rules="' in arg_join: + host_resolver_rules = ( + arg_join.split("--host_resolver_rules=")[1].split('"')[0] + ) if driver_version is None: if "--driver-version=" in arg_join: driver_version = ( @@ -486,6 +496,7 @@ def Driver( enable_3d_apis=enable_3d_apis, swiftshader=swiftshader, ad_block_on=ad_block_on, + host_resolver_rules=host_resolver_rules, block_images=block_images, do_not_track=do_not_track, chromium_arg=chromium_arg, diff --git a/seleniumbase/plugins/pytest_plugin.py b/seleniumbase/plugins/pytest_plugin.py index a5e86a7388b..ca0686e89eb 100644 --- a/seleniumbase/plugins/pytest_plugin.py +++ b/seleniumbase/plugins/pytest_plugin.py @@ -76,6 +76,7 @@ def pytest_addoption(parser): --message-duration=SECONDS (The time length for Messenger alerts.) --check-js (Check for JavaScript errors after page loads.) --ad-block (Block some types of display ads from loading.) + --host-resolver-rules=RULES (Set host-resolver-rules, comma-separated.) --block-images (Block images from loading during tests.) --do-not-track (Indicate to websites that you don't want to be tracked.) --verify-delay=SECONDS (The delay before MasterQA verification checks.) @@ -822,6 +823,25 @@ def pytest_addoption(parser): help="""Using this makes WebDriver block display ads that are defined in ad_block_list.AD_BLOCK_LIST.""", ) + parser.addoption( + "--host_resolver_rules", + "--host-resolver-rules", + action="store", + dest="host_resolver_rules", + default=None, + help="""Use this option to set "host-resolver-rules". + This lets you re-map traffic from any domain. + Eg. "MAP www.google-analytics.com 0.0.0.0". + Eg. "MAP * ~NOTFOUND , EXCLUDE myproxy". + Eg. "MAP * 0.0.0.0 , EXCLUDE 127.0.0.1". + Eg. "MAP *.google.com myproxy". + Find more examples on these pages: + (https://www.electronjs.org/docs/ + latest/api/command-line-switches) + (https://www.chromium.org/developers/ + design-documents/network-stack/socks-proxy/) + Use comma-separation for multiple host rules.""", + ) parser.addoption( "--block_images", "--block-images", @@ -1499,6 +1519,7 @@ def pytest_configure(config): sb_config.message_duration = config.getoption("message_duration") sb_config.js_checking_on = config.getoption("js_checking_on") sb_config.ad_block_on = config.getoption("ad_block_on") + sb_config.host_resolver_rules = config.getoption("host_resolver_rules") sb_config.block_images = config.getoption("block_images") sb_config.do_not_track = config.getoption("do_not_track") sb_config.verify_delay = config.getoption("verify_delay") diff --git a/seleniumbase/plugins/sb_manager.py b/seleniumbase/plugins/sb_manager.py index 5ab3ba5f93c..e0b1336857e 100644 --- a/seleniumbase/plugins/sb_manager.py +++ b/seleniumbase/plugins/sb_manager.py @@ -63,6 +63,7 @@ def SB( enable_3d_apis=None, # Enable WebGL and 3D APIs. swiftshader=None, # Chrome: --use-gl=angle / --use-angle=swiftshader-webgl ad_block_on=None, # Block some types of display ads from loading. + host_resolver_rules=None, # Set host-resolver-rules, comma-separated. block_images=None, # Block images from loading during tests. do_not_track=None, # Tell websites that you don't want to be tracked. chromium_arg=None, # "ARG=N,ARG2" (Set Chromium args, ","-separated.) @@ -604,6 +605,15 @@ def SB( ad_block_on = True else: ad_block_on = False + if host_resolver_rules is None: + if '--host-resolver-rules="' in arg_join: + host_resolver_rules = ( + arg_join.split('--host-resolver-rules="')[1].split('"')[0] + ) + elif '--host_resolver_rules="' in arg_join: + host_resolver_rules = ( + arg_join.split("--host_resolver_rules=")[1].split('"')[0] + ) if driver_version is None: if "--driver-version=" in arg_join: driver_version = ( @@ -710,6 +720,7 @@ def SB( sb_config.dashboard = False sb_config._dashboard_initialized = False sb_config.message_duration = message_duration + sb_config.host_resolver_rules = host_resolver_rules sb_config.block_images = block_images sb_config.do_not_track = do_not_track sb_config.use_wire = use_wire @@ -811,6 +822,7 @@ def SB( sb.dashboard = sb_config.dashboard sb._dash_initialized = sb_config._dashboard_initialized sb.message_duration = sb_config.message_duration + sb.host_resolver_rules = sb_config.host_resolver_rules sb.block_images = sb_config.block_images sb.do_not_track = sb_config.do_not_track sb.use_wire = sb_config.use_wire diff --git a/seleniumbase/plugins/selenium_plugin.py b/seleniumbase/plugins/selenium_plugin.py index 227bb9a1b3c..3e9af8bc0ff 100644 --- a/seleniumbase/plugins/selenium_plugin.py +++ b/seleniumbase/plugins/selenium_plugin.py @@ -55,6 +55,7 @@ class SeleniumBrowser(Plugin): --message-duration=SECONDS (The time length for Messenger alerts.) --check-js (Check for JavaScript errors after page loads.) --ad-block (Block some types of display ads from loading.) + --host-resolver-rules=RULES (Set host-resolver-rules, comma-separated.) --block-images (Block images from loading during tests.) --do-not-track (Indicate to websites that you don't want to be tracked.) --verify-delay=SECONDS (The delay before MasterQA verification checks.) @@ -553,6 +554,25 @@ def options(self, parser, env): help="""Using this makes WebDriver block display ads that are defined in ad_block_list.AD_BLOCK_LIST.""", ) + parser.addoption( + "--host_resolver_rules", + "--host-resolver-rules", + action="store", + dest="host_resolver_rules", + default=None, + help="""Use this option to set "host-resolver-rules". + This lets you re-map traffic from any domain. + Eg. "MAP www.google-analytics.com 0.0.0.0". + Eg. "MAP * ~NOTFOUND , EXCLUDE myproxy". + Eg. "MAP * 0.0.0.0 , EXCLUDE 127.0.0.1". + Eg. "MAP *.google.com myproxy". + Find more examples on these pages: + (https://www.electronjs.org/docs/ + latest/api/command-line-switches) + (https://www.chromium.org/developers/ + design-documents/network-stack/socks-proxy/) + Use comma-separation for multiple host rules.""", + ) parser.addoption( "--block_images", "--block-images", @@ -1090,6 +1110,7 @@ def beforeTest(self, test): test.test.message_duration = self.options.message_duration test.test.js_checking_on = self.options.js_checking_on test.test.ad_block_on = self.options.ad_block_on + test.test.host_resolver_rules = self.options.host_resolver_rules test.test.block_images = self.options.block_images test.test.do_not_track = self.options.do_not_track test.test.verify_delay = self.options.verify_delay # MasterQA From 8dca9806bd4a560906956b77b25596618d1d721a Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Tue, 14 Nov 2023 21:13:17 -0500 Subject: [PATCH 07/10] Update the documentation --- README.md | 1 + help_docs/customizing_test_runs.md | 1 + help_docs/method_summary.md | 14 +++++++++++++- mkdocs.yml | 1 + mkdocs_build/requirements.txt | 2 +- 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6099d39148c..470cc141ae2 100755 --- a/README.md +++ b/README.md @@ -679,6 +679,7 @@ pytest test_coffee_cart.py --trace --message-duration=SECONDS # (The time length for Messenger alerts.) --check-js # (Check for JavaScript errors after page loads.) --ad-block # (Block some types of display ads from loading.) +--host-resolver-rules=RULES # (Set host-resolver-rules, comma-separated.) --block-images # (Block images from loading during tests.) --do-not-track # (Indicate to websites that you don't want to be tracked.) --verify-delay=SECONDS # (The delay before MasterQA verification checks.) diff --git a/help_docs/customizing_test_runs.md b/help_docs/customizing_test_runs.md index ae375223981..2a8ed61498d 100644 --- a/help_docs/customizing_test_runs.md +++ b/help_docs/customizing_test_runs.md @@ -159,6 +159,7 @@ pytest my_first_test.py --settings-file=custom_settings.py --message-duration=SECONDS # (The time length for Messenger alerts.) --check-js # (Check for JavaScript errors after page loads.) --ad-block # (Block some types of display ads from loading.) +--host-resolver-rules=RULES # (Set host-resolver-rules, comma-separated.) --block-images # (Block images from loading during tests.) --do-not-track # (Indicate to websites that you don't want to be tracked.) --verify-delay=SECONDS # (The delay before MasterQA verification checks.) diff --git a/help_docs/method_summary.md b/help_docs/method_summary.md index 7dca4ce53eb..7c1965da721 100644 --- a/help_docs/method_summary.md +++ b/help_docs/method_summary.md @@ -993,10 +993,16 @@ driver.highlight_click(selector) driver.sleep(seconds) +driver.locator(selector) + +driver.get_attribute(selector, attribute) + driver.get_page_source() driver.get_title() +driver.switch_to_frame(frame) + ############ # "driver"-specific methods added by SeleniumBase for UC Mode: "--uc" / uc=True @@ -1007,7 +1013,13 @@ driver.uc_open_with_tab(url) driver.uc_open_with_reconnect(url, reconnect_time=None) -driver.uc_click(selector) +driver.reconnect(timeout) + +driver.uc_click( + selector, by="css selector", + timeout=settings.SMALL_TIMEOUT, reconnect_time=None) + +driver.uc_switch_to_frame(frame) ``` -------- diff --git a/mkdocs.yml b/mkdocs.yml index 580dc7c7611..76f615cd6ed 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -157,6 +157,7 @@ nav: - 🔑 CF Turnstile on Form: https://seleniumbase.io/apps/form_turnstile - 🔐 reCAPTCHA v2 Test: https://seleniumbase.io/apps/recaptcha - 🔐 reCAPTCHA v2 on Form: https://seleniumbase.io/apps/form_recaptcha + - 🔐 reCAPTCHA, invisible: https://seleniumbase.io/apps/invisible_recaptcha - Additional Help Docs: - 📑 Table of Contents: help_docs/ReadMe.md - 🖼️ How to handle iframes: help_docs/handling_iframes.md diff --git a/mkdocs_build/requirements.txt b/mkdocs_build/requirements.txt index e23a4f5e6cf..8fb01cf898b 100644 --- a/mkdocs_build/requirements.txt +++ b/mkdocs_build/requirements.txt @@ -3,7 +3,7 @@ regex>=2023.10.3 PyYAML>=6.0.1 -pymdown-extensions>=10.3.1 +pymdown-extensions>=10.4 pipdeptree>=2.13.1 python-dateutil>=2.8.2 Markdown==3.5.1 From f357c39e33c12b03c2de3e0cac375f1e87a3aec4 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Tue, 14 Nov 2023 21:14:57 -0500 Subject: [PATCH 08/10] Refresh Python dependencies --- requirements.txt | 6 +++--- setup.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/requirements.txt b/requirements.txt index fa668b9f899..c137f4f664b 100755 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,7 @@ attrs>=23.1.0 certifi>=2023.7.22 filelock>=3.12.2;python_version<"3.8" filelock>=3.13.1;python_version>="3.8" -platformdirs>=3.11.0 +platformdirs>=4.0.0 parse>=1.19.1 parse-type>=0.6.2 six==1.16.0 @@ -15,7 +15,7 @@ idna==3.4 chardet==5.2.0 charset-normalizer==3.3.2 urllib3>=1.26.18,<2;python_version<"3.10" -urllib3>=1.26.18,<2.1.0;python_version>="3.10" +urllib3>=1.26.18,<2.2.0;python_version>="3.10" requests==2.31.0 pynose==1.4.8 sniffio==1.3.0 @@ -40,7 +40,7 @@ pytest-html==2.0.1 pytest-metadata==3.0.0 pytest-ordering==0.6 pytest-rerunfailures==12.0 -pytest-xdist==3.3.1 +pytest-xdist==3.4.0 parameterized==0.9.0 sbvirtualdisplay==1.3.0 behave==1.2.6 diff --git a/setup.py b/setup.py index a3b3bc8ba64..a54fc2a089d 100755 --- a/setup.py +++ b/setup.py @@ -140,7 +140,7 @@ "certifi>=2023.7.22", 'filelock>=3.12.2;python_version<"3.8"', 'filelock>=3.13.1;python_version>="3.8"', - 'platformdirs>=3.11.0', + 'platformdirs>=4.0.0', 'parse>=1.19.1', 'parse-type>=0.6.2', "six==1.16.0", @@ -148,7 +148,7 @@ 'chardet==5.2.0', 'charset-normalizer==3.3.2', 'urllib3>=1.26.18,<2;python_version<"3.10"', - 'urllib3>=1.26.18,<2.1.0;python_version>="3.10"', + 'urllib3>=1.26.18,<2.2.0;python_version>="3.10"', 'requests==2.31.0', "pynose==1.4.8", 'sniffio==1.3.0', @@ -173,7 +173,7 @@ 'pytest-metadata==3.0.0', "pytest-ordering==0.6", 'pytest-rerunfailures==12.0', - 'pytest-xdist==3.3.1', + 'pytest-xdist==3.4.0', 'parameterized==0.9.0', "sbvirtualdisplay==1.3.0", "behave==1.2.6", From d5976c441bb7bcf175466756cd904f2e1a9d2ba6 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Tue, 14 Nov 2023 21:15:46 -0500 Subject: [PATCH 09/10] Update examples --- examples/presenter/edge_presentation.py | 42 +++++++++++++++++-------- examples/presenter/multi_uc.py | 4 +-- examples/presenter/uc_presentation.py | 8 ++--- examples/raw_form_turnstile.py | 4 +-- examples/raw_turnstile.py | 4 +-- examples/test_chromedriver.py | 1 + examples/test_verify_chromedriver.py | 5 +++ 7 files changed, 43 insertions(+), 25 deletions(-) diff --git a/examples/presenter/edge_presentation.py b/examples/presenter/edge_presentation.py index 80df3ff1ee3..3ca53e8a8d0 100644 --- a/examples/presenter/edge_presentation.py +++ b/examples/presenter/edge_presentation.py @@ -42,7 +42,7 @@ def test_presentation(self): self.play_tour() self.sleep(0.25) self.open("data:,") - self.create_presentation(theme="sky", transition="fade") + self.create_presentation(theme="beige", transition="fade") self.add_slide( "

About the presenter:

\n" "
    \n" @@ -153,24 +153,40 @@ def test_presentation(self): self.play_tour() self.highlight('[href*="microsoft-edge/tools/webdriver"]') - self.get_new_driver(browser="edge") + self.get_new_driver(browser="edge", disable_csp=True) self.maximize_window() self.open( "https://developer.microsoft.com/en-us/" "microsoft-edge/tools/webdriver/" ) - self.wait_for_element("#page-heading") - self.scroll_to("#page-heading") - zoom_in = '#page-heading{zoom: 1.2;-moz-transform: scale(1.2);}' + self.wait_for_element("div.common-heading") + self.scroll_to("div.common-heading") + zoom_in = 'div.h1{zoom: 1.02;-moz-transform: scale(1.02);}' self.add_css_style(zoom_in) - self.highlight("#page-heading", loops=8) - self.sleep(1.2) - self.highlight("#downloads-channel", loops=8) - self.sleep(1.2) - self.highlight("#downloads", loops=12) - self.sleep(1.8) - self.highlight("#installation", loops=12) - self.sleep(1.8) + self.highlight("div.common-heading", loops=8) + self.create_tour(theme="driverjs") + self.add_tour_step( + "", "div.common-heading", alignment="left" + ) + self.play_tour() + self.highlight('div[data-fetch-key="block-web-driver:0"]', loops=12) + self.create_tour(theme="driverjs") + self.add_tour_step( + "", 'div[data-fetch-key="block-web-driver:0"]', alignment="top" + ) + self.play_tour() + self.highlight('div[data-fetch-key="block-web-driver:1"]', loops=12) + self.create_tour(theme="driverjs") + self.add_tour_step( + "", 'div[data-fetch-key="block-web-driver:1"]', alignment="top" + ) + self.play_tour() + self.highlight('section[data-section-id="installation"]', loops=12) + self.create_tour(theme="driverjs") + self.add_tour_step( + "", "div.block-heading--sixtyforty", alignment="left" + ) + self.play_tour() self.quit_extra_driver() self.switch_to_default_driver() diff --git a/examples/presenter/multi_uc.py b/examples/presenter/multi_uc.py index d1107cec3ab..37f621dacf4 100644 --- a/examples/presenter/multi_uc.py +++ b/examples/presenter/multi_uc.py @@ -7,14 +7,14 @@ @pytest.mark.parametrize("", [[]] * 3) def test_multi_threaded(sb): - sb.driver.get("https://nowsecure.nl/#relax") + sb.driver.uc_open_with_tab("https://nowsecure.nl/#relax") sb.set_window_rect(randint(0, 755), randint(38, 403), 700, 500) try: sb.assert_text("OH YEAH, you passed!", "h1", timeout=4) sb.post_message("Selenium wasn't detected!", duration=4) sb._print("\n Success! Website did not detect Selenium! ") except Exception: - sb.driver.get("https://nowsecure.nl/#relax") + sb.driver.uc_open_with_tab("https://nowsecure.nl/#relax") try: sb.assert_text("OH YEAH, you passed!", "h1", timeout=4) sb.post_message("Selenium wasn't detected!", duration=4) diff --git a/examples/presenter/uc_presentation.py b/examples/presenter/uc_presentation.py index a94aee7a76e..fd98fb46bed 100644 --- a/examples/presenter/uc_presentation.py +++ b/examples/presenter/uc_presentation.py @@ -29,13 +29,13 @@ def test_presentation(self): self.get_new_driver(undetectable=True) try: - self.driver.get("https://nowsecure.nl/#relax") + self.driver.uc_open_with_tab("https://nowsecure.nl/#relax") try: self.assert_text("OH YEAH, you passed!", "h1", timeout=4) self.post_message("Selenium wasn't detected!", duration=4) except Exception: self.clear_all_cookies() - self.driver.get("https://nowsecure.nl/#relax") + self.driver.uc_open_with_tab("https://nowsecure.nl/#relax") self.assert_text("OH YEAH, you passed!", "h1", timeout=4) self.post_message("Selenium wasn't detected!", duration=4) finally: @@ -355,10 +355,10 @@ def test_presentation(self): try: with SB(uc=True) as sb: - sb.driver.get("https://nowsecure.nl/#relax") + sb.driver.uc_open_with_tab("https://nowsecure.nl/#relax") sb.sleep(1) if not sb.is_text_visible("OH YEAH, you passed", "h1"): - sb.driver.get("https://nowsecure.nl/#relax") + sb.driver.uc_open_with_tab("https://nowsecure.nl/#relax") sb.sleep(1) sb.activate_demo_mode() sb.assert_text("OH YEAH, you passed!", "h1", timeout=3) diff --git a/examples/raw_form_turnstile.py b/examples/raw_form_turnstile.py index 84df796ecfa..3c169b03f44 100644 --- a/examples/raw_form_turnstile.py +++ b/examples/raw_form_turnstile.py @@ -8,9 +8,7 @@ def open_the_form_turnstile_page(sb): def click_turnstile_and_verify(sb): - iframe = sb.driver.find_element("iframe") - sb.driver.reconnect(0.1) # Another way to reconnect - sb.driver.switch_to.frame(iframe) + sb.driver.uc_switch_to_frame("iframe") sb.driver.uc_click("span.mark") sb.highlight("img#captcha-success", timeout=3.33) diff --git a/examples/raw_turnstile.py b/examples/raw_turnstile.py index 15d747e4bc9..4cc46144648 100644 --- a/examples/raw_turnstile.py +++ b/examples/raw_turnstile.py @@ -8,9 +8,7 @@ def open_the_turnstile_page(sb): def click_turnstile_and_verify(sb): - iframe = sb.driver.find_element("iframe") - sb.driver.reconnect(0.1) # Another way to reconnect - sb.driver.switch_to.frame(iframe) + sb.driver.uc_switch_to_frame("iframe") sb.driver.uc_click("span.mark") sb.assert_element("img#captcha-success", timeout=3.33) diff --git a/examples/test_chromedriver.py b/examples/test_chromedriver.py index 6056d72cbd9..4ce8d444d3a 100644 --- a/examples/test_chromedriver.py +++ b/examples/test_chromedriver.py @@ -9,6 +9,7 @@ class ChromedriverTests(BaseCase): def test_chromedriver_matches_chrome(self): if self.browser != "chrome": + self.open_if_not_url("data:,") print("\n This test is only for Chrome!") print(' (Run with: "--browser=chrome")') self.skip("This test is only for Chrome!") diff --git a/examples/test_verify_chromedriver.py b/examples/test_verify_chromedriver.py index f73d6493282..81a5851579d 100644 --- a/examples/test_verify_chromedriver.py +++ b/examples/test_verify_chromedriver.py @@ -28,3 +28,8 @@ def test_fail_if_versions_dont_match(self): print("\nWarning -> " + message) elif int(major_chromedriver_version) != int(major_chrome_version): raise Exception(message) + else: + print( + "\n* Chrome version: {%s}\n* Driver version: {%s}" + % (chromedriver_version, chrome_version) + ) From 383683be0b8214b97b967ca9a11f6b0122f0c2c1 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Tue, 14 Nov 2023 21:16:50 -0500 Subject: [PATCH 10/10] Version 4.21.2 --- seleniumbase/__version__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seleniumbase/__version__.py b/seleniumbase/__version__.py index f738015ba0e..7cd5ef0f256 100755 --- a/seleniumbase/__version__.py +++ b/seleniumbase/__version__.py @@ -1,2 +1,2 @@ # seleniumbase package -__version__ = "4.21.1" +__version__ = "4.21.2"