"""Unit tests for cloud.sdk.client.CloudClient (task 8.2).""" from __future__ import annotations import pytest from cloud.config import CloudConfig from cloud.plugins import PluginRegistry from cloud.pool import DevicePool from cloud.sdk.api import create_cloud_router from cloud.sdk.client import CloudClient from cloud.scheduler import TaskScheduler from cloud.store import CloudStore from core.models import Device pytest.importorskip("fastapi") from fastapi import FastAPI # noqa: E402 from fastapi.testclient import TestClient # noqa: E402 def _config() -> CloudConfig: return CloudConfig( sync_interval_seconds=30, stale_after_seconds=60, max_queue_depth=100, default_assignment_strategy="fifo_match", api_version_prefix="/v1", db_path="cloud/cloud.sqlite3", ) def _client_and_pool(tmp_path): store = CloudStore(tmp_path / "cloud.sqlite3") pool = DevicePool(store, _config()) scheduler = TaskScheduler(pool, store, _config()) plugin_registry = PluginRegistry(store) app = FastAPI() app.include_router( create_cloud_router( pool=pool, scheduler=scheduler, plugin_registry=plugin_registry, ) ) test_client = TestClient(app) cloud_client = CloudClient("http://testserver", http_client=test_client) return cloud_client, pool def test_client_submit_and_get_status_round_trip(tmp_path) -> None: client, _ = _client_and_pool(tmp_path) submission = client.submit_task(goal="open settings") assert "task_id" in submission task_id = submission["task_id"] status = client.get_task_status(task_id) assert status["id"] == task_id assert status["status"] == "queued" assert status["goal"] == "open settings" def test_client_list_devices_and_hosts(tmp_path) -> None: client, pool = _client_and_pool(tmp_path) pool.sync_host_devices( "host-a", [Device(id="dev-1", driver_type="wda", status="idle")], # type: ignore[arg-type] address="a:8000", ) devices = client.list_devices() assert [d["device_id"] for d in devices] == ["dev-1"] assert devices[0]["host_id"] == "host-a" hosts = client.list_hosts() assert [h["host_id"] for h in hosts] == ["host-a"] def test_client_plugin_listing_and_registration(tmp_path) -> None: client, _ = _client_and_pool(tmp_path) assert client.list_plugins() == [] registered = client.register_plugin( name="demo", version="1.0.0", entry_point_kind="tool", target="cloud.store:CloudStore", ) assert registered["name"] == "demo" assert registered["wired"] is False listed = client.list_plugins() assert [p["name"] for p in listed] == ["demo"] def test_client_submit_with_constraints(tmp_path) -> None: client, pool = _client_and_pool(tmp_path) pool.sync_host_devices( "host-a", [Device(id="dev-1", driver_type="wda", status="idle")], # type: ignore[arg-type] ) submission = client.submit_task( goal="x", driver_type="wda", capability_tags=[], ) task_id = submission["task_id"] status = client.get_task_status(task_id) assert status["status"] == "queued" def test_client_unknown_task_raises(tmp_path) -> None: import httpx client, _ = _client_and_pool(tmp_path) with pytest.raises(httpx.HTTPStatusError): client.get_task_status("does-not-exist")