osn-selenium 0.0.0__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- osn_selenium/_functions.py +84 -0
- osn_selenium/_typehints.py +19 -0
- osn_selenium/abstract/executors/cdp/__init__.py +435 -0
- osn_selenium/abstract/executors/cdp/accessibility.py +62 -0
- osn_selenium/abstract/executors/cdp/animation.py +47 -0
- osn_selenium/abstract/executors/cdp/audits.py +39 -0
- osn_selenium/abstract/executors/cdp/autofill.py +34 -0
- osn_selenium/abstract/executors/cdp/background_service.py +22 -0
- osn_selenium/abstract/executors/cdp/bluetooth_emulation.py +95 -0
- osn_selenium/abstract/executors/cdp/browser.py +122 -0
- osn_selenium/abstract/executors/cdp/cache_storage.py +49 -0
- osn_selenium/abstract/executors/cdp/cast.py +31 -0
- osn_selenium/abstract/executors/cdp/console.py +18 -0
- osn_selenium/abstract/executors/cdp/css.py +197 -0
- osn_selenium/abstract/executors/cdp/debugger.py +198 -0
- osn_selenium/abstract/executors/cdp/device_access.py +22 -0
- osn_selenium/abstract/executors/cdp/device_orientation.py +14 -0
- osn_selenium/abstract/executors/cdp/dom.py +305 -0
- osn_selenium/abstract/executors/cdp/dom_debugger.py +57 -0
- osn_selenium/abstract/executors/cdp/dom_snapshot.py +42 -0
- osn_selenium/abstract/executors/cdp/dom_storage.py +31 -0
- osn_selenium/abstract/executors/cdp/emulation.py +259 -0
- osn_selenium/abstract/executors/cdp/event_breakpoints.py +18 -0
- osn_selenium/abstract/executors/cdp/extensions.py +31 -0
- osn_selenium/abstract/executors/cdp/fed_cm.py +35 -0
- osn_selenium/abstract/executors/cdp/fetch.py +76 -0
- osn_selenium/abstract/executors/cdp/file_system.py +11 -0
- osn_selenium/abstract/executors/cdp/headless_experimental.py +30 -0
- osn_selenium/abstract/executors/cdp/heap_profiler.py +73 -0
- osn_selenium/abstract/executors/cdp/indexed_db.py +99 -0
- osn_selenium/abstract/executors/cdp/input.py +158 -0
- osn_selenium/abstract/executors/cdp/inspector.py +14 -0
- osn_selenium/abstract/executors/cdp/io.py +24 -0
- osn_selenium/abstract/executors/cdp/layer_tree.py +61 -0
- osn_selenium/abstract/executors/cdp/log.py +27 -0
- osn_selenium/abstract/executors/cdp/media.py +14 -0
- osn_selenium/abstract/executors/cdp/memory.py +61 -0
- osn_selenium/abstract/executors/cdp/network.py +252 -0
- osn_selenium/abstract/executors/cdp/overlay.py +166 -0
- osn_selenium/abstract/executors/cdp/page.py +347 -0
- osn_selenium/abstract/executors/cdp/performance.py +28 -0
- osn_selenium/abstract/executors/cdp/performance_timeline.py +11 -0
- osn_selenium/abstract/executors/cdp/preload.py +14 -0
- osn_selenium/abstract/executors/cdp/profiler.py +54 -0
- osn_selenium/abstract/executors/cdp/pwa.py +46 -0
- osn_selenium/abstract/executors/cdp/runtime.py +176 -0
- osn_selenium/abstract/executors/cdp/schema.py +11 -0
- osn_selenium/abstract/executors/cdp/security.py +26 -0
- osn_selenium/abstract/executors/cdp/service_worker.py +54 -0
- osn_selenium/abstract/executors/cdp/storage.py +175 -0
- osn_selenium/abstract/executors/cdp/system_info.py +24 -0
- osn_selenium/abstract/executors/cdp/target.py +125 -0
- osn_selenium/abstract/executors/cdp/tethering.py +14 -0
- osn_selenium/abstract/executors/cdp/tracing.py +48 -0
- osn_selenium/abstract/executors/cdp/web_audio.py +19 -0
- osn_selenium/abstract/executors/cdp/web_authn.py +76 -0
- osn_selenium/abstract/executors/javascript.py +203 -0
- osn_selenium/abstract/instances/action_chains/__init__.py +12 -0
- osn_selenium/abstract/instances/action_chains/base.py +25 -0
- osn_selenium/abstract/instances/action_chains/click.py +93 -0
- osn_selenium/abstract/instances/action_chains/drag_and_drop.py +46 -0
- osn_selenium/abstract/instances/action_chains/hm_keyboard.py +44 -0
- osn_selenium/abstract/instances/action_chains/hm_move.py +104 -0
- osn_selenium/abstract/instances/action_chains/hm_scroll.py +75 -0
- osn_selenium/abstract/instances/action_chains/keyboard.py +79 -0
- osn_selenium/abstract/instances/action_chains/move.py +60 -0
- osn_selenium/abstract/instances/action_chains/scroll.py +61 -0
- osn_selenium/abstract/instances/action_chains/utils.py +44 -0
- osn_selenium/abstract/instances/alert.py +67 -0
- osn_selenium/abstract/instances/browser.py +76 -0
- osn_selenium/abstract/instances/browsing_context.py +310 -0
- osn_selenium/abstract/instances/dialog.py +107 -0
- osn_selenium/abstract/instances/fedcm.py +133 -0
- osn_selenium/abstract/instances/mobile.py +79 -0
- osn_selenium/abstract/instances/network.py +100 -0
- osn_selenium/abstract/instances/permissions.py +52 -0
- osn_selenium/abstract/instances/script.py +109 -0
- osn_selenium/abstract/instances/shadow_root.py +81 -0
- osn_selenium/abstract/instances/storage.py +98 -0
- osn_selenium/abstract/instances/switch_to.py +104 -0
- osn_selenium/abstract/instances/web_driver_wait.py +57 -0
- osn_selenium/abstract/instances/web_element.py +395 -0
- osn_selenium/abstract/instances/web_extension.py +70 -0
- osn_selenium/abstract/webdriver/blink/__init__.py +18 -0
- osn_selenium/abstract/webdriver/blink/base.py +80 -0
- osn_selenium/abstract/webdriver/blink/casting.py +82 -0
- osn_selenium/abstract/webdriver/blink/features.py +51 -0
- osn_selenium/abstract/webdriver/blink/lifecycle.py +76 -0
- osn_selenium/abstract/webdriver/blink/logging.py +40 -0
- osn_selenium/abstract/webdriver/blink/network.py +45 -0
- osn_selenium/abstract/webdriver/blink/settings.py +68 -0
- osn_selenium/abstract/webdriver/chrome/__init__.py +18 -0
- osn_selenium/abstract/webdriver/chrome/base.py +36 -0
- osn_selenium/abstract/webdriver/chrome/lifecycle.py +92 -0
- osn_selenium/abstract/webdriver/chrome/settings.py +110 -0
- osn_selenium/abstract/webdriver/core/__init__.py +16 -0
- osn_selenium/abstract/webdriver/core/actions.py +58 -0
- osn_selenium/abstract/webdriver/core/auth.py +145 -0
- osn_selenium/abstract/webdriver/core/base.py +298 -0
- osn_selenium/abstract/webdriver/core/capture.py +84 -0
- osn_selenium/abstract/webdriver/core/components.py +82 -0
- osn_selenium/abstract/webdriver/core/devtools.py +69 -0
- osn_selenium/abstract/webdriver/core/element.py +55 -0
- osn_selenium/abstract/webdriver/core/file.py +82 -0
- osn_selenium/abstract/webdriver/core/lifecycle.py +103 -0
- osn_selenium/abstract/webdriver/core/navigation.py +65 -0
- osn_selenium/abstract/webdriver/core/script.py +88 -0
- osn_selenium/abstract/webdriver/core/settings.py +43 -0
- osn_selenium/abstract/webdriver/core/storage.py +81 -0
- osn_selenium/abstract/webdriver/core/timeouts.py +101 -0
- osn_selenium/abstract/webdriver/core/window.py +237 -0
- osn_selenium/abstract/webdriver/edge/__init__.py +18 -0
- osn_selenium/abstract/webdriver/edge/base.py +36 -0
- osn_selenium/abstract/webdriver/edge/lifecycle.py +92 -0
- osn_selenium/abstract/webdriver/edge/settings.py +110 -0
- osn_selenium/abstract/webdriver/yandex/__init__.py +18 -0
- osn_selenium/abstract/webdriver/yandex/base.py +18 -0
- osn_selenium/abstract/webdriver/yandex/lifecycle.py +92 -0
- osn_selenium/abstract/webdriver/yandex/settings.py +110 -0
- osn_selenium/base_mixin.py +122 -0
- osn_selenium/browsers_handler/__init__.py +47 -17
- osn_selenium/browsers_handler/_linux.py +226 -0
- osn_selenium/browsers_handler/_windows.py +21 -14
- osn_selenium/browsers_handler/{types.py → models.py} +5 -2
- osn_selenium/dev_tools/_decorators.py +140 -0
- osn_selenium/dev_tools/_exception_helpers.py +116 -0
- osn_selenium/dev_tools/_functions.py +174 -0
- osn_selenium/dev_tools/_system_utils.py +35 -0
- osn_selenium/dev_tools/_typehints.py +32 -0
- osn_selenium/dev_tools/_validators.py +227 -0
- osn_selenium/dev_tools/_wrappers.py +95 -0
- osn_selenium/dev_tools/domains/__init__.py +7 -40
- osn_selenium/dev_tools/domains/abstract.py +98 -254
- osn_selenium/dev_tools/domains/fetch.py +229 -906
- osn_selenium/dev_tools/domains_default/fetch.py +40 -28
- osn_selenium/dev_tools/filters.py +40 -0
- osn_selenium/dev_tools/logger/main.py +226 -0
- osn_selenium/dev_tools/logger/models.py +232 -0
- osn_selenium/dev_tools/logger/target.py +258 -0
- osn_selenium/dev_tools/manager/__init__.py +16 -0
- osn_selenium/dev_tools/manager/base.py +147 -0
- osn_selenium/dev_tools/manager/lifecycle.py +236 -0
- osn_selenium/dev_tools/manager/logging.py +153 -0
- osn_selenium/dev_tools/manager/settings.py +89 -0
- osn_selenium/dev_tools/manager/targets.py +175 -0
- osn_selenium/dev_tools/models.py +49 -0
- osn_selenium/dev_tools/settings.py +135 -0
- osn_selenium/dev_tools/target/__init__.py +16 -0
- osn_selenium/dev_tools/target/base.py +438 -0
- osn_selenium/dev_tools/target/detach.py +54 -0
- osn_selenium/dev_tools/target/discovery.py +112 -0
- osn_selenium/dev_tools/target/events.py +120 -0
- osn_selenium/dev_tools/target/fingerprint.py +126 -0
- osn_selenium/dev_tools/target/lifecycle.py +179 -0
- osn_selenium/dev_tools/target/logging.py +155 -0
- osn_selenium/exceptions/__init__.py +1 -0
- osn_selenium/exceptions/base.py +9 -0
- osn_selenium/exceptions/configuration.py +84 -0
- osn_selenium/exceptions/devtools.py +114 -0
- osn_selenium/exceptions/flags.py +45 -0
- osn_selenium/exceptions/instance.py +92 -0
- osn_selenium/exceptions/javascript.py +31 -0
- osn_selenium/exceptions/logic.py +31 -0
- osn_selenium/exceptions/path.py +77 -0
- osn_selenium/exceptions/platform.py +33 -0
- osn_selenium/exceptions/protocol.py +86 -0
- osn_selenium/exceptions/webdriver.py +44 -0
- osn_selenium/exceptions/window.py +63 -0
- osn_selenium/executors/__init__.py +1 -0
- osn_selenium/executors/sync/__init__.py +1 -0
- osn_selenium/executors/sync/cdp/__init__.py +550 -0
- osn_selenium/executors/sync/cdp/accessibility.py +74 -0
- osn_selenium/executors/sync/cdp/animation.py +50 -0
- osn_selenium/executors/sync/cdp/audits.py +48 -0
- osn_selenium/executors/sync/cdp/autofill.py +39 -0
- osn_selenium/executors/sync/cdp/background_service.py +30 -0
- osn_selenium/executors/sync/cdp/bluetooth_emulation.py +101 -0
- osn_selenium/executors/sync/cdp/browser.py +131 -0
- osn_selenium/executors/sync/cdp/cache_storage.py +66 -0
- osn_selenium/executors/sync/cdp/cast.py +38 -0
- osn_selenium/executors/sync/cdp/console.py +24 -0
- osn_selenium/executors/sync/cdp/css.py +187 -0
- osn_selenium/executors/sync/cdp/debugger.py +206 -0
- osn_selenium/executors/sync/cdp/device_access.py +27 -0
- osn_selenium/executors/sync/cdp/device_orientation.py +24 -0
- osn_selenium/executors/sync/cdp/dom.py +310 -0
- osn_selenium/executors/sync/cdp/dom_debugger.py +56 -0
- osn_selenium/executors/sync/cdp/dom_snapshot.py +58 -0
- osn_selenium/executors/sync/cdp/dom_storage.py +38 -0
- osn_selenium/executors/sync/cdp/emulation.py +270 -0
- osn_selenium/executors/sync/cdp/event_breakpoints.py +27 -0
- osn_selenium/executors/sync/cdp/extensions.py +39 -0
- osn_selenium/executors/sync/cdp/fed_cm.py +45 -0
- osn_selenium/executors/sync/cdp/fetch.py +96 -0
- osn_selenium/executors/sync/cdp/file_system.py +18 -0
- osn_selenium/executors/sync/cdp/headless_experimental.py +44 -0
- osn_selenium/executors/sync/cdp/heap_profiler.py +89 -0
- osn_selenium/executors/sync/cdp/indexed_db.py +142 -0
- osn_selenium/executors/sync/cdp/input.py +233 -0
- osn_selenium/executors/sync/cdp/inspector.py +21 -0
- osn_selenium/executors/sync/cdp/io.py +33 -0
- osn_selenium/executors/sync/cdp/layer_tree.py +71 -0
- osn_selenium/executors/sync/cdp/log.py +35 -0
- osn_selenium/executors/sync/cdp/media.py +21 -0
- osn_selenium/executors/sync/cdp/memory.py +62 -0
- osn_selenium/executors/sync/cdp/network.py +287 -0
- osn_selenium/executors/sync/cdp/overlay.py +174 -0
- osn_selenium/executors/sync/cdp/page.py +365 -0
- osn_selenium/executors/sync/cdp/performance.py +33 -0
- osn_selenium/executors/sync/cdp/performance_timeline.py +26 -0
- osn_selenium/executors/sync/cdp/preload.py +21 -0
- osn_selenium/executors/sync/cdp/profiler.py +58 -0
- osn_selenium/executors/sync/cdp/pwa.py +55 -0
- osn_selenium/executors/sync/cdp/runtime.py +221 -0
- osn_selenium/executors/sync/cdp/schema.py +23 -0
- osn_selenium/executors/sync/cdp/security.py +30 -0
- osn_selenium/executors/sync/cdp/service_worker.py +56 -0
- osn_selenium/executors/sync/cdp/storage.py +151 -0
- osn_selenium/executors/sync/cdp/system_info.py +30 -0
- osn_selenium/executors/sync/cdp/target.py +147 -0
- osn_selenium/executors/sync/cdp/tethering.py +21 -0
- osn_selenium/executors/sync/cdp/tracing.py +62 -0
- osn_selenium/executors/sync/cdp/web_audio.py +24 -0
- osn_selenium/executors/sync/cdp/web_authn.py +82 -0
- osn_selenium/executors/sync/javascript.py +79 -0
- osn_selenium/executors/trio_threads/__init__.py +1 -0
- osn_selenium/executors/trio_threads/cdp/__init__.py +771 -0
- osn_selenium/executors/trio_threads/cdp/accessibility.py +87 -0
- osn_selenium/executors/trio_threads/cdp/animation.py +63 -0
- osn_selenium/executors/trio_threads/cdp/audits.py +57 -0
- osn_selenium/executors/trio_threads/cdp/autofill.py +52 -0
- osn_selenium/executors/trio_threads/cdp/background_service.py +40 -0
- osn_selenium/executors/trio_threads/cdp/bluetooth_emulation.py +111 -0
- osn_selenium/executors/trio_threads/cdp/browser.py +140 -0
- osn_selenium/executors/trio_threads/cdp/cache_storage.py +79 -0
- osn_selenium/executors/trio_threads/cdp/cast.py +47 -0
- osn_selenium/executors/trio_threads/cdp/console.py +33 -0
- osn_selenium/executors/trio_threads/cdp/css.py +196 -0
- osn_selenium/executors/trio_threads/cdp/debugger.py +219 -0
- osn_selenium/executors/trio_threads/cdp/device_access.py +40 -0
- osn_selenium/executors/trio_threads/cdp/device_orientation.py +34 -0
- osn_selenium/executors/trio_threads/cdp/dom.py +319 -0
- osn_selenium/executors/trio_threads/cdp/dom_debugger.py +69 -0
- osn_selenium/executors/trio_threads/cdp/dom_snapshot.py +71 -0
- osn_selenium/executors/trio_threads/cdp/dom_storage.py +51 -0
- osn_selenium/executors/trio_threads/cdp/emulation.py +283 -0
- osn_selenium/executors/trio_threads/cdp/event_breakpoints.py +37 -0
- osn_selenium/executors/trio_threads/cdp/extensions.py +52 -0
- osn_selenium/executors/trio_threads/cdp/fed_cm.py +54 -0
- osn_selenium/executors/trio_threads/cdp/fetch.py +105 -0
- osn_selenium/executors/trio_threads/cdp/file_system.py +31 -0
- osn_selenium/executors/trio_threads/cdp/headless_experimental.py +54 -0
- osn_selenium/executors/trio_threads/cdp/heap_profiler.py +102 -0
- osn_selenium/executors/trio_threads/cdp/indexed_db.py +155 -0
- osn_selenium/executors/trio_threads/cdp/input.py +242 -0
- osn_selenium/executors/trio_threads/cdp/inspector.py +34 -0
- osn_selenium/executors/trio_threads/cdp/io.py +42 -0
- osn_selenium/executors/trio_threads/cdp/layer_tree.py +84 -0
- osn_selenium/executors/trio_threads/cdp/log.py +44 -0
- osn_selenium/executors/trio_threads/cdp/media.py +30 -0
- osn_selenium/executors/trio_threads/cdp/memory.py +71 -0
- osn_selenium/executors/trio_threads/cdp/network.py +296 -0
- osn_selenium/executors/trio_threads/cdp/overlay.py +183 -0
- osn_selenium/executors/trio_threads/cdp/page.py +374 -0
- osn_selenium/executors/trio_threads/cdp/performance.py +46 -0
- osn_selenium/executors/trio_threads/cdp/performance_timeline.py +36 -0
- osn_selenium/executors/trio_threads/cdp/preload.py +30 -0
- osn_selenium/executors/trio_threads/cdp/profiler.py +71 -0
- osn_selenium/executors/trio_threads/cdp/pwa.py +64 -0
- osn_selenium/executors/trio_threads/cdp/runtime.py +230 -0
- osn_selenium/executors/trio_threads/cdp/schema.py +32 -0
- osn_selenium/executors/trio_threads/cdp/security.py +43 -0
- osn_selenium/executors/trio_threads/cdp/service_worker.py +69 -0
- osn_selenium/executors/trio_threads/cdp/storage.py +162 -0
- osn_selenium/executors/trio_threads/cdp/system_info.py +43 -0
- osn_selenium/executors/trio_threads/cdp/target.py +156 -0
- osn_selenium/executors/trio_threads/cdp/tethering.py +34 -0
- osn_selenium/executors/trio_threads/cdp/tracing.py +71 -0
- osn_selenium/executors/trio_threads/cdp/web_audio.py +37 -0
- osn_selenium/executors/trio_threads/cdp/web_authn.py +95 -0
- osn_selenium/executors/trio_threads/javascript.py +90 -0
- osn_selenium/executors/unified/__init__.py +1 -0
- osn_selenium/executors/unified/cdp/__init__.py +1 -0
- osn_selenium/executors/unified/cdp/accessibility.py +81 -0
- osn_selenium/executors/unified/cdp/animation.py +50 -0
- osn_selenium/executors/unified/cdp/audits.py +45 -0
- osn_selenium/executors/unified/cdp/autofill.py +41 -0
- osn_selenium/executors/unified/cdp/background_service.py +24 -0
- osn_selenium/executors/unified/cdp/bluetooth_emulation.py +132 -0
- osn_selenium/executors/unified/cdp/browser.py +143 -0
- osn_selenium/executors/unified/cdp/cache_storage.py +69 -0
- osn_selenium/executors/unified/cdp/cast.py +32 -0
- osn_selenium/executors/unified/cdp/console.py +18 -0
- osn_selenium/executors/unified/cdp/css.py +237 -0
- osn_selenium/executors/unified/cdp/debugger.py +243 -0
- osn_selenium/executors/unified/cdp/device_access.py +21 -0
- osn_selenium/executors/unified/cdp/device_orientation.py +18 -0
- osn_selenium/executors/unified/cdp/dom.py +380 -0
- osn_selenium/executors/unified/cdp/dom_debugger.py +65 -0
- osn_selenium/executors/unified/cdp/dom_snapshot.py +58 -0
- osn_selenium/executors/unified/cdp/dom_storage.py +38 -0
- osn_selenium/executors/unified/cdp/emulation.py +312 -0
- osn_selenium/executors/unified/cdp/event_breakpoints.py +24 -0
- osn_selenium/executors/unified/cdp/extensions.py +45 -0
- osn_selenium/executors/unified/cdp/fed_cm.py +51 -0
- osn_selenium/executors/unified/cdp/fetch.py +111 -0
- osn_selenium/executors/unified/cdp/file_system.py +15 -0
- osn_selenium/executors/unified/cdp/headless_experimental.py +38 -0
- osn_selenium/executors/unified/cdp/heap_profiler.py +101 -0
- osn_selenium/executors/unified/cdp/indexed_db.py +157 -0
- osn_selenium/executors/unified/cdp/input.py +254 -0
- osn_selenium/executors/unified/cdp/inspector.py +15 -0
- osn_selenium/executors/unified/cdp/io.py +29 -0
- osn_selenium/executors/unified/cdp/layer_tree.py +71 -0
- osn_selenium/executors/unified/cdp/log.py +29 -0
- osn_selenium/executors/unified/cdp/media.py +15 -0
- osn_selenium/executors/unified/cdp/memory.py +59 -0
- osn_selenium/executors/unified/cdp/network.py +323 -0
- osn_selenium/executors/unified/cdp/overlay.py +209 -0
- osn_selenium/executors/unified/cdp/page.py +410 -0
- osn_selenium/executors/unified/cdp/performance.py +27 -0
- osn_selenium/executors/unified/cdp/performance_timeline.py +17 -0
- osn_selenium/executors/unified/cdp/preload.py +15 -0
- osn_selenium/executors/unified/cdp/profiler.py +55 -0
- osn_selenium/executors/unified/cdp/pwa.py +55 -0
- osn_selenium/executors/unified/cdp/runtime.py +245 -0
- osn_selenium/executors/unified/cdp/schema.py +17 -0
- osn_selenium/executors/unified/cdp/security.py +27 -0
- osn_selenium/executors/unified/cdp/service_worker.py +62 -0
- osn_selenium/executors/unified/cdp/storage.py +178 -0
- osn_selenium/executors/unified/cdp/system_info.py +24 -0
- osn_selenium/executors/unified/cdp/target.py +165 -0
- osn_selenium/executors/unified/cdp/tethering.py +15 -0
- osn_selenium/executors/unified/cdp/tracing.py +62 -0
- osn_selenium/executors/unified/cdp/web_audio.py +18 -0
- osn_selenium/executors/unified/cdp/web_authn.py +103 -0
- osn_selenium/executors/unified/javascript.py +108 -0
- osn_selenium/flags/__init__.py +1 -0
- osn_selenium/flags/_functions.py +45 -0
- osn_selenium/flags/_typehints.py +34 -0
- osn_selenium/flags/_validators.py +101 -0
- osn_selenium/{webdrivers/BaseDriver/flags.py → flags/base.py} +165 -243
- osn_selenium/{webdrivers/Blink/flags.py → flags/blink.py} +133 -371
- osn_selenium/flags/chrome.py +259 -0
- osn_selenium/flags/edge.py +259 -0
- osn_selenium/flags/models/__init__.py +1 -0
- osn_selenium/flags/models/base.py +130 -0
- osn_selenium/flags/models/blink.py +263 -0
- osn_selenium/{webdrivers/Chrome/flags.py → flags/models/chrome.py} +25 -75
- osn_selenium/{webdrivers/Edge/flags.py → flags/models/edge.py} +25 -75
- osn_selenium/flags/models/values.py +44 -0
- osn_selenium/{webdrivers/Yandex/flags.py → flags/models/yandex.py} +26 -76
- osn_selenium/flags/yandex.py +259 -0
- osn_selenium/instances/__init__.py +1 -0
- osn_selenium/instances/_functions.py +242 -0
- osn_selenium/instances/_typehints.py +148 -0
- osn_selenium/instances/_utils.py +143 -0
- osn_selenium/instances/convert.py +287 -0
- osn_selenium/instances/protocols.py +105 -0
- osn_selenium/instances/sync/__init__.py +1 -0
- osn_selenium/instances/sync/action_chains/__init__.py +26 -0
- osn_selenium/instances/sync/action_chains/base.py +74 -0
- osn_selenium/instances/sync/action_chains/click.py +61 -0
- osn_selenium/instances/sync/action_chains/drag_and_drop.py +45 -0
- osn_selenium/instances/sync/action_chains/hm_keyboard.py +37 -0
- osn_selenium/instances/sync/action_chains/hm_move.py +81 -0
- osn_selenium/instances/sync/action_chains/hm_scroll.py +60 -0
- osn_selenium/instances/sync/action_chains/keyboard.py +55 -0
- osn_selenium/instances/sync/action_chains/move.py +46 -0
- osn_selenium/instances/sync/action_chains/scroll.py +43 -0
- osn_selenium/instances/sync/action_chains/utils.py +30 -0
- osn_selenium/instances/sync/alert.py +69 -0
- osn_selenium/instances/sync/browser.py +72 -0
- osn_selenium/instances/sync/browsing_context.py +193 -0
- osn_selenium/instances/sync/dialog.py +81 -0
- osn_selenium/instances/sync/fedcm.py +92 -0
- osn_selenium/instances/sync/mobile.py +75 -0
- osn_selenium/instances/sync/network.py +90 -0
- osn_selenium/instances/sync/permissions.py +80 -0
- osn_selenium/instances/sync/script.py +77 -0
- osn_selenium/instances/sync/shadow_root.py +91 -0
- osn_selenium/instances/sync/storage.py +91 -0
- osn_selenium/instances/sync/switch_to.py +92 -0
- osn_selenium/instances/sync/web_driver_wait.py +83 -0
- osn_selenium/instances/sync/web_element.py +179 -0
- osn_selenium/instances/sync/web_extension.py +77 -0
- osn_selenium/instances/trio_threads/__init__.py +1 -0
- osn_selenium/instances/trio_threads/action_chains/__init__.py +26 -0
- osn_selenium/instances/trio_threads/action_chains/base.py +88 -0
- osn_selenium/instances/trio_threads/action_chains/click.py +71 -0
- osn_selenium/instances/trio_threads/action_chains/drag_and_drop.py +49 -0
- osn_selenium/instances/trio_threads/action_chains/hm_keyboard.py +41 -0
- osn_selenium/instances/trio_threads/action_chains/hm_move.py +91 -0
- osn_selenium/instances/trio_threads/action_chains/hm_scroll.py +66 -0
- osn_selenium/instances/trio_threads/action_chains/keyboard.py +63 -0
- osn_selenium/instances/trio_threads/action_chains/move.py +52 -0
- osn_selenium/instances/trio_threads/action_chains/scroll.py +49 -0
- osn_selenium/instances/trio_threads/action_chains/utils.py +32 -0
- osn_selenium/instances/trio_threads/alert.py +87 -0
- osn_selenium/instances/trio_threads/browser.py +90 -0
- osn_selenium/instances/trio_threads/browsing_context.py +216 -0
- osn_selenium/instances/trio_threads/dialog.py +99 -0
- osn_selenium/instances/trio_threads/fedcm.py +110 -0
- osn_selenium/instances/trio_threads/mobile.py +93 -0
- osn_selenium/instances/trio_threads/network.py +108 -0
- osn_selenium/instances/trio_threads/permissions.py +102 -0
- osn_selenium/instances/trio_threads/script.py +95 -0
- osn_selenium/instances/trio_threads/shadow_root.py +123 -0
- osn_selenium/instances/trio_threads/storage.py +109 -0
- osn_selenium/instances/trio_threads/switch_to.py +124 -0
- osn_selenium/instances/trio_threads/web_driver_wait.py +101 -0
- osn_selenium/instances/trio_threads/web_element.py +217 -0
- osn_selenium/instances/trio_threads/web_extension.py +99 -0
- osn_selenium/instances/unified/__init__.py +1 -0
- osn_selenium/instances/unified/action_chains/__init__.py +22 -0
- osn_selenium/instances/unified/action_chains/base.py +31 -0
- osn_selenium/instances/unified/action_chains/click.py +27 -0
- osn_selenium/instances/unified/action_chains/drag_and_drop.py +24 -0
- osn_selenium/instances/unified/action_chains/hm_keyboard.py +30 -0
- osn_selenium/instances/unified/action_chains/hm_move.py +66 -0
- osn_selenium/instances/unified/action_chains/hm_scroll.py +79 -0
- osn_selenium/instances/unified/action_chains/keyboard.py +24 -0
- osn_selenium/instances/unified/action_chains/move.py +24 -0
- osn_selenium/instances/unified/action_chains/scroll.py +21 -0
- osn_selenium/instances/unified/action_chains/utils.py +19 -0
- osn_selenium/instances/unified/alert.py +29 -0
- osn_selenium/instances/unified/browser.py +33 -0
- osn_selenium/instances/unified/browsing_context.py +151 -0
- osn_selenium/instances/unified/dialog.py +42 -0
- osn_selenium/instances/unified/fedcm.py +48 -0
- osn_selenium/instances/unified/mobile.py +36 -0
- osn_selenium/instances/unified/network.py +50 -0
- osn_selenium/instances/unified/permissions.py +43 -0
- osn_selenium/instances/unified/script.py +38 -0
- osn_selenium/instances/unified/shadow_root.py +46 -0
- osn_selenium/instances/unified/storage.py +48 -0
- osn_selenium/instances/unified/switch_to.py +49 -0
- osn_selenium/instances/unified/web_driver_wait.py +45 -0
- osn_selenium/instances/unified/web_element.py +145 -0
- osn_selenium/instances/unified/web_extension.py +38 -0
- osn_selenium/javascript/__init__.py +1 -0
- osn_selenium/javascript/_functions.py +63 -0
- osn_selenium/javascript/fingerprint/__init__.py +120 -0
- osn_selenium/javascript/fingerprint/_decorators.py +41 -0
- osn_selenium/javascript/fingerprint/_detect/__init__.py +1 -0
- osn_selenium/javascript/fingerprint/_detect/functions.py +253 -0
- osn_selenium/javascript/fingerprint/_detect/templates.py +128 -0
- osn_selenium/javascript/fingerprint/_functions.py +35 -0
- osn_selenium/javascript/fingerprint/_typehints.py +27 -0
- osn_selenium/javascript/fingerprint/registry/__init__.py +7 -0
- osn_selenium/javascript/fingerprint/registry/_core_functions.py +236 -0
- osn_selenium/javascript/fingerprint/registry/_functions.py +923 -0
- osn_selenium/javascript/fingerprint/registry/_typehints.py +6 -0
- osn_selenium/javascript/fingerprint/registry/_utils.py +6 -0
- osn_selenium/javascript/fingerprint/registry/models.py +41 -0
- osn_selenium/javascript/fingerprint/spoof/__init__.py +1 -0
- osn_selenium/javascript/fingerprint/spoof/_functions.py +172 -0
- osn_selenium/javascript/fingerprint/spoof/_templates.py +134 -0
- osn_selenium/javascript/fingerprint/spoof/_typehints.py +22 -0
- osn_selenium/javascript/fingerprint/spoof/core_rules.py +141 -0
- osn_selenium/javascript/fingerprint/spoof/noise.py +51 -0
- osn_selenium/javascript/fingerprint/spoof/rules.py +313 -0
- osn_selenium/javascript/functions.py +44 -0
- osn_selenium/javascript/models.py +35 -0
- osn_selenium/javascript/scripts/start_fingerprint_detection.js +56 -0
- osn_selenium/models.py +139 -0
- osn_selenium/webdrivers/_args_helpers.py +181 -0
- osn_selenium/webdrivers/_bridges.py +57 -0
- osn_selenium/webdrivers/_decorators.py +83 -0
- osn_selenium/webdrivers/_executable_tables/__init__.py +1 -0
- osn_selenium/webdrivers/_executable_tables/functions.py +113 -0
- osn_selenium/webdrivers/_executable_tables/models.py +19 -0
- osn_selenium/webdrivers/_typehints.py +10 -0
- osn_selenium/webdrivers/protocols.py +50 -0
- osn_selenium/webdrivers/sync/__init__.py +1 -0
- osn_selenium/webdrivers/sync/blink/__init__.py +114 -0
- osn_selenium/webdrivers/sync/blink/base.py +128 -0
- osn_selenium/webdrivers/sync/blink/casting.py +34 -0
- osn_selenium/webdrivers/sync/blink/features.py +28 -0
- osn_selenium/webdrivers/sync/blink/lifecycle.py +66 -0
- osn_selenium/webdrivers/sync/blink/logging.py +25 -0
- osn_selenium/webdrivers/sync/blink/network.py +28 -0
- osn_selenium/webdrivers/sync/blink/settings.py +63 -0
- osn_selenium/webdrivers/sync/chrome/__init__.py +67 -0
- osn_selenium/webdrivers/sync/chrome/base.py +106 -0
- osn_selenium/webdrivers/sync/chrome/lifecycle.py +63 -0
- osn_selenium/webdrivers/sync/chrome/settings.py +58 -0
- osn_selenium/webdrivers/sync/core/__init__.py +91 -0
- osn_selenium/webdrivers/sync/core/actions.py +59 -0
- osn_selenium/webdrivers/sync/core/auth.py +77 -0
- osn_selenium/webdrivers/sync/core/base.py +167 -0
- osn_selenium/webdrivers/sync/core/capture.py +37 -0
- osn_selenium/webdrivers/sync/core/comonents.py +57 -0
- osn_selenium/webdrivers/sync/core/devtools.py +47 -0
- osn_selenium/webdrivers/sync/core/element.py +42 -0
- osn_selenium/webdrivers/sync/core/file.py +40 -0
- osn_selenium/webdrivers/sync/core/lifecycle.py +59 -0
- osn_selenium/webdrivers/sync/core/navigation.py +36 -0
- osn_selenium/webdrivers/sync/core/script.py +53 -0
- osn_selenium/webdrivers/sync/core/settings.py +35 -0
- osn_selenium/webdrivers/sync/core/storage.py +48 -0
- osn_selenium/webdrivers/sync/core/timeouts.py +59 -0
- osn_selenium/webdrivers/sync/core/window.py +99 -0
- osn_selenium/webdrivers/sync/edge/__init__.py +67 -0
- osn_selenium/webdrivers/sync/edge/base.py +102 -0
- osn_selenium/webdrivers/sync/edge/lifecycle.py +63 -0
- osn_selenium/webdrivers/sync/edge/settings.py +58 -0
- osn_selenium/webdrivers/sync/yandex/__init__.py +67 -0
- osn_selenium/webdrivers/sync/yandex/base.py +99 -0
- osn_selenium/webdrivers/sync/yandex/lifecycle.py +63 -0
- osn_selenium/webdrivers/sync/yandex/settings.py +58 -0
- osn_selenium/webdrivers/trio_threads/__init__.py +1 -0
- osn_selenium/webdrivers/trio_threads/blink/__init__.py +124 -0
- osn_selenium/webdrivers/trio_threads/blink/base.py +133 -0
- osn_selenium/webdrivers/trio_threads/blink/casting.py +35 -0
- osn_selenium/webdrivers/trio_threads/blink/features.py +29 -0
- osn_selenium/webdrivers/trio_threads/blink/lifecycle.py +66 -0
- osn_selenium/webdrivers/trio_threads/blink/logging.py +26 -0
- osn_selenium/webdrivers/trio_threads/blink/network.py +29 -0
- osn_selenium/webdrivers/trio_threads/blink/settings.py +63 -0
- osn_selenium/webdrivers/trio_threads/chrome/__init__.py +81 -0
- osn_selenium/webdrivers/trio_threads/chrome/base.py +107 -0
- osn_selenium/webdrivers/trio_threads/chrome/lifecycle.py +63 -0
- osn_selenium/webdrivers/trio_threads/chrome/settings.py +63 -0
- osn_selenium/webdrivers/trio_threads/core/__init__.py +109 -0
- osn_selenium/webdrivers/trio_threads/core/actions.py +72 -0
- osn_selenium/webdrivers/trio_threads/core/auth.py +88 -0
- osn_selenium/webdrivers/trio_threads/core/base.py +191 -0
- osn_selenium/webdrivers/trio_threads/core/capture.py +38 -0
- osn_selenium/webdrivers/trio_threads/core/comonents.py +92 -0
- osn_selenium/webdrivers/trio_threads/core/devtools.py +53 -0
- osn_selenium/webdrivers/trio_threads/core/element.py +58 -0
- osn_selenium/webdrivers/trio_threads/core/file.py +45 -0
- osn_selenium/webdrivers/trio_threads/core/lifecycle.py +60 -0
- osn_selenium/webdrivers/trio_threads/core/navigation.py +41 -0
- osn_selenium/webdrivers/trio_threads/core/script.py +59 -0
- osn_selenium/webdrivers/trio_threads/core/settings.py +36 -0
- osn_selenium/webdrivers/trio_threads/core/storage.py +54 -0
- osn_selenium/webdrivers/trio_threads/core/timeouts.py +60 -0
- osn_selenium/webdrivers/trio_threads/core/window.py +105 -0
- osn_selenium/webdrivers/trio_threads/edge/__init__.py +81 -0
- osn_selenium/webdrivers/trio_threads/edge/base.py +103 -0
- osn_selenium/webdrivers/trio_threads/edge/lifecycle.py +63 -0
- osn_selenium/webdrivers/trio_threads/edge/settings.py +63 -0
- osn_selenium/webdrivers/trio_threads/yandex/__init__.py +81 -0
- osn_selenium/webdrivers/trio_threads/yandex/base.py +100 -0
- osn_selenium/webdrivers/trio_threads/yandex/lifecycle.py +63 -0
- osn_selenium/webdrivers/trio_threads/yandex/settings.py +63 -0
- osn_selenium/webdrivers/unified/__init__.py +1 -0
- osn_selenium/webdrivers/unified/blink/__init__.py +1 -0
- osn_selenium/webdrivers/unified/blink/base.py +131 -0
- osn_selenium/webdrivers/unified/blink/casting.py +30 -0
- osn_selenium/webdrivers/unified/blink/features.py +22 -0
- osn_selenium/webdrivers/unified/blink/lifecycle.py +114 -0
- osn_selenium/webdrivers/unified/blink/logging.py +18 -0
- osn_selenium/webdrivers/unified/blink/network.py +22 -0
- osn_selenium/webdrivers/unified/blink/settings.py +86 -0
- osn_selenium/webdrivers/unified/chrome/__init__.py +1 -0
- osn_selenium/webdrivers/unified/chrome/base.py +54 -0
- osn_selenium/webdrivers/unified/chrome/lifecycle.py +88 -0
- osn_selenium/webdrivers/unified/chrome/settings.py +48 -0
- osn_selenium/webdrivers/unified/core/__init__.py +1 -0
- osn_selenium/webdrivers/unified/core/actions.py +43 -0
- osn_selenium/webdrivers/unified/core/auth.py +70 -0
- osn_selenium/webdrivers/unified/core/base.py +132 -0
- osn_selenium/webdrivers/unified/core/capture.py +32 -0
- osn_selenium/webdrivers/unified/core/components.py +32 -0
- osn_selenium/webdrivers/unified/core/devtools.py +35 -0
- osn_selenium/webdrivers/unified/core/element.py +24 -0
- osn_selenium/webdrivers/unified/core/file.py +35 -0
- osn_selenium/webdrivers/unified/core/lifecycle.py +84 -0
- osn_selenium/webdrivers/unified/core/navigation.py +31 -0
- osn_selenium/webdrivers/unified/core/script.py +32 -0
- osn_selenium/webdrivers/unified/core/settings.py +44 -0
- osn_selenium/webdrivers/unified/core/storage.py +37 -0
- osn_selenium/webdrivers/unified/core/timeouts.py +56 -0
- osn_selenium/webdrivers/unified/core/window.py +135 -0
- osn_selenium/webdrivers/unified/edge/__init__.py +1 -0
- osn_selenium/webdrivers/unified/edge/base.py +52 -0
- osn_selenium/webdrivers/unified/edge/lifecycle.py +88 -0
- osn_selenium/webdrivers/unified/edge/settings.py +48 -0
- osn_selenium/webdrivers/unified/yandex/__init__.py +1 -0
- osn_selenium/webdrivers/unified/yandex/base.py +54 -0
- osn_selenium/webdrivers/unified/yandex/lifecycle.py +58 -0
- osn_selenium/webdrivers/unified/yandex/settings.py +48 -0
- osn_selenium-1.0.0.dist-info/METADATA +239 -0
- osn_selenium-1.0.0.dist-info/RECORD +608 -0
- {osn_selenium-0.0.0.dist-info → osn_selenium-1.0.0.dist-info}/WHEEL +1 -1
- osn_selenium/captcha_workers/__init__.py +0 -26
- osn_selenium/dev_tools/_types.py +0 -22
- osn_selenium/dev_tools/errors.py +0 -89
- osn_selenium/dev_tools/logger.py +0 -558
- osn_selenium/dev_tools/manager.py +0 -1551
- osn_selenium/dev_tools/utils.py +0 -509
- osn_selenium/errors.py +0 -16
- osn_selenium/types.py +0 -118
- osn_selenium/webdrivers/BaseDriver/_utils.py +0 -37
- osn_selenium/webdrivers/BaseDriver/protocols.py +0 -2135
- osn_selenium/webdrivers/BaseDriver/trio_wrapper.py +0 -71
- osn_selenium/webdrivers/BaseDriver/webdriver.py +0 -2626
- osn_selenium/webdrivers/Blink/protocols.py +0 -330
- osn_selenium/webdrivers/Blink/webdriver.py +0 -637
- osn_selenium/webdrivers/Chrome/protocols.py +0 -228
- osn_selenium/webdrivers/Chrome/webdriver.py +0 -394
- osn_selenium/webdrivers/Edge/protocols.py +0 -228
- osn_selenium/webdrivers/Edge/webdriver.py +0 -394
- osn_selenium/webdrivers/Yandex/protocols.py +0 -211
- osn_selenium/webdrivers/Yandex/webdriver.py +0 -350
- osn_selenium/webdrivers/_functions.py +0 -504
- osn_selenium/webdrivers/types.py +0 -390
- osn_selenium-0.0.0.dist-info/METADATA +0 -710
- osn_selenium-0.0.0.dist-info/RECORD +0 -57
- /osn_selenium/{webdrivers/BaseDriver → abstract}/__init__.py +0 -0
- /osn_selenium/{webdrivers/Blink → abstract/executors}/__init__.py +0 -0
- /osn_selenium/{webdrivers/Chrome → abstract/instances}/__init__.py +0 -0
- /osn_selenium/{webdrivers/Edge → abstract/webdriver}/__init__.py +0 -0
- /osn_selenium/{webdrivers/Yandex → dev_tools/logger}/__init__.py +0 -0
- /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/check_element_in_viewport.js +0 -0
- /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/get_document_scroll_size.js +0 -0
- /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/get_element_css.js +0 -0
- /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/get_element_rect_in_viewport.js +0 -0
- /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/get_random_element_point_in_viewport.js +0 -0
- /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/get_viewport_position.js +0 -0
- /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/get_viewport_rect.js +0 -0
- /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/get_viewport_size.js +0 -0
- /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/open_new_tab.js +0 -0
- /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/stop_window_loading.js +0 -0
- {osn_selenium-0.0.0.dist-info → osn_selenium-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -1,2626 +0,0 @@
|
|
|
1
|
-
import trio
|
|
2
|
-
import pathlib
|
|
3
|
-
import warnings
|
|
4
|
-
from random import random
|
|
5
|
-
from selenium import webdriver
|
|
6
|
-
from selenium.webdriver import ActionChains
|
|
7
|
-
from selenium.webdriver.remote.fedcm import FedCM
|
|
8
|
-
from selenium.webdriver.common.fedcm.dialog import Dialog
|
|
9
|
-
from selenium.webdriver.remote.webelement import WebElement
|
|
10
|
-
from selenium.webdriver.common.actions.key_input import KeyInput
|
|
11
|
-
from osn_selenium.captcha_workers import (
|
|
12
|
-
CaptchaWorkerSettings
|
|
13
|
-
)
|
|
14
|
-
from selenium.webdriver.common.print_page_options import PrintOptions
|
|
15
|
-
from osn_selenium.webdrivers.BaseDriver._utils import build_cdp_kwargs
|
|
16
|
-
from selenium.webdriver.common.actions.pointer_input import PointerInput
|
|
17
|
-
from selenium.webdriver.remote.remote_connection import RemoteConnection
|
|
18
|
-
from osn_selenium.dev_tools.manager import (
|
|
19
|
-
DevTools,
|
|
20
|
-
DevToolsSettings
|
|
21
|
-
)
|
|
22
|
-
from osn_selenium.types import (
|
|
23
|
-
Position,
|
|
24
|
-
Rectangle,
|
|
25
|
-
Size,
|
|
26
|
-
WindowRect
|
|
27
|
-
)
|
|
28
|
-
from osn_selenium.webdrivers.types import (
|
|
29
|
-
ActionPoint,
|
|
30
|
-
_any_flags_mapping
|
|
31
|
-
)
|
|
32
|
-
from typing import (
|
|
33
|
-
Any,
|
|
34
|
-
Literal,
|
|
35
|
-
Optional,
|
|
36
|
-
TYPE_CHECKING,
|
|
37
|
-
Type,
|
|
38
|
-
Union,
|
|
39
|
-
cast
|
|
40
|
-
)
|
|
41
|
-
from selenium.webdriver.common.actions.wheel_input import (
|
|
42
|
-
ScrollOrigin,
|
|
43
|
-
WheelInput
|
|
44
|
-
)
|
|
45
|
-
from osn_selenium.webdrivers.BaseDriver.protocols import (
|
|
46
|
-
TrioWebDriverWrapperProtocol
|
|
47
|
-
)
|
|
48
|
-
from osn_selenium.webdrivers.BaseDriver.trio_wrapper import (
|
|
49
|
-
TrioBrowserWebDriverWrapper
|
|
50
|
-
)
|
|
51
|
-
from osn_selenium.webdrivers.BaseDriver.flags import (
|
|
52
|
-
BrowserFlags,
|
|
53
|
-
BrowserFlagsManager
|
|
54
|
-
)
|
|
55
|
-
from selenium.webdriver.common.virtual_authenticator import (
|
|
56
|
-
Credential,
|
|
57
|
-
VirtualAuthenticatorOptions
|
|
58
|
-
)
|
|
59
|
-
from osn_selenium.webdrivers._functions import (
|
|
60
|
-
move_to_parts,
|
|
61
|
-
read_js_scripts,
|
|
62
|
-
scroll_to_parts,
|
|
63
|
-
text_input_to_parts
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if TYPE_CHECKING:
|
|
68
|
-
from osn_selenium.webdrivers.Blink.flags import BlinkFlagsManager
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
class BrowserWebDriver:
|
|
72
|
-
"""
|
|
73
|
-
A base class for managing a Selenium WebDriver instance and browser interactions.
|
|
74
|
-
|
|
75
|
-
This class provides common functionalities for controlling a web browser using Selenium,
|
|
76
|
-
including action chains, JavaScript execution, element interactions, window management,
|
|
77
|
-
and integration with Trio for asynchronous operations. It serves as a foundation
|
|
78
|
-
for browser-specific WebDriver implementations.
|
|
79
|
-
|
|
80
|
-
Attributes:
|
|
81
|
-
_window_rect (Optional[WindowRect]): The desired window size and position settings.
|
|
82
|
-
_js_scripts (dict[str, str]): A dictionary of pre-loaded JavaScript snippets for common tasks.
|
|
83
|
-
_webdriver_path (str): The file path to the WebDriver executable (e.g., chromedriver.exe).
|
|
84
|
-
_webdriver_flags_manager (Union[BrowserFlagsManager, BlinkFlagsManager]): An object
|
|
85
|
-
responsible for managing browser-specific flags and options.
|
|
86
|
-
_driver (Optional[Union[webdriver.Chrome, webdriver.Edge, webdriver.Firefox]]): The active
|
|
87
|
-
Selenium WebDriver instance. This will be None until `start_webdriver` is called.
|
|
88
|
-
_base_implicitly_wait (int): The default implicit wait time in seconds for element searches.
|
|
89
|
-
_base_page_load_timeout (int): The default page load timeout in seconds.
|
|
90
|
-
_base_script_timeout (int): The default script timeout in seconds.
|
|
91
|
-
_captcha_workers (Sequence[CaptchaWorkerSettings]): A list of configured captcha worker settings.
|
|
92
|
-
_is_active (bool): A flag indicating if the WebDriver instance is currently active and connected.
|
|
93
|
-
trio_capacity_limiter (trio.CapacityLimiter): A Trio capacity limiter used to control the
|
|
94
|
-
concurrency of synchronous WebDriver operations when called from an async context.
|
|
95
|
-
dev_tools (DevTools): An interface for interacting with the browser's DevTools protocol.
|
|
96
|
-
"""
|
|
97
|
-
|
|
98
|
-
def __init__(
|
|
99
|
-
self,
|
|
100
|
-
webdriver_path: str,
|
|
101
|
-
flags_manager_type: Type[BrowserFlagsManager] = BrowserFlagsManager,
|
|
102
|
-
flags: Optional[Union[BrowserFlags, _any_flags_mapping]] = None,
|
|
103
|
-
implicitly_wait: int = 5,
|
|
104
|
-
page_load_timeout: int = 5,
|
|
105
|
-
script_timeout: int = 5,
|
|
106
|
-
window_rect: Optional[WindowRect] = None,
|
|
107
|
-
trio_tokens_limit: Union[int, float] = 40,
|
|
108
|
-
captcha_workers: Optional[list[CaptchaWorkerSettings]] = None,
|
|
109
|
-
devtools_settings: Optional[DevToolsSettings] = None,
|
|
110
|
-
):
|
|
111
|
-
"""
|
|
112
|
-
Initializes the BrowserWebDriver instance.
|
|
113
|
-
|
|
114
|
-
Args:
|
|
115
|
-
webdriver_path (str): The file path to the WebDriver executable.
|
|
116
|
-
flags_manager_type (Type[BrowserFlagsManager]): The type of
|
|
117
|
-
flags manager to use (e.g., `BrowserFlagsManager` or `BlinkFlagsManager`).
|
|
118
|
-
Defaults to `BrowserFlagsManager`.
|
|
119
|
-
flags (Optional[Union[BrowserFlags, _any_flags_mapping]]): Initial browser flags/options
|
|
120
|
-
to apply. Can be a `BrowserFlags` object or a Mapping. Defaults to None.
|
|
121
|
-
implicitly_wait (int): The default implicit wait time in seconds for element searches.
|
|
122
|
-
Defaults to 5.
|
|
123
|
-
page_load_timeout (int): The default page load timeout in seconds. Defaults to 5.
|
|
124
|
-
script_timeout (int): The default asynchronous script timeout in seconds. Defaults to 5.
|
|
125
|
-
window_rect (Optional[WindowRect]): The initial window size and position. If None,
|
|
126
|
-
the browser's default window size will be used. Defaults to None.
|
|
127
|
-
trio_tokens_limit (Union[int, float]): The maximum number of concurrent synchronous
|
|
128
|
-
WebDriver operations allowed when using the Trio wrapper. Defaults to 40.
|
|
129
|
-
captcha_workers (Optional[Sequence[CaptchaWorkerSettings]]): A list of dictionaries,
|
|
130
|
-
each defining a captcha worker with a name, check function, and solve function.
|
|
131
|
-
Defaults to an empty list.
|
|
132
|
-
devtools_settings (Optional[DevToolsSettings]): Settings for the DevTools integration.
|
|
133
|
-
Defaults to None.
|
|
134
|
-
"""
|
|
135
|
-
|
|
136
|
-
self._window_rect = window_rect
|
|
137
|
-
self._js_scripts = read_js_scripts()
|
|
138
|
-
self._webdriver_path = webdriver_path
|
|
139
|
-
self._webdriver_flags_manager: Union[BrowserFlagsManager, "BlinkFlagsManager"] = flags_manager_type()
|
|
140
|
-
self._driver: Optional[Union[webdriver.Chrome, webdriver.Edge, webdriver.Firefox]] = None
|
|
141
|
-
self._base_implicitly_wait = implicitly_wait
|
|
142
|
-
self._base_page_load_timeout = page_load_timeout
|
|
143
|
-
self._base_script_timeout = script_timeout
|
|
144
|
-
|
|
145
|
-
self._captcha_workers = captcha_workers if captcha_workers is not None else []
|
|
146
|
-
|
|
147
|
-
self._is_active = False
|
|
148
|
-
self.trio_capacity_limiter = trio.CapacityLimiter(trio_tokens_limit)
|
|
149
|
-
|
|
150
|
-
self.dev_tools = DevTools(self, devtools_settings)
|
|
151
|
-
|
|
152
|
-
self.update_settings(flags=flags)
|
|
153
|
-
|
|
154
|
-
def add_captcha_worker(self, captcha_worker: CaptchaWorkerSettings):
|
|
155
|
-
"""
|
|
156
|
-
Adds a new captcha worker to the list of active captcha workers.
|
|
157
|
-
|
|
158
|
-
Args:
|
|
159
|
-
captcha_worker (CaptchaWorkerSettings): A dictionary containing the name,
|
|
160
|
-
check function, and solve function for the captcha worker.
|
|
161
|
-
"""
|
|
162
|
-
|
|
163
|
-
self._captcha_workers.append(captcha_worker)
|
|
164
|
-
|
|
165
|
-
def add_cookie(self, cookie_dict: dict[str, Any]):
|
|
166
|
-
"""
|
|
167
|
-
Adds a single cookie to the current browser session.
|
|
168
|
-
|
|
169
|
-
Args:
|
|
170
|
-
cookie_dict (dict[str, Any]): A dictionary representing the cookie to add.
|
|
171
|
-
"""
|
|
172
|
-
|
|
173
|
-
return self._driver.add_cookie(cookie_dict=cookie_dict)
|
|
174
|
-
|
|
175
|
-
def add_credential(self, credential: Credential):
|
|
176
|
-
"""
|
|
177
|
-
Adds a WebAuthn credential to the browser's virtual authenticator.
|
|
178
|
-
|
|
179
|
-
Args:
|
|
180
|
-
credential (Credential): The `Credential` object representing the WebAuthn credential.
|
|
181
|
-
"""
|
|
182
|
-
|
|
183
|
-
self._driver.add_credential(credential=credential)
|
|
184
|
-
|
|
185
|
-
def add_virtual_authenticator(self, options: VirtualAuthenticatorOptions):
|
|
186
|
-
"""
|
|
187
|
-
Adds a virtual authenticator to the browser for WebAuthn testing.
|
|
188
|
-
|
|
189
|
-
Args:
|
|
190
|
-
options (VirtualAuthenticatorOptions): The `VirtualAuthenticatorOptions` object
|
|
191
|
-
specifying the properties of the virtual authenticator.
|
|
192
|
-
"""
|
|
193
|
-
|
|
194
|
-
self._driver.add_virtual_authenticator(options=options)
|
|
195
|
-
|
|
196
|
-
def build_action_chains(
|
|
197
|
-
self,
|
|
198
|
-
duration: int = 250,
|
|
199
|
-
devices: Optional[list[Union[PointerInput, KeyInput, WheelInput]]] = None
|
|
200
|
-
) -> ActionChains:
|
|
201
|
-
"""
|
|
202
|
-
Builds and returns a new Selenium ActionChains instance.
|
|
203
|
-
|
|
204
|
-
Initializes an ActionChains object associated with the current WebDriver instance (`self.driver`).
|
|
205
|
-
Allows specifying the default pause duration between actions and custom input device sources.
|
|
206
|
-
|
|
207
|
-
Args:
|
|
208
|
-
duration (int): The default duration in milliseconds to pause between actions
|
|
209
|
-
within the chain. Defaults to 250.
|
|
210
|
-
devices (Optional[list[Union[PointerInput, KeyInput, WheelInput]]]): A list of
|
|
211
|
-
specific input device sources (Pointer, Key, Wheel) to use for the actions.
|
|
212
|
-
If None, default devices are used. Defaults to None.
|
|
213
|
-
|
|
214
|
-
Returns:
|
|
215
|
-
ActionChains: A new ActionChains instance configured with the specified driver,
|
|
216
|
-
duration, and devices.
|
|
217
|
-
"""
|
|
218
|
-
|
|
219
|
-
return ActionChains(driver=self._driver, duration=duration, devices=devices)
|
|
220
|
-
|
|
221
|
-
def build_hm_move_action(
|
|
222
|
-
self,
|
|
223
|
-
start_position: ActionPoint,
|
|
224
|
-
end_position: ActionPoint,
|
|
225
|
-
parent_action: Optional[ActionChains] = None,
|
|
226
|
-
duration: int = 250,
|
|
227
|
-
devices: Optional[list[Union[PointerInput, KeyInput, WheelInput]]] = None
|
|
228
|
-
) -> ActionChains:
|
|
229
|
-
"""
|
|
230
|
-
Builds a human-like mouse move action sequence between two points.
|
|
231
|
-
|
|
232
|
-
Simulates a more natural mouse movement by breaking the path into smaller segments with pauses,
|
|
233
|
-
calculated by the external `move_to_parts` function. Adds the corresponding move-by-offset
|
|
234
|
-
actions and pauses to an ActionChains sequence. Assumes the starting point of the cursor
|
|
235
|
-
is implicitly handled or should be set prior to performing this chain.
|
|
236
|
-
|
|
237
|
-
Args:
|
|
238
|
-
start_position (ActionPoint): The starting coordinates (absolute or relative, depends on `move_to_parts` logic).
|
|
239
|
-
end_position (ActionPoint): The target coordinates for the mouse cursor.
|
|
240
|
-
parent_action (Optional[ActionChains]): An existing ActionChains instance to append actions to.
|
|
241
|
-
If None, a new chain is created. Defaults to None.
|
|
242
|
-
duration (int): The base duration (in milliseconds) used when creating a new ActionChains
|
|
243
|
-
instance if `parent_action` is None. Total move time depends on `move_to_parts`. Defaults to 250.
|
|
244
|
-
devices (Optional[list[Union[PointerInput, KeyInput, WheelInput]]]): Specific input devices
|
|
245
|
-
if creating a new ActionChains instance. Defaults to None.
|
|
246
|
-
|
|
247
|
-
Returns:
|
|
248
|
-
ActionChains: The ActionChains instance (new or parent) with the human-like move sequence added.
|
|
249
|
-
Needs to be finalized with `.perform()`.
|
|
250
|
-
"""
|
|
251
|
-
|
|
252
|
-
if parent_action is None:
|
|
253
|
-
action = self.build_action_chains(duration=duration, devices=devices)
|
|
254
|
-
else:
|
|
255
|
-
action = parent_action
|
|
256
|
-
|
|
257
|
-
move_parts = move_to_parts(start_position=start_position, end_position=end_position)
|
|
258
|
-
|
|
259
|
-
for part in move_parts:
|
|
260
|
-
action.pause(part.duration * 0.001)
|
|
261
|
-
action.move_by_offset(xoffset=part.offset.x, yoffset=part.offset.y)
|
|
262
|
-
|
|
263
|
-
return action
|
|
264
|
-
|
|
265
|
-
def execute_js_script(self, script: str, *args) -> Any:
|
|
266
|
-
"""
|
|
267
|
-
Executes a JavaScript script in the current browser context.
|
|
268
|
-
|
|
269
|
-
Executes arbitrary JavaScript code within the currently loaded webpage. This allows for
|
|
270
|
-
performing actions that are not directly supported by WebDriver commands, such as complex
|
|
271
|
-
DOM manipulations or accessing browser APIs.
|
|
272
|
-
|
|
273
|
-
Args:
|
|
274
|
-
script (str): The JavaScript code to execute as a string.
|
|
275
|
-
*args: Arguments to pass to the JavaScript script. These are accessible in the script as `arguments[0]`, `arguments[1]`, etc.
|
|
276
|
-
|
|
277
|
-
Returns:
|
|
278
|
-
Any: The result of the JavaScript execution. JavaScript return values are converted to Python types.
|
|
279
|
-
For example, JavaScript objects become Python dictionaries, arrays become lists, and primitives are converted directly.
|
|
280
|
-
"""
|
|
281
|
-
|
|
282
|
-
return self._driver.execute_script(script, *args)
|
|
283
|
-
|
|
284
|
-
def get_element_rect_in_viewport(self, element: WebElement) -> Rectangle:
|
|
285
|
-
"""
|
|
286
|
-
Gets the position and dimensions of an element relative to the viewport.
|
|
287
|
-
|
|
288
|
-
Executes a predefined JavaScript snippet that calculates the element's bounding rectangle
|
|
289
|
-
as seen in the current viewport.
|
|
290
|
-
|
|
291
|
-
Args:
|
|
292
|
-
element (WebElement): The Selenium WebElement whose rectangle is needed.
|
|
293
|
-
|
|
294
|
-
Returns:
|
|
295
|
-
Rectangle: A TypedDict containing the 'x', 'y', 'width', and 'height' of the element
|
|
296
|
-
relative to the viewport's top-left corner. 'x' and 'y' can be negative
|
|
297
|
-
if the element is partially scrolled out of view to the top or left.
|
|
298
|
-
"""
|
|
299
|
-
|
|
300
|
-
rect = self.execute_js_script(self._js_scripts["get_element_rect_in_viewport"], element)
|
|
301
|
-
|
|
302
|
-
return Rectangle(
|
|
303
|
-
x=int(rect["x"]),
|
|
304
|
-
y=int(rect["y"]),
|
|
305
|
-
width=int(rect["width"]),
|
|
306
|
-
height=int(rect["height"])
|
|
307
|
-
)
|
|
308
|
-
|
|
309
|
-
def get_random_element_point_in_viewport(self, element: WebElement, step: int = 1) -> Optional[Position]:
|
|
310
|
-
"""
|
|
311
|
-
Calculates a random point within the visible portion of a given element in the viewport.
|
|
312
|
-
|
|
313
|
-
Executes a predefined JavaScript snippet that determines the element's bounding box
|
|
314
|
-
relative to the viewport, calculates the intersection of this box with the viewport,
|
|
315
|
-
and then selects a random point within that intersection, potentially aligned to a grid defined by `step`.
|
|
316
|
-
|
|
317
|
-
Args:
|
|
318
|
-
element (WebElement): The Selenium WebElement to find a random point within.
|
|
319
|
-
step (int): Defines the grid step for selecting the random point. The coordinates
|
|
320
|
-
will be multiples of this step within the valid range. Defaults to 1 (any pixel).
|
|
321
|
-
|
|
322
|
-
Returns:
|
|
323
|
-
Position: A TypedDict containing the integer 'x' and 'y' coordinates of a random point
|
|
324
|
-
within the element's visible area in the viewport. Coordinates are relative
|
|
325
|
-
to the element's top-left corner (0,0).
|
|
326
|
-
"""
|
|
327
|
-
|
|
328
|
-
position = self.execute_js_script(self._js_scripts["get_random_element_point_in_viewport"], element, step)
|
|
329
|
-
|
|
330
|
-
if position is not None:
|
|
331
|
-
return Position(x=int(position["x"]), y=int(position["y"]))
|
|
332
|
-
|
|
333
|
-
return None
|
|
334
|
-
|
|
335
|
-
def get_random_element_point(self, element: WebElement) -> ActionPoint:
|
|
336
|
-
"""
|
|
337
|
-
Gets the coordinates of a random point within an element, relative to the viewport origin.
|
|
338
|
-
|
|
339
|
-
Calculates a random point within the visible portion of the element relative to the
|
|
340
|
-
element's own top-left corner. It then adds the element's top-left coordinates
|
|
341
|
-
(relative to the viewport) to get the final coordinates of the random point,
|
|
342
|
-
also relative to the viewport's top-left origin (0,0).
|
|
343
|
-
|
|
344
|
-
Args:
|
|
345
|
-
element (WebElement): The target element within which to find a random point.
|
|
346
|
-
|
|
347
|
-
Returns:
|
|
348
|
-
ActionPoint: An ActionPoint named tuple containing the 'x' and 'y' coordinates
|
|
349
|
-
of the random point within the element, relative to the viewport origin.
|
|
350
|
-
"""
|
|
351
|
-
|
|
352
|
-
point_in_viewport = self.get_random_element_point_in_viewport(element=element, step=1)
|
|
353
|
-
element_viewport_pos = self.get_element_rect_in_viewport(element=element)
|
|
354
|
-
|
|
355
|
-
x = int(element_viewport_pos["x"] + point_in_viewport["x"])
|
|
356
|
-
y = int(element_viewport_pos["y"] + point_in_viewport["y"])
|
|
357
|
-
|
|
358
|
-
return ActionPoint(x=x, y=y)
|
|
359
|
-
|
|
360
|
-
def build_hm_move_to_element_action(
|
|
361
|
-
self,
|
|
362
|
-
start_position: ActionPoint,
|
|
363
|
-
element: WebElement,
|
|
364
|
-
parent_action: Optional[ActionChains] = None,
|
|
365
|
-
duration: int = 250,
|
|
366
|
-
devices: Optional[list[Union[PointerInput, KeyInput, WheelInput]]] = None
|
|
367
|
-
) -> tuple[ActionChains, ActionPoint]:
|
|
368
|
-
"""
|
|
369
|
-
Builds a human-like mouse move action from a start point to a random point within a target element.
|
|
370
|
-
|
|
371
|
-
Determines a random target point within the element's boundary relative to the viewport
|
|
372
|
-
(using `get_random_element_point`) and then uses `build_hm_move_action` to create
|
|
373
|
-
a human-like movement sequence to that point. Returns both the action chain and the
|
|
374
|
-
calculated end point.
|
|
375
|
-
|
|
376
|
-
Args:
|
|
377
|
-
start_position (ActionPoint): The starting coordinates (relative to viewport) for the mouse movement.
|
|
378
|
-
element (WebElement): The target element to move the mouse into.
|
|
379
|
-
parent_action (Optional[ActionChains]): An existing ActionChains instance to append actions to.
|
|
380
|
-
If None, a new chain is created. Defaults to None.
|
|
381
|
-
duration (int): Base duration (in milliseconds) used when creating a new ActionChains
|
|
382
|
-
instance if `parent_action` is None. Total move time depends on the
|
|
383
|
-
`move_to_parts` calculation within `build_hm_move_action`. Defaults to 250.
|
|
384
|
-
devices (Optional[list[Union[PointerInput, KeyInput, WheelInput]]]): Specific input devices
|
|
385
|
-
to use if creating a new ActionChains
|
|
386
|
-
instance. Defaults to None.
|
|
387
|
-
|
|
388
|
-
Returns:
|
|
389
|
-
Tuple[ActionChains, ActionPoint]: A tuple containing:
|
|
390
|
-
|
|
391
|
-
- The ActionChains instance with the human-like move-to-element sequence added.
|
|
392
|
-
Needs to be finalized with `.perform()`.
|
|
393
|
-
- The calculated end `ActionPoint` (relative to viewport) within the element that the
|
|
394
|
-
mouse path targets.
|
|
395
|
-
"""
|
|
396
|
-
|
|
397
|
-
end_position = self.get_random_element_point(element=element)
|
|
398
|
-
|
|
399
|
-
return (
|
|
400
|
-
self.build_hm_move_action(
|
|
401
|
-
start_position=start_position,
|
|
402
|
-
end_position=end_position,
|
|
403
|
-
parent_action=parent_action,
|
|
404
|
-
duration=duration,
|
|
405
|
-
devices=devices
|
|
406
|
-
),
|
|
407
|
-
end_position
|
|
408
|
-
)
|
|
409
|
-
|
|
410
|
-
def get_viewport_size(self) -> Size:
|
|
411
|
-
"""
|
|
412
|
-
Gets the current dimensions (width and height) of the browser's viewport.
|
|
413
|
-
|
|
414
|
-
Executes a predefined JavaScript snippet to retrieve the inner width and height
|
|
415
|
-
of the window.
|
|
416
|
-
|
|
417
|
-
Returns:
|
|
418
|
-
Size: A TypedDict containing the 'width' and 'height' of the viewport in pixels.
|
|
419
|
-
"""
|
|
420
|
-
|
|
421
|
-
size = self.execute_js_script(self._js_scripts["get_viewport_size"])
|
|
422
|
-
|
|
423
|
-
return Size(width=int(size["width"]), height=int(size["height"]))
|
|
424
|
-
|
|
425
|
-
def build_hm_scroll_action(
|
|
426
|
-
self,
|
|
427
|
-
delta_x: int,
|
|
428
|
-
delta_y: int,
|
|
429
|
-
origin: Optional[ScrollOrigin] = None,
|
|
430
|
-
parent_action: Optional[ActionChains] = None,
|
|
431
|
-
duration: int = 250,
|
|
432
|
-
devices: Optional[list[Union[PointerInput, KeyInput, WheelInput]]] = None
|
|
433
|
-
) -> ActionChains:
|
|
434
|
-
"""
|
|
435
|
-
Builds a human-like scroll action sequence by breaking the scroll into smaller parts with pauses.
|
|
436
|
-
|
|
437
|
-
This method simulates a more natural scroll compared to a direct jump. It calculates scroll segments
|
|
438
|
-
using an external `scroll_to_parts` function and adds corresponding scroll actions and pauses
|
|
439
|
-
to an ActionChains sequence. If no origin is provided, it defaults to scrolling from the
|
|
440
|
-
bottom-right corner for positive deltas and top-left for negative deltas of the viewport.
|
|
441
|
-
|
|
442
|
-
Args:
|
|
443
|
-
delta_x (int): The total horizontal distance to scroll. Positive scrolls right, negative scrolls left.
|
|
444
|
-
delta_y (int): The total vertical distance to scroll. Positive scrolls down, negative scrolls up.
|
|
445
|
-
origin (Optional[ScrollOrigin]): The origin point for the scroll (viewport or element center).
|
|
446
|
-
If None, defaults to a viewport corner based on scroll direction. Defaults to None.
|
|
447
|
-
parent_action (Optional[ActionChains]): An existing ActionChains instance to append actions to.
|
|
448
|
-
If None, a new chain is created. Defaults to None.
|
|
449
|
-
duration (int): The base duration (in milliseconds) used when creating a new ActionChains
|
|
450
|
-
instance if `parent_action` is None. This duration is *not* directly the total scroll time,
|
|
451
|
-
which is determined by the sum of pauses from `scroll_to_parts`. Defaults to 250.
|
|
452
|
-
devices (Optional[list[Union[PointerInput, KeyInput, WheelInput]]]): Specific input devices
|
|
453
|
-
to use if creating a new ActionChains instance. Defaults to None.
|
|
454
|
-
|
|
455
|
-
Returns:
|
|
456
|
-
ActionChains: The ActionChains instance (new or parent) with the human-like scroll sequence added.
|
|
457
|
-
Needs to be finalized with `.perform()`.
|
|
458
|
-
"""
|
|
459
|
-
|
|
460
|
-
if parent_action is None:
|
|
461
|
-
action = self.build_action_chains(duration=duration, devices=devices)
|
|
462
|
-
else:
|
|
463
|
-
action = parent_action
|
|
464
|
-
|
|
465
|
-
if origin is None:
|
|
466
|
-
viewport_size = self.get_viewport_size()
|
|
467
|
-
origin_x = 0 if delta_x >= 0 else viewport_size["width"]
|
|
468
|
-
origin_y = 0 if delta_y >= 0 else viewport_size["height"]
|
|
469
|
-
origin = ScrollOrigin.from_viewport(origin_x, origin_y)
|
|
470
|
-
|
|
471
|
-
start_position = ActionPoint(x=int(origin.x_offset), y=int(origin.y_offset))
|
|
472
|
-
end_position = ActionPoint(x=int(origin.x_offset) + delta_x, y=int(origin.y_offset) + delta_y)
|
|
473
|
-
|
|
474
|
-
scroll_parts = scroll_to_parts(start_position=start_position, end_position=end_position)
|
|
475
|
-
|
|
476
|
-
for part in scroll_parts:
|
|
477
|
-
action.pause(part.duration * 0.001)
|
|
478
|
-
action.scroll_from_origin(scroll_origin=origin, delta_x=int(part.delta.x), delta_y=int(part.delta.y))
|
|
479
|
-
|
|
480
|
-
return action
|
|
481
|
-
|
|
482
|
-
def get_viewport_rect(self) -> Rectangle:
|
|
483
|
-
"""
|
|
484
|
-
Gets the position and dimensions of the viewport relative to the document origin.
|
|
485
|
-
|
|
486
|
-
Combines the scroll position (top-left corner) and the viewport dimensions.
|
|
487
|
-
Executes a predefined JavaScript snippet.
|
|
488
|
-
|
|
489
|
-
Returns:
|
|
490
|
-
Rectangle: A TypedDict where 'x' and 'y' represent the current scroll offsets
|
|
491
|
-
(window.pageXOffset, window.pageYOffset) and 'width' and 'height' represent
|
|
492
|
-
the viewport dimensions (window.innerWidth, window.innerHeight).
|
|
493
|
-
"""
|
|
494
|
-
|
|
495
|
-
rect = self.execute_js_script(self._js_scripts["get_viewport_rect"])
|
|
496
|
-
|
|
497
|
-
return Rectangle(
|
|
498
|
-
x=int(rect["x"]),
|
|
499
|
-
y=int(rect["y"]),
|
|
500
|
-
width=int(rect["width"]),
|
|
501
|
-
height=int(rect["height"])
|
|
502
|
-
)
|
|
503
|
-
|
|
504
|
-
def build_hm_scroll_to_element_action(
|
|
505
|
-
self,
|
|
506
|
-
element: WebElement,
|
|
507
|
-
additional_lower_y_offset: int = 0,
|
|
508
|
-
additional_upper_y_offset: int = 0,
|
|
509
|
-
additional_right_x_offset: int = 0,
|
|
510
|
-
additional_left_x_offset: int = 0,
|
|
511
|
-
origin: Optional[ScrollOrigin] = None,
|
|
512
|
-
parent_action: Optional[ActionChains] = None,
|
|
513
|
-
duration: int = 250,
|
|
514
|
-
devices: Optional[list[Union[PointerInput, KeyInput, WheelInput]]] = None
|
|
515
|
-
) -> ActionChains:
|
|
516
|
-
"""
|
|
517
|
-
Builds a human-like scroll action to bring an element into view with optional offsets.
|
|
518
|
-
|
|
519
|
-
Calculates the necessary scroll delta (dx, dy) to make the target element visible within the
|
|
520
|
-
viewport, considering additional offset margins. It then uses `build_hm_scroll_action`
|
|
521
|
-
to perform the scroll in a human-like manner.
|
|
522
|
-
|
|
523
|
-
Args:
|
|
524
|
-
element (WebElement): The target element to scroll into view.
|
|
525
|
-
additional_lower_y_offset (int): Extra space (in pixels) to leave below the element within the viewport. Defaults to 0.
|
|
526
|
-
additional_upper_y_offset (int): Extra space (in pixels) to leave above the element within the viewport. Defaults to 0.
|
|
527
|
-
additional_right_x_offset (int): Extra space (in pixels) to leave to the right of the element within the viewport. Defaults to 0.
|
|
528
|
-
additional_left_x_offset (int): Extra space (in pixels) to leave to the left of the element within the viewport. Defaults to 0.
|
|
529
|
-
origin (Optional[ScrollOrigin]): The origin point for the scroll. Passed to `build_hm_scroll_action`. Defaults to None.
|
|
530
|
-
parent_action (Optional[ActionChains]): An existing ActionChains instance. Passed to `build_hm_scroll_action`. Defaults to None.
|
|
531
|
-
duration (int): Base duration for creating a new ActionChains instance. Passed to `build_hm_scroll_action`. Defaults to 250.
|
|
532
|
-
devices (Optional[list[Union[PointerInput, KeyInput, WheelInput]]]): Specific input devices. Passed to `build_hm_scroll_action`. Defaults to None.
|
|
533
|
-
|
|
534
|
-
Returns:
|
|
535
|
-
ActionChains: The ActionChains instance containing the human-like scroll-to-element sequence.
|
|
536
|
-
Needs to be finalized with `.perform()`.
|
|
537
|
-
"""
|
|
538
|
-
|
|
539
|
-
viewport_rect = self.get_viewport_rect()
|
|
540
|
-
element_rect = self.get_element_rect_in_viewport(element)
|
|
541
|
-
|
|
542
|
-
if element_rect["x"] < additional_left_x_offset:
|
|
543
|
-
delta_x = int(element_rect["x"] - additional_left_x_offset)
|
|
544
|
-
elif element_rect["x"] + element_rect["width"] > viewport_rect["width"] - additional_right_x_offset:
|
|
545
|
-
delta_x = int(
|
|
546
|
-
element_rect["x"] +
|
|
547
|
-
element_rect["width"] -
|
|
548
|
-
(viewport_rect["width"] - additional_right_x_offset)
|
|
549
|
-
)
|
|
550
|
-
else:
|
|
551
|
-
delta_x = 0
|
|
552
|
-
|
|
553
|
-
if element_rect["y"] < additional_upper_y_offset:
|
|
554
|
-
delta_y = int(element_rect["y"] - additional_upper_y_offset)
|
|
555
|
-
elif element_rect["y"] + element_rect["height"] > viewport_rect["height"] - additional_lower_y_offset:
|
|
556
|
-
delta_y = int(
|
|
557
|
-
element_rect["y"] +
|
|
558
|
-
element_rect["height"] -
|
|
559
|
-
(viewport_rect["height"] - additional_lower_y_offset)
|
|
560
|
-
)
|
|
561
|
-
else:
|
|
562
|
-
delta_y = 0
|
|
563
|
-
|
|
564
|
-
return self.build_hm_scroll_action(
|
|
565
|
-
delta_x=delta_x,
|
|
566
|
-
delta_y=delta_y,
|
|
567
|
-
origin=origin,
|
|
568
|
-
parent_action=parent_action,
|
|
569
|
-
duration=duration,
|
|
570
|
-
devices=devices
|
|
571
|
-
)
|
|
572
|
-
|
|
573
|
-
def build_hm_text_input_action(
|
|
574
|
-
self,
|
|
575
|
-
text: str,
|
|
576
|
-
parent_action: Optional[ActionChains] = None,
|
|
577
|
-
duration: int = 250,
|
|
578
|
-
devices: Optional[list[Union[PointerInput, KeyInput, WheelInput]]] = None
|
|
579
|
-
) -> ActionChains:
|
|
580
|
-
"""
|
|
581
|
-
Builds a human-like text input action sequence.
|
|
582
|
-
|
|
583
|
-
Simulates typing by breaking the input text into smaller chunks with pauses between them,
|
|
584
|
-
calculated by the external `text_input_to_parts` function. Adds the corresponding
|
|
585
|
-
send_keys actions and pauses to an ActionChains sequence.
|
|
586
|
-
|
|
587
|
-
Args:
|
|
588
|
-
text (str): The text string to be typed.
|
|
589
|
-
parent_action (Optional[ActionChains]): An existing ActionChains instance to append actions to.
|
|
590
|
-
If None, a new chain is created. Defaults to None.
|
|
591
|
-
duration (int): The base duration (in milliseconds) used when creating a new ActionChains
|
|
592
|
-
instance if `parent_action` is None. Total input time depends on `text_input_to_parts`. Defaults to 250.
|
|
593
|
-
devices (Optional[list[Union[PointerInput, KeyInput, WheelInput]]]): Specific input devices
|
|
594
|
-
if creating a new ActionChains instance. Defaults to None.
|
|
595
|
-
|
|
596
|
-
Returns:
|
|
597
|
-
ActionChains: The ActionChains instance (new or parent) with the human-like text input sequence added.
|
|
598
|
-
Needs to be finalized with `.perform()`. Requires the target input element to have focus.
|
|
599
|
-
"""
|
|
600
|
-
|
|
601
|
-
if parent_action is None:
|
|
602
|
-
action = self.build_action_chains(duration=duration, devices=devices)
|
|
603
|
-
else:
|
|
604
|
-
action = parent_action
|
|
605
|
-
|
|
606
|
-
input_parts = text_input_to_parts(text)
|
|
607
|
-
|
|
608
|
-
for part in input_parts:
|
|
609
|
-
action.pause(part.duration * 0.001)
|
|
610
|
-
action.send_keys(part.text)
|
|
611
|
-
|
|
612
|
-
return action
|
|
613
|
-
|
|
614
|
-
@property
|
|
615
|
-
def captcha_workers(self) -> list[CaptchaWorkerSettings]:
|
|
616
|
-
"""
|
|
617
|
-
Gets the current list of configured captcha workers.
|
|
618
|
-
|
|
619
|
-
Returns:
|
|
620
|
-
list[CaptchaWorkerSettings]: A list containing the current captcha worker settings.
|
|
621
|
-
"""
|
|
622
|
-
|
|
623
|
-
return self._captcha_workers
|
|
624
|
-
|
|
625
|
-
def check_captcha(self, check_all: bool = False) -> list[str]:
|
|
626
|
-
"""
|
|
627
|
-
Iterates through registered captcha workers to detect and solve captchas.
|
|
628
|
-
|
|
629
|
-
For each registered captcha worker, it calls a `check_func` to determine
|
|
630
|
-
if a captcha is present. If found, it then calls the associated `solve_func`
|
|
631
|
-
to attempt to solve it and records the name of the solved captcha.
|
|
632
|
-
The process stops after the first solved captcha unless `check_all` is True.
|
|
633
|
-
|
|
634
|
-
Args:
|
|
635
|
-
check_all (bool): If True, all registered captcha workers will be checked
|
|
636
|
-
and solved if present. If False, the method stops after the first
|
|
637
|
-
captcha is successfully detected and solved. Defaults to False.
|
|
638
|
-
|
|
639
|
-
Returns:
|
|
640
|
-
list[str]: A list of names of the captchas that were detected and for which
|
|
641
|
-
the `solve_func` was executed. The list will contain at most one element
|
|
642
|
-
if `check_all` is False.
|
|
643
|
-
"""
|
|
644
|
-
|
|
645
|
-
found_captchas = []
|
|
646
|
-
|
|
647
|
-
for captcha_worker in self._captcha_workers:
|
|
648
|
-
if captcha_worker["check_func"](self):
|
|
649
|
-
captcha_worker["solve_func"](self)
|
|
650
|
-
found_captchas.append(captcha_worker["name"])
|
|
651
|
-
|
|
652
|
-
if not check_all:
|
|
653
|
-
break
|
|
654
|
-
|
|
655
|
-
return found_captchas
|
|
656
|
-
|
|
657
|
-
def check_element_in_viewport(self, element: WebElement) -> bool:
|
|
658
|
-
"""
|
|
659
|
-
Checks if the specified web element is currently within the browser's viewport.
|
|
660
|
-
|
|
661
|
-
Executes a predefined JavaScript snippet to determine the visibility status.
|
|
662
|
-
|
|
663
|
-
Args:
|
|
664
|
-
element (WebElement): The Selenium WebElement to check.
|
|
665
|
-
|
|
666
|
-
Returns:
|
|
667
|
-
bool: True if the element is at least partially within the viewport, False otherwise.
|
|
668
|
-
"""
|
|
669
|
-
|
|
670
|
-
return self.execute_js_script(self._js_scripts["check_element_in_viewport"], element)
|
|
671
|
-
|
|
672
|
-
def click_action(
|
|
673
|
-
self,
|
|
674
|
-
element: Optional[WebElement] = None,
|
|
675
|
-
duration: int = 250,
|
|
676
|
-
action_chain: Optional[ActionChains] = None
|
|
677
|
-
) -> ActionChains:
|
|
678
|
-
"""
|
|
679
|
-
Adds a click action. Clicks on the specified element or the current mouse position if no element is provided.
|
|
680
|
-
|
|
681
|
-
If an existing ActionChains object is provided via `action_chain`, this action
|
|
682
|
-
is appended to it. Otherwise, a new ActionChains object is created using
|
|
683
|
-
`self.build_action_chains` with the specified duration before adding the action.
|
|
684
|
-
|
|
685
|
-
Args:
|
|
686
|
-
element (Optional[WebElement]): The web element to click. If None, clicks at the
|
|
687
|
-
current mouse cursor position. Defaults to None.
|
|
688
|
-
duration (int): The duration in milliseconds to use when creating a new
|
|
689
|
-
ActionChains instance if `action_chain` is None. Defaults to 250.
|
|
690
|
-
action_chain (Optional[ActionChains]): An existing ActionChains instance to append
|
|
691
|
-
this action to. If None, a new chain is created. Defaults to None.
|
|
692
|
-
|
|
693
|
-
Returns:
|
|
694
|
-
ActionChains: The ActionChains instance (either the one passed in or a new one)
|
|
695
|
-
with the click action added, allowing for method chaining.
|
|
696
|
-
"""
|
|
697
|
-
|
|
698
|
-
if action_chain is None:
|
|
699
|
-
action_chain = self.build_action_chains(duration=duration)
|
|
700
|
-
|
|
701
|
-
action_chain.click(on_element=element)
|
|
702
|
-
|
|
703
|
-
return action_chain
|
|
704
|
-
|
|
705
|
-
def click_and_hold_action(
|
|
706
|
-
self,
|
|
707
|
-
element: Optional[WebElement] = None,
|
|
708
|
-
duration: int = 250,
|
|
709
|
-
action_chain: Optional[ActionChains] = None
|
|
710
|
-
) -> ActionChains:
|
|
711
|
-
"""
|
|
712
|
-
Adds a click-and-hold action. Holds down the left mouse button on the specified element or the current mouse position.
|
|
713
|
-
|
|
714
|
-
If an existing ActionChains object is provided via `action_chain`, this action
|
|
715
|
-
is appended to it. Otherwise, a new ActionChains object is created using
|
|
716
|
-
`self.build_action_chains` with the specified duration before adding the action.
|
|
717
|
-
|
|
718
|
-
Args:
|
|
719
|
-
element (Optional[WebElement]): The web element to click and hold. If None, clicks
|
|
720
|
-
and holds at the current mouse cursor position. Defaults to None.
|
|
721
|
-
duration (int): The duration in milliseconds to use when creating a new
|
|
722
|
-
ActionChains instance if `action_chain` is None. Defaults to 250.
|
|
723
|
-
action_chain (Optional[ActionChains]): An existing ActionChains instance to append
|
|
724
|
-
this action to. If None, a new chain is created. Defaults to None.
|
|
725
|
-
|
|
726
|
-
Returns:
|
|
727
|
-
ActionChains: The ActionChains instance (either the one passed in or a new one)
|
|
728
|
-
with the click-and-hold action added, allowing for method chaining.
|
|
729
|
-
"""
|
|
730
|
-
|
|
731
|
-
if action_chain is None:
|
|
732
|
-
action_chain = self.build_action_chains(duration=duration)
|
|
733
|
-
|
|
734
|
-
action_chain.click_and_hold(on_element=element)
|
|
735
|
-
|
|
736
|
-
return action_chain
|
|
737
|
-
|
|
738
|
-
@property
|
|
739
|
-
def windows_handles(self) -> list[str]:
|
|
740
|
-
"""
|
|
741
|
-
Gets the handles of all open windows.
|
|
742
|
-
|
|
743
|
-
Returns a list of handles for all browser windows or tabs currently open and managed by the WebDriver.
|
|
744
|
-
This is useful for iterating through or managing multiple windows in a browser session.
|
|
745
|
-
|
|
746
|
-
Returns:
|
|
747
|
-
list[str]: A list of window handles. Each handle is a string identifier for an open window.
|
|
748
|
-
"""
|
|
749
|
-
|
|
750
|
-
return self._driver.window_handles
|
|
751
|
-
|
|
752
|
-
def get_window_handle(self, window: Optional[Union[str, int]] = None) -> str:
|
|
753
|
-
"""
|
|
754
|
-
Retrieves a window handle string based on the provided identifier.
|
|
755
|
-
|
|
756
|
-
If the identifier is already a string, it's assumed to be a valid handle and returned directly.
|
|
757
|
-
If it's an integer, it's treated as an index into the list of currently open window handles.
|
|
758
|
-
If it's None or not provided, the handle of the currently active window is returned.
|
|
759
|
-
|
|
760
|
-
Args:
|
|
761
|
-
window (Optional[Union[str, int]]): The identifier for the desired window handle.
|
|
762
|
-
|
|
763
|
-
- str: Assumed to be the window handle itself.
|
|
764
|
-
- int: Index into the list of window handles (self.driver.window_handles).
|
|
765
|
-
- None: Get the handle of the currently focused window.
|
|
766
|
-
|
|
767
|
-
Returns:
|
|
768
|
-
str: The window handle string corresponding to the input identifier.
|
|
769
|
-
"""
|
|
770
|
-
|
|
771
|
-
if isinstance(window, str):
|
|
772
|
-
return window
|
|
773
|
-
elif isinstance(window, int):
|
|
774
|
-
return self._driver.window_handles[window]
|
|
775
|
-
else:
|
|
776
|
-
return self._driver.current_window_handle
|
|
777
|
-
|
|
778
|
-
def switch_to_window(self, window: Optional[Union[str, int]] = None):
|
|
779
|
-
"""
|
|
780
|
-
Switches the driver's focus to the specified browser window.
|
|
781
|
-
|
|
782
|
-
Uses get_window_handle to resolve the target window identifier (handle string or index)
|
|
783
|
-
before instructing the driver to switch. If no window identifier is provided,
|
|
784
|
-
it effectively switches to the current window.
|
|
785
|
-
|
|
786
|
-
Args:
|
|
787
|
-
window (Optional[Union[str, int]]): The identifier of the window to switch to.
|
|
788
|
-
Can be a window handle (string) or an index (int) in the list of window handles.
|
|
789
|
-
If None, targets the current window handle.
|
|
790
|
-
"""
|
|
791
|
-
|
|
792
|
-
self._driver.switch_to.window(self.get_window_handle(window))
|
|
793
|
-
|
|
794
|
-
@property
|
|
795
|
-
def current_window_handle(self) -> str:
|
|
796
|
-
"""
|
|
797
|
-
Gets the current window handle.
|
|
798
|
-
|
|
799
|
-
Retrieves the handle of the currently active browser window or tab. Window handles are unique identifiers
|
|
800
|
-
used by WebDriver to distinguish between different browser windows.
|
|
801
|
-
|
|
802
|
-
Returns:
|
|
803
|
-
str: The current window handle.
|
|
804
|
-
"""
|
|
805
|
-
|
|
806
|
-
return self._driver.current_window_handle
|
|
807
|
-
|
|
808
|
-
def close_window(self, window: Optional[Union[str, int]] = None):
|
|
809
|
-
"""
|
|
810
|
-
Closes the specified browser window and manages focus switching.
|
|
811
|
-
|
|
812
|
-
Identifies the target window to close using get_window_handle. Switches to that window,
|
|
813
|
-
closes it, and then switches focus back. If the closed window was the currently focused
|
|
814
|
-
window, it switches focus to the last window in the remaining list. Otherwise, it switches
|
|
815
|
-
back to the window that had focus before the close operation began.
|
|
816
|
-
|
|
817
|
-
Args:
|
|
818
|
-
window (Optional[Union[str, int]]): The identifier of the window to close.
|
|
819
|
-
Can be a window handle (string), an index (int), or None to close the
|
|
820
|
-
currently focused window.
|
|
821
|
-
"""
|
|
822
|
-
|
|
823
|
-
start_window_handle = self.current_window_handle
|
|
824
|
-
close_window_handle = self.get_window_handle(window)
|
|
825
|
-
|
|
826
|
-
is_current_closing = close_window_handle == start_window_handle
|
|
827
|
-
|
|
828
|
-
if not is_current_closing:
|
|
829
|
-
self.switch_to_window(close_window_handle)
|
|
830
|
-
|
|
831
|
-
self._driver.close()
|
|
832
|
-
|
|
833
|
-
if len(self.windows_handles) > 0:
|
|
834
|
-
if is_current_closing:
|
|
835
|
-
self.switch_to_window(-1)
|
|
836
|
-
else:
|
|
837
|
-
self.switch_to_window(start_window_handle)
|
|
838
|
-
|
|
839
|
-
def close_all_windows(self):
|
|
840
|
-
"""
|
|
841
|
-
Closes all open windows.
|
|
842
|
-
|
|
843
|
-
Iterates through all window handles and closes each window associated with the WebDriver instance.
|
|
844
|
-
This effectively closes the entire browser session managed by the driver.
|
|
845
|
-
"""
|
|
846
|
-
|
|
847
|
-
for window in self.windows_handles:
|
|
848
|
-
self.close_window(window)
|
|
849
|
-
|
|
850
|
-
def execute_cdp_cmd(self, cmd: str, cmd_args: dict[str, Any]) -> Any:
|
|
851
|
-
"""
|
|
852
|
-
Executes a Chrome DevTools Protocol (CDP) command.
|
|
853
|
-
|
|
854
|
-
This method allows direct interaction with the browser's underlying DevTools Protocol,
|
|
855
|
-
enabling fine-grained control over browser behavior, network, page rendering, and more.
|
|
856
|
-
|
|
857
|
-
Args:
|
|
858
|
-
cmd (str): The name of the CDP command to execute (e.g., "Page.navigate", "Network.enable", "Emulation.setDeviceMetricsOverride").
|
|
859
|
-
cmd_args (dict[str, Any]): A dictionary of arguments specific to the given CDP command.
|
|
860
|
-
The structure and required keys depend on the `cmd` being executed, as defined
|
|
861
|
-
by the Chrome DevTools Protocol specification.
|
|
862
|
-
|
|
863
|
-
Returns:
|
|
864
|
-
Any: The result of the CDP command execution. The type and structure of the
|
|
865
|
-
returned value depend on the specific `cmd` and its defined return type
|
|
866
|
-
in the CDP specification.
|
|
867
|
-
"""
|
|
868
|
-
|
|
869
|
-
return self._driver.execute_cdp_cmd(cmd=cmd, cmd_args=build_cdp_kwargs(**cmd_args))
|
|
870
|
-
|
|
871
|
-
def cmd_activate_target(self, target_id: str,):
|
|
872
|
-
"""
|
|
873
|
-
Activates a specific browser target, bringing it to the foreground.
|
|
874
|
-
|
|
875
|
-
This command makes the specified target (tab or window) the active one,
|
|
876
|
-
similar to clicking on a tab in a browser.
|
|
877
|
-
|
|
878
|
-
Args:
|
|
879
|
-
target_id (str): The unique ID of the target to activate.
|
|
880
|
-
"""
|
|
881
|
-
|
|
882
|
-
cmd_args = locals()
|
|
883
|
-
cmd_args.pop("self")
|
|
884
|
-
|
|
885
|
-
self.execute_cdp_cmd(cmd="Target.activateTarget", cmd_args=cmd_args)
|
|
886
|
-
|
|
887
|
-
def cmd_attach_to_browser_target(self) -> str:
|
|
888
|
-
"""
|
|
889
|
-
Attaches the DevTools session to the browser itself, not a specific tab or page.
|
|
890
|
-
|
|
891
|
-
This allows for control over browser-wide features, such as managing browser contexts,
|
|
892
|
-
extensions, or global network settings.
|
|
893
|
-
|
|
894
|
-
Returns:
|
|
895
|
-
str: The `sessionId` of the newly created DevTools session for the browser.
|
|
896
|
-
"""
|
|
897
|
-
|
|
898
|
-
cmd_args = locals()
|
|
899
|
-
cmd_args.pop("self")
|
|
900
|
-
|
|
901
|
-
return self.execute_cdp_cmd(cmd="Target.attachToBrowserTarget", cmd_args=cmd_args)
|
|
902
|
-
|
|
903
|
-
def cmd_attach_to_target(self, target_id: str, flatten: Optional[bool] = None,) -> str:
|
|
904
|
-
"""
|
|
905
|
-
Attaches the DevTools session to a specific browser target.
|
|
906
|
-
|
|
907
|
-
Attaching allows you to send CDP commands and receive events for that specific target.
|
|
908
|
-
This is typically done to control a specific tab or iframe.
|
|
909
|
-
|
|
910
|
-
Args:
|
|
911
|
-
target_id (str): The unique ID of the target to attach to.
|
|
912
|
-
flatten (Optional[bool]): If True, all child targets (e.g., iframes within a page)
|
|
913
|
-
will also be automatically attached. Defaults to False.
|
|
914
|
-
|
|
915
|
-
Returns:
|
|
916
|
-
str: The `sessionId` of the newly created DevTools session for this target.
|
|
917
|
-
This session ID is used in subsequent CDP commands to specify which session
|
|
918
|
-
the command applies to.
|
|
919
|
-
"""
|
|
920
|
-
|
|
921
|
-
cmd_args = locals()
|
|
922
|
-
cmd_args.pop("self")
|
|
923
|
-
|
|
924
|
-
return self.execute_cdp_cmd(cmd="Target.attachToTarget", cmd_args=cmd_args)
|
|
925
|
-
|
|
926
|
-
def cmd_close_target(self, target_id: str,) -> bool:
|
|
927
|
-
"""
|
|
928
|
-
Closes a specific browser target (tab or window).
|
|
929
|
-
|
|
930
|
-
Args:
|
|
931
|
-
target_id (str): The unique ID of the target to close.
|
|
932
|
-
|
|
933
|
-
Returns:
|
|
934
|
-
bool: True if the target was successfully closed, False otherwise.
|
|
935
|
-
"""
|
|
936
|
-
|
|
937
|
-
cmd_args = locals()
|
|
938
|
-
cmd_args.pop("self")
|
|
939
|
-
|
|
940
|
-
return self.execute_cdp_cmd(cmd="Target.closeTarget", cmd_args=cmd_args)
|
|
941
|
-
|
|
942
|
-
def cmd_create_browser_context(
|
|
943
|
-
self,
|
|
944
|
-
dispose_on_detach: Optional[bool] = None,
|
|
945
|
-
proxy_server: Optional[str] = None,
|
|
946
|
-
proxy_bypass_list: Optional[str] = None,
|
|
947
|
-
origins_with_universal_network_access: Optional[list[str]] = None,
|
|
948
|
-
) -> str:
|
|
949
|
-
"""
|
|
950
|
-
Sends a Chrome DevTools Protocol (CDP) command to create a new browser context.
|
|
951
|
-
|
|
952
|
-
A browser context is an isolated environment, similar to an incognito window,
|
|
953
|
-
where cookies, local storage, and other browser data are separate from
|
|
954
|
-
the default context.
|
|
955
|
-
|
|
956
|
-
Args:
|
|
957
|
-
dispose_on_detach (Optional[bool]): If True, the browser context will be
|
|
958
|
-
disposed of when the last target in it is detached.
|
|
959
|
-
proxy_server (Optional[str]): Proxy server to use for the browser context
|
|
960
|
-
(e.g., "http://localhost:8080").
|
|
961
|
-
proxy_bypass_list (Optional[str]): Comma-separated list of hosts or IP addresses
|
|
962
|
-
for which proxying should be bypassed.
|
|
963
|
-
origins_with_universal_network_access (Optional[Sequence[str]]): A list of
|
|
964
|
-
origins that are allowed to make network requests to any origin.
|
|
965
|
-
|
|
966
|
-
Returns:
|
|
967
|
-
str: The `browserContextId` of the newly created browser context.
|
|
968
|
-
"""
|
|
969
|
-
|
|
970
|
-
cmd_args = locals()
|
|
971
|
-
cmd_args.pop("self")
|
|
972
|
-
|
|
973
|
-
return self.execute_cdp_cmd(cmd="Target.createBrowserContext", cmd_args=cmd_args)
|
|
974
|
-
|
|
975
|
-
def cmd_create_target(
|
|
976
|
-
self,
|
|
977
|
-
url: str = "",
|
|
978
|
-
left: Optional[int] = None,
|
|
979
|
-
top: Optional[int] = None,
|
|
980
|
-
width: Optional[int] = None,
|
|
981
|
-
height: Optional[int] = None,
|
|
982
|
-
window_state: Optional[Literal["normal", "minimized", "maximized", "fullscreen"]] = None,
|
|
983
|
-
browser_context_id: Optional[str] = None,
|
|
984
|
-
enable_begin_frame_control: Optional[bool] = None,
|
|
985
|
-
new_window: Optional[bool] = None,
|
|
986
|
-
background: Optional[bool] = None,
|
|
987
|
-
for_tab: Optional[bool] = None,
|
|
988
|
-
hidden: Optional[bool] = None,
|
|
989
|
-
) -> str:
|
|
990
|
-
"""
|
|
991
|
-
Sends a Chrome DevTools Protocol (CDP) command to create a new browser target (tab or window).
|
|
992
|
-
|
|
993
|
-
This method wraps the `Target.createTarget` CDP command, allowing for the creation
|
|
994
|
-
of new browsing contexts with various configurations such as URL, dimensions,
|
|
995
|
-
window state, and association with a specific browser context.
|
|
996
|
-
|
|
997
|
-
Args:
|
|
998
|
-
url (str): The URL to open in the new target. Defaults to an empty string,
|
|
999
|
-
which typically opens a blank page.
|
|
1000
|
-
left (Optional[int]): The x-coordinate (left edge) of the new window/tab.
|
|
1001
|
-
Only applicable if `new_window` is True.
|
|
1002
|
-
top (Optional[int]): The y-coordinate (top edge) of the new window/tab.
|
|
1003
|
-
Only applicable if `new_window` is True.
|
|
1004
|
-
width (Optional[int]): The width of the new window/tab in pixels.
|
|
1005
|
-
Only applicable if `new_window` is True.
|
|
1006
|
-
height (Optional[int]): The height of the new window/tab in pixels.
|
|
1007
|
-
Only applicable if `new_window` is True.
|
|
1008
|
-
window_state (Optional[Literal["normal", "minimized", "maximized", "fullscreen"]]): The desired state of the new window.
|
|
1009
|
-
Only applicable if `new_window` is True.
|
|
1010
|
-
browser_context_id (Optional[str]): If specified, the new target will be
|
|
1011
|
-
created in the browser context with this ID. This is useful for
|
|
1012
|
-
incognito modes or separate user profiles.
|
|
1013
|
-
enable_begin_frame_control (Optional[bool]): Whether to enable BeginFrame control
|
|
1014
|
-
for the new target. This is an advanced feature for precise rendering control.
|
|
1015
|
-
new_window (Optional[bool]): If True, the target will be opened in a new browser window.
|
|
1016
|
-
If False or None, it will typically open as a new tab.
|
|
1017
|
-
background (Optional[bool]): If True, the new target will be opened in the background
|
|
1018
|
-
without immediately gaining focus.
|
|
1019
|
-
for_tab (Optional[bool]): If True, indicates that the target is intended to be a tab.
|
|
1020
|
-
This parameter is often used in conjunction with `new_window=False`.
|
|
1021
|
-
hidden (Optional[bool]): If True, the new target will be created but not immediately
|
|
1022
|
-
visible.
|
|
1023
|
-
|
|
1024
|
-
Returns:
|
|
1025
|
-
str: The `targetId` of the newly created browser target. This ID is essential
|
|
1026
|
-
for interacting with the new target via other CDP commands.
|
|
1027
|
-
"""
|
|
1028
|
-
|
|
1029
|
-
cmd_args = locals()
|
|
1030
|
-
cmd_args.pop("self")
|
|
1031
|
-
|
|
1032
|
-
return self.execute_cdp_cmd(cmd="Target.createTarget", cmd_args=cmd_args)
|
|
1033
|
-
|
|
1034
|
-
def cmd_detach_from_target(self, session_id: Optional[str] = None, target_id: Optional[str] = None,):
|
|
1035
|
-
"""
|
|
1036
|
-
Detaches the DevTools session from a specific target.
|
|
1037
|
-
|
|
1038
|
-
Detaching stops the ability to send CDP commands and receive events for that target
|
|
1039
|
-
via the specified session. Either `session_id` or `target_id` must be provided.
|
|
1040
|
-
|
|
1041
|
-
Args:
|
|
1042
|
-
session_id (Optional[str]): The ID of the DevTools session to detach.
|
|
1043
|
-
target_id (Optional[str]): The ID of the target from which to detach.
|
|
1044
|
-
If `session_id` is not provided, this ID is used.
|
|
1045
|
-
"""
|
|
1046
|
-
|
|
1047
|
-
cmd_args = locals()
|
|
1048
|
-
cmd_args.pop("self")
|
|
1049
|
-
|
|
1050
|
-
self.execute_cdp_cmd(cmd="Target.detachFromTarget", cmd_args=cmd_args)
|
|
1051
|
-
|
|
1052
|
-
def cmd_dispose_browser_context(self, browser_context_id: str,):
|
|
1053
|
-
"""
|
|
1054
|
-
Disposes of an existing browser context.
|
|
1055
|
-
|
|
1056
|
-
This closes all targets (tabs/windows) associated with the specified browser context
|
|
1057
|
-
and clears all associated data (e.g., cookies, local storage).
|
|
1058
|
-
|
|
1059
|
-
Args:
|
|
1060
|
-
browser_context_id (str): The ID of the browser context to dispose of.
|
|
1061
|
-
"""
|
|
1062
|
-
|
|
1063
|
-
cmd_args = locals()
|
|
1064
|
-
cmd_args.pop("self")
|
|
1065
|
-
|
|
1066
|
-
self.execute_cdp_cmd(cmd="Target.disposeBrowserContext", cmd_args=cmd_args)
|
|
1067
|
-
|
|
1068
|
-
def cmd_expose_dev_tools_protocol(
|
|
1069
|
-
self,
|
|
1070
|
-
target_id: str,
|
|
1071
|
-
binding_name: Optional[str] = None,
|
|
1072
|
-
inherit_permissions: Optional[bool] = None,
|
|
1073
|
-
):
|
|
1074
|
-
"""
|
|
1075
|
-
Exposes the DevTools Protocol API to the JavaScript context of a target.
|
|
1076
|
-
|
|
1077
|
-
This allows JavaScript running within the target to directly interact with
|
|
1078
|
-
the DevTools Protocol by calling methods like `DevTools.evaluate` or `DevTools.send`.
|
|
1079
|
-
|
|
1080
|
-
Args:
|
|
1081
|
-
target_id (str): The unique ID of the target to expose the protocol to.
|
|
1082
|
-
binding_name (Optional[str]): The name of the global object that will be
|
|
1083
|
-
exposed in the target's JavaScript context (default is "DevTools").
|
|
1084
|
-
inherit_permissions (Optional[bool]): If True, the exposed protocol will
|
|
1085
|
-
inherit permissions from the current DevTools session.
|
|
1086
|
-
"""
|
|
1087
|
-
|
|
1088
|
-
cmd_args = locals()
|
|
1089
|
-
cmd_args.pop("self")
|
|
1090
|
-
|
|
1091
|
-
self.execute_cdp_cmd(cmd="Target.exposeDevToolsProtocol", cmd_args=cmd_args)
|
|
1092
|
-
|
|
1093
|
-
def cmd_get_browser_contexts(self) -> list[str]:
|
|
1094
|
-
"""
|
|
1095
|
-
Retrieves a list of all existing browser context IDs.
|
|
1096
|
-
|
|
1097
|
-
Returns:
|
|
1098
|
-
list[str]: A list of strings, where each string is the unique ID of a browser context.
|
|
1099
|
-
|
|
1100
|
-
"""
|
|
1101
|
-
|
|
1102
|
-
cmd_args = locals()
|
|
1103
|
-
cmd_args.pop("self")
|
|
1104
|
-
|
|
1105
|
-
return self.execute_cdp_cmd(cmd="Target.getBrowserContexts", cmd_args=cmd_args)
|
|
1106
|
-
|
|
1107
|
-
def cmd_get_target_info(self, target_id: Optional[str] = None,) -> Any:
|
|
1108
|
-
"""
|
|
1109
|
-
Retrieves detailed information about a specific target.
|
|
1110
|
-
|
|
1111
|
-
If `target_id` is not provided, it typically returns information about the
|
|
1112
|
-
current default target or the browser target if no specific target is active.
|
|
1113
|
-
|
|
1114
|
-
Args:
|
|
1115
|
-
target_id (Optional[str]): The unique ID of the target to get information for.
|
|
1116
|
-
If None, information about the current or default target is returned.
|
|
1117
|
-
|
|
1118
|
-
Returns:
|
|
1119
|
-
Any: The `TargetInfo` object.
|
|
1120
|
-
"""
|
|
1121
|
-
|
|
1122
|
-
cmd_args = locals()
|
|
1123
|
-
cmd_args.pop("self")
|
|
1124
|
-
|
|
1125
|
-
return self.execute_cdp_cmd(cmd="Target.getTargetInfo", cmd_args=cmd_args)
|
|
1126
|
-
|
|
1127
|
-
def cmd_get_targets(self, filter_: Optional[list[Any]] = None,) -> Any:
|
|
1128
|
-
"""
|
|
1129
|
-
Retrieves a list of all available browser targets.
|
|
1130
|
-
|
|
1131
|
-
This command can optionally filter the returned targets by type or other criteria.
|
|
1132
|
-
|
|
1133
|
-
Args:
|
|
1134
|
-
filter_ (Optional[Sequence[Any]]): A list of target types or other filter criteria
|
|
1135
|
-
to narrow down the results. For example, `["page", "iframe"]` to get only
|
|
1136
|
-
pages and iframes.
|
|
1137
|
-
|
|
1138
|
-
Returns:
|
|
1139
|
-
Any: A list of `TargetInfo` objects.
|
|
1140
|
-
"""
|
|
1141
|
-
|
|
1142
|
-
cmd_args = locals()
|
|
1143
|
-
cmd_args.pop("self")
|
|
1144
|
-
|
|
1145
|
-
return self.execute_cdp_cmd(cmd="Target.getTargets", cmd_args=cmd_args)
|
|
1146
|
-
|
|
1147
|
-
def cmd_send_message_to_target(
|
|
1148
|
-
self,
|
|
1149
|
-
message: str,
|
|
1150
|
-
session_id: Optional[str] = None,
|
|
1151
|
-
target_id: Optional[str] = None,
|
|
1152
|
-
):
|
|
1153
|
-
"""
|
|
1154
|
-
Sends a raw DevTools Protocol message to a specific target.
|
|
1155
|
-
|
|
1156
|
-
This is a low-level command for sending arbitrary CDP messages.
|
|
1157
|
-
Either `session_id` or `target_id` must be provided.
|
|
1158
|
-
|
|
1159
|
-
Args:
|
|
1160
|
-
message (str): The raw JSON string of the CDP message to send.
|
|
1161
|
-
This message should conform to the CDP message format (e.g., `{"id": 1, "method": "Page.reload", "params": {}}`).
|
|
1162
|
-
session_id (Optional[str]): The ID of the DevTools session to send the message through.
|
|
1163
|
-
target_id (Optional[str]): The ID of the target to send the message to.
|
|
1164
|
-
If `session_id` is not provided, this ID is used.
|
|
1165
|
-
"""
|
|
1166
|
-
|
|
1167
|
-
cmd_args = locals()
|
|
1168
|
-
cmd_args.pop("self")
|
|
1169
|
-
|
|
1170
|
-
self.execute_cdp_cmd(cmd="Target.sendMessageToTarget", cmd_args=cmd_args)
|
|
1171
|
-
|
|
1172
|
-
def context_click_action(
|
|
1173
|
-
self,
|
|
1174
|
-
element: Optional[WebElement] = None,
|
|
1175
|
-
duration: int = 250,
|
|
1176
|
-
action_chain: Optional[ActionChains] = None
|
|
1177
|
-
) -> ActionChains:
|
|
1178
|
-
"""
|
|
1179
|
-
Adds a context-click (right-click) action. Performs the action on the specified element or the current mouse position.
|
|
1180
|
-
|
|
1181
|
-
If an existing ActionChains object is provided via `action_chain`, this action
|
|
1182
|
-
is appended to it. Otherwise, a new ActionChains object is created using
|
|
1183
|
-
`self.build_action_chains` with the specified duration before adding the action.
|
|
1184
|
-
|
|
1185
|
-
Args:
|
|
1186
|
-
element (Optional[WebElement]): The web element to context-click. If None, performs
|
|
1187
|
-
the context-click at the current mouse cursor position. Defaults to None.
|
|
1188
|
-
duration (int): The duration in milliseconds to use when creating a new
|
|
1189
|
-
ActionChains instance if `action_chain` is None. Defaults to 250.
|
|
1190
|
-
action_chain (Optional[ActionChains]): An existing ActionChains instance to append
|
|
1191
|
-
this action to. If None, a new chain is created. Defaults to None.
|
|
1192
|
-
|
|
1193
|
-
Returns:
|
|
1194
|
-
ActionChains: The ActionChains instance (either the one passed in or a new one)
|
|
1195
|
-
with the context-click action added, allowing for method chaining.
|
|
1196
|
-
"""
|
|
1197
|
-
|
|
1198
|
-
if action_chain is None:
|
|
1199
|
-
action_chain = self.build_action_chains(duration=duration)
|
|
1200
|
-
|
|
1201
|
-
action_chain.context_click(on_element=element)
|
|
1202
|
-
|
|
1203
|
-
return action_chain
|
|
1204
|
-
|
|
1205
|
-
@property
|
|
1206
|
-
def cookies(self) -> list[dict[str, Any]]:
|
|
1207
|
-
"""
|
|
1208
|
-
Gets all cookies visible to the current page.
|
|
1209
|
-
|
|
1210
|
-
Returns:
|
|
1211
|
-
list[dict[str, Any]]: A list of dictionaries, where each dictionary represents a cookie.
|
|
1212
|
-
"""
|
|
1213
|
-
|
|
1214
|
-
return self._driver.get_cookies()
|
|
1215
|
-
|
|
1216
|
-
@property
|
|
1217
|
-
def current_url(self) -> str:
|
|
1218
|
-
"""
|
|
1219
|
-
Gets the current URL.
|
|
1220
|
-
|
|
1221
|
-
Retrieves the URL of the current page loaded in the browser window under WebDriver control.
|
|
1222
|
-
|
|
1223
|
-
Returns:
|
|
1224
|
-
str: The current URL of the webpage.
|
|
1225
|
-
"""
|
|
1226
|
-
|
|
1227
|
-
return self._driver.current_url
|
|
1228
|
-
|
|
1229
|
-
def delete_all_cookies(self):
|
|
1230
|
-
"""
|
|
1231
|
-
Deletes all cookies from the current session.
|
|
1232
|
-
"""
|
|
1233
|
-
|
|
1234
|
-
self._driver.delete_all_cookies()
|
|
1235
|
-
|
|
1236
|
-
def delete_cookie(self, name: str):
|
|
1237
|
-
"""
|
|
1238
|
-
Deletes a single cookie by its name from the current session.
|
|
1239
|
-
|
|
1240
|
-
Args:
|
|
1241
|
-
name (str): The name of the cookie to delete.
|
|
1242
|
-
"""
|
|
1243
|
-
|
|
1244
|
-
self._driver.delete_cookie(name=name)
|
|
1245
|
-
|
|
1246
|
-
def delete_downloadable_files(self):
|
|
1247
|
-
"""
|
|
1248
|
-
Deletes all downloadable files.
|
|
1249
|
-
"""
|
|
1250
|
-
|
|
1251
|
-
self._driver.delete_downloadable_files()
|
|
1252
|
-
|
|
1253
|
-
def double_click_action(
|
|
1254
|
-
self,
|
|
1255
|
-
element: Optional[WebElement] = None,
|
|
1256
|
-
duration: int = 250,
|
|
1257
|
-
action_chain: Optional[ActionChains] = None
|
|
1258
|
-
) -> ActionChains:
|
|
1259
|
-
"""
|
|
1260
|
-
Adds a double-click action. Performs the action on the specified element or the current mouse position.
|
|
1261
|
-
|
|
1262
|
-
If an existing ActionChains object is provided via `action_chain`, this action
|
|
1263
|
-
is appended to it. Otherwise, a new ActionChains object is created using
|
|
1264
|
-
`self.build_action_chains` with the specified duration before adding the action.
|
|
1265
|
-
|
|
1266
|
-
Args:
|
|
1267
|
-
element (Optional[WebElement]): The web element to double-click. If None, double-clicks
|
|
1268
|
-
at the current mouse cursor position. Defaults to None.
|
|
1269
|
-
duration (int): The duration in milliseconds to use when creating a new
|
|
1270
|
-
ActionChains instance if `action_chain` is None. Defaults to 250.
|
|
1271
|
-
action_chain (Optional[ActionChains]): An existing ActionChains instance to append
|
|
1272
|
-
this action to. If None, a new chain is created. Defaults to None.
|
|
1273
|
-
|
|
1274
|
-
Returns:
|
|
1275
|
-
ActionChains: The ActionChains instance (either the one passed in or a new one)
|
|
1276
|
-
with the double-click action added, allowing for method chaining.
|
|
1277
|
-
"""
|
|
1278
|
-
|
|
1279
|
-
if action_chain is None:
|
|
1280
|
-
action_chain = self.build_action_chains(duration=duration)
|
|
1281
|
-
|
|
1282
|
-
action_chain.double_click(on_element=element)
|
|
1283
|
-
|
|
1284
|
-
return action_chain
|
|
1285
|
-
|
|
1286
|
-
def download_file(self, file_name: str, target_directory: pathlib.Path):
|
|
1287
|
-
"""
|
|
1288
|
-
Downloads a file from the browser.
|
|
1289
|
-
|
|
1290
|
-
Args:
|
|
1291
|
-
file_name (str): The name of the file to download as it appears in the browser's download list.
|
|
1292
|
-
target_directory (pathlib.Path): The local directory where the file should be saved.
|
|
1293
|
-
"""
|
|
1294
|
-
|
|
1295
|
-
return self._driver.download_file(file_name=file_name, target_directory=str(target_directory.resolve()))
|
|
1296
|
-
|
|
1297
|
-
def drag_and_drop_action(
|
|
1298
|
-
self,
|
|
1299
|
-
source_element: WebElement,
|
|
1300
|
-
target_element: WebElement,
|
|
1301
|
-
duration: int = 250,
|
|
1302
|
-
action_chain: Optional[ActionChains] = None
|
|
1303
|
-
) -> ActionChains:
|
|
1304
|
-
"""
|
|
1305
|
-
Adds a drag-and-drop action from a source element to a target element.
|
|
1306
|
-
|
|
1307
|
-
Combines click-and-hold on the source, move to the target, and release.
|
|
1308
|
-
If an existing ActionChains object is provided via `action_chain`, this action
|
|
1309
|
-
is appended to it. Otherwise, a new ActionChains object is created using
|
|
1310
|
-
`self.build_action_chains` with the specified duration before adding the action.
|
|
1311
|
-
|
|
1312
|
-
Args:
|
|
1313
|
-
source_element (WebElement): The element to click and hold (the start of the drag).
|
|
1314
|
-
target_element (WebElement): The element to move to and release over (the end of the drop).
|
|
1315
|
-
duration (int): The duration in milliseconds to use when creating a new
|
|
1316
|
-
ActionChains instance if `action_chain` is None. Defaults to 250.
|
|
1317
|
-
action_chain (Optional[ActionChains]): An existing ActionChains instance to append
|
|
1318
|
-
this action to. If None, a new chain is created. Defaults to None.
|
|
1319
|
-
|
|
1320
|
-
Returns:
|
|
1321
|
-
ActionChains: The ActionChains instance (either the one passed in or a new one)
|
|
1322
|
-
with the drag-and-drop action added, allowing for method chaining.
|
|
1323
|
-
"""
|
|
1324
|
-
|
|
1325
|
-
if action_chain is None:
|
|
1326
|
-
action_chain = self.build_action_chains(duration=duration)
|
|
1327
|
-
|
|
1328
|
-
action_chain.drag_and_drop(source=source_element, target=target_element)
|
|
1329
|
-
|
|
1330
|
-
return action_chain
|
|
1331
|
-
|
|
1332
|
-
def drag_and_drop_by_offset_action(
|
|
1333
|
-
self,
|
|
1334
|
-
source_element: WebElement,
|
|
1335
|
-
xoffset: int,
|
|
1336
|
-
yoffset: int,
|
|
1337
|
-
duration: int = 250,
|
|
1338
|
-
action_chain: Optional[ActionChains] = None
|
|
1339
|
-
) -> ActionChains:
|
|
1340
|
-
"""
|
|
1341
|
-
Adds a drag-and-drop action from a source element by a given offset.
|
|
1342
|
-
|
|
1343
|
-
Combines click-and-hold on the source, move by the offset, and release.
|
|
1344
|
-
If an existing ActionChains object is provided via `action_chain`, this action
|
|
1345
|
-
is appended to it. Otherwise, a new ActionChains object is created using
|
|
1346
|
-
`self.build_action_chains` with the specified duration before adding the action.
|
|
1347
|
-
|
|
1348
|
-
Args:
|
|
1349
|
-
source_element (WebElement): The element to click and hold (the start of the drag).
|
|
1350
|
-
xoffset (int): The horizontal distance to move the mouse.
|
|
1351
|
-
yoffset (int): The vertical distance to move the mouse.
|
|
1352
|
-
duration (int): The duration in milliseconds to use when creating a new
|
|
1353
|
-
ActionChains instance if `action_chain` is None. Defaults to 250.
|
|
1354
|
-
action_chain (Optional[ActionChains]): An existing ActionChains instance to append
|
|
1355
|
-
this action to. If None, a new chain is created. Defaults to None.
|
|
1356
|
-
|
|
1357
|
-
Returns:
|
|
1358
|
-
ActionChains: The ActionChains instance (either the one passed in or a new one)
|
|
1359
|
-
with the drag-and-drop by offset action added, allowing for method chaining.
|
|
1360
|
-
"""
|
|
1361
|
-
|
|
1362
|
-
if action_chain is None:
|
|
1363
|
-
action_chain = self.build_action_chains(duration=duration)
|
|
1364
|
-
|
|
1365
|
-
action_chain.drag_and_drop_by_offset(source=source_element, xoffset=xoffset, yoffset=yoffset)
|
|
1366
|
-
|
|
1367
|
-
return action_chain
|
|
1368
|
-
|
|
1369
|
-
@property
|
|
1370
|
-
def driver(self) -> Optional[Union[webdriver.Chrome, webdriver.Edge, webdriver.Firefox]]:
|
|
1371
|
-
"""
|
|
1372
|
-
Gets the underlying Selenium WebDriver instance associated with this object.
|
|
1373
|
-
|
|
1374
|
-
This property provides direct access to the WebDriver object (e.g., Chrome, Edge, Firefox)
|
|
1375
|
-
that is being controlled, allowing for direct Selenium operations if needed.
|
|
1376
|
-
|
|
1377
|
-
Returns:
|
|
1378
|
-
Optional[Union[webdriver.Chrome, webdriver.Edge, webdriver.Firefox]]:
|
|
1379
|
-
The active WebDriver instance, or None if no driver is currently set or active.
|
|
1380
|
-
"""
|
|
1381
|
-
|
|
1382
|
-
return self._driver
|
|
1383
|
-
|
|
1384
|
-
async def execute_async_js_script(self, script: str, *args) -> Any:
|
|
1385
|
-
"""
|
|
1386
|
-
Executes an asynchronous JavaScript script in the context of the current page.
|
|
1387
|
-
|
|
1388
|
-
This method allows you to run JavaScript code that can perform asynchronous
|
|
1389
|
-
operations (e.g., fetch data, wait for elements). The script is executed
|
|
1390
|
-
with a callback function as its last argument, which must be called to
|
|
1391
|
-
signal the completion of the script and return a value.
|
|
1392
|
-
|
|
1393
|
-
Args:
|
|
1394
|
-
script (str): The JavaScript code to execute. The script must call
|
|
1395
|
-
the provided callback function (which will be the last argument
|
|
1396
|
-
passed to the script) to signal completion and return a value.
|
|
1397
|
-
For example: `arguments[arguments.length - 1](result);`
|
|
1398
|
-
*args (Any): Variable-length arguments to be passed to the JavaScript script.
|
|
1399
|
-
These arguments will be available in the JavaScript context as `arguments[0]`,
|
|
1400
|
-
`arguments[1]`, etc., before the callback function.
|
|
1401
|
-
|
|
1402
|
-
Returns:
|
|
1403
|
-
Any: The value returned by the JavaScript script via the callback function.
|
|
1404
|
-
The type depends on what the JavaScript script returns.
|
|
1405
|
-
"""
|
|
1406
|
-
|
|
1407
|
-
self._driver.execute_async_script(script, *args)
|
|
1408
|
-
|
|
1409
|
-
@property
|
|
1410
|
-
def fedcm(self) -> FedCM:
|
|
1411
|
-
"""
|
|
1412
|
-
Gets the FedCM (Federated Credential Management) interface.
|
|
1413
|
-
|
|
1414
|
-
Returns:
|
|
1415
|
-
FedCM: An object providing methods to interact with the FedCM API in the browser.
|
|
1416
|
-
"""
|
|
1417
|
-
|
|
1418
|
-
return self._driver.fedcm
|
|
1419
|
-
|
|
1420
|
-
@property
|
|
1421
|
-
def fedcm_dialog(self) -> Dialog:
|
|
1422
|
-
"""
|
|
1423
|
-
Gets the FedCM dialog interface.
|
|
1424
|
-
|
|
1425
|
-
Returns:
|
|
1426
|
-
Dialog: An object providing methods to interact with the FedCM dialog.
|
|
1427
|
-
"""
|
|
1428
|
-
|
|
1429
|
-
return self._driver.dialog
|
|
1430
|
-
|
|
1431
|
-
def set_script_timeout(self, script_timeout: float):
|
|
1432
|
-
"""
|
|
1433
|
-
Sets the script timeout for WebDriver operations.
|
|
1434
|
-
|
|
1435
|
-
Configures the maximum time WebDriver will wait for an JavaScript
|
|
1436
|
-
script to complete its execution before timing out.
|
|
1437
|
-
|
|
1438
|
-
Args:
|
|
1439
|
-
script_timeout (float): The script timeout value in seconds.
|
|
1440
|
-
"""
|
|
1441
|
-
|
|
1442
|
-
self._driver.set_script_timeout(script_timeout)
|
|
1443
|
-
|
|
1444
|
-
def set_implicitly_wait_timeout(self, implicitly_wait_timeout: float):
|
|
1445
|
-
"""
|
|
1446
|
-
Sets the implicit wait timeout for WebDriver element searches.
|
|
1447
|
-
|
|
1448
|
-
Configures the implicit wait time, which is the maximum time WebDriver will wait
|
|
1449
|
-
when searching for elements before throwing a `NoSuchElementException`. This setting
|
|
1450
|
-
applies globally to all element searches for the duration of the WebDriver session.
|
|
1451
|
-
|
|
1452
|
-
Args:
|
|
1453
|
-
implicitly_wait_timeout (float): The implicit wait timeout value in seconds.
|
|
1454
|
-
"""
|
|
1455
|
-
|
|
1456
|
-
self._driver.implicitly_wait(implicitly_wait_timeout)
|
|
1457
|
-
|
|
1458
|
-
def set_page_load_timeout(self, page_load_timeout: float):
|
|
1459
|
-
"""
|
|
1460
|
-
Sets the page load timeout for WebDriver operations.
|
|
1461
|
-
|
|
1462
|
-
Defines the maximum time WebDriver will wait for a page to fully load before timing out
|
|
1463
|
-
and throwing a `TimeoutException`. This is useful to prevent tests from hanging indefinitely
|
|
1464
|
-
on slow-loading pages.
|
|
1465
|
-
|
|
1466
|
-
Args:
|
|
1467
|
-
page_load_timeout (float): The page load timeout value in seconds.
|
|
1468
|
-
"""
|
|
1469
|
-
|
|
1470
|
-
self._driver.set_page_load_timeout(page_load_timeout)
|
|
1471
|
-
|
|
1472
|
-
def set_driver_timeouts(
|
|
1473
|
-
self,
|
|
1474
|
-
page_load_timeout: float,
|
|
1475
|
-
implicit_wait_timeout: float,
|
|
1476
|
-
script_timeout: float,
|
|
1477
|
-
):
|
|
1478
|
-
"""
|
|
1479
|
-
Sets all three WebDriver timeouts: page load, implicit wait, and script timeout.
|
|
1480
|
-
|
|
1481
|
-
Args:
|
|
1482
|
-
page_load_timeout (float): The page load timeout in seconds.
|
|
1483
|
-
implicit_wait_timeout (float): The implicit wait timeout in seconds.
|
|
1484
|
-
script_timeout (float): The script timeout in seconds.
|
|
1485
|
-
"""
|
|
1486
|
-
|
|
1487
|
-
self.set_page_load_timeout(page_load_timeout)
|
|
1488
|
-
self.set_implicitly_wait_timeout(implicit_wait_timeout)
|
|
1489
|
-
self.set_script_timeout(script_timeout)
|
|
1490
|
-
|
|
1491
|
-
def update_times(
|
|
1492
|
-
self,
|
|
1493
|
-
temp_implicitly_wait: Optional[float] = None,
|
|
1494
|
-
temp_page_load_timeout: Optional[float] = None,
|
|
1495
|
-
temp_script_timeout: Optional[float] = None,
|
|
1496
|
-
):
|
|
1497
|
-
"""
|
|
1498
|
-
Updates the WebDriver's timeout settings, adding a small random delay for human-like behavior.
|
|
1499
|
-
|
|
1500
|
-
If temporary timeouts are provided, they are used; otherwise, the base timeouts are used.
|
|
1501
|
-
A random float between 0 and 1 is added to each timeout to simulate variability.
|
|
1502
|
-
|
|
1503
|
-
Args:
|
|
1504
|
-
temp_implicitly_wait (Optional[float]): Temporary implicit wait time in seconds.
|
|
1505
|
-
If provided, overrides the base implicit wait for this update. Defaults to None.
|
|
1506
|
-
temp_page_load_timeout (Optional[float]): Temporary page load timeout in seconds.
|
|
1507
|
-
If provided, overrides the base page load timeout for this update. Defaults to None.
|
|
1508
|
-
temp_script_timeout (Optional[float]): Temporary script timeout in seconds.
|
|
1509
|
-
If provided, overrides the base script timeout for this update. Defaults to None.
|
|
1510
|
-
"""
|
|
1511
|
-
|
|
1512
|
-
if temp_implicitly_wait:
|
|
1513
|
-
implicitly_wait = temp_implicitly_wait + random()
|
|
1514
|
-
else:
|
|
1515
|
-
implicitly_wait = self._base_implicitly_wait + random()
|
|
1516
|
-
|
|
1517
|
-
if temp_page_load_timeout:
|
|
1518
|
-
page_load_timeout = temp_page_load_timeout + random()
|
|
1519
|
-
else:
|
|
1520
|
-
page_load_timeout = self._base_page_load_timeout + random()
|
|
1521
|
-
|
|
1522
|
-
if temp_page_load_timeout:
|
|
1523
|
-
script_timeout = temp_script_timeout + random()
|
|
1524
|
-
else:
|
|
1525
|
-
script_timeout = self._base_script_timeout + random()
|
|
1526
|
-
|
|
1527
|
-
self.set_driver_timeouts(
|
|
1528
|
-
page_load_timeout=page_load_timeout,
|
|
1529
|
-
implicit_wait_timeout=implicitly_wait,
|
|
1530
|
-
script_timeout=script_timeout,
|
|
1531
|
-
)
|
|
1532
|
-
|
|
1533
|
-
def find_inner_web_element(
|
|
1534
|
-
self,
|
|
1535
|
-
parent_element: WebElement,
|
|
1536
|
-
by: str,
|
|
1537
|
-
value: str,
|
|
1538
|
-
temp_implicitly_wait: Optional[int] = None,
|
|
1539
|
-
temp_page_load_timeout: Optional[int] = None,
|
|
1540
|
-
temp_script_timeout: Optional[float] = None,
|
|
1541
|
-
) -> WebElement:
|
|
1542
|
-
"""
|
|
1543
|
-
Finds a single web element within another element.
|
|
1544
|
-
|
|
1545
|
-
Searches for a specific web element that is a descendant of a given parent web element.
|
|
1546
|
-
This is useful for locating elements within a specific section or component of a webpage.
|
|
1547
|
-
|
|
1548
|
-
Args:
|
|
1549
|
-
parent_element (WebElement): The parent web element to search within. The search is scoped to this element's descendants.
|
|
1550
|
-
by (str): Locator strategy to use for finding the element (e.g., By.ID, By.XPATH).
|
|
1551
|
-
value (str): Locator value. The actual string used by the locator strategy to find the element.
|
|
1552
|
-
temp_implicitly_wait (Optional[int]): Temporary implicit wait time in seconds for this operation. Overrides default if provided. Defaults to None.
|
|
1553
|
-
temp_page_load_timeout (Optional[int]): Temporary page load timeout in seconds for this operation. Overrides default if provided. Defaults to None.
|
|
1554
|
-
temp_script_timeout (Optional[int]): Temporary script timeout in seconds for this operation. Overrides default if provided. Defaults to None.
|
|
1555
|
-
|
|
1556
|
-
Returns:
|
|
1557
|
-
WebElement: The found web element. If no element is found within the timeout, a `NoSuchElementException` is raised.
|
|
1558
|
-
"""
|
|
1559
|
-
|
|
1560
|
-
self.update_times(
|
|
1561
|
-
temp_implicitly_wait=temp_implicitly_wait,
|
|
1562
|
-
temp_page_load_timeout=temp_page_load_timeout,
|
|
1563
|
-
temp_script_timeout=temp_script_timeout
|
|
1564
|
-
)
|
|
1565
|
-
return parent_element.find_element(by, value)
|
|
1566
|
-
|
|
1567
|
-
def find_inner_web_elements(
|
|
1568
|
-
self,
|
|
1569
|
-
parent_element: WebElement,
|
|
1570
|
-
by: str,
|
|
1571
|
-
value: str,
|
|
1572
|
-
temp_implicitly_wait: Optional[int] = None,
|
|
1573
|
-
temp_page_load_timeout: Optional[int] = None,
|
|
1574
|
-
temp_script_timeout: Optional[float] = None,
|
|
1575
|
-
) -> list[WebElement]:
|
|
1576
|
-
"""
|
|
1577
|
-
Finds multiple web elements within another element.
|
|
1578
|
-
|
|
1579
|
-
Searches for all web elements that match the given criteria and are descendants of a
|
|
1580
|
-
specified parent web element. Returns a list of all matching elements found within the parent.
|
|
1581
|
-
|
|
1582
|
-
Args:
|
|
1583
|
-
parent_element (WebElement): The parent web element to search within. The search is limited to this element's children.
|
|
1584
|
-
by (str): Locator strategy to use (e.g., By.CLASS_NAME, By.CSS_SELECTOR).
|
|
1585
|
-
value (str): Locator value. Used in conjunction with the 'by' strategy to locate elements.
|
|
1586
|
-
temp_implicitly_wait (Optional[int]): Temporary implicit wait time in seconds for this operation. Defaults to None.
|
|
1587
|
-
temp_page_load_timeout (Optional[int]): Temporary page load timeout in seconds for this operation. Defaults to None.
|
|
1588
|
-
temp_script_timeout (Optional[int]): Temporary script timeout in seconds for this operation. Overrides default if provided. Defaults to None.
|
|
1589
|
-
|
|
1590
|
-
Returns:
|
|
1591
|
-
list[WebElement]: A list of found web elements. Returns an empty list if no elements are found.
|
|
1592
|
-
"""
|
|
1593
|
-
|
|
1594
|
-
self.update_times(
|
|
1595
|
-
temp_implicitly_wait=temp_implicitly_wait,
|
|
1596
|
-
temp_page_load_timeout=temp_page_load_timeout,
|
|
1597
|
-
temp_script_timeout=temp_script_timeout
|
|
1598
|
-
)
|
|
1599
|
-
return parent_element.find_elements(by, value)
|
|
1600
|
-
|
|
1601
|
-
def find_web_element(
|
|
1602
|
-
self,
|
|
1603
|
-
by: str,
|
|
1604
|
-
value: str,
|
|
1605
|
-
temp_implicitly_wait: Optional[int] = None,
|
|
1606
|
-
temp_page_load_timeout: Optional[int] = None,
|
|
1607
|
-
temp_script_timeout: Optional[float] = None,
|
|
1608
|
-
) -> WebElement:
|
|
1609
|
-
"""
|
|
1610
|
-
Finds a single web element on the page.
|
|
1611
|
-
|
|
1612
|
-
Searches the entire webpage DOM for the first web element that matches the specified locator
|
|
1613
|
-
strategy and value. Returns the found element or raises an exception if no element is found within the timeout.
|
|
1614
|
-
|
|
1615
|
-
Args:
|
|
1616
|
-
by (str): Locator strategy to use (e.g., By.ID, By.NAME).
|
|
1617
|
-
value (str): Locator value. Used with the 'by' strategy to identify the element.
|
|
1618
|
-
temp_implicitly_wait (Optional[int]): Temporary implicit wait time in seconds for this operation. Defaults to None.
|
|
1619
|
-
temp_page_load_timeout (Optional[int]): Temporary page load timeout in seconds for this operation. Defaults to None.
|
|
1620
|
-
temp_script_timeout (Optional[int]): Temporary script timeout in seconds for this operation. Overrides default if provided. Defaults to None.
|
|
1621
|
-
|
|
1622
|
-
Returns:
|
|
1623
|
-
WebElement: The found web element.
|
|
1624
|
-
"""
|
|
1625
|
-
|
|
1626
|
-
self.update_times(
|
|
1627
|
-
temp_implicitly_wait=temp_implicitly_wait,
|
|
1628
|
-
temp_page_load_timeout=temp_page_load_timeout,
|
|
1629
|
-
temp_script_timeout=temp_script_timeout
|
|
1630
|
-
)
|
|
1631
|
-
return self._driver.find_element(by, value)
|
|
1632
|
-
|
|
1633
|
-
def find_web_elements(
|
|
1634
|
-
self,
|
|
1635
|
-
by: str,
|
|
1636
|
-
value: str,
|
|
1637
|
-
temp_implicitly_wait: Optional[int] = None,
|
|
1638
|
-
temp_page_load_timeout: Optional[int] = None,
|
|
1639
|
-
temp_script_timeout: Optional[float] = None,
|
|
1640
|
-
) -> list[WebElement]:
|
|
1641
|
-
"""
|
|
1642
|
-
Finds multiple web elements on the page.
|
|
1643
|
-
|
|
1644
|
-
Searches the entire webpage for all web elements that match the specified locator strategy and value.
|
|
1645
|
-
Returns a list containing all matching elements. If no elements are found, an empty list is returned.
|
|
1646
|
-
|
|
1647
|
-
Args:
|
|
1648
|
-
by (str): Locator strategy (e.g., By.TAG_NAME, By.LINK_TEXT).
|
|
1649
|
-
value (str): Locator value. Used with the 'by' strategy to locate elements.
|
|
1650
|
-
temp_implicitly_wait (Optional[int]): Temporary implicit wait time in seconds for this operation. Defaults to None.
|
|
1651
|
-
temp_page_load_timeout (Optional[int]): Temporary page load timeout in seconds for this operation. Defaults to None.
|
|
1652
|
-
temp_script_timeout (Optional[int]): Temporary script timeout in seconds for this operation. Overrides default if provided. Defaults to None.
|
|
1653
|
-
|
|
1654
|
-
Returns:
|
|
1655
|
-
list[WebElement]: A list of found web elements. Returns an empty list if no elements are found.
|
|
1656
|
-
"""
|
|
1657
|
-
|
|
1658
|
-
self.update_times(
|
|
1659
|
-
temp_implicitly_wait=temp_implicitly_wait,
|
|
1660
|
-
temp_page_load_timeout=temp_page_load_timeout,
|
|
1661
|
-
temp_script_timeout=temp_script_timeout
|
|
1662
|
-
)
|
|
1663
|
-
return self._driver.find_elements(by, value)
|
|
1664
|
-
|
|
1665
|
-
def fullscreen_window(self):
|
|
1666
|
-
"""
|
|
1667
|
-
Makes the current browser window full screen.
|
|
1668
|
-
"""
|
|
1669
|
-
|
|
1670
|
-
self._driver.fullscreen_window()
|
|
1671
|
-
|
|
1672
|
-
def get_cookie(self, name: str) -> Optional[dict[str, Any]]:
|
|
1673
|
-
"""
|
|
1674
|
-
Gets a single cookie by its name.
|
|
1675
|
-
|
|
1676
|
-
Args:
|
|
1677
|
-
name (str): The name of the cookie to retrieve.
|
|
1678
|
-
|
|
1679
|
-
Returns:
|
|
1680
|
-
Optional[dict[str, Any]]: A dictionary representing the cookie if found, otherwise None.
|
|
1681
|
-
"""
|
|
1682
|
-
|
|
1683
|
-
return self._driver.get_cookie(name=name)
|
|
1684
|
-
|
|
1685
|
-
def get_credentials(self) -> list[Credential]:
|
|
1686
|
-
"""
|
|
1687
|
-
Gets a list of all registered WebAuthn credentials.
|
|
1688
|
-
|
|
1689
|
-
Returns:
|
|
1690
|
-
list[Credential]: A list of `Credential` objects.
|
|
1691
|
-
"""
|
|
1692
|
-
|
|
1693
|
-
return self._driver.get_credentials()
|
|
1694
|
-
|
|
1695
|
-
def get_document_scroll_size(self) -> Size:
|
|
1696
|
-
"""
|
|
1697
|
-
Gets the total scrollable dimensions of the HTML document.
|
|
1698
|
-
|
|
1699
|
-
Executes a predefined JavaScript snippet to retrieve the document's scrollWidth
|
|
1700
|
-
and scrollHeight.
|
|
1701
|
-
|
|
1702
|
-
Returns:
|
|
1703
|
-
Size: A TypedDict where 'width' represents the document's scrollWidth,
|
|
1704
|
-
'height' represents the scrollHeight.
|
|
1705
|
-
"""
|
|
1706
|
-
|
|
1707
|
-
size = self.execute_js_script(self._js_scripts["get_document_scroll_size"])
|
|
1708
|
-
|
|
1709
|
-
return Size(width=int(size["width"]), height=int(size["height"]))
|
|
1710
|
-
|
|
1711
|
-
def get_downloadable_files(self) -> list[str]:
|
|
1712
|
-
"""
|
|
1713
|
-
Gets a list of downloadable files.
|
|
1714
|
-
|
|
1715
|
-
Returns:
|
|
1716
|
-
list[str]: A list of file names that are currently available for download.
|
|
1717
|
-
"""
|
|
1718
|
-
|
|
1719
|
-
return self._driver.get_downloadable_files()
|
|
1720
|
-
|
|
1721
|
-
def get_element_css_style(self, element: WebElement) -> dict[str, str]:
|
|
1722
|
-
"""
|
|
1723
|
-
Retrieves the computed CSS style of a WebElement.
|
|
1724
|
-
|
|
1725
|
-
Uses JavaScript to get all computed CSS properties and their values for a given web element.
|
|
1726
|
-
Returns a dictionary where keys are CSS property names and values are their computed values.
|
|
1727
|
-
|
|
1728
|
-
Args:
|
|
1729
|
-
element (WebElement): The WebElement for which to retrieve the CSS style.
|
|
1730
|
-
|
|
1731
|
-
Returns:
|
|
1732
|
-
dict[str, str]: A dictionary of CSS property names and their computed values as strings.
|
|
1733
|
-
"""
|
|
1734
|
-
|
|
1735
|
-
return self.execute_js_script(self._js_scripts["get_element_css"], element)
|
|
1736
|
-
|
|
1737
|
-
def get_fedcm_dialog(
|
|
1738
|
-
self,
|
|
1739
|
-
ignored_exceptions: Any,
|
|
1740
|
-
timeout: int = 5,
|
|
1741
|
-
poll_frequency: float = 0.5
|
|
1742
|
-
) -> Dialog:
|
|
1743
|
-
"""
|
|
1744
|
-
Waits for and retrieves the FedCM dialog.
|
|
1745
|
-
|
|
1746
|
-
Args:
|
|
1747
|
-
ignored_exceptions (Any): Exceptions to ignore while waiting for the dialog.
|
|
1748
|
-
timeout (int): The maximum time to wait for the dialog to appear, in seconds. Defaults to 5.
|
|
1749
|
-
poll_frequency (float): How often to check for the dialog's presence, in seconds. Defaults to 0.5.
|
|
1750
|
-
|
|
1751
|
-
Returns:
|
|
1752
|
-
Dialog: The FedCM dialog object.
|
|
1753
|
-
"""
|
|
1754
|
-
|
|
1755
|
-
return self._driver.fedcm_dialog(
|
|
1756
|
-
timeout=timeout,
|
|
1757
|
-
poll_frequency=poll_frequency,
|
|
1758
|
-
ignored_exceptions=ignored_exceptions
|
|
1759
|
-
)
|
|
1760
|
-
|
|
1761
|
-
def get_screenshot_as_base64(self) -> str:
|
|
1762
|
-
"""
|
|
1763
|
-
Gets the screenshot of the current page as a Base64 encoded string.
|
|
1764
|
-
|
|
1765
|
-
Returns:
|
|
1766
|
-
str: A Base64 encoded string representing the screenshot.
|
|
1767
|
-
"""
|
|
1768
|
-
|
|
1769
|
-
return self._driver.get_screenshot_as_base64()
|
|
1770
|
-
|
|
1771
|
-
def get_screenshot_as_file(self, file_path: pathlib.Path) -> bool:
|
|
1772
|
-
"""
|
|
1773
|
-
Saves a screenshot of the current page to a specified file.
|
|
1774
|
-
|
|
1775
|
-
Args:
|
|
1776
|
-
file_path (pathlib.Path): The path where the screenshot should be saved.
|
|
1777
|
-
|
|
1778
|
-
Returns:
|
|
1779
|
-
bool: True if the screenshot was successfully saved, False otherwise.
|
|
1780
|
-
"""
|
|
1781
|
-
|
|
1782
|
-
return self._driver.get_screenshot_as_file(filename=file_path)
|
|
1783
|
-
|
|
1784
|
-
def get_screenshot_as_png(self) -> bytes:
|
|
1785
|
-
"""
|
|
1786
|
-
Gets the screenshot of the current page as a PNG image in bytes.
|
|
1787
|
-
|
|
1788
|
-
Returns:
|
|
1789
|
-
bytes: The screenshot as PNG formatted bytes.
|
|
1790
|
-
"""
|
|
1791
|
-
|
|
1792
|
-
return self._driver.get_screenshot_as_png()
|
|
1793
|
-
|
|
1794
|
-
def get_vars_for_remote(self) -> RemoteConnection:
|
|
1795
|
-
"""
|
|
1796
|
-
Gets variables necessary to create a remote WebDriver instance.
|
|
1797
|
-
|
|
1798
|
-
Provides the command executor and session ID of the current WebDriver instance.
|
|
1799
|
-
These are needed to re-establish a connection to the same browser session from a different WebDriver client,
|
|
1800
|
-
for example, in a distributed testing environment.
|
|
1801
|
-
|
|
1802
|
-
Returns:
|
|
1803
|
-
RemoteConnection: The command executor (for establishing connection).
|
|
1804
|
-
"""
|
|
1805
|
-
|
|
1806
|
-
return self._driver.command_executor
|
|
1807
|
-
|
|
1808
|
-
def get_viewport_position(self) -> Position:
|
|
1809
|
-
"""
|
|
1810
|
-
Gets the current scroll position of the viewport relative to the document origin (0,0).
|
|
1811
|
-
|
|
1812
|
-
Executes a predefined JavaScript snippet to retrieve window.scrollX and window.scrollY.
|
|
1813
|
-
|
|
1814
|
-
Returns:
|
|
1815
|
-
Position: A TypedDict containing the 'x' (horizontal scroll offset) and
|
|
1816
|
-
'y' (vertical scroll offset) of the viewport.
|
|
1817
|
-
"""
|
|
1818
|
-
|
|
1819
|
-
position = self.execute_js_script(self._js_scripts["get_viewport_position"])
|
|
1820
|
-
|
|
1821
|
-
return Position(x=int(position["x"]), y=int(position["y"]))
|
|
1822
|
-
|
|
1823
|
-
def key_down_action(
|
|
1824
|
-
self,
|
|
1825
|
-
value: str,
|
|
1826
|
-
element: Optional[WebElement] = None,
|
|
1827
|
-
duration: int = 250,
|
|
1828
|
-
action_chain: Optional[ActionChains] = None
|
|
1829
|
-
) -> ActionChains:
|
|
1830
|
-
"""
|
|
1831
|
-
Adds a key down (press and hold) action for a specific modifier key.
|
|
1832
|
-
|
|
1833
|
-
Sends the key press to the specified element or the currently focused element.
|
|
1834
|
-
If an existing ActionChains object is provided via `action_chain`, this action
|
|
1835
|
-
is appended to it. Otherwise, a new ActionChains object is created using
|
|
1836
|
-
`self.build_action_chains` with the specified duration before adding the action.
|
|
1837
|
-
|
|
1838
|
-
Args:
|
|
1839
|
-
value (str): The modifier key to press (e.g., Keys.CONTROL, Keys.SHIFT).
|
|
1840
|
-
element (Optional[WebElement]): The element to send the key press to. If None,
|
|
1841
|
-
sends to the currently focused element. Defaults to None.
|
|
1842
|
-
duration (int): The duration in milliseconds to use when creating a new
|
|
1843
|
-
ActionChains instance if `action_chain` is None. Defaults to 250.
|
|
1844
|
-
action_chain (Optional[ActionChains]): An existing ActionChains instance to append
|
|
1845
|
-
this action to. If None, a new chain is created. Defaults to None.
|
|
1846
|
-
|
|
1847
|
-
Returns:
|
|
1848
|
-
ActionChains: The ActionChains instance (either the one passed in or a new one)
|
|
1849
|
-
with the key down action added, allowing for method chaining.
|
|
1850
|
-
"""
|
|
1851
|
-
|
|
1852
|
-
if action_chain is None:
|
|
1853
|
-
action_chain = self.build_action_chains(duration=duration)
|
|
1854
|
-
|
|
1855
|
-
action_chain.key_down(value=value, element=element)
|
|
1856
|
-
|
|
1857
|
-
return action_chain
|
|
1858
|
-
|
|
1859
|
-
def key_up_action(
|
|
1860
|
-
self,
|
|
1861
|
-
value: str,
|
|
1862
|
-
element: Optional[WebElement] = None,
|
|
1863
|
-
duration: int = 250,
|
|
1864
|
-
action_chain: Optional[ActionChains] = None
|
|
1865
|
-
) -> ActionChains:
|
|
1866
|
-
"""
|
|
1867
|
-
Adds a key up (release) action for a specific modifier key.
|
|
1868
|
-
|
|
1869
|
-
Sends the key release to the specified element or the currently focused element.
|
|
1870
|
-
If an existing ActionChains object is provided via `action_chain`, this action
|
|
1871
|
-
is appended to it. Otherwise, a new ActionChains object is created using
|
|
1872
|
-
`self.build_action_chains` with the specified duration before adding the action. Typically used after `key_down_action`.
|
|
1873
|
-
|
|
1874
|
-
Args:
|
|
1875
|
-
value (str): The modifier key to release (e.g., Keys.CONTROL, Keys.SHIFT).
|
|
1876
|
-
element (Optional[WebElement]): The element to send the key release to. If None,
|
|
1877
|
-
sends to the currently focused element. Defaults to None.
|
|
1878
|
-
duration (int): The duration in milliseconds to use when creating a new
|
|
1879
|
-
ActionChains instance if `action_chain` is None. Defaults to 250.
|
|
1880
|
-
action_chain (Optional[ActionChains]): An existing ActionChains instance to append
|
|
1881
|
-
this action to. If None, a new chain is created. Defaults to None.
|
|
1882
|
-
|
|
1883
|
-
Returns:
|
|
1884
|
-
ActionChains: The ActionChains instance (either the one passed in or a new one)
|
|
1885
|
-
with the key up action added, allowing for method chaining.
|
|
1886
|
-
"""
|
|
1887
|
-
|
|
1888
|
-
if action_chain is None:
|
|
1889
|
-
action_chain = self.build_action_chains(duration=duration)
|
|
1890
|
-
|
|
1891
|
-
action_chain.key_up(value=value, element=element)
|
|
1892
|
-
|
|
1893
|
-
return action_chain
|
|
1894
|
-
|
|
1895
|
-
def maximize_window(self):
|
|
1896
|
-
"""
|
|
1897
|
-
Maximizes the current browser window.
|
|
1898
|
-
"""
|
|
1899
|
-
|
|
1900
|
-
self._driver.maximize_window()
|
|
1901
|
-
|
|
1902
|
-
def minimize_window(self):
|
|
1903
|
-
"""
|
|
1904
|
-
Minimizes the current browser window.
|
|
1905
|
-
"""
|
|
1906
|
-
|
|
1907
|
-
self._driver.minimize_window()
|
|
1908
|
-
|
|
1909
|
-
def move_to_element_action(
|
|
1910
|
-
self,
|
|
1911
|
-
element: WebElement,
|
|
1912
|
-
duration: int = 250,
|
|
1913
|
-
action_chain: Optional[ActionChains] = None
|
|
1914
|
-
) -> ActionChains:
|
|
1915
|
-
"""
|
|
1916
|
-
Adds a move mouse cursor action to the specified web element.
|
|
1917
|
-
|
|
1918
|
-
If an existing ActionChains object is provided via `action_chain`, this action
|
|
1919
|
-
is appended to it. Otherwise, a new ActionChains object is created using
|
|
1920
|
-
`self.build_action_chains` with the specified duration before adding the action.
|
|
1921
|
-
|
|
1922
|
-
Args:
|
|
1923
|
-
element (WebElement): The target web element to move the mouse to.
|
|
1924
|
-
duration (int): The duration in milliseconds to use when creating a new
|
|
1925
|
-
ActionChains instance if `action_chain` is None. Defaults to 250.
|
|
1926
|
-
action_chain (Optional[ActionChains]): An existing ActionChains instance to append
|
|
1927
|
-
this action to. If None, a new chain is created. Defaults to None.
|
|
1928
|
-
|
|
1929
|
-
Returns:
|
|
1930
|
-
ActionChains: The ActionChains instance (either the one passed in or a new one)
|
|
1931
|
-
with the move action added, allowing for method chaining.
|
|
1932
|
-
"""
|
|
1933
|
-
|
|
1934
|
-
if action_chain is None:
|
|
1935
|
-
action_chain = self.build_action_chains(duration=duration)
|
|
1936
|
-
|
|
1937
|
-
action_chain.move_to_element(element)
|
|
1938
|
-
|
|
1939
|
-
return action_chain
|
|
1940
|
-
|
|
1941
|
-
def move_to_element_with_offset_action(
|
|
1942
|
-
self,
|
|
1943
|
-
element: WebElement,
|
|
1944
|
-
xoffset: int,
|
|
1945
|
-
yoffset: int,
|
|
1946
|
-
duration: int = 250,
|
|
1947
|
-
action_chain: Optional[ActionChains] = None
|
|
1948
|
-
) -> ActionChains:
|
|
1949
|
-
"""
|
|
1950
|
-
Adds an action to move the mouse cursor to an offset from the center of a specified element.
|
|
1951
|
-
|
|
1952
|
-
If an existing ActionChains object is provided via `action_chain`, this action
|
|
1953
|
-
is appended to it. Otherwise, a new ActionChains object is created using
|
|
1954
|
-
`self.build_action_chains` with the specified duration before adding the action.
|
|
1955
|
-
|
|
1956
|
-
Args:
|
|
1957
|
-
element (WebElement): The target web element to base the offset from.
|
|
1958
|
-
xoffset (int): The horizontal offset from the element's center. Positive is right, negative is left.
|
|
1959
|
-
yoffset (int): The vertical offset from the element's center. Positive is down, negative is up.
|
|
1960
|
-
duration (int): The duration in milliseconds to use when creating a new
|
|
1961
|
-
ActionChains instance if `action_chain` is None. Defaults to 250.
|
|
1962
|
-
action_chain (Optional[ActionChains]): An existing ActionChains instance to append
|
|
1963
|
-
this action to. If None, a new chain is created. Defaults to None.
|
|
1964
|
-
|
|
1965
|
-
Returns:
|
|
1966
|
-
ActionChains: The ActionChains instance (either the one passed in or a new one)
|
|
1967
|
-
with the move-with-offset action added, allowing for method chaining.
|
|
1968
|
-
"""
|
|
1969
|
-
|
|
1970
|
-
if action_chain is None:
|
|
1971
|
-
action_chain = self.build_action_chains(duration=duration)
|
|
1972
|
-
|
|
1973
|
-
action_chain.move_to_element_with_offset(element, xoffset=xoffset, yoffset=yoffset)
|
|
1974
|
-
|
|
1975
|
-
return action_chain
|
|
1976
|
-
|
|
1977
|
-
def open_new_tab(self, link: str = ""):
|
|
1978
|
-
"""
|
|
1979
|
-
Opens a new tab with the given URL.
|
|
1980
|
-
|
|
1981
|
-
Opens a new browser tab and optionally navigates it to a specified URL. If no URL is provided, a blank tab is opened.
|
|
1982
|
-
|
|
1983
|
-
Args:
|
|
1984
|
-
link (str): URL to open in the new tab. If empty, opens a blank tab. Defaults to "".
|
|
1985
|
-
"""
|
|
1986
|
-
|
|
1987
|
-
self.execute_js_script(self._js_scripts["open_new_tab"], link)
|
|
1988
|
-
|
|
1989
|
-
@property
|
|
1990
|
-
def orientation(self) -> Literal["LANDSCAPE", "PORTRAIT"]:
|
|
1991
|
-
"""
|
|
1992
|
-
Gets the current screen orientation (LANDSCAPE or PORTRAIT).
|
|
1993
|
-
|
|
1994
|
-
Returns:
|
|
1995
|
-
Literal["LANDSCAPE", "PORTRAIT"]: The current screen orientation.
|
|
1996
|
-
"""
|
|
1997
|
-
|
|
1998
|
-
return self._driver.orientation
|
|
1999
|
-
|
|
2000
|
-
@orientation.setter
|
|
2001
|
-
def orientation(self, value: Literal["LANDSCAPE", "PORTRAIT"]):
|
|
2002
|
-
"""
|
|
2003
|
-
Sets the screen orientation.
|
|
2004
|
-
|
|
2005
|
-
Args:
|
|
2006
|
-
value (Literal["LANDSCAPE", "PORTRAIT"]): The desired screen orientation.
|
|
2007
|
-
"""
|
|
2008
|
-
|
|
2009
|
-
self._driver.orientation = value
|
|
2010
|
-
|
|
2011
|
-
@property
|
|
2012
|
-
def page_source(self) -> str:
|
|
2013
|
-
"""
|
|
2014
|
-
Gets the HTML source code of the current page.
|
|
2015
|
-
|
|
2016
|
-
Returns:
|
|
2017
|
-
str: The HTML source code as a string.
|
|
2018
|
-
"""
|
|
2019
|
-
|
|
2020
|
-
return self._driver.page_source
|
|
2021
|
-
|
|
2022
|
-
def print_page(self, print_options: Optional[PrintOptions] = None) -> str:
|
|
2023
|
-
"""
|
|
2024
|
-
Prints the current page to PDF.
|
|
2025
|
-
|
|
2026
|
-
Args:
|
|
2027
|
-
print_options (Optional[PrintOptions]): Options for printing the page (e.g., orientation, scale).
|
|
2028
|
-
|
|
2029
|
-
Returns:
|
|
2030
|
-
str: A Base64 encoded string of the PDF document.
|
|
2031
|
-
"""
|
|
2032
|
-
|
|
2033
|
-
return self._driver.print_page(print_options=print_options)
|
|
2034
|
-
|
|
2035
|
-
@property
|
|
2036
|
-
def rect(self) -> WindowRect:
|
|
2037
|
-
"""
|
|
2038
|
-
Gets the window rectangle.
|
|
2039
|
-
|
|
2040
|
-
Retrieves the current position and size of the browser window as a `WindowRect` object.
|
|
2041
|
-
This object contains the x and y coordinates of the window's top-left corner, as well as its width and height.
|
|
2042
|
-
|
|
2043
|
-
Returns:
|
|
2044
|
-
WindowRect: The window rectangle object containing x, y, width, and height.
|
|
2045
|
-
"""
|
|
2046
|
-
|
|
2047
|
-
window_rect = self._driver.get_window_rect()
|
|
2048
|
-
|
|
2049
|
-
return WindowRect(
|
|
2050
|
-
window_rect["x"],
|
|
2051
|
-
window_rect["y"],
|
|
2052
|
-
window_rect["width"],
|
|
2053
|
-
window_rect["height"]
|
|
2054
|
-
)
|
|
2055
|
-
|
|
2056
|
-
def refresh_webdriver(self):
|
|
2057
|
-
"""
|
|
2058
|
-
Refreshes the current page.
|
|
2059
|
-
|
|
2060
|
-
Reloads the currently loaded webpage in the browser. This action fetches the latest version of the page from the server.
|
|
2061
|
-
"""
|
|
2062
|
-
|
|
2063
|
-
self._driver.refresh()
|
|
2064
|
-
|
|
2065
|
-
def release_action(
|
|
2066
|
-
self,
|
|
2067
|
-
element: Optional[WebElement] = None,
|
|
2068
|
-
duration: int = 250,
|
|
2069
|
-
action_chain: Optional[ActionChains] = None
|
|
2070
|
-
) -> ActionChains:
|
|
2071
|
-
"""
|
|
2072
|
-
Adds a release mouse button action. Releases the depressed left mouse button on the specified element or the current mouse position.
|
|
2073
|
-
|
|
2074
|
-
If an existing ActionChains object is provided via `action_chain`, this action
|
|
2075
|
-
is appended to it. Otherwise, a new ActionChains object is created using
|
|
2076
|
-
`self.build_action_chains` with the specified duration before adding the action. Typically used after a `click_and_hold_action`.
|
|
2077
|
-
|
|
2078
|
-
Args:
|
|
2079
|
-
element (Optional[WebElement]): The web element on which to release the mouse button.
|
|
2080
|
-
If None, releases at the current mouse cursor position. Defaults to None.
|
|
2081
|
-
duration (int): The duration in milliseconds to use when creating a new
|
|
2082
|
-
ActionChains instance if `action_chain` is None. Defaults to 250.
|
|
2083
|
-
action_chain (Optional[ActionChains]): An existing ActionChains instance to append
|
|
2084
|
-
this action to. If None, a new chain is created. Defaults to None.
|
|
2085
|
-
|
|
2086
|
-
Returns:
|
|
2087
|
-
ActionChains: The ActionChains instance (either the one passed in or a new one)
|
|
2088
|
-
with the release action added, allowing for method chaining.
|
|
2089
|
-
"""
|
|
2090
|
-
|
|
2091
|
-
if action_chain is None:
|
|
2092
|
-
action_chain = self.build_action_chains(duration=duration)
|
|
2093
|
-
|
|
2094
|
-
action_chain.release(on_element=element)
|
|
2095
|
-
|
|
2096
|
-
return action_chain
|
|
2097
|
-
|
|
2098
|
-
def remote_connect_driver(self, command_executor: Union[str, RemoteConnection]):
|
|
2099
|
-
"""
|
|
2100
|
-
Connects to an existing remote WebDriver session.
|
|
2101
|
-
|
|
2102
|
-
This method establishes a connection to a remote Selenium WebDriver server and reuses an existing browser session of Browser.
|
|
2103
|
-
It allows you to control a browser instance that is already running remotely, given the command executor URL and session ID of that session.
|
|
2104
|
-
|
|
2105
|
-
Args:
|
|
2106
|
-
command_executor (Union[str, RemoteConnection]): The URL of the remote WebDriver server or a `RemoteConnection` object.
|
|
2107
|
-
"""
|
|
2108
|
-
|
|
2109
|
-
self._driver = webdriver.Remote(
|
|
2110
|
-
command_executor=command_executor,
|
|
2111
|
-
options=self._webdriver_flags_manager.options
|
|
2112
|
-
)
|
|
2113
|
-
|
|
2114
|
-
self.set_driver_timeouts(
|
|
2115
|
-
page_load_timeout=self._base_page_load_timeout,
|
|
2116
|
-
implicit_wait_timeout=self._base_implicitly_wait,
|
|
2117
|
-
script_timeout=self._base_script_timeout
|
|
2118
|
-
)
|
|
2119
|
-
|
|
2120
|
-
def remove_all_credentials(self):
|
|
2121
|
-
"""
|
|
2122
|
-
Removes all registered WebAuthn credentials from the browser's virtual authenticator.
|
|
2123
|
-
"""
|
|
2124
|
-
|
|
2125
|
-
self._driver.remove_all_credentials()
|
|
2126
|
-
|
|
2127
|
-
def remove_captcha_worker(self, name: str):
|
|
2128
|
-
"""
|
|
2129
|
-
Removes a captcha worker from the list by its name.
|
|
2130
|
-
|
|
2131
|
-
The method iterates through the registered workers and removes the first one
|
|
2132
|
-
that matches the given name. If no worker with the specified name is found,
|
|
2133
|
-
no action is taken.
|
|
2134
|
-
|
|
2135
|
-
Args:
|
|
2136
|
-
name (str): The name of the captcha worker to remove.
|
|
2137
|
-
"""
|
|
2138
|
-
|
|
2139
|
-
for i, captcha_worker in enumerate(self._captcha_workers):
|
|
2140
|
-
if captcha_worker["name"] == name:
|
|
2141
|
-
self._captcha_workers.pop(i)
|
|
2142
|
-
break
|
|
2143
|
-
|
|
2144
|
-
def remove_credential(self, credential_id: Union[str, bytearray]):
|
|
2145
|
-
"""
|
|
2146
|
-
Removes a specific WebAuthn credential by its ID.
|
|
2147
|
-
|
|
2148
|
-
Args:
|
|
2149
|
-
credential_id (Union[str, bytearray]): The ID of the credential to remove.
|
|
2150
|
-
"""
|
|
2151
|
-
|
|
2152
|
-
self._driver.remove_credential(credential_id=credential_id)
|
|
2153
|
-
|
|
2154
|
-
def remove_virtual_authenticator(self):
|
|
2155
|
-
"""
|
|
2156
|
-
Removes the currently active virtual authenticator from the browser.
|
|
2157
|
-
"""
|
|
2158
|
-
|
|
2159
|
-
self._driver.remove_virtual_authenticator()
|
|
2160
|
-
|
|
2161
|
-
def reset_captcha_workers(self, captcha_workers: Optional[list[CaptchaWorkerSettings]] = None):
|
|
2162
|
-
"""
|
|
2163
|
-
Resets the list of captcha workers, optionally replacing it with a new sequence.
|
|
2164
|
-
|
|
2165
|
-
If `captcha_workers` is provided, the internal list is set to this new sequence.
|
|
2166
|
-
If `captcha_workers` is None, the internal list is cleared.
|
|
2167
|
-
|
|
2168
|
-
Args:
|
|
2169
|
-
captcha_workers (Optional[Sequence[CaptchaWorkerSettings]]): An optional
|
|
2170
|
-
sequence of `CaptchaWorkerSettings` to replace the current list of workers.
|
|
2171
|
-
Defaults to None, which clears the list.
|
|
2172
|
-
"""
|
|
2173
|
-
|
|
2174
|
-
self._captcha_workers = captcha_workers if captcha_workers is not None else []
|
|
2175
|
-
|
|
2176
|
-
def set_trio_tokens_limit(self, trio_tokens_limit: Union[int, float]):
|
|
2177
|
-
"""
|
|
2178
|
-
Updates the total number of tokens for the Trio capacity limiter.
|
|
2179
|
-
|
|
2180
|
-
Args:
|
|
2181
|
-
trio_tokens_limit (Union[int, float]): The new total token limit. Use math.inf for unlimited.
|
|
2182
|
-
"""
|
|
2183
|
-
|
|
2184
|
-
self.trio_capacity_limiter.total_tokens = trio_tokens_limit
|
|
2185
|
-
|
|
2186
|
-
@property
|
|
2187
|
-
def is_active(self) -> bool:
|
|
2188
|
-
"""
|
|
2189
|
-
Checks if the WebDriver instance is currently active and connected.
|
|
2190
|
-
|
|
2191
|
-
This property provides a way to determine the current status of the WebDriver.
|
|
2192
|
-
It reflects whether the WebDriver is initialized and considered operational.
|
|
2193
|
-
|
|
2194
|
-
Returns:
|
|
2195
|
-
bool: True if the WebDriver is active, False otherwise.
|
|
2196
|
-
"""
|
|
2197
|
-
|
|
2198
|
-
return self._is_active
|
|
2199
|
-
|
|
2200
|
-
def reset_settings(
|
|
2201
|
-
self,
|
|
2202
|
-
flags: Optional[BrowserFlags] = None,
|
|
2203
|
-
window_rect: Optional[WindowRect] = None,
|
|
2204
|
-
trio_tokens_limit: Union[int, float] = 40,
|
|
2205
|
-
):
|
|
2206
|
-
"""
|
|
2207
|
-
Resets all configurable browser settings to their default or specified values.
|
|
2208
|
-
|
|
2209
|
-
This method resets various browser settings to the provided values. If no value
|
|
2210
|
-
is provided for certain settings, they are reset to their default states.
|
|
2211
|
-
This can only be done when the browser is not active.
|
|
2212
|
-
|
|
2213
|
-
Args:
|
|
2214
|
-
flags (Optional[BrowserFlags]): A dictionary of flags to apply. If provided, existing flags are cleared and replaced. If None, all flags are cleared.
|
|
2215
|
-
window_rect (Optional[WindowRect]): Updates the window rectangle settings. Defaults to a new WindowRect().
|
|
2216
|
-
trio_tokens_limit (Union[int, float]): The total number of tokens for the Trio capacity limiter. Defaults to 40.
|
|
2217
|
-
"""
|
|
2218
|
-
|
|
2219
|
-
if not self.is_active:
|
|
2220
|
-
if window_rect is None:
|
|
2221
|
-
window_rect = WindowRect()
|
|
2222
|
-
|
|
2223
|
-
if flags is not None:
|
|
2224
|
-
self._webdriver_flags_manager.set_flags(flags)
|
|
2225
|
-
else:
|
|
2226
|
-
self._webdriver_flags_manager.clear_flags()
|
|
2227
|
-
|
|
2228
|
-
self.set_trio_tokens_limit(trio_tokens_limit)
|
|
2229
|
-
self._window_rect = window_rect
|
|
2230
|
-
else:
|
|
2231
|
-
warnings.warn("Browser is already running.")
|
|
2232
|
-
|
|
2233
|
-
def _create_driver(self):
|
|
2234
|
-
"""
|
|
2235
|
-
Abstract method to create a WebDriver instance. Must be implemented in child classes.
|
|
2236
|
-
|
|
2237
|
-
This method is intended to be overridden in subclasses to provide browser-specific
|
|
2238
|
-
WebDriver instantiation logic (e.g., creating ChromeDriver, FirefoxDriver, etc.).
|
|
2239
|
-
|
|
2240
|
-
Raises:
|
|
2241
|
-
NotImplementedError: If the method is not implemented in a subclass.
|
|
2242
|
-
"""
|
|
2243
|
-
|
|
2244
|
-
raise NotImplementedError("This function must be implemented in child classes.")
|
|
2245
|
-
|
|
2246
|
-
def update_settings(
|
|
2247
|
-
self,
|
|
2248
|
-
flags: Optional[Union[BrowserFlags, _any_flags_mapping]] = None,
|
|
2249
|
-
window_rect: Optional[WindowRect] = None,
|
|
2250
|
-
trio_tokens_limit: Optional[Union[int, float]] = None,
|
|
2251
|
-
):
|
|
2252
|
-
"""
|
|
2253
|
-
Updates various browser settings after initialization or selectively.
|
|
2254
|
-
|
|
2255
|
-
This method allows for dynamic updating of browser settings. Only the settings
|
|
2256
|
-
provided (not None) will be updated.
|
|
2257
|
-
|
|
2258
|
-
Args:
|
|
2259
|
-
flags (Optional[Union[BrowserFlags, _any_flags_mapping]]): A dictionary of flags to update. Existing flags will be overwritten, others remain.
|
|
2260
|
-
window_rect (Optional[WindowRect]): Update the window rectangle settings. Defaults to None (no change).
|
|
2261
|
-
trio_tokens_limit (Optional[Union[int, float]]): Update the Trio token limit. Defaults to None (no change).
|
|
2262
|
-
"""
|
|
2263
|
-
|
|
2264
|
-
if flags is not None:
|
|
2265
|
-
self._webdriver_flags_manager.update_flags(flags)
|
|
2266
|
-
|
|
2267
|
-
if window_rect is not None:
|
|
2268
|
-
self._window_rect = window_rect
|
|
2269
|
-
|
|
2270
|
-
if trio_tokens_limit is not None:
|
|
2271
|
-
self.set_trio_tokens_limit(trio_tokens_limit)
|
|
2272
|
-
|
|
2273
|
-
def start_webdriver(
|
|
2274
|
-
self,
|
|
2275
|
-
flags: Optional[Union[BrowserFlags, _any_flags_mapping]] = None,
|
|
2276
|
-
window_rect: Optional[WindowRect] = None,
|
|
2277
|
-
trio_tokens_limit: Optional[Union[int, float]] = None,
|
|
2278
|
-
):
|
|
2279
|
-
"""
|
|
2280
|
-
Starts the WebDriver service and the browser session.
|
|
2281
|
-
|
|
2282
|
-
Initializes and starts the WebDriver instance and the associated browser process.
|
|
2283
|
-
It first updates settings based on provided parameters (if the driver is not already running),
|
|
2284
|
-
and then creates the WebDriver client instance (`self.driver`).
|
|
2285
|
-
|
|
2286
|
-
Args:
|
|
2287
|
-
flags (Optional[Union[BrowserFlags, _any_flags_mapping]]): Override flags for this start. Defaults to None (use current settings).
|
|
2288
|
-
window_rect (Optional[WindowRect]): Override window rectangle for this start. Defaults to None (use current setting).
|
|
2289
|
-
trio_tokens_limit (Optional[Union[int, float]]): Override Trio token limit for this start. Defaults to None (use current setting).
|
|
2290
|
-
"""
|
|
2291
|
-
|
|
2292
|
-
if self._driver is None:
|
|
2293
|
-
self.update_settings(
|
|
2294
|
-
flags=flags,
|
|
2295
|
-
window_rect=window_rect,
|
|
2296
|
-
trio_tokens_limit=trio_tokens_limit,
|
|
2297
|
-
)
|
|
2298
|
-
|
|
2299
|
-
self._create_driver()
|
|
2300
|
-
|
|
2301
|
-
def close_webdriver(self):
|
|
2302
|
-
"""
|
|
2303
|
-
Closes the WebDriver instance and terminates the associated browser subprocess.
|
|
2304
|
-
|
|
2305
|
-
Quits the current WebDriver session, closes all browser windows, and then forcefully terminates
|
|
2306
|
-
the browser process. This ensures a clean shutdown of the browser and WebDriver environment.
|
|
2307
|
-
"""
|
|
2308
|
-
|
|
2309
|
-
if self._driver is not None:
|
|
2310
|
-
self._driver.quit()
|
|
2311
|
-
self._driver = None
|
|
2312
|
-
|
|
2313
|
-
def restart_webdriver(
|
|
2314
|
-
self,
|
|
2315
|
-
flags: Optional[Union[BrowserFlags, _any_flags_mapping]] = None,
|
|
2316
|
-
window_rect: Optional[WindowRect] = None,
|
|
2317
|
-
trio_tokens_limit: Optional[Union[int, float]] = None,
|
|
2318
|
-
):
|
|
2319
|
-
"""
|
|
2320
|
-
Restarts the WebDriver and browser session gracefully.
|
|
2321
|
-
|
|
2322
|
-
Performs a clean restart by first closing the existing WebDriver session and browser
|
|
2323
|
-
(using `close_webdriver`), and then initiating a new session (using `start_webdriver`)
|
|
2324
|
-
with potentially updated settings. If settings arguments are provided, they override
|
|
2325
|
-
the existing settings for the new session; otherwise, the current settings are used.
|
|
2326
|
-
|
|
2327
|
-
Args:
|
|
2328
|
-
flags (Optional[Union[BrowserFlags, _any_flags_mapping]]): Override flags for the new session. Defaults to None (use current).
|
|
2329
|
-
window_rect (Optional[WindowRect]): Override window rectangle for the new session. Defaults to None (use current).
|
|
2330
|
-
trio_tokens_limit (Optional[Union[int, float]]): Override Trio token limit for the new session. Defaults to None (use current).
|
|
2331
|
-
"""
|
|
2332
|
-
|
|
2333
|
-
self.close_webdriver()
|
|
2334
|
-
self.start_webdriver(
|
|
2335
|
-
flags=flags,
|
|
2336
|
-
window_rect=window_rect,
|
|
2337
|
-
trio_tokens_limit=trio_tokens_limit,
|
|
2338
|
-
)
|
|
2339
|
-
|
|
2340
|
-
def scroll_by_amount_action(
|
|
2341
|
-
self,
|
|
2342
|
-
delta_x: int,
|
|
2343
|
-
delta_y: int,
|
|
2344
|
-
duration: int = 250,
|
|
2345
|
-
action_chain: Optional[ActionChains] = None
|
|
2346
|
-
) -> ActionChains:
|
|
2347
|
-
"""
|
|
2348
|
-
Adds a scroll action to the current mouse position by the specified amounts.
|
|
2349
|
-
|
|
2350
|
-
If an existing ActionChains object is provided via `action_chain`, this action
|
|
2351
|
-
is appended to it. Otherwise, a new ActionChains object is created using
|
|
2352
|
-
`self.build_action_chains` with the specified duration before adding the action.
|
|
2353
|
-
|
|
2354
|
-
Args:
|
|
2355
|
-
delta_x (int): The amount to scroll horizontally. Positive scrolls right, negative scrolls left.
|
|
2356
|
-
delta_y (int): The amount to scroll vertically. Positive scrolls down, negative scrolls up.
|
|
2357
|
-
duration (int): The duration in milliseconds to use when creating a new
|
|
2358
|
-
ActionChains instance if `action_chain` is None. Defaults to 250.
|
|
2359
|
-
action_chain (Optional[ActionChains]): An existing ActionChains instance to append
|
|
2360
|
-
this action to. If None, a new chain is created. Defaults to None.
|
|
2361
|
-
|
|
2362
|
-
Returns:
|
|
2363
|
-
ActionChains: The ActionChains instance (either the one passed in or a new one)
|
|
2364
|
-
with the scroll action added, allowing for method chaining.
|
|
2365
|
-
"""
|
|
2366
|
-
|
|
2367
|
-
if action_chain is None:
|
|
2368
|
-
action_chain = self.build_action_chains(duration=duration)
|
|
2369
|
-
|
|
2370
|
-
action_chain.scroll_by_amount(delta_x=delta_x, delta_y=delta_y)
|
|
2371
|
-
|
|
2372
|
-
return action_chain
|
|
2373
|
-
|
|
2374
|
-
def scroll_from_origin_action(
|
|
2375
|
-
self,
|
|
2376
|
-
origin: ScrollOrigin,
|
|
2377
|
-
delta_x: int,
|
|
2378
|
-
delta_y: int,
|
|
2379
|
-
duration: int = 250,
|
|
2380
|
-
action_chain: Optional[ActionChains] = None
|
|
2381
|
-
) -> ActionChains:
|
|
2382
|
-
"""
|
|
2383
|
-
Adds a scroll action relative to a specified origin (viewport or element center).
|
|
2384
|
-
|
|
2385
|
-
If an existing ActionChains object is provided via `action_chain`, this action
|
|
2386
|
-
is appended to it. Otherwise, a new ActionChains object is created using
|
|
2387
|
-
`self.build_action_chains` with the specified duration before adding the action.
|
|
2388
|
-
|
|
2389
|
-
Args:
|
|
2390
|
-
origin (ScrollOrigin): The origin point for the scroll. This object defines
|
|
2391
|
-
whether the scroll is relative to the viewport or an element's center.
|
|
2392
|
-
Use `ScrollOrigin.from_viewport()` or `ScrollOrigin.from_element()`.
|
|
2393
|
-
delta_x (int): The horizontal scroll amount. Positive scrolls right, negative left.
|
|
2394
|
-
delta_y (int): The vertical scroll amount. Positive scrolls down, negative up.
|
|
2395
|
-
duration (int): The duration in milliseconds to use when creating a new
|
|
2396
|
-
ActionChains instance if `action_chain` is None. Defaults to 250.
|
|
2397
|
-
action_chain (Optional[ActionChains]): An existing ActionChains instance to append
|
|
2398
|
-
this action to. If None, a new chain is created. Defaults to None.
|
|
2399
|
-
|
|
2400
|
-
Returns:
|
|
2401
|
-
ActionChains: The ActionChains instance (either the one passed in or a new one)
|
|
2402
|
-
with the scroll action added, allowing for method chaining.
|
|
2403
|
-
"""
|
|
2404
|
-
|
|
2405
|
-
if action_chain is None:
|
|
2406
|
-
action_chain = self.build_action_chains(duration=duration)
|
|
2407
|
-
|
|
2408
|
-
action_chain.scroll_from_origin(scroll_origin=origin, delta_x=delta_x, delta_y=delta_y)
|
|
2409
|
-
|
|
2410
|
-
return action_chain
|
|
2411
|
-
|
|
2412
|
-
def scroll_to_element_action(
|
|
2413
|
-
self,
|
|
2414
|
-
element: WebElement,
|
|
2415
|
-
duration: int = 250,
|
|
2416
|
-
action_chain: Optional[ActionChains] = None
|
|
2417
|
-
) -> ActionChains:
|
|
2418
|
-
"""
|
|
2419
|
-
Adds an action to scroll the viewport until the specified element is in view.
|
|
2420
|
-
|
|
2421
|
-
If an existing ActionChains object is provided via `action_chain`, this action
|
|
2422
|
-
is appended to it. Otherwise, a new ActionChains object is created using
|
|
2423
|
-
`self.build_action_chains` with the specified duration before adding the action.
|
|
2424
|
-
|
|
2425
|
-
Args:
|
|
2426
|
-
element (WebElement): The target web element to scroll into view.
|
|
2427
|
-
duration (int): The duration in milliseconds to use when creating a new
|
|
2428
|
-
ActionChains instance if `action_chain` is None. Defaults to 250.
|
|
2429
|
-
action_chain (Optional[ActionChains]): An existing ActionChains instance to append
|
|
2430
|
-
this action to. If None, a new chain is created. Defaults to None.
|
|
2431
|
-
|
|
2432
|
-
Returns:
|
|
2433
|
-
ActionChains: The ActionChains instance (either the one passed in or a new one)
|
|
2434
|
-
with the scroll-to-element action added, allowing for method chaining.
|
|
2435
|
-
"""
|
|
2436
|
-
|
|
2437
|
-
if action_chain is None:
|
|
2438
|
-
action_chain = self.build_action_chains(duration=duration)
|
|
2439
|
-
|
|
2440
|
-
action_chain.scroll_to_element(element)
|
|
2441
|
-
|
|
2442
|
-
return action_chain
|
|
2443
|
-
|
|
2444
|
-
def search_url(
|
|
2445
|
-
self,
|
|
2446
|
-
url: str,
|
|
2447
|
-
temp_implicitly_wait: Optional[int] = None,
|
|
2448
|
-
temp_page_load_timeout: Optional[int] = None
|
|
2449
|
-
):
|
|
2450
|
-
"""
|
|
2451
|
-
Opens a URL in the current browser session.
|
|
2452
|
-
|
|
2453
|
-
Navigates the browser to a specified URL. This action loads the new webpage in the current browser window or tab.
|
|
2454
|
-
|
|
2455
|
-
Args:
|
|
2456
|
-
url (str): The URL to open. Must be a valid web address (e.g., "https://www.example.com").
|
|
2457
|
-
temp_implicitly_wait (Optional[int]): Temporary implicit wait time in seconds for page load. Defaults to None.
|
|
2458
|
-
temp_page_load_timeout (Optional[int]): Temporary page load timeout in seconds for page load. Defaults to None.
|
|
2459
|
-
"""
|
|
2460
|
-
|
|
2461
|
-
self.update_times(temp_implicitly_wait, temp_page_load_timeout)
|
|
2462
|
-
self._driver.get(url)
|
|
2463
|
-
|
|
2464
|
-
def send_keys_action(
|
|
2465
|
-
self,
|
|
2466
|
-
keys_to_send: str,
|
|
2467
|
-
duration: int = 250,
|
|
2468
|
-
action_chain: Optional[ActionChains] = None
|
|
2469
|
-
) -> ActionChains:
|
|
2470
|
-
"""
|
|
2471
|
-
Adds a send keys action to the currently focused element.
|
|
2472
|
-
|
|
2473
|
-
If an existing ActionChains object is provided via `action_chain`, this action
|
|
2474
|
-
is appended to it. Otherwise, a new ActionChains object is created using
|
|
2475
|
-
`self.build_action_chains` with the specified duration before adding the action.
|
|
2476
|
-
|
|
2477
|
-
Args:
|
|
2478
|
-
keys_to_send (str): The sequence of keys to send.
|
|
2479
|
-
duration (int): The duration in milliseconds to use when creating a new
|
|
2480
|
-
ActionChains instance if `action_chain` is None. Defaults to 250.
|
|
2481
|
-
action_chain (Optional[ActionChains]): An existing ActionChains instance to append
|
|
2482
|
-
this action to. If None, a new chain is created. Defaults to None.
|
|
2483
|
-
|
|
2484
|
-
Returns:
|
|
2485
|
-
ActionChains: The ActionChains instance (either the one passed in or a new one)
|
|
2486
|
-
with the send keys action added, allowing for method chaining.
|
|
2487
|
-
"""
|
|
2488
|
-
|
|
2489
|
-
if action_chain is None:
|
|
2490
|
-
action_chain = self.build_action_chains(duration=duration)
|
|
2491
|
-
|
|
2492
|
-
action_chain.send_keys(keys_to_send)
|
|
2493
|
-
|
|
2494
|
-
return action_chain
|
|
2495
|
-
|
|
2496
|
-
def send_keys_to_element_action(
|
|
2497
|
-
self,
|
|
2498
|
-
element: WebElement,
|
|
2499
|
-
keys_to_send: str,
|
|
2500
|
-
duration: int = 250,
|
|
2501
|
-
action_chain: Optional[ActionChains] = None
|
|
2502
|
-
) -> ActionChains:
|
|
2503
|
-
"""
|
|
2504
|
-
Adds a send keys action specifically to the provided web element.
|
|
2505
|
-
|
|
2506
|
-
If an existing ActionChains object is provided via `action_chain`, this action
|
|
2507
|
-
is appended to it. Otherwise, a new ActionChains object is created using
|
|
2508
|
-
`self.build_action_chains` with the specified duration before adding the action.
|
|
2509
|
-
|
|
2510
|
-
Args:
|
|
2511
|
-
element (WebElement): The target web element to send keys to.
|
|
2512
|
-
keys_to_send (str): The sequence of keys to send.
|
|
2513
|
-
duration (int): The duration in milliseconds to use when creating a new
|
|
2514
|
-
ActionChains instance if `action_chain` is None. Defaults to 250.
|
|
2515
|
-
action_chain (Optional[ActionChains]): An existing ActionChains instance to append
|
|
2516
|
-
this action to. If None, a new chain is created. Defaults to None.
|
|
2517
|
-
|
|
2518
|
-
Returns:
|
|
2519
|
-
ActionChains: The ActionChains instance (either the one passed in or a new one)
|
|
2520
|
-
with the send keys to element action added, allowing for method chaining.
|
|
2521
|
-
"""
|
|
2522
|
-
|
|
2523
|
-
if action_chain is None:
|
|
2524
|
-
action_chain = self.build_action_chains(duration=duration)
|
|
2525
|
-
|
|
2526
|
-
action_chain.send_keys_to_element(element, keys_to_send)
|
|
2527
|
-
|
|
2528
|
-
return action_chain
|
|
2529
|
-
|
|
2530
|
-
def set_captcha_worker(self, captcha_worker: CaptchaWorkerSettings):
|
|
2531
|
-
"""
|
|
2532
|
-
Adds a captcha worker configuration to the list of workers.
|
|
2533
|
-
|
|
2534
|
-
Args:
|
|
2535
|
-
captcha_worker (CaptchaWorkerSettings): The captcha worker settings to add.
|
|
2536
|
-
"""
|
|
2537
|
-
|
|
2538
|
-
self._captcha_workers.append(captcha_worker)
|
|
2539
|
-
|
|
2540
|
-
def set_user_verified(self, verified: bool):
|
|
2541
|
-
"""
|
|
2542
|
-
Sets the user verification state for WebAuthn.
|
|
2543
|
-
|
|
2544
|
-
This is typically used with virtual authenticators to simulate user verification.
|
|
2545
|
-
|
|
2546
|
-
Args:
|
|
2547
|
-
verified (bool): True to set the user as verified, False otherwise.
|
|
2548
|
-
"""
|
|
2549
|
-
|
|
2550
|
-
self._driver.set_user_verified(verified=verified)
|
|
2551
|
-
|
|
2552
|
-
def set_window_rect(self, rect: WindowRect):
|
|
2553
|
-
"""
|
|
2554
|
-
Sets the browser window rectangle.
|
|
2555
|
-
|
|
2556
|
-
Adjusts the position and size of the browser window to the specified rectangle. This can be used
|
|
2557
|
-
to manage window placement and dimensions for testing or display purposes.
|
|
2558
|
-
|
|
2559
|
-
Args:
|
|
2560
|
-
rect (WindowRect): An object containing the desired window rectangle parameters (x, y, width, height).
|
|
2561
|
-
"""
|
|
2562
|
-
|
|
2563
|
-
self._driver.set_window_rect(x=rect.x, y=rect.y, width=rect.width, height=rect.height)
|
|
2564
|
-
|
|
2565
|
-
def stop_window_loading(self):
|
|
2566
|
-
"""
|
|
2567
|
-
Stops the current page loading.
|
|
2568
|
-
|
|
2569
|
-
Interrupts the loading process of the current webpage. This can be useful when a page is taking too long
|
|
2570
|
-
to load or when you want to halt resource loading for performance testing or specific scenarios.
|
|
2571
|
-
"""
|
|
2572
|
-
|
|
2573
|
-
self.execute_js_script(self._js_scripts["stop_window_loading"])
|
|
2574
|
-
|
|
2575
|
-
@property
|
|
2576
|
-
def supports_fedcm(self) -> bool:
|
|
2577
|
-
"""
|
|
2578
|
-
Checks if the browser supports the Federated Credential Management (FedCM) API.
|
|
2579
|
-
|
|
2580
|
-
Returns:
|
|
2581
|
-
bool: True if FedCM is supported, False otherwise.
|
|
2582
|
-
"""
|
|
2583
|
-
|
|
2584
|
-
return self._driver.supports_fedcm
|
|
2585
|
-
|
|
2586
|
-
def switch_to_frame(self, frame: Union[str, int, WebElement]):
|
|
2587
|
-
"""
|
|
2588
|
-
Switches the driver's focus to a frame.
|
|
2589
|
-
|
|
2590
|
-
Changes the WebDriver's focus to a specific frame within the current page. Frames are often used to embed
|
|
2591
|
-
content from other sources within a webpage. After switching to a frame, all WebDriver commands will be
|
|
2592
|
-
directed to elements within that frame until focus is switched back.
|
|
2593
|
-
|
|
2594
|
-
Args:
|
|
2595
|
-
frame (Union[str, int, WebElement]): Specifies the frame to switch to. Can be a frame name (str), index (int), or a WebElement representing the frame.
|
|
2596
|
-
"""
|
|
2597
|
-
|
|
2598
|
-
self._driver.switch_to.frame(frame)
|
|
2599
|
-
|
|
2600
|
-
def to_wrapper(self) -> TrioWebDriverWrapperProtocol:
|
|
2601
|
-
"""
|
|
2602
|
-
Creates a TrioBrowserWebDriverWrapper instance for asynchronous operations with Trio.
|
|
2603
|
-
|
|
2604
|
-
Wraps the ...WebDriver instance in a TrioBrowserWebDriverWrapper, which allows for running WebDriver
|
|
2605
|
-
commands in a non-blocking manner within a Trio asynchronous context. This is essential for
|
|
2606
|
-
integrating Selenium WebDriver with asynchronous frameworks like Trio.
|
|
2607
|
-
|
|
2608
|
-
Returns:
|
|
2609
|
-
TrioWebDriverWrapperProtocol: A TrioBrowserWebDriverWrapper instance wrapping this BrowserWebDriver.
|
|
2610
|
-
"""
|
|
2611
|
-
|
|
2612
|
-
return cast(
|
|
2613
|
-
TrioWebDriverWrapperProtocol,
|
|
2614
|
-
TrioBrowserWebDriverWrapper(_webdriver=self)
|
|
2615
|
-
)
|
|
2616
|
-
|
|
2617
|
-
@property
|
|
2618
|
-
def virtual_authenticator_id(self) -> Optional[str]:
|
|
2619
|
-
"""
|
|
2620
|
-
Gets the ID of the active virtual authenticator.
|
|
2621
|
-
|
|
2622
|
-
Returns:
|
|
2623
|
-
Optional[str]: The ID of the virtual authenticator if one is active, otherwise None.
|
|
2624
|
-
"""
|
|
2625
|
-
|
|
2626
|
-
return self._driver.virtual_authenticator_id
|