diff --git a/browser_cli/client/core.py b/browser_cli/client/core.py index bb318e4..f734e51 100644 --- a/browser_cli/client/core.py +++ b/browser_cli/client/core.py @@ -151,21 +151,25 @@ def active_browser_targets(*, include_remotes: bool = True, key=None, suppress_p targets.extend(_remote_browser_targets(key=key, suppress_pq_warning=suppress_pq_warning)) return targets -def _cached_client_row(target: BrowserTarget) -> dict | None: +def _cached_client_row(target: BrowserTarget, *, scoped: bool = False) -> dict | None: """Build a clients row from a target's discovery data, skipping a roundtrip. Returns None when the remote didn't advertise its version (older serve), so - callers fall back to an explicit ``clients.list`` query. + callers fall back to an explicit ``clients.list`` query. When *scoped* is + true, the caller already selected one remote host, so render profile-only + labels instead of adding a host group header. """ if target.version is None and target.extension_version is None: return None - return { - "profile": target.display_name, - "profileGroup": target.display_group, + row = { + "profile": target.profile if scoped else target.display_name, "name": target.browser_name or "", "version": target.version or "", "extensionVersion": target.extension_version or "", } + if target.display_group and not scoped: + row["profileGroup"] = target.display_group + return row def _rows_from_result(result, label: str, profile_group: str | None) -> list[dict]: rows = [] @@ -249,18 +253,17 @@ def collect_browser_clients( if targets: uncached = [] for target in targets: - cached = _cached_client_row(target) + cached = _cached_client_row(target, scoped=True) if cached is not None: rows.append(cached) else: uncached.append(target) results = _run_concurrent([ (lambda t=t: _client_rows_async( - t.display_name, + t.profile, profile=t.profile, remote=remote, key=key, - profile_group=t.display_group, )) for t in uncached ]) diff --git a/extension/manifest.json b/extension/manifest.json index 964e852..c3ac5cc 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "browser-cli", - "version": "0.16.4", + "version": "0.16.5", "description": "Control your browser from the terminal or Python SDK", "browser_specific_settings": { "gecko": { diff --git a/pyproject.toml b/pyproject.toml index 15cf558..1b4deca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "real-browser-cli" -version = "0.16.4" +version = "0.16.5" description = "Control your real running browser from the terminal or Python SDK" readme = "README.md" license = { file = "LICENSE" } diff --git a/tests/test_cli.py b/tests/test_cli.py index 24dfc8f..4dee03b 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -294,29 +294,52 @@ def test_clients_reads_registry_with_trailing_garbage(tmp_path): assert "0.8.2" in result.output def test_clients_remote_uses_remote_endpoint_without_local_registry(): - def fake_send_command(command, args=None, profile=None, remote=None, key=None): - assert command == "clients.list" - assert profile is None - assert remote == "127.0.0.1:8765" - return [{"name": "Chrome", "version": "1", "extensionVersion": "2.3.4"}] + target = BrowserTarget( + profile="work", + display_name="127.0.0.1:work", + socket_path="", + remote="127.0.0.1:8765", + browser_name="Chrome", + display_group="127.0.0.1", + version="1", + extension_version="2.3.4", + ) with patch.dict(os.environ, {}, clear=True), patch( "browser_cli.commands.clients.REGISTRY_PATH", Path("/nonexistent/browser-cli-registry.json") - ), patch("browser_cli.client.core.send_command", side_effect=fake_send_command) as send_command: + ), patch("browser_cli.client.core.remote_browser_targets", return_value=[target]), patch( + "browser_cli.client.core.send_command" + ) as send_command: result = CliRunner().invoke(main, ["--remote", "127.0.0.1:8765", "clients"]) assert result.exit_code == 0 - send_command.assert_called_once() - assert "remote" in result.output + send_command.assert_not_called() + assert "work" in result.output + assert "127.0.0.1" not in result.output assert "Chrome" in result.output assert "2.3.4" in result.output def test_clients_remote_respects_global_browser_route(): - with patch.dict(os.environ, {}, clear=True), patch("browser_cli.client.core.send_command", return_value=[]) as send_command: + target = BrowserTarget( + profile="work", + display_name="127.0.0.1:work", + socket_path="", + remote="127.0.0.1:8765", + browser_name="Chrome", + display_group="127.0.0.1", + version="1", + extension_version="2.3.4", + ) + + with patch.dict(os.environ, {}, clear=True), patch( + "browser_cli.client.core.remote_browser_targets", return_value=[target] + ), patch("browser_cli.client.core.send_command") as send_command: result = CliRunner().invoke(main, ["--remote", "127.0.0.1:8765", "--browser", "work", "clients"]) - assert result.exit_code == 1 - send_command.assert_called_once_with("clients.list", profile="work", remote="127.0.0.1:8765", key=None) + assert result.exit_code == 0 + send_command.assert_not_called() + assert "work" in result.output + assert "127.0.0.1" not in result.output def test_clients_browser_alias_resolves_to_remote(): """--browser without --remote resolves the alias, fetches all targets from that remote, diff --git a/tests/test_client.py b/tests/test_client.py index 6407474..bddd558 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -681,7 +681,8 @@ def test_collect_browser_clients_with_explicit_remote_lists_all_targets(monkeypa rows = collect_browser_clients(remote="browser-host.example:8765", registry_path=tmp_path / "missing-registry.json") - assert [row["profile"] for row in rows] == ["browser-host.example:main", "browser-host.example:work"] + assert [row["profile"] for row in rows] == ["main", "work"] + assert [row.get("profileGroup") for row in rows] == [None, None] assert [row["name"] for row in rows] == ["Chrome", "Firefox"] def test_collect_browser_clients_with_explicit_remote_and_browser_filters_target(monkeypatch, tmp_path): @@ -696,7 +697,8 @@ def test_collect_browser_clients_with_explicit_remote_and_browser_filters_target rows = collect_browser_clients(remote="browser-host.example:8765", browser_alias="work", registry_path=tmp_path / "missing-registry.json") - assert [row["profile"] for row in rows] == ["browser-host.example:work"] + assert [row["profile"] for row in rows] == ["work"] + assert rows[0].get("profileGroup") is None def test_collect_browser_clients_falls_back_when_version_unknown(monkeypatch, tmp_path): """An older remote (no advertised version) still triggers a clients.list query.""" diff --git a/uv.lock b/uv.lock index 4ee06e4..acb93b2 100644 --- a/uv.lock +++ b/uv.lock @@ -474,7 +474,7 @@ wheels = [ [[package]] name = "real-browser-cli" -version = "0.16.4" +version = "0.16.5" source = { editable = "." } dependencies = [ { name = "click" },