wavexis 2.0.0__tar.gz → 2.0.2__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.0.0 → wavexis-2.0.2}/CHANGELOG.md +22 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/PKG-INFO +1 -1
- {wavexis-2.0.0 → wavexis-2.0.2}/pyproject.toml +1 -1
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_manager.py +2 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_serve.py +10 -10
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/__init__.py +1 -1
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/auth.py +46 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/backend/manager.py +20 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/cli/app.py +84 -61
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/serve.py +7 -28
- {wavexis-2.0.0 → wavexis-2.0.2}/.dockerignore +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/.github/workflows/ci.yml +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/.github/workflows/docs.yml +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/.github/workflows/release.yml +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/.gitignore +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/CODE_OF_CONDUCT.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/CONTRIBUTING.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/Dockerfile +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/LICENSE +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/README.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/SECURITY.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/api/actions.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/api/backends.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/api/cli.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/api/config.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/api/exceptions.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/api/multi.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/api/plugins.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/api/serve.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/cookbook/auth.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/cookbook/ci-cd.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/cookbook/css.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/cookbook/debug.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/cookbook/record-replay.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/cookbook/scraping.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/cookbook/screenshots.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/cookbook/serve-mode.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/guide/assert.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/guide/backends.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/guide/commands.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/guide/init.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/guide/installation.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/guide/multi.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/guide/perf.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/guide/plugins.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/guide/quickstart.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/guide/raw.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/guide/repl.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/guide/troubleshooting.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/docs/index.md +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/mkdocs.yml +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/stubs/bidiwave/__init__.pyi +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/stubs/cdpwave/__init__.pyi +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/__init__.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/conftest.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/__init__.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_a11y.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_animation.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_backend_selection.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_browser.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_console.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_css.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_debug.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_dialog.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_dom.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_dom_snapshot.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_emulation.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_emulation_advanced.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_eval.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_har.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_input.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_media.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_multi.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_navigate.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_network.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_network_advanced.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_overlay.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_pdf.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_perf.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_permissions.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_raw.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_record.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_scrape.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_screenshot.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_security.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_serve.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_service_worker.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_storage.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_tabs.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_webaudio.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/integration/test_webauthn.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/__init__.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_abstract_backend_phase5.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_actions.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_actions_phase5.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_animation_action.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_assert_multi.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_auth.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_backend_manager.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_bidi_backend.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_bidi_phase5.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_bluetooth_action.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_cast_action.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_cli_phase5.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_config.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_config_phase5.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_cookies_headers_actions.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_css_action.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_debug_action.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_dom_snapshot_action.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_download_screencast.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_emulation_action.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_error_handling.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_exceptions.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_format_record.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_global_options.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_init.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_input_action.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_interactions_crawl.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_media_action.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_multi.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_multi_improvements.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_new_features.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_output.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_overlay_action.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_perf_action.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_perf_console.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_plugins.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_raw.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_record.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_repl.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_service_worker_action.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_storage_action.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_webaudio_action.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/tests/unit/test_webauthn_action.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/__main__.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/__init__.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/accessibility.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/animation.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/base.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/bluetooth.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/browser.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/cast.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/console.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/cookies.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/crawl.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/css.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/debug.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/dialog.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/dom.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/dom_snapshot.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/download.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/emulation.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/eval.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/extract.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/form.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/har.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/headers.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/input.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/lighthouse.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/media.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/multi.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/navigate.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/network.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/overlay.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/pdf.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/performance.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/permissions.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/record.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/scrape.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/screencast.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/screenshot.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/security.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/service_worker.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/session.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/storage.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/tabs.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/wait.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/webaudio.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/webauthn.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/actions/websocket.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/backend/__init__.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/backend/base.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/backend/bidi.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/backend/cdp.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/cli/__init__.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/config.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/exceptions.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/init.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/multi.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/output.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/plugins.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/record.py +0 -0
- {wavexis-2.0.0 → wavexis-2.0.2}/wavexis/repl.py +0 -0
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to wavexis are documented in this file.
|
|
4
4
|
|
|
5
|
+
## v2.0.2 — 2026-07-06
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Removed redundant `import json as _json` in `webauthn` and `raw` commands — uses top-level `json` import
|
|
10
|
+
- Consolidated `_write_perf_output` into `_write_json_output` — eliminates duplicate function
|
|
11
|
+
- Replaced inline JSON output in `raw` command with `_write_json_output` call
|
|
12
|
+
|
|
13
|
+
### Refactored
|
|
14
|
+
|
|
15
|
+
- Extracted `apply_auth_context` to `wavexis/auth.py` — eliminates duplication between `serve.py` `handle_auth` and `cli/app.py` `auth` command
|
|
16
|
+
- Removed unused `_basic_auth` helper from `cli/app.py`
|
|
17
|
+
|
|
18
|
+
## v2.0.1 — 2026-07-06
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- `serve.py` `/version` endpoint now returns the correct package version instead of hardcoded `1.11.2`
|
|
23
|
+
- `BackendManager` is now cached as a singleton via `get_manager()` — avoids re-discovering entry points on every call
|
|
24
|
+
- Added missing `return` after `_handle_error(e)` in 66 CLI command paths — prevents `NameError` and unintended output after errors
|
|
25
|
+
- `FakeBackend` in `test_manager.py` now implements `set_files` abstract method
|
|
26
|
+
|
|
5
27
|
## v2.0.0 — 2026-07-06
|
|
6
28
|
|
|
7
29
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wavexis
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.2
|
|
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
|
|
@@ -162,7 +162,7 @@ class TestServeHandlerMocks:
|
|
|
162
162
|
server = TestServer(app)
|
|
163
163
|
client = TestClient(server)
|
|
164
164
|
await client.start_server()
|
|
165
|
-
with patch("wavexis.
|
|
165
|
+
with patch("wavexis.backend.manager.BackendManager.select", return_value=mock_backend):
|
|
166
166
|
resp = await client.post(
|
|
167
167
|
"/screenshot",
|
|
168
168
|
json={"url": "https://example.com"},
|
|
@@ -186,7 +186,7 @@ class TestServeHandlerMocks:
|
|
|
186
186
|
server = TestServer(app)
|
|
187
187
|
client = TestClient(server)
|
|
188
188
|
await client.start_server()
|
|
189
|
-
with patch("wavexis.
|
|
189
|
+
with patch("wavexis.backend.manager.BackendManager.select", return_value=mock_backend):
|
|
190
190
|
resp = await client.post(
|
|
191
191
|
"/pdf",
|
|
192
192
|
json={"url": "https://example.com"},
|
|
@@ -210,7 +210,7 @@ class TestServeHandlerMocks:
|
|
|
210
210
|
server = TestServer(app)
|
|
211
211
|
client = TestClient(server)
|
|
212
212
|
await client.start_server()
|
|
213
|
-
with patch("wavexis.
|
|
213
|
+
with patch("wavexis.backend.manager.BackendManager.select", return_value=mock_backend):
|
|
214
214
|
resp = await client.post(
|
|
215
215
|
"/eval",
|
|
216
216
|
json={"url": "https://example.com", "expression": "1+1"},
|
|
@@ -233,7 +233,7 @@ class TestServeHandlerMocks:
|
|
|
233
233
|
server = TestServer(app)
|
|
234
234
|
client = TestClient(server)
|
|
235
235
|
await client.start_server()
|
|
236
|
-
with patch("wavexis.
|
|
236
|
+
with patch("wavexis.backend.manager.BackendManager.select", return_value=mock_backend):
|
|
237
237
|
resp = await client.post(
|
|
238
238
|
"/perf/metrics",
|
|
239
239
|
json={"url": "https://example.com"},
|
|
@@ -256,7 +256,7 @@ class TestServeHandlerMocks:
|
|
|
256
256
|
server = TestServer(app)
|
|
257
257
|
client = TestClient(server)
|
|
258
258
|
await client.start_server()
|
|
259
|
-
with patch("wavexis.
|
|
259
|
+
with patch("wavexis.backend.manager.BackendManager.select", return_value=mock_backend):
|
|
260
260
|
resp = await client.post(
|
|
261
261
|
"/perf/trace",
|
|
262
262
|
json={"url": "https://example.com", "duration_ms": 1000},
|
|
@@ -279,7 +279,7 @@ class TestServeHandlerMocks:
|
|
|
279
279
|
server = TestServer(app)
|
|
280
280
|
client = TestClient(server)
|
|
281
281
|
await client.start_server()
|
|
282
|
-
with patch("wavexis.
|
|
282
|
+
with patch("wavexis.backend.manager.BackendManager.select", return_value=mock_backend):
|
|
283
283
|
resp = await client.post(
|
|
284
284
|
"/navigate",
|
|
285
285
|
json={"url": "https://example.com"},
|
|
@@ -302,7 +302,7 @@ class TestServeHandlerMocks:
|
|
|
302
302
|
server = TestServer(app)
|
|
303
303
|
client = TestClient(server)
|
|
304
304
|
await client.start_server()
|
|
305
|
-
with patch("wavexis.
|
|
305
|
+
with patch("wavexis.backend.manager.BackendManager.select", return_value=mock_backend):
|
|
306
306
|
resp = await client.post(
|
|
307
307
|
"/cookies/get",
|
|
308
308
|
json={"url": "https://example.com"},
|
|
@@ -325,7 +325,7 @@ class TestServeHandlerMocks:
|
|
|
325
325
|
server = TestServer(app)
|
|
326
326
|
client = TestClient(server)
|
|
327
327
|
await client.start_server()
|
|
328
|
-
with patch("wavexis.
|
|
328
|
+
with patch("wavexis.backend.manager.BackendManager.select", return_value=mock_backend):
|
|
329
329
|
resp = await client.post(
|
|
330
330
|
"/cookies/set",
|
|
331
331
|
json={
|
|
@@ -353,7 +353,7 @@ class TestServeHandlerMocks:
|
|
|
353
353
|
server = TestServer(app)
|
|
354
354
|
client = TestClient(server)
|
|
355
355
|
await client.start_server()
|
|
356
|
-
with patch("wavexis.
|
|
356
|
+
with patch("wavexis.backend.manager.BackendManager.select", return_value=mock_backend):
|
|
357
357
|
ws = await client.ws_connect("/ws")
|
|
358
358
|
await ws.send_json({
|
|
359
359
|
"url": "https://example.com",
|
|
@@ -383,7 +383,7 @@ class TestServeHandlerMocks:
|
|
|
383
383
|
server = TestServer(app)
|
|
384
384
|
client = TestClient(server)
|
|
385
385
|
await client.start_server()
|
|
386
|
-
with patch("wavexis.
|
|
386
|
+
with patch("wavexis.backend.manager.BackendManager.select", return_value=mock_backend):
|
|
387
387
|
ws = await client.ws_connect("/ws")
|
|
388
388
|
await ws.send_json({
|
|
389
389
|
"url": "https://example.com",
|
|
@@ -2,9 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import base64
|
|
5
6
|
import json
|
|
6
7
|
from dataclasses import dataclass, field
|
|
7
8
|
from pathlib import Path
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from wavexis.backend.base import AbstractBackend
|
|
13
|
+
from wavexis.config import WaitStrategy
|
|
8
14
|
|
|
9
15
|
|
|
10
16
|
@dataclass
|
|
@@ -84,3 +90,43 @@ def load_headers(path: str | Path) -> dict[str, str]:
|
|
|
84
90
|
return data["headers"]
|
|
85
91
|
return data
|
|
86
92
|
return {}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
async def apply_auth_context(
|
|
96
|
+
backend: AbstractBackend,
|
|
97
|
+
ctx: AuthContext,
|
|
98
|
+
url: str,
|
|
99
|
+
wait: WaitStrategy | None = None,
|
|
100
|
+
) -> None:
|
|
101
|
+
"""Apply auth context to a backend and navigate to a URL.
|
|
102
|
+
|
|
103
|
+
Sets headers, basic auth, navigates, sets cookies, and re-navigates.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
backend: The browser backend to apply auth to.
|
|
107
|
+
ctx: The auth context with cookies, headers, and credentials.
|
|
108
|
+
url: The URL to navigate to.
|
|
109
|
+
wait: Wait strategy for navigation. Defaults to "load".
|
|
110
|
+
"""
|
|
111
|
+
from wavexis.config import CookieParams, WaitStrategy
|
|
112
|
+
|
|
113
|
+
if wait is None:
|
|
114
|
+
wait = WaitStrategy(strategy="load")
|
|
115
|
+
|
|
116
|
+
if ctx.headers:
|
|
117
|
+
await backend.set_headers(ctx.headers)
|
|
118
|
+
if ctx.username and ctx.password:
|
|
119
|
+
cred = base64.b64encode(
|
|
120
|
+
f"{ctx.username}:{ctx.password}".encode()
|
|
121
|
+
).decode()
|
|
122
|
+
await backend.set_headers({"Authorization": f"Basic {cred}"})
|
|
123
|
+
await backend.navigate(url, wait)
|
|
124
|
+
for cookie in ctx.cookies:
|
|
125
|
+
cp = CookieParams(
|
|
126
|
+
name=cookie.get("name", ""),
|
|
127
|
+
value=cookie.get("value", ""),
|
|
128
|
+
domain=cookie.get("domain", ""),
|
|
129
|
+
path=cookie.get("path", "/"),
|
|
130
|
+
)
|
|
131
|
+
await backend.set_cookie(cp)
|
|
132
|
+
await backend.navigate(url, wait)
|
|
@@ -5,6 +5,26 @@ from __future__ import annotations
|
|
|
5
5
|
from wavexis.backend.base import AbstractBackend
|
|
6
6
|
from wavexis.exceptions import BackendNotAvailableError, BackendNotSupportedError
|
|
7
7
|
|
|
8
|
+
_manager: BackendManager | None = None
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_manager() -> BackendManager:
|
|
12
|
+
"""Return the singleton BackendManager instance.
|
|
13
|
+
|
|
14
|
+
Returns:
|
|
15
|
+
The shared BackendManager, created on first call.
|
|
16
|
+
"""
|
|
17
|
+
global _manager
|
|
18
|
+
if _manager is None:
|
|
19
|
+
_manager = BackendManager()
|
|
20
|
+
return _manager
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def reset_manager() -> None:
|
|
24
|
+
"""Reset the singleton manager (useful for tests)."""
|
|
25
|
+
global _manager
|
|
26
|
+
_manager = None
|
|
27
|
+
|
|
8
28
|
|
|
9
29
|
class BackendManager:
|
|
10
30
|
"""Manages backend availability, selection, and registration.
|