vproxy / tests /unit /test_cdp_client.py
jlshu's picture
Upload 85 files
95f8c4b verified
Raw History Blame Contribute Delete
4.41 kB
"""Unit tests for native async CDP client and protocol handling."""
from __future__ import annotations
import asyncio
import json
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from aistudio_api.infrastructure.browser.cdp_client import (
BLOCKED_URL_PATTERNS,
CDPClient,
CDPConnection,
CDPError,
CDPPage,
)
def test_blocked_url_patterns_coverage():
"""Verify kernel-level asset pruning covers images, fonts, and trackers."""
assert "*.png" in BLOCKED_URL_PATTERNS
assert "*.jpg" in BLOCKED_URL_PATTERNS
assert "*.woff2" in BLOCKED_URL_PATTERNS
assert "*google-analytics.com*" in BLOCKED_URL_PATTERNS
assert "*play.google.com/log*" in BLOCKED_URL_PATTERNS
@pytest.mark.anyio
async def test_cdp_connection_send_and_receive():
"""Test CDPConnection request-response matching and error handling."""
conn = CDPConnection("ws://127.0.0.1:9222/devtools/page/test")
fake_ws = AsyncMock()
conn.ws = fake_ws
# Mock sending and receiving
async def fake_send(text):
data = json.loads(text)
req_id = data["id"]
# Simulate response in future
fut = conn._futures.get(req_id)
if fut and not fut.done():
fut.set_result({"result": {"value": 42}})
fake_ws.send = fake_send
res = await conn.send("Runtime.evaluate", {"expression": "1 + 1"})
assert res == {"result": {"value": 42}}
@pytest.mark.anyio
async def test_cdp_connection_error_handling():
"""Test CDPConnection properly raises CDPError on JSON-RPC error."""
conn = CDPConnection("ws://127.0.0.1:9222/devtools/page/test")
fake_ws = AsyncMock()
conn.ws = fake_ws
async def fake_send(text):
data = json.loads(text)
req_id = data["id"]
fut = conn._futures.get(req_id)
if fut and not fut.done():
fut.set_exception(CDPError(code=-32000, message="Target closed"))
fake_ws.send = fake_send
with pytest.raises(CDPError) as exc_info:
await conn.send("Page.navigate", {"url": "https://example.com"})
assert "Target closed" in str(exc_info.value)
@pytest.mark.anyio
async def test_cdp_page_blocked_urls_configuration():
"""Test CDPPage sets blocked URLs on Network domain."""
conn = MagicMock(spec=CDPConnection)
conn.send = AsyncMock(return_value={})
conn.on = MagicMock()
page = CDPPage(conn, target_id="target-1")
await page.set_blocked_urls(BLOCKED_URL_PATTERNS)
conn.send.assert_called_with("Network.setBlockedURLs", {"urls": BLOCKED_URL_PATTERNS})
@pytest.mark.anyio
async def test_cdp_page_evaluate_argument_wrapping():
"""Test CDPPage.evaluate correctly wraps expressions with arguments and unwraps value."""
conn = MagicMock(spec=CDPConnection)
conn.send = AsyncMock(return_value={"result": {"type": "string", "value": "hello world"}})
page = CDPPage(conn, target_id="target-1")
res = await page.evaluate("(args) => args.val", {"val": "hello world"})
assert res == "hello world"
call_args = conn.send.call_args[0]
assert call_args[0] == "Runtime.evaluate"
expr = call_args[1]["expression"]
assert "hello world" in expr
assert call_args[1]["awaitPromise"] is True
@pytest.mark.anyio
async def test_cdp_page_set_cookies_normalization():
"""Test cookie normalization handles __Host- prefixes and domains properly."""
conn = MagicMock(spec=CDPConnection)
conn.send = AsyncMock(return_value={})
page = CDPPage(conn, target_id="target-1")
cookies = [
{
"name": "SID",
"value": "sid123",
"domain": ".google.com",
"path": "/",
"sameSite": "None",
},
{
"name": "__Host-GAPS",
"value": "gaps123",
"domain": "accounts.google.com",
"path": "/",
},
]
await page.set_cookies(cookies)
conn.send.assert_called()
payload = conn.send.call_args[0][1]["cookies"]
assert len(payload) == 2
sid = next(c for c in payload if c["name"] == "SID")
assert sid["domain"] == ".google.com"
assert sid["sameSite"] == "None"
host_cookie = next(c for c in payload if c["name"] == "__Host-GAPS")
# Must NOT have domain attribute with leading dot, must have url
assert "domain" not in host_cookie
assert host_cookie["url"] == "https://accounts.google.com/"