Skip to main content
Glama
Fayeblade1488

Venice Browser MCP Bridge

test_framers.py5.86 kB
import asyncio import json import pytest import sys import os from unittest.mock import MagicMock, AsyncMock, patch # Make src module available for testing sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../src'))) from venice_browser_mcp_v23_impl import ContentLengthFramer, LineFramer, run_main, _AsyncStdoutWriter class MockStreamReader(asyncio.StreamReader): def __init__(self, data): super().__init__() self.feed_data(data) self.feed_eof() class MockAsyncWriter(_AsyncStdoutWriter): def __init__(self): self.written_data = bytearray() # We don't need the stream or lock for this mock self._buf = self.written_data async def drain(self): # The real drain clears the buffer, we don't want that for inspection pass @pytest.fixture def mock_browser_env_fixture(): """Fixture to provide a mocked BrowserEnv instance.""" with patch('venice_browser_mcp_v23_impl.BrowserEnv') as MockBrowserEnv: mock_instance = MockBrowserEnv.return_value mock_instance.close = AsyncMock() yield mock_instance @pytest.mark.asyncio async def test_content_length_framer_invalid_header_is_handled(mock_browser_env_fixture): """ Test that the main loop handles a malformed Content-Length header gracefully. """ # 1. Prepare a malformed message malformed_message = b"Content-Length: not-a-number\r\n\r\n" # 2. Mock the environment mock_reader = MockStreamReader(malformed_message) mock_writer = MockAsyncWriter() # 3. Run the main loop, passing mocks directly await run_main( framing="content-length", headless=True, storage_state="", nav_timeout_ms=1000, browser_name="chromium", reader=mock_reader, writer=mock_writer, ) # 4. Assert that a JSON-RPC error was written output_bytes = mock_writer.written_data # The framer should have written a valid Content-Length message for the error header_part, body_part = output_bytes.split(b'\r\n\r\n', 1) response = json.loads(body_part.decode('utf-8')) assert "error" in response assert response["error"]["code"] == -32700 # Parse Error assert "Invalid Content-Length header" in response["error"]["message"] # Assert that the browser was closed because the loop terminated mock_browser_env_fixture.close.assert_awaited_once() @pytest.mark.asyncio async def test_shutdown_command_closes_browser_gracefully(mock_browser_env_fixture): """ Test that the mcp.shutdown command terminates the loop and closes the browser once. """ message = b'{"id": "shutdown-1", "method": "mcp.shutdown", "params": {}}\n' mock_reader = MockStreamReader(message) mock_writer = MockAsyncWriter() await run_main( framing="line", headless=True, storage_state="", nav_timeout_ms=1000, browser_name="chromium", reader=mock_reader, writer=mock_writer, ) # Assert that a success response was written output = mock_writer.written_data.decode('utf-8') response = json.loads(output) assert response["id"] == "shutdown-1" assert response["result"]["ok"] is True assert response["result"]["shutdown"] is True # Assert that close was called exactly once from the finally block mock_browser_env_fixture.close.assert_awaited_once() @pytest.mark.asyncio async def test_ping_command(mock_browser_env_fixture): """Test the ping command returns the echo parameter.""" message = b'{"id": "ping-1", "method": "ping", "params": {"echo": "hello"}}\n' mock_reader = MockStreamReader(message) mock_writer = MockAsyncWriter() await run_main( framing="line", headless=True, storage_state="", nav_timeout_ms=1000, browser_name="chromium", reader=mock_reader, writer=mock_writer, ) output = mock_writer.written_data.decode('utf-8') response = json.loads(output) assert response["result"]["echo"] == "hello" @pytest.mark.asyncio async def test_unknown_method(mock_browser_env_fixture): """Test that an unknown RPC method returns a proper error.""" message = b'{"id": "unknown-1", "method": "foo.bar", "params": {}}\n' mock_reader = MockStreamReader(message) mock_writer = MockAsyncWriter() await run_main( framing="line", headless=True, storage_state="", nav_timeout_ms=1000, browser_name="chromium", reader=mock_reader, writer=mock_writer, ) output = mock_writer.written_data.decode('utf-8') response = json.loads(output) assert "error" in response assert response["error"]["code"] == -32603 assert "Unknown method: foo.bar" in response["error"]["message"] @pytest.mark.asyncio async def test_line_framer_invalid_json_is_handled(mock_browser_env_fixture): """ Test that the main loop handles malformed JSON with the line framer. """ malformed_message = b'{"id": 1, "method": "ping", "params": {}}\nnot json\n' mock_reader = MockStreamReader(malformed_message) mock_writer = MockAsyncWriter() await run_main( framing="line", headless=True, storage_state="", nav_timeout_ms=1000, browser_name="chromium", reader=mock_reader, writer=mock_writer, ) output = mock_writer.written_data.decode('utf-8').strip().split('\n') # First message should be a valid response response1 = json.loads(output[0]) assert "result" in response1 assert response1["id"] == 1 # Second message should be a parse error response2 = json.loads(output[1]) assert "error" in response2 assert response2["error"]["code"] == -32700 mock_browser_env_fixture.close.assert_awaited_once()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Fayeblade1488/Fayeblade_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server