- web_ui.py: major refactor with improved runner, mode selection, progress tracking - scripts: add device_runtime, device_calibrate, calibration_trace, record_android_flow - docs: add phone-control-manual, update device-adaptation and windows-migration - invoice_tool: enhance H5 automation flow and visual fallback - calibrate.py: expand calibration capabilities - add skills/ and tests/ directories - remove obsolete .opencode/skills/invoice-wrapup Co-Authored-By: Claude <noreply@anthropic.com>
58 lines
2.6 KiB
Python
58 lines
2.6 KiB
Python
from __future__ import annotations
|
|
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
SCRIPTS = Path(__file__).resolve().parents[1] / "scripts"
|
|
if str(SCRIPTS) not in sys.path:
|
|
sys.path.insert(0, str(SCRIPTS))
|
|
|
|
import device_runtime
|
|
|
|
|
|
class DeviceRuntimeTests(unittest.TestCase):
|
|
def test_list_devices_parses_adb_long_output(self) -> None:
|
|
output = "List of devices attached\nABC123\tdevice product:foo model:Pixel_8 device:shiba transport_id:1\n"
|
|
completed = subprocess.CompletedProcess(["adb"], 0, output, "")
|
|
with patch.object(device_runtime, "_raw_adb", return_value=completed):
|
|
devices = device_runtime.list_devices()
|
|
self.assertEqual(devices, [{"serial": "ABC123", "state": "device", "product": "foo", "model": "Pixel_8", "device": "shiba", "transport_id": "1"}])
|
|
|
|
def test_require_single_device_rejects_multiple(self) -> None:
|
|
with patch.object(device_runtime, "list_devices", return_value=[
|
|
{"serial": "a", "state": "device"}, {"serial": "b", "state": "device"},
|
|
]):
|
|
with self.assertRaisesRegex(device_runtime.DeviceError, "多台"):
|
|
device_runtime.require_single_device()
|
|
|
|
def test_registry_round_trip_isolated_from_project_workdir(self) -> None:
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
path = Path(directory) / "device_profiles.json"
|
|
with patch.object(device_runtime, "PROFILE_REGISTRY_PATH", path), patch.object(device_runtime, "WORK_DIR", Path(directory)):
|
|
device_runtime.save_registry({"schema_version": 2, "devices": {"serial-a": {"status": "verified"}}})
|
|
loaded = device_runtime.load_registry()
|
|
self.assertEqual(loaded["devices"]["serial-a"]["status"], "verified")
|
|
|
|
def test_connect_wireless_rejects_non_ip_address(self) -> None:
|
|
with self.assertRaisesRegex(device_runtime.DeviceError, "IP"):
|
|
device_runtime.connect_wireless("not-an-ip")
|
|
|
|
def test_connect_wireless_reports_connected_device(self) -> None:
|
|
completed = subprocess.CompletedProcess(["adb"], 0, "connected to 192.168.1.8:5555", "")
|
|
with patch.object(device_runtime, "_raw_adb", return_value=completed), patch.object(
|
|
device_runtime,
|
|
"list_devices",
|
|
return_value=[{"serial": "192.168.1.8:5555", "state": "device"}],
|
|
):
|
|
result = device_runtime.connect_wireless("192.168.1.8")
|
|
self.assertTrue(result["connected"])
|
|
self.assertEqual(result["endpoint"], "192.168.1.8:5555")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|