diff --git a/browser_cli/cli.py b/browser_cli/cli.py index 6b063a5..63afe2a 100755 --- a/browser_cli/cli.py +++ b/browser_cli/cli.py @@ -21,7 +21,13 @@ from browser_cli.commands.dom import dom_group from browser_cli.commands.extract import extract_group from browser_cli.commands.session import session_group from browser_cli.commands.search import search_group -from browser_cli.client import send_command, BrowserNotConnected, REGISTRY_PATH, display_browser_name +from browser_cli.client import ( + send_command, + BrowserNotConnected, + REGISTRY_PATH, + active_browser_targets, + display_browser_name, +) console = Console() @@ -51,6 +57,30 @@ NATIVE_HOST_DIRS = { } +def _rename_target_profile(target_browser: str | None) -> str | None: + if target_browser: + return target_browser + + active = active_browser_targets() + if len(active) == 1: + return active[0].profile + return None + + +def _ensure_unique_browser_alias(alias: str, target_browser: str | None) -> None: + target_profile = _rename_target_profile(target_browser) + + profiles: dict[str, str] = {} + if REGISTRY_PATH.exists(): + try: + profiles = json.loads(REGISTRY_PATH.read_text()) + except Exception: + profiles = {} + + if alias in profiles and alias != target_profile: + raise click.ClickException(f"Browser alias '{alias}' already exists") + + def _native_host_wrapper_path() -> Path: if sys.platform == "darwin": base_dir = Path.home() / "Library" / "Application Support" / "browser-cli" @@ -184,6 +214,7 @@ main.add_command(clients_group) def cmd_clients_rename(target_browser, alias): """Set the profile alias used to identify this browser instance.""" try: + _ensure_unique_browser_alias(alias, target_browser) send_command("clients.rename_profile", {"alias": alias}, profile=target_browser) except BrowserNotConnected as e: console.print(f"[red]Error:[/red] {e}") diff --git a/extension/manifest.json b/extension/manifest.json index fd9b582..0d6def5 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "browser-cli", - "version": "0.5.6", + "version": "0.5.7", "description": "Control your browser from the terminal via browser-cli", "permissions": [ "tabs", diff --git a/pyproject.toml b/pyproject.toml index 05f970e..d7d37bd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "browser-cli" -version = "0.5.6" +version = "0.5.7" description = "Control your real running browser from the terminal via a Chrome extension" requires-python = ">=3.10" dependencies = [ diff --git a/tests/test_cli.py b/tests/test_cli.py index 09d4ee7..039b509 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -45,6 +45,27 @@ def test_clients_rename_uses_global_browser_target_when_set(): send_command.assert_called_once_with("clients.rename_profile", {"alias": "work"}, profile=None) assert "Restart the browser" not in result.output +def test_clients_rename_rejects_duplicate_alias(tmp_path): + registry_path = tmp_path / "registry.json" + registry_path.write_text('{"work": "/tmp/work.sock", "old-id": "/tmp/old-id.sock"}', encoding="utf-8") + + with patch("browser_cli.cli.REGISTRY_PATH", registry_path), patch("browser_cli.cli.send_command") as send_command: + result = CliRunner().invoke(main, ["clients", "rename", "--browser", "old-id", "work"]) + + assert result.exit_code != 0 + assert "Browser alias 'work' already exists" in result.output + send_command.assert_not_called() + +def test_clients_rename_allows_same_alias_for_same_target(tmp_path): + registry_path = tmp_path / "registry.json" + registry_path.write_text('{"work": "/tmp/work.sock"}', encoding="utf-8") + + with patch("browser_cli.cli.REGISTRY_PATH", registry_path), patch("browser_cli.cli.send_command") as send_command: + result = CliRunner().invoke(main, ["clients", "rename", "--browser", "work", "work"]) + + assert result.exit_code == 0 + send_command.assert_called_once_with("clients.rename_profile", {"alias": "work"}, profile="work") + def test_install_help_lists_supported_browsers(): result = CliRunner().invoke(main, ["install", "--help"])