test_browser_cdp_override.py
1 from unittest.mock import Mock, patch 2 3 4 HOST = "example-host" 5 PORT = 9223 6 WS_URL = f"ws://{HOST}:{PORT}/devtools/browser/abc123" 7 HTTP_URL = f"http://{HOST}:{PORT}" 8 VERSION_URL = f"{HTTP_URL}/json/version" 9 10 11 class TestResolveCdpOverride: 12 def test_keeps_full_devtools_websocket_url(self): 13 from tools.browser_tool import _resolve_cdp_override 14 15 assert _resolve_cdp_override(WS_URL) == WS_URL 16 17 def test_resolves_http_discovery_endpoint_to_websocket(self): 18 from tools.browser_tool import _resolve_cdp_override 19 20 response = Mock() 21 response.raise_for_status.return_value = None 22 response.json.return_value = {"webSocketDebuggerUrl": WS_URL} 23 24 with patch("tools.browser_tool.requests.get", return_value=response) as mock_get: 25 resolved = _resolve_cdp_override(HTTP_URL) 26 27 assert resolved == WS_URL 28 mock_get.assert_called_once_with(VERSION_URL, timeout=10) 29 30 def test_resolves_bare_ws_hostport_to_discovery_websocket(self): 31 from tools.browser_tool import _resolve_cdp_override 32 33 response = Mock() 34 response.raise_for_status.return_value = None 35 response.json.return_value = {"webSocketDebuggerUrl": WS_URL} 36 37 with patch("tools.browser_tool.requests.get", return_value=response) as mock_get: 38 resolved = _resolve_cdp_override(f"ws://{HOST}:{PORT}") 39 40 assert resolved == WS_URL 41 mock_get.assert_called_once_with(VERSION_URL, timeout=10) 42 43 def test_falls_back_to_raw_url_when_discovery_fails(self): 44 from tools.browser_tool import _resolve_cdp_override 45 46 with patch("tools.browser_tool.requests.get", side_effect=RuntimeError("boom")): 47 assert _resolve_cdp_override(HTTP_URL) == HTTP_URL 48 49 def test_normalizes_provider_returned_http_cdp_url_when_creating_session(self, monkeypatch): 50 import tools.browser_tool as browser_tool 51 52 provider = Mock() 53 provider.create_session.return_value = { 54 "session_name": "cloud-session", 55 "bb_session_id": "bu_123", 56 "cdp_url": "https://cdp.browser-use.example/session", 57 "features": {"browser_use": True}, 58 } 59 60 response = Mock() 61 response.raise_for_status.return_value = None 62 response.json.return_value = {"webSocketDebuggerUrl": WS_URL} 63 64 monkeypatch.setattr(browser_tool, "_active_sessions", {}) 65 monkeypatch.setattr(browser_tool, "_session_last_activity", {}) 66 monkeypatch.setattr(browser_tool, "_start_browser_cleanup_thread", lambda: None) 67 monkeypatch.setattr(browser_tool, "_update_session_activity", lambda task_id: None) 68 monkeypatch.setattr(browser_tool, "_get_cdp_override", lambda: "") 69 monkeypatch.setattr(browser_tool, "_get_cloud_provider", lambda: provider) 70 71 with patch("tools.browser_tool.requests.get", return_value=response) as mock_get: 72 session_info = browser_tool._get_session_info("task-browser-use") 73 74 assert session_info["cdp_url"] == WS_URL 75 provider.create_session.assert_called_once_with("task-browser-use") 76 mock_get.assert_called_once_with( 77 "https://cdp.browser-use.example/session/json/version", 78 timeout=10, 79 ) 80 81 82 class TestGetCdpOverride: 83 def test_prefers_env_var_over_config(self, monkeypatch): 84 import tools.browser_tool as browser_tool 85 86 monkeypatch.setenv("BROWSER_CDP_URL", HTTP_URL) 87 monkeypatch.setattr( 88 browser_tool, 89 "read_raw_config", 90 lambda: {"browser": {"cdp_url": "http://config-host:9222"}}, 91 raising=False, 92 ) 93 94 response = Mock() 95 response.raise_for_status.return_value = None 96 response.json.return_value = {"webSocketDebuggerUrl": WS_URL} 97 98 with patch("tools.browser_tool.requests.get", return_value=response) as mock_get: 99 resolved = browser_tool._get_cdp_override() 100 101 assert resolved == WS_URL 102 mock_get.assert_called_once_with(VERSION_URL, timeout=10) 103 104 def test_uses_config_browser_cdp_url_when_env_missing(self, monkeypatch): 105 import tools.browser_tool as browser_tool 106 107 monkeypatch.delenv("BROWSER_CDP_URL", raising=False) 108 109 response = Mock() 110 response.raise_for_status.return_value = None 111 response.json.return_value = {"webSocketDebuggerUrl": WS_URL} 112 113 with patch("hermes_cli.config.read_raw_config", return_value={"browser": {"cdp_url": HTTP_URL}}), \ 114 patch("tools.browser_tool.requests.get", return_value=response) as mock_get: 115 resolved = browser_tool._get_cdp_override() 116 117 assert resolved == WS_URL 118 mock_get.assert_called_once_with(VERSION_URL, timeout=10)