Spaces:
Paused
Paused
File size: 7,951 Bytes
a5784e9 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 | """
Tests for browser_utils/initialization/debug.py
Target coverage: >80% (from baseline 10%)
"""
from unittest.mock import Mock, PropertyMock, patch
import pytest
from browser_utils.initialization.debug import setup_debug_listeners
@pytest.fixture
def mock_page():
"""Create mock page"""
page = Mock()
page.on = Mock()
return page
@pytest.fixture
def mock_state_with_logs():
"""Create a mock state with console_logs and network_log that we can inspect."""
mock_state = Mock()
mock_state.console_logs = []
mock_state.network_log = {"requests": [], "responses": []}
with patch("api_utils.server_state.state", mock_state):
yield mock_state
@pytest.fixture
def mock_console_message():
"""Create mock console message"""
msg = Mock()
msg.type = "log"
msg.text = "test message"
msg.location = {"url": "https://example.com/page.js", "lineNumber": 42}
return msg
@pytest.fixture
def mock_request():
"""Create mock network request"""
req = Mock()
req.url = "https://example.com/api/data"
req.method = "GET"
req.resource_type = "xhr"
return req
@pytest.fixture
def mock_response():
"""Create mock network response"""
resp = Mock()
resp.url = "https://example.com/api/data"
resp.status = 200
resp.status_text = "OK"
return resp
def test_listeners_attached(mock_page, mock_state_with_logs):
"""Test all listeners attached"""
setup_debug_listeners(mock_page)
assert mock_page.on.call_count == 3
listener_names = [call_args[0][0] for call_args in mock_page.on.call_args_list]
assert "console" in listener_names
assert "request" in listener_names
assert "response" in listener_names
def test_console_handler_log(mock_page, mock_state_with_logs, mock_console_message):
"""Test console log captured"""
setup_debug_listeners(mock_page)
# Extract console handler
console_handler = None
for call_args in mock_page.on.call_args_list:
if call_args[0][0] == "console":
console_handler = call_args[0][1]
break
assert console_handler is not None
# Trigger handler (datetime is imported inside the handler, no need to mock)
console_handler(mock_console_message)
# Verify log captured
assert len(mock_state_with_logs.console_logs) == 1
log_entry = mock_state_with_logs.console_logs[0]
assert log_entry["type"] == "log"
assert log_entry["text"] == "test message"
assert "timestamp" in log_entry
assert "location" in log_entry
def test_console_handler_error(mock_page, mock_state_with_logs):
"""Test console error captured"""
setup_debug_listeners(mock_page)
console_handler = None
for call_args in mock_page.on.call_args_list:
if call_args[0][0] == "console":
console_handler = call_args[0][1]
break
error_msg = Mock()
error_msg.type = "error"
error_msg.text = "Critical error"
error_msg.location = {"url": "test.js", "lineNumber": 1}
assert console_handler is not None
console_handler(error_msg)
assert len(mock_state_with_logs.console_logs) == 1
assert mock_state_with_logs.console_logs[0]["type"] == "error"
def test_request_handler_xhr(mock_page, mock_state_with_logs, mock_request):
"""Test XHR request captured"""
setup_debug_listeners(mock_page)
request_handler = None
for call_args in mock_page.on.call_args_list:
if call_args[0][0] == "request":
request_handler = call_args[0][1]
break
assert request_handler is not None
request_handler(mock_request)
assert len(mock_state_with_logs.network_log["requests"]) == 1
req_entry = mock_state_with_logs.network_log["requests"][0]
assert req_entry["url"] == "https://example.com/api/data"
assert req_entry["method"] == "GET"
assert "timestamp" in req_entry
def test_request_handler_image_filtered(mock_page, mock_state_with_logs):
"""Test image request filtered out"""
setup_debug_listeners(mock_page)
request_handler = None
for call_args in mock_page.on.call_args_list:
if call_args[0][0] == "request":
request_handler = call_args[0][1]
break
image_req = Mock()
image_req.url = "https://example.com/logo.png"
image_req.method = "GET"
image_req.resource_type = "image"
assert request_handler is not None
request_handler(image_req)
assert len(mock_state_with_logs.network_log["requests"]) == 0
def test_request_handler_css_filtered(mock_page, mock_state_with_logs):
"""Test CSS request filtered out"""
setup_debug_listeners(mock_page)
request_handler = None
for call_args in mock_page.on.call_args_list:
if call_args[0][0] == "request":
request_handler = call_args[0][1]
break
css_req = Mock()
css_req.url = "https://example.com/styles.css"
css_req.method = "GET"
css_req.resource_type = "stylesheet"
assert request_handler is not None
request_handler(css_req)
assert len(mock_state_with_logs.network_log["requests"]) == 0
def test_response_handler_success(mock_page, mock_state_with_logs, mock_response):
"""Test successful response captured"""
setup_debug_listeners(mock_page)
response_handler = None
for call_args in mock_page.on.call_args_list:
if call_args[0][0] == "response":
response_handler = call_args[0][1]
break
assert response_handler is not None
response_handler(mock_response)
assert len(mock_state_with_logs.network_log["responses"]) == 1
resp_entry = mock_state_with_logs.network_log["responses"][0]
assert resp_entry["status"] == 200
assert resp_entry["url"] == "https://example.com/api/data"
assert "timestamp" in resp_entry
def test_response_handler_error_status(mock_page, mock_state_with_logs):
"""Test error response captured"""
setup_debug_listeners(mock_page)
response_handler = None
for call_args in mock_page.on.call_args_list:
if call_args[0][0] == "response":
response_handler = call_args[0][1]
break
error_resp = Mock()
error_resp.url = "https://example.com/api/error"
error_resp.status = 404
error_resp.status_text = "Not Found"
assert response_handler is not None
response_handler(error_resp)
assert len(mock_state_with_logs.network_log["responses"]) == 1
assert mock_state_with_logs.network_log["responses"][0]["status"] == 404
def test_console_handler_exception_caught(mock_page, mock_state_with_logs):
"""Test exception in console handler caught"""
setup_debug_listeners(mock_page)
console_handler = None
for call_args in mock_page.on.call_args_list:
if call_args[0][0] == "console":
console_handler = call_args[0][1]
break
bad_msg = Mock()
# Use PropertyMock to raise exception when .text is accessed as property
type(bad_msg).text = PropertyMock(side_effect=RuntimeError("Extraction failed"))
assert console_handler is not None
with patch("browser_utils.initialization.debug.logger") as mock_logger:
# Should not raise
console_handler(bad_msg)
# Verify error logged
assert mock_logger.error.called
def test_request_handler_exception_caught(mock_page, mock_state_with_logs):
"""Test exception in request handler caught"""
setup_debug_listeners(mock_page)
request_handler = None
for call_args in mock_page.on.call_args_list:
if call_args[0][0] == "request":
request_handler = call_args[0][1]
break
bad_req = Mock()
bad_req.url = Mock(side_effect=RuntimeError("URL access failed"))
assert request_handler is not None
with patch("browser_utils.initialization.debug.logger") as mock_logger:
request_handler(bad_req)
assert mock_logger.error.called
|