Add grid planner, CI, and tests
Some checks failed
CI / test (push) Failing after 1m12s

This commit is contained in:
2026-04-05 19:27:55 +02:00
parent a2ef50401b
commit b1d2b6b321
16 changed files with 383 additions and 19 deletions

29
tests/conftest.py Normal file
View File

@@ -0,0 +1,29 @@
import base64
import pytest
from server.main import manager
@pytest.fixture
def fake_screenshot() -> str:
"""Return a reproducible base64 string representing a dummy screenshot."""
return base64.b64encode(b"clickthrough-dummy").decode()
@pytest.fixture
def default_grid_request(fake_screenshot):
return {
"width": 640,
"height": 480,
"screenshot_base64": fake_screenshot,
"rows": 3,
"columns": 3,
}
@pytest.fixture(autouse=True)
def reset_manager_state():
manager._grids.clear()
yield
manager._grids.clear()

View File

@@ -0,0 +1,53 @@
from typing import Any, Dict
from skill.agent_runner import ClickthroughAgentRunner
from skill.clickthrough_skill import ActionPlan, ClickthroughSkill
class DummySkill(ClickthroughSkill):
def __init__(self):
self.last_plan: ActionPlan | None = None
def describe_grid(
self,
screenshot_base64: str,
width: int,
height: int,
rows: int = 4,
columns: int = 4,
) -> Dict[str, Any]:
return {
"grid_id": "dummy-grid",
"cells": [
{"cell_id": "dummy-grid-1", "label": "button", "bounds": [0, 0, 100, 100]},
{"cell_id": "dummy-grid-2", "label": "target", "bounds": [100, 0, 200, 100]},
],
}
def plan_action(self, plan: ActionPlan) -> Dict[str, Any]:
self.last_plan = plan
return {"success": True, "target_cell": plan.target_cell}
def grid_summary(self, grid_id: str) -> Dict[str, Any]:
return {"grid_id": grid_id, "summary": "ok"}
def grid_history(self, grid_id: str) -> Dict[str, Any]:
return {"grid_id": grid_id, "history": []}
def test_agent_runner_prefers_label():
runner = ClickthroughAgentRunner(DummySkill())
result = runner.run_once(
screenshot_base64="AA==",
width=120,
height=80,
preferred_label="target",
)
assert result.action["target_cell"] == "dummy-grid-2"
assert result.summary["summary"] == "ok"
def test_agent_runner_defaults_to_center():
runner = ClickthroughAgentRunner(DummySkill())
result = runner.run_once(screenshot_base64="AA==", width=120, height=80)
assert result.action["target_cell"] == "dummy-grid-2"

51
tests/test_grid.py Normal file
View File

@@ -0,0 +1,51 @@
from server.config import ServerSettings
from server.grid import GridManager
from server.models import ActionPayload, ActionType, GridInitRequest
def test_grid_creation_respects_dimensions(default_grid_request):
settings = ServerSettings(grid_rows=2, grid_cols=2)
manager = GridManager(settings)
request = GridInitRequest(**default_grid_request)
grid = manager.create_grid(request)
descriptor = grid.describe()
assert descriptor.grid_id
assert descriptor.rows == 3
assert descriptor.columns == 3
assert len(descriptor.cells) == 9
assert descriptor.metadata.get("width") == 640
assert descriptor.metadata.get("height") == 480
def test_grid_action_records_history(default_grid_request):
manager = GridManager(ServerSettings())
request = GridInitRequest(**default_grid_request)
grid = manager.create_grid(request)
descriptor = grid.describe()
target_cell = descriptor.cells[0].cell_id
payload = ActionPayload(
grid_id=descriptor.grid_id,
action=ActionType.CLICK,
target_cell=target_cell,
comment="click test",
)
result = grid.apply_action(payload)
assert result.success
assert result.coordinates is not None
assert grid.action_history[-1]["coordinates"] == result.coordinates
def test_manager_get_grid_missing(default_grid_request):
manager = GridManager(ServerSettings())
request = GridInitRequest(**default_grid_request)
_ = manager.create_grid(request)
try:
manager.get_grid("does-not-exist")
found = True
except KeyError:
found = False
assert not found