wavexis 2.2.0__tar.gz → 2.2.1__tar.gz
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.
- {wavexis-2.2.0 → wavexis-2.2.1}/CHANGELOG.md +9 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/PKG-INFO +1 -1
- {wavexis-2.2.0 → wavexis-2.2.1}/pyproject.toml +1 -1
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_global_options.py +16 -1
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/__init__.py +1 -1
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/backend/cdp.py +13 -5
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/cli/_shared.py +9 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/config.py +2 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/.dockerignore +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/.github/workflows/ci.yml +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/.github/workflows/docs.yml +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/.github/workflows/release.yml +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/.gitignore +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/CODE_OF_CONDUCT.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/CONTRIBUTING.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/Dockerfile +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/LICENSE +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/README.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/SECURITY.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/api/actions.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/api/backends.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/api/cli.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/api/config.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/api/exceptions.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/api/multi.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/api/plugins.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/api/serve.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/cookbook/auth.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/cookbook/ci-cd.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/cookbook/css.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/cookbook/debug.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/cookbook/record-replay.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/cookbook/scraping.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/cookbook/screenshots.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/cookbook/serve-mode.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/guide/assert.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/guide/backends.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/guide/commands.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/guide/init.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/guide/installation.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/guide/multi.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/guide/perf.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/guide/plugins.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/guide/quickstart.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/guide/raw.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/guide/repl.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/guide/troubleshooting.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/docs/index.md +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/mkdocs.yml +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/stubs/bidiwave/__init__.pyi +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/stubs/cdpwave/__init__.pyi +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/__init__.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/conftest.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/__init__.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_a11y.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_animation.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_backend_selection.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_browser.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_console.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_css.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_debug.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_dialog.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_dom.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_dom_snapshot.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_emulation.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_emulation_advanced.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_eval.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_har.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_input.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_media.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_multi.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_navigate.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_network.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_network_advanced.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_overlay.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_pdf.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_perf.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_permissions.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_raw.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_record.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_scrape.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_screenshot.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_security.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_serve.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_service_worker.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_storage.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_tabs.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_webaudio.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/integration/test_webauthn.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/__init__.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_abstract_backend_phase5.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_actions.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_actions_phase5.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_animation_action.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_assert_multi.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_auth.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_backend_manager.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_bidi_backend.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_bidi_phase5.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_bluetooth_action.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_cast_action.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_cli_phase5.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_config.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_config_phase5.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_cookies_headers_actions.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_css_action.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_debug_action.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_dom_snapshot_action.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_download_screencast.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_emulation_action.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_error_handling.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_exceptions.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_format_record.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_init.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_input_action.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_interactions_crawl.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_manager.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_media_action.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_multi.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_multi_improvements.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_new_features.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_output.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_overlay_action.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_perf_action.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_perf_console.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_plugins.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_raw.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_record.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_repl.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_serve.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_service_worker_action.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_storage_action.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_webaudio_action.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/tests/unit/test_webauthn_action.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/__main__.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/__init__.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/accessibility.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/animation.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/base.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/bluetooth.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/browser.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/cast.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/console.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/cookies.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/crawl.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/css.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/debug.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/dialog.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/dom.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/dom_snapshot.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/download.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/emulation.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/eval.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/extract.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/form.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/har.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/headers.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/input.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/lighthouse.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/media.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/multi.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/navigate.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/network.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/overlay.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/pdf.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/performance.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/permissions.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/record.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/scrape.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/screencast.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/screenshot.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/security.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/service_worker.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/session.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/storage.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/tabs.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/wait.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/webaudio.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/webauthn.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/actions/websocket.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/auth.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/backend/__init__.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/backend/base.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/backend/bidi.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/backend/manager.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/cli/__init__.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/cli/_advanced.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/cli/_capture.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/cli/_config.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/cli/_debug.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/cli/_emulation.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/cli/_experimental.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/cli/_input.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/cli/_navigation.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/cli/_network.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/cli/_perf.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/cli/_serve.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/cli/_session.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/cli/_workflow.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/cli/app.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/exceptions.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/init.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/multi.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/output.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/plugins.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/record.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/repl.py +0 -0
- {wavexis-2.2.0 → wavexis-2.2.1}/wavexis/serve.py +0 -0
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to wavexis are documented in this file.
|
|
4
4
|
|
|
5
|
+
## v2.2.1 — 2026-07-07
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `--browser-url` global flag to connect to an existing browser (e.g. `--browser-url ws://localhost:9222`)
|
|
10
|
+
- `browser_url` field in `BrowserOptions` dataclass
|
|
11
|
+
- `browser_url` support in `config.yml` (`browser_url: ws://localhost:9222`)
|
|
12
|
+
- `CDPBackend.launch()` now uses `CDPClient.connect()` when `browser_url` is set instead of launching a new browser
|
|
13
|
+
|
|
5
14
|
## v2.2.0 — 2026-07-07
|
|
6
15
|
|
|
7
16
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wavexis
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.1
|
|
4
4
|
Summary: Browser automation CLI — wraps cdpwave and bidiwave, no Node.js, no Chromium download
|
|
5
5
|
Project-URL: Homepage, https://github.com/MathiasPaulenko/wavexis
|
|
6
6
|
Project-URL: Repository, https://github.com/MathiasPaulenko/wavexis
|
|
@@ -31,6 +31,11 @@ class TestBrowserOptions:
|
|
|
31
31
|
assert opts.proxy is None
|
|
32
32
|
assert opts.timeout == 30000
|
|
33
33
|
assert opts.user_data_dir is None
|
|
34
|
+
assert opts.browser_url is None
|
|
35
|
+
|
|
36
|
+
def test_with_browser_url(self) -> None:
|
|
37
|
+
opts = BrowserOptions(browser_url="ws://localhost:9222")
|
|
38
|
+
assert opts.browser_url == "ws://localhost:9222"
|
|
34
39
|
|
|
35
40
|
def test_with_user_data_dir(self) -> None:
|
|
36
41
|
opts = BrowserOptions(user_data_dir="/tmp/wavexis-profile")
|
|
@@ -63,6 +68,13 @@ class TestBrowserOptionsHelper:
|
|
|
63
68
|
assert opts.timeout == 30000
|
|
64
69
|
assert opts.proxy is None
|
|
65
70
|
assert opts.user_data_dir is None
|
|
71
|
+
assert opts.browser_url is None
|
|
72
|
+
|
|
73
|
+
def test_browser_url_options(self) -> None:
|
|
74
|
+
ctx = _fresh_ctx()
|
|
75
|
+
ctx.browser_url = "ws://localhost:9222"
|
|
76
|
+
opts = _cli._browser_options()
|
|
77
|
+
assert opts.browser_url == "ws://localhost:9222"
|
|
66
78
|
|
|
67
79
|
def test_user_data_dir_options(self) -> None:
|
|
68
80
|
ctx = _fresh_ctx()
|
|
@@ -101,6 +113,7 @@ class TestLoadGlobalConfig:
|
|
|
101
113
|
assert ctx.timeout == 30000
|
|
102
114
|
assert ctx.proxy is None
|
|
103
115
|
assert ctx.user_data_dir is None
|
|
116
|
+
assert ctx.browser_url is None
|
|
104
117
|
|
|
105
118
|
def test_loads_config(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
106
119
|
config_dir = tmp_path / ".wavexis"
|
|
@@ -111,7 +124,8 @@ class TestLoadGlobalConfig:
|
|
|
111
124
|
"headless: false\n"
|
|
112
125
|
"timeout: 60000\n"
|
|
113
126
|
"proxy: http://proxy:9090\n"
|
|
114
|
-
"user_data_dir: /tmp/profile\n"
|
|
127
|
+
"user_data_dir: /tmp/profile\n"
|
|
128
|
+
"browser_url: ws://localhost:9222\n",
|
|
115
129
|
encoding="utf-8",
|
|
116
130
|
)
|
|
117
131
|
monkeypatch.setattr(Path, "home", lambda: tmp_path)
|
|
@@ -124,6 +138,7 @@ class TestLoadGlobalConfig:
|
|
|
124
138
|
assert ctx.timeout == 60000
|
|
125
139
|
assert ctx.proxy == "http://proxy:9090"
|
|
126
140
|
assert ctx.user_data_dir == "/tmp/profile"
|
|
141
|
+
assert ctx.browser_url == "ws://localhost:9222"
|
|
127
142
|
|
|
128
143
|
def test_cli_overrides_config(
|
|
129
144
|
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
@@ -83,11 +83,19 @@ class CDPBackend(AbstractBackend):
|
|
|
83
83
|
if options.proxy:
|
|
84
84
|
extra_args.append(f"--proxy-server={options.proxy}")
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
if options.browser_url:
|
|
87
|
+
from urllib.parse import urlparse
|
|
88
|
+
|
|
89
|
+
parsed = urlparse(options.browser_url)
|
|
90
|
+
host = parsed.hostname or "localhost"
|
|
91
|
+
port = parsed.port or 9222
|
|
92
|
+
self._client = await CDPClient.connect(host=host, port=port) # type: ignore[attr-defined]
|
|
93
|
+
else:
|
|
94
|
+
self._client = await CDPClient.launch(
|
|
95
|
+
headless=options.headless,
|
|
96
|
+
user_data_dir=options.user_data_dir, # type: ignore[call-arg]
|
|
97
|
+
extra_args=extra_args if extra_args else None,
|
|
98
|
+
)
|
|
91
99
|
self._session = await self._client.new_page()
|
|
92
100
|
|
|
93
101
|
if options.user_agent:
|
|
@@ -76,6 +76,7 @@ class CLIContext:
|
|
|
76
76
|
timeout: int = 30000
|
|
77
77
|
proxy: str | None = None
|
|
78
78
|
user_data_dir: str | None = None
|
|
79
|
+
browser_url: str | None = None
|
|
79
80
|
|
|
80
81
|
|
|
81
82
|
_ctx: contextvars.ContextVar[CLIContext | None] = contextvars.ContextVar(
|
|
@@ -116,6 +117,8 @@ def _load_global_config() -> None:
|
|
|
116
117
|
ctx.proxy = str(raw["proxy"])
|
|
117
118
|
if "user_data_dir" in raw:
|
|
118
119
|
ctx.user_data_dir = str(raw["user_data_dir"])
|
|
120
|
+
if "browser_url" in raw:
|
|
121
|
+
ctx.browser_url = str(raw["browser_url"])
|
|
119
122
|
except (OSError, ValueError, TypeError, yaml.YAMLError) as exc:
|
|
120
123
|
if ctx.verbose:
|
|
121
124
|
_echo(f"Warning: failed to load config from {config_path}: {exc}")
|
|
@@ -144,6 +147,9 @@ def main_callback(
|
|
|
144
147
|
user_data_dir: str | None = typer.Option(
|
|
145
148
|
None, "--user-data-dir", help="Path to persistent browser profile directory"
|
|
146
149
|
),
|
|
150
|
+
browser_url: str | None = typer.Option(
|
|
151
|
+
None, "--browser-url", help="Connect to existing browser (e.g. ws://localhost:9222)"
|
|
152
|
+
),
|
|
147
153
|
version: bool = typer.Option(
|
|
148
154
|
False, "--version", help="Print wavexis version and exit"
|
|
149
155
|
),
|
|
@@ -162,6 +168,8 @@ def main_callback(
|
|
|
162
168
|
ctx.proxy = proxy
|
|
163
169
|
if user_data_dir:
|
|
164
170
|
ctx.user_data_dir = user_data_dir
|
|
171
|
+
if browser_url:
|
|
172
|
+
ctx.browser_url = browser_url
|
|
165
173
|
if version:
|
|
166
174
|
from wavexis import __version__
|
|
167
175
|
|
|
@@ -236,6 +244,7 @@ def _browser_options() -> BrowserOptions:
|
|
|
236
244
|
timeout=ctx.timeout,
|
|
237
245
|
proxy=ctx.proxy,
|
|
238
246
|
user_data_dir=ctx.user_data_dir,
|
|
247
|
+
browser_url=ctx.browser_url,
|
|
239
248
|
)
|
|
240
249
|
|
|
241
250
|
|
|
@@ -147,6 +147,7 @@ class BrowserOptions:
|
|
|
147
147
|
proxy: Proxy server URL (e.g. http://proxy:8080 or socks5://proxy:1080).
|
|
148
148
|
timeout: Default navigation timeout in milliseconds.
|
|
149
149
|
user_data_dir: Path to a persistent user data directory for browser profiles.
|
|
150
|
+
browser_url: URL of an existing browser to connect to (e.g. ws://localhost:9222).
|
|
150
151
|
"""
|
|
151
152
|
|
|
152
153
|
headless: bool = True
|
|
@@ -157,6 +158,7 @@ class BrowserOptions:
|
|
|
157
158
|
proxy: str | None = None
|
|
158
159
|
timeout: int = 30000
|
|
159
160
|
user_data_dir: str | None = None
|
|
161
|
+
browser_url: str | None = None
|
|
160
162
|
|
|
161
163
|
|
|
162
164
|
@dataclass
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|