feat: group multi-browser output by source
Testing / remote-protocol-compat (0.9.3) (push) Successful in 52s
Testing / test (push) Successful in 1m2s
Testing / remote-protocol-compat (0.9.5) (push) Successful in 1m0s
Package Extension / package-extension (push) Successful in 1m11s
Build & Publish Package / publish (push) Successful in 1m7s
Testing / remote-protocol-compat (0.9.3) (push) Successful in 52s
Testing / test (push) Successful in 1m2s
Testing / remote-protocol-compat (0.9.5) (push) Successful in 1m0s
Package Extension / package-extension (push) Successful in 1m11s
Build & Publish Package / publish (push) Successful in 1m7s
- Add browser source grouping metadata to SDK-created tabs, groups, list results, and aggregate count results. - Render grouped local/remote browser tables consistently for clients, tabs, groups, windows, sessions, and remote status output. - Document remote control, auth, HTTP gateway usage, and the refreshed project structure in the README. - Add coverage for grouped output and BrowserCounts browser_groups. - Bump the Python package, extension manifest, and lockfile to 0.15.6. - Add a just publish helper for building and publishing release artifacts.
This commit is contained in:
+35
-6
@@ -559,12 +559,37 @@ class TestTabs:
|
||||
mock_send.side_effect = [3, 4]
|
||||
result = b.tabs.count("github")
|
||||
|
||||
assert result == BrowserCounts(total=7, by_browser={"uuid-1": 3, "work": 4})
|
||||
assert result == BrowserCounts(
|
||||
total=7,
|
||||
by_browser={"uuid-1": 3, "work": 4},
|
||||
browser_groups={"uuid-1": "local", "work": "local"},
|
||||
)
|
||||
assert mock_send.call_args_list == [
|
||||
call("tabs.count", {"pattern": "github"}, profile="default"),
|
||||
call("tabs.count", {"pattern": "github"}, profile="work"),
|
||||
]
|
||||
|
||||
def test_tabs_count_multi_browser_keeps_remote_display_groups(self, b, mock_send):
|
||||
with patch(
|
||||
"browser_cli.active_browser_targets",
|
||||
return_value=[
|
||||
BrowserTarget("main", "browser-host.example:main", "", remote="browser-host.example:8765", display_group="browser-host.example"),
|
||||
BrowserTarget("work", "browser-host.example:work", "", remote="browser-host.example:8765", display_group="browser-host.example"),
|
||||
],
|
||||
):
|
||||
mock_send.side_effect = [1, 2]
|
||||
result = b.tabs.count()
|
||||
|
||||
assert result == BrowserCounts(
|
||||
total=3,
|
||||
by_browser={"browser-host.example:main": 1, "browser-host.example:work": 2},
|
||||
browser_groups={"browser-host.example:main": "browser-host.example", "browser-host.example:work": "browser-host.example"},
|
||||
)
|
||||
assert mock_send.call_args_list == [
|
||||
call("tabs.count", {"pattern": None}, profile="main", remote="browser-host.example:8765", key=None),
|
||||
call("tabs.count", {"pattern": None}, profile="work", remote="browser-host.example:8765", key=None),
|
||||
]
|
||||
|
||||
def test_tabs_query(self, b, mock_send):
|
||||
mock_send.return_value = [TAB_DATA]
|
||||
result = b.tabs.query("example")
|
||||
@@ -713,7 +738,11 @@ class TestGroups:
|
||||
mock_send.side_effect = [2, 5]
|
||||
result = b.groups.count()
|
||||
|
||||
assert result == BrowserCounts(total=7, by_browser={"uuid-1": 2, "work": 5})
|
||||
assert result == BrowserCounts(
|
||||
total=7,
|
||||
by_browser={"uuid-1": 2, "work": 5},
|
||||
browser_groups={"uuid-1": "local", "work": "local"},
|
||||
)
|
||||
|
||||
def test_group_query(self, b, mock_send):
|
||||
mock_send.return_value = [GROUP_DATA]
|
||||
@@ -772,8 +801,8 @@ class TestWindows:
|
||||
result = b.windows.list()
|
||||
|
||||
assert result == [
|
||||
{"id": 1, "tabCount": 2, "state": "normal", "browser": "uuid-1"},
|
||||
{"id": 2, "tabCount": 3, "state": "maximized", "browser": "work"},
|
||||
{"id": 1, "tabCount": 2, "state": "normal", "browser": "uuid-1", "browserGroup": "local"},
|
||||
{"id": 2, "tabCount": 3, "state": "maximized", "browser": "work", "browserGroup": "local"},
|
||||
]
|
||||
|
||||
def test_windows_open_without_url(self, b, mock_send):
|
||||
@@ -907,8 +936,8 @@ class TestSession:
|
||||
result = b.session.list()
|
||||
|
||||
assert result == [
|
||||
{"name": "first", "tabs": 2, "savedAt": 1712707200000, "browser": "uuid-1"},
|
||||
{"name": "second", "tabs": 5, "savedAt": 1712707300000, "browser": "work"},
|
||||
{"name": "first", "tabs": 2, "savedAt": 1712707200000, "browser": "uuid-1", "browserGroup": "local"},
|
||||
{"name": "second", "tabs": 5, "savedAt": 1712707300000, "browser": "work", "browserGroup": "local"},
|
||||
]
|
||||
assert mock_send.call_args_list == [
|
||||
call("session.list", {}, profile="default"),
|
||||
|
||||
+135
-1
@@ -217,7 +217,13 @@ def test_clients_without_remote_shows_saved_remotes_without_pq_warning(tmp_path)
|
||||
|
||||
registry_path = tmp_path / "registry.json"
|
||||
registry_path.write_text('{"main": "/tmp/.browser_cli/main.sock"}', encoding="utf-8")
|
||||
remote_target = BrowserTarget("work", "browser-host.example:work", "", remote="browser-host.example:8765")
|
||||
remote_target = BrowserTarget(
|
||||
"work",
|
||||
"browser-host.example:work",
|
||||
"",
|
||||
remote="browser-host.example:8765",
|
||||
display_group="browser-host.example",
|
||||
)
|
||||
|
||||
def fake_send_command(command, args=None, profile=None, remote=None, key=None, suppress_pq_warning=False):
|
||||
assert command == "clients.list"
|
||||
@@ -239,7 +245,11 @@ def test_clients_without_remote_shows_saved_remotes_without_pq_warning(tmp_path)
|
||||
|
||||
assert result.exit_code == 0
|
||||
active_targets.assert_called_once_with(suppress_pq_warning=True)
|
||||
assert "local" in result.output
|
||||
assert "Chrome" in result.output
|
||||
assert "browser-host.example" in result.output
|
||||
assert "browser-host.example:work" not in result.output
|
||||
assert "work" in result.output
|
||||
assert "Remote Chrome" in result.output
|
||||
assert "post-quantum" not in result.output
|
||||
|
||||
@@ -362,9 +372,33 @@ def test_tabs_list_multi_browser_shows_browser_column():
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "Browser" in result.output
|
||||
assert "local" in result.output
|
||||
assert "550e8400-e29b-41d4-a716-446655440000" in result.output
|
||||
assert "work" in result.output
|
||||
|
||||
def test_tabs_list_unscoped_groups_remote_targets_by_host():
|
||||
targets = [
|
||||
BrowserTarget("main", "browser-host.example:main", "", remote="browser-host.example:8765", display_group="browser-host.example"),
|
||||
BrowserTarget("work", "browser-host.example:work", "", remote="browser-host.example:8765", display_group="browser-host.example"),
|
||||
]
|
||||
|
||||
def fake_send_command(command, args=None, profile=None, remote=None, key=None):
|
||||
assert command == "tabs.list"
|
||||
assert remote == "browser-host.example:8765"
|
||||
return [{"id": 1, "windowId": 1, "active": True, "title": profile, "url": "https://example.com"}]
|
||||
|
||||
with patch("browser_cli.active_browser_targets", return_value=targets), patch(
|
||||
"browser_cli.send_command", side_effect=fake_send_command
|
||||
):
|
||||
result = CliRunner().invoke(main, ["tabs", "list"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "browser-host.example" in result.output
|
||||
assert "browser-host.example:main" not in result.output
|
||||
assert "browser-host.example:work" not in result.output
|
||||
assert "main" in result.output
|
||||
assert "work" in result.output
|
||||
|
||||
def test_tabs_list_with_remote_uses_only_remote_targets():
|
||||
with patch(
|
||||
"browser_cli.active_browser_targets",
|
||||
@@ -495,9 +529,36 @@ def test_tabs_count_multi_browser_shows_total():
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "Browser" in result.output
|
||||
assert "local" in result.output
|
||||
assert "Total" in result.output
|
||||
assert "7" in result.output
|
||||
|
||||
def test_tabs_count_unscoped_groups_remote_targets_by_host():
|
||||
counts = {"main": 1, "work": 2}
|
||||
|
||||
def fake_send_command(command, args=None, profile=None, remote=None, key=None):
|
||||
assert command == "tabs.count"
|
||||
assert remote == "browser-host.example:8765"
|
||||
return counts[profile]
|
||||
|
||||
with patch(
|
||||
"browser_cli.active_browser_targets",
|
||||
return_value=[
|
||||
BrowserTarget("main", "browser-host.example:main", "", remote="browser-host.example:8765", display_group="browser-host.example"),
|
||||
BrowserTarget("work", "browser-host.example:work", "", remote="browser-host.example:8765", display_group="browser-host.example"),
|
||||
],
|
||||
), patch("browser_cli.send_command", side_effect=fake_send_command):
|
||||
result = CliRunner().invoke(main, ["tabs", "count"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "browser-host.example" in result.output
|
||||
assert "browser-host.example:main" not in result.output
|
||||
assert "browser-host.example:work" not in result.output
|
||||
assert "main" in result.output
|
||||
assert "work" in result.output
|
||||
assert "Total" in result.output
|
||||
assert "3" in result.output
|
||||
|
||||
def test_group_count_multi_browser_shows_total():
|
||||
counts = {"default": 1, "work": 2}
|
||||
|
||||
@@ -519,6 +580,29 @@ def test_group_count_multi_browser_shows_total():
|
||||
assert "Total" in result.output
|
||||
assert "3" in result.output
|
||||
|
||||
def test_groups_list_unscoped_groups_remote_targets_by_host():
|
||||
targets = [
|
||||
BrowserTarget("main", "browser-host.example:main", "", remote="browser-host.example:8765", display_group="browser-host.example"),
|
||||
BrowserTarget("work", "browser-host.example:work", "", remote="browser-host.example:8765", display_group="browser-host.example"),
|
||||
]
|
||||
|
||||
def fake_send_command(command, args=None, profile=None, remote=None, key=None):
|
||||
assert command == "group.list"
|
||||
assert remote == "browser-host.example:8765"
|
||||
return [{"id": 1, "title": profile, "color": "blue", "collapsed": False, "tabCount": 2}]
|
||||
|
||||
with patch("browser_cli.active_browser_targets", return_value=targets), patch(
|
||||
"browser_cli.send_command", side_effect=fake_send_command
|
||||
):
|
||||
result = CliRunner().invoke(main, ["groups", "list"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "browser-host.example" in result.output
|
||||
assert "browser-host.example:main" not in result.output
|
||||
assert "browser-host.example:work" not in result.output
|
||||
assert "main" in result.output
|
||||
assert "work" in result.output
|
||||
|
||||
def test_group_list_leaves_unnamed_group_cell_empty():
|
||||
with patch(
|
||||
"browser_cli.send_command",
|
||||
@@ -567,10 +651,34 @@ def test_windows_list_multi_browser_shows_browser_column():
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "Browser" in result.output
|
||||
assert "local" in result.output
|
||||
assert "Focused" not in result.output
|
||||
assert "uuid-1" in result.output
|
||||
assert "work" in result.output
|
||||
|
||||
def test_windows_list_unscoped_groups_remote_targets_by_host():
|
||||
targets = [
|
||||
BrowserTarget("main", "browser-host.example:main", "", remote="browser-host.example:8765", display_group="browser-host.example"),
|
||||
BrowserTarget("work", "browser-host.example:work", "", remote="browser-host.example:8765", display_group="browser-host.example"),
|
||||
]
|
||||
|
||||
def fake_send_command(command, args=None, profile=None, remote=None, key=None):
|
||||
assert command == "windows.list"
|
||||
assert remote == "browser-host.example:8765"
|
||||
return [{"id": 1, "alias": profile, "focused": True, "tabCount": 2, "state": "normal"}]
|
||||
|
||||
with patch("browser_cli.active_browser_targets", return_value=targets), patch(
|
||||
"browser_cli.send_command", side_effect=fake_send_command
|
||||
):
|
||||
result = CliRunner().invoke(main, ["windows", "list"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "browser-host.example" in result.output
|
||||
assert "browser-host.example:main" not in result.output
|
||||
assert "browser-host.example:work" not in result.output
|
||||
assert "main" in result.output
|
||||
assert "work" in result.output
|
||||
|
||||
def test_session_list_multi_browser_shows_browser_column():
|
||||
def fake_send_command(command, args=None, profile=None):
|
||||
assert command == "session.list"
|
||||
@@ -587,11 +695,37 @@ def test_session_list_multi_browser_shows_browser_column():
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "Browser" in result.output
|
||||
assert "local" in result.output
|
||||
assert "uuid-1" in result.output
|
||||
assert "work" in result.output
|
||||
assert "default-session" in result.output
|
||||
assert "work-session" in result.output
|
||||
|
||||
def test_session_list_unscoped_groups_remote_targets_by_host():
|
||||
targets = [
|
||||
BrowserTarget("main", "browser-host.example:main", "", remote="browser-host.example:8765", display_group="browser-host.example"),
|
||||
BrowserTarget("work", "browser-host.example:work", "", remote="browser-host.example:8765", display_group="browser-host.example"),
|
||||
]
|
||||
|
||||
def fake_send_command(command, args=None, profile=None, remote=None, key=None):
|
||||
assert command == "session.list"
|
||||
assert remote == "browser-host.example:8765"
|
||||
return [{"name": f"{profile}-session", "tabs": 2, "savedAt": 1712707200000}]
|
||||
|
||||
with patch("browser_cli.active_browser_targets", return_value=targets), patch(
|
||||
"browser_cli.send_command", side_effect=fake_send_command
|
||||
):
|
||||
result = CliRunner().invoke(main, ["session", "list"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "browser-host.example" in result.output
|
||||
assert "browser-host.example:main" not in result.output
|
||||
assert "browser-host.example:work" not in result.output
|
||||
assert "main" in result.output
|
||||
assert "work" in result.output
|
||||
assert "main-session" in result.output
|
||||
assert "work-session" in result.output
|
||||
|
||||
def test_session_list_with_explicit_browser_does_not_show_browser_column():
|
||||
with patch(
|
||||
"browser_cli.active_browser_targets",
|
||||
|
||||
Reference in New Issue
Block a user