Files
OpenJarvis/tests/tools/test_browser_axtree.py
T
Jon Saad-FalconandClaude Opus 4.6 3040f468b6 feat: integrate Exo, Nexa, Uzu, and Apple FM inference engines
Add four new OpenAI-compatible inference engines across the full stack:

Rust backend:
- Config structs with serde defaults (ExoEngineConfig, NexaEngineConfig,
  UzuEngineConfig, AppleFmEngineConfig) in openjarvis-core
- Factory constructors on OpenAICompatEngine (exo, nexa, uzu, apple_fm)
- Engine enum variants with delegate_engine! macro dispatch
- Discovery and resolution in get_engine_static()
- PyO3 bridge support in PyEngine

Python frontend:
- Data-driven engine class registration in openai_compat_engines.py
- Config dataclasses with backward-compat host properties
- Discovery host map entries
- DEFAULT_SEARCH_SPACE updated with new engine backends
- Apple FM shim (FastAPI wrapper for python-apple-fm-sdk, macOS only)

Config & tests:
- TOML config sections for all four engines
- Unit tests for factory methods, enum variants, and search space

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 02:00:10 +00:00

122 lines
4.5 KiB
Python

"""Tests for browser_axtree tool."""
from unittest.mock import MagicMock, PropertyMock, patch
from openjarvis.tools.browser_axtree import BrowserAXTreeTool
def _make_mock_page():
page = MagicMock()
page.accessibility.snapshot.return_value = {
"role": "WebArea",
"name": "Test Page",
"children": [
{"role": "heading", "name": "Welcome", "level": 1},
{"role": "link", "name": "Click me", "url": "https://example.com"},
{"role": "textbox", "name": "Search", "value": ""},
],
}
return page
def _make_mock_session(page=None):
if page is None:
page = _make_mock_page()
session = MagicMock()
type(session).page = PropertyMock(return_value=page)
return session
class TestBrowserAXTreeTool:
def test_instantiation(self) -> None:
tool = BrowserAXTreeTool()
assert tool.tool_id == "browser_axtree"
assert tool.spec.name == "browser_axtree"
def test_execute_returns_tree(self) -> None:
session = _make_mock_session()
with patch("openjarvis.tools.browser_axtree._session", session):
tool = BrowserAXTreeTool()
result = tool.execute()
assert result.success is True
assert "heading" in result.content
assert "Welcome" in result.content
def test_execute_includes_all_roles(self) -> None:
session = _make_mock_session()
with patch("openjarvis.tools.browser_axtree._session", session):
tool = BrowserAXTreeTool()
result = tool.execute()
assert result.success is True
assert "WebArea" in result.content
assert "link" in result.content
assert "textbox" in result.content
def test_execute_includes_node_count_metadata(self) -> None:
session = _make_mock_session()
with patch("openjarvis.tools.browser_axtree._session", session):
tool = BrowserAXTreeTool()
result = tool.execute()
assert result.success is True
# 1 root + 3 children = 4 nodes
assert result.metadata["node_count"] == 4
def test_execute_max_depth(self) -> None:
"""When max_depth=1 only the root node should appear."""
session = _make_mock_session()
with patch("openjarvis.tools.browser_axtree._session", session):
tool = BrowserAXTreeTool()
result = tool.execute(max_depth=1)
assert result.success is True
assert "WebArea" in result.content
# Children at depth 1 should not be present
assert "heading" not in result.content
def test_execute_empty_snapshot(self) -> None:
page = MagicMock()
page.accessibility.snapshot.return_value = None
session = _make_mock_session(page)
with patch("openjarvis.tools.browser_axtree._session", session):
tool = BrowserAXTreeTool()
result = tool.execute()
assert result.success is False
assert "No accessibility tree" in result.content
def test_playwright_not_installed(self) -> None:
session = MagicMock()
type(session).page = PropertyMock(
side_effect=ImportError("playwright not installed")
)
with patch("openjarvis.tools.browser_axtree._session", session):
tool = BrowserAXTreeTool()
result = tool.execute()
assert result.success is False
assert "playwright" in result.content.lower()
def test_spec_category_and_capabilities(self) -> None:
tool = BrowserAXTreeTool()
assert tool.spec.category == "browser"
assert "network:fetch" in tool.spec.required_capabilities
def test_spec_has_max_depth_parameter(self) -> None:
tool = BrowserAXTreeTool()
props = tool.spec.parameters.get("properties", {})
assert "max_depth" in props
assert props["max_depth"]["type"] == "integer"
def test_to_openai_function(self) -> None:
tool = BrowserAXTreeTool()
fn = tool.to_openai_function()
assert fn["type"] == "function"
assert fn["function"]["name"] == "browser_axtree"
def test_execute_snapshot_error(self) -> None:
page = MagicMock()
page.accessibility.snapshot.side_effect = Exception("Browser crashed")
session = _make_mock_session(page)
with patch("openjarvis.tools.browser_axtree._session", session):
tool = BrowserAXTreeTool()
result = tool.execute()
assert result.success is False
assert "AX tree extraction error" in result.content