from __future__ import annotations from runtime.tool_specs import ( ACTION_TOOL_SPECS, ALL_TOOL_SPECS, FINISH_TASK_SPEC, INPUT_TEXT_SPEC, LAUNCH_APP_SPEC, SWIPE_SPEC, TAP_SPEC, TERMINATE_APP_SPEC, ToolSpec, ) def test_action_tool_specs_has_five_entries_and_all_tool_specs_adds_finish_task() -> None: assert len(ACTION_TOOL_SPECS) == 5 assert len(ALL_TOOL_SPECS) == 6 assert ALL_TOOL_SPECS == [*ACTION_TOOL_SPECS, FINISH_TASK_SPEC] assert FINISH_TASK_SPEC not in ACTION_TOOL_SPECS def test_all_tool_spec_names_are_unique() -> None: names = [spec.name for spec in ALL_TOOL_SPECS] assert len(names) == len(set(names)) def test_every_tool_spec_schema_forbids_additional_properties() -> None: for spec in ALL_TOOL_SPECS: assert isinstance(spec, ToolSpec) assert spec.parameters["type"] == "object" assert spec.parameters["additionalProperties"] is False def test_tap_spec_requires_x_and_y() -> None: assert TAP_SPEC.parameters["required"] == ["x", "y"] assert set(TAP_SPEC.parameters["properties"]) == {"x", "y"} def test_swipe_spec_requires_coordinates_and_makes_duration_optional() -> None: assert SWIPE_SPEC.parameters["required"] == ["start_x", "start_y", "end_x", "end_y"] assert set(SWIPE_SPEC.parameters["properties"]) == { "start_x", "start_y", "end_x", "end_y", "duration_ms", } assert "duration_ms" not in SWIPE_SPEC.parameters["required"] assert SWIPE_SPEC.parameters["properties"]["duration_ms"]["default"] == 500 def test_input_text_spec_requires_text() -> None: assert INPUT_TEXT_SPEC.parameters["required"] == ["text"] assert set(INPUT_TEXT_SPEC.parameters["properties"]) == {"text"} def test_launch_and_terminate_app_specs_require_app_id() -> None: for spec in (LAUNCH_APP_SPEC, TERMINATE_APP_SPEC): assert spec.parameters["required"] == ["app_id"] assert set(spec.parameters["properties"]) == {"app_id"} def test_finish_task_spec_requires_success_and_reason() -> None: assert FINISH_TASK_SPEC.parameters["required"] == ["success", "reason"] assert set(FINISH_TASK_SPEC.parameters["properties"]) == {"success", "reason"} assert FINISH_TASK_SPEC.parameters["properties"]["success"]["type"] == "boolean" def test_no_tool_spec_declares_device_id() -> None: for spec in ALL_TOOL_SPECS: assert "device_id" not in spec.parameters["properties"]