076914e5b7
- Split client, native, remote, serve, markdown, and SDK internals into focused packages with direct imports. - Move local and remote transport framing/protocol helpers behind clearer module boundaries. - Break up the extension injected DOM logic into a separate content dispatch bundle and dedicated content modules. - Add explicit client handling for passive remote discovery without noisy PQ warnings. - Keep behavior covered with updated unit, integration, and extension tests.
124 lines
5.1 KiB
Python
124 lines
5.1 KiB
Python
"""Guards for the module boundaries introduced by the modularity refactor.
|
|
|
|
Three things must hold so the split stays invisible to callers:
|
|
* the new leaf modules own their logic and behave correctly,
|
|
* ``browser_cli.client`` still re-exports the names that moved out of it, and
|
|
* ``BrowserCLI`` still exposes the factory/routing helpers (now mixins).
|
|
"""
|
|
from unittest.mock import patch
|
|
|
|
import browser_cli
|
|
from browser_cli import BrowserCLI, BrowserCounts
|
|
|
|
# ── endpoints module ────────────────────────────────────────────────────────
|
|
|
|
class TestEndpoints:
|
|
def test_normalize_strips_default_https_port_for_domains(self):
|
|
from browser_cli.endpoints import _normalize_endpoint
|
|
|
|
assert _normalize_endpoint("example.com:443") == "example.com"
|
|
assert _normalize_endpoint("example.com:8765") == "example.com:8765"
|
|
assert _normalize_endpoint("203.0.113.10:443") == "203.0.113.10:443"
|
|
|
|
def test_resolve_connect_endpoint_defaults_domain_to_443(self):
|
|
from browser_cli.endpoints import _resolve_connect_endpoint
|
|
|
|
assert _resolve_connect_endpoint("example.com") == "example.com:443"
|
|
assert _resolve_connect_endpoint("host:9000") == "host:9000"
|
|
|
|
def test_resolve_connect_endpoint_rejects_bare_non_domain(self):
|
|
from browser_cli.errors import BrowserNotConnected
|
|
from browser_cli.endpoints import _resolve_connect_endpoint
|
|
|
|
try:
|
|
_resolve_connect_endpoint("localhost")
|
|
except BrowserNotConnected:
|
|
pass
|
|
else:
|
|
raise AssertionError("expected BrowserNotConnected for bare 'localhost'")
|
|
|
|
def test_looks_like_domain(self):
|
|
from browser_cli.endpoints import _looks_like_domain
|
|
|
|
assert _looks_like_domain("example.com") is True
|
|
assert _looks_like_domain("localhost") is False
|
|
assert _looks_like_domain("127.0.0.1") is False
|
|
|
|
# ── markdown module ─────────────────────────────────────────────────────────
|
|
|
|
class TestRenderMarkdown:
|
|
def test_html_payload_is_converted(self):
|
|
from browser_cli.markdown import render_markdown
|
|
|
|
assert render_markdown("<h1>Title</h1>") == "# Title"
|
|
|
|
def test_markdown_payload_is_cleaned_not_html_parsed(self):
|
|
from browser_cli.markdown import render_markdown
|
|
|
|
assert render_markdown(r"hello\_world \- item") == "hello_world - item"
|
|
|
|
def test_none_and_empty_are_safe(self):
|
|
from browser_cli.markdown import render_markdown
|
|
|
|
assert render_markdown(None) == ""
|
|
assert render_markdown("") == ""
|
|
|
|
# ── backward-compatible re-exports ──────────────────────────────────────────
|
|
|
|
class TestReExports:
|
|
def test_client_still_exposes_moved_names(self):
|
|
from browser_cli import client
|
|
|
|
# moved to endpoints / remote.transport / errors but still reachable here
|
|
for name in (
|
|
"BrowserNotConnected",
|
|
"_normalize_endpoint",
|
|
"_resolve_connect_endpoint",
|
|
"display_browser_name",
|
|
"_remote_display_name",
|
|
"_send_remote",
|
|
"_recv_all",
|
|
"_recv_exact",
|
|
):
|
|
assert hasattr(client, name), f"browser_cli.client.{name} missing after refactor"
|
|
|
|
def test_browsercounts_reexported_from_package(self):
|
|
# BrowserCounts moved to models but is still part of the public API.
|
|
from browser_cli.models import BrowserCounts as ModelsBrowserCounts
|
|
|
|
assert BrowserCounts is ModelsBrowserCounts
|
|
|
|
def test_patching_client_send_remote_still_intercepts(self):
|
|
# send_command resolves _send_remote as a browser_cli.client global, so
|
|
# patching there must still take effect after the move to remote.transport.
|
|
with patch("browser_cli.client.core._send_remote", return_value=None) as fake:
|
|
assert browser_cli.client.core._send_remote is fake
|
|
|
|
# ── BrowserCLI mixin composition ─────────────────────────────────────────────
|
|
|
|
class TestMixinComposition:
|
|
def test_factory_builds_bound_tab(self):
|
|
b = BrowserCLI()
|
|
tab = b.tab_from({"id": 7, "windowId": 1, "title": "t", "url": "u"})
|
|
assert tab.id == 7
|
|
assert tab._browser is b
|
|
|
|
def test_factory_tab_for_remote_target_binds_sibling_client(self):
|
|
b = BrowserCLI()
|
|
|
|
class _Target:
|
|
profile = "work"
|
|
display_name = "host:work"
|
|
remote = "host:8765"
|
|
|
|
tab = b.tab_from_target({"id": 1, "windowId": 0}, _Target())
|
|
assert tab.browser == "host:work"
|
|
assert isinstance(tab._browser, BrowserCLI)
|
|
assert tab._browser is not b
|
|
assert tab._browser.browser == "work"
|
|
|
|
def test_field_helper_handles_non_dict(self):
|
|
b = BrowserCLI()
|
|
assert b._field({"tabId": 5}, "tabId") == 5
|
|
assert b._field("not-a-dict", "tabId", fallback=9) == 9
|