91e75e620b
CI: cua-driver distro-compat matrix / debian:12 (glibc 2.36) (push) Has been cancelled
CI: SPDX Headers / Check SPDX headers (warn-only) (push) Has been cancelled
CD: Docs MCP Server / build (linux/amd64) (push) Has been cancelled
CD: Docs MCP Server / build (linux/arm64) (push) Has been cancelled
CD: Docs MCP Server / merge (push) Has been cancelled
CI: cua-driver distro-compat matrix / Resolve release version (push) Has been cancelled
CI: cua-driver distro-compat matrix / fedora:41 (glibc 2.40) (push) Has been cancelled
CI: cua-driver distro-compat matrix / rockylinux:9 (glibc 2.34) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:22.04 (glibc 2.35) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:24.04 (glibc 2.39) (push) Has been cancelled
CI: cua-driver distro-compat matrix / Distro compat summary (push) Has been cancelled
CI: Rust Linux unit / Rust Linux unit and compile (push) Has been cancelled
CI: Rust Windows unit / Rust Windows unit and compile (push) Has been cancelled
CI: Nix Linux Rust source / Nix / compositor build (push) Has been cancelled
CI: Nix Linux Rust source / Nix / driver package (push) Has been cancelled
CI: Nix Linux Rust source / Nix / Rust unit tests (push) Has been cancelled
125 lines
3.9 KiB
Python
125 lines
3.9 KiB
Python
"""Integration tests — cloud sandbox via CUA API.
|
|
|
|
CUA_API_KEY=sk-... pytest tests/test_cloud.py -v -s
|
|
|
|
Requires a running cloud VM. Set CUA_TEST_CLOUD_VM_NAME to the VM name.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
|
|
import pytest
|
|
from cua_sandbox import Image, Sandbox
|
|
|
|
pytestmark = pytest.mark.asyncio
|
|
|
|
API_KEY = os.environ.get("CUA_API_KEY")
|
|
VM_NAME = os.environ.get("CUA_TEST_CLOUD_VM_NAME", "steady-bluebird")
|
|
|
|
skip_no_key = pytest.mark.skipif(not API_KEY, reason="CUA_API_KEY not set")
|
|
|
|
|
|
@skip_no_key
|
|
async def test_cloud_connect_by_name():
|
|
"""Connect to an existing cloud VM by name and take a screenshot."""
|
|
sb = await Sandbox.connect(VM_NAME, api_key=API_KEY)
|
|
screenshot = await sb.screenshot()
|
|
assert screenshot[:4] == b"\x89PNG"
|
|
assert len(screenshot) > 1000
|
|
await sb.disconnect()
|
|
|
|
|
|
@skip_no_key
|
|
async def test_cloud_shell():
|
|
"""Run a shell command on a cloud VM."""
|
|
sb = await Sandbox.connect(VM_NAME, api_key=API_KEY)
|
|
result = await sb.shell.run("echo hello-cloud")
|
|
assert result.success
|
|
assert "hello-cloud" in result.stdout
|
|
await sb.disconnect()
|
|
|
|
|
|
@skip_no_key
|
|
async def test_cloud_screen_size():
|
|
"""Get screen dimensions from a cloud VM."""
|
|
sb = await Sandbox.connect(VM_NAME, api_key=API_KEY)
|
|
w, h = await sb.get_dimensions()
|
|
assert w > 0
|
|
assert h > 0
|
|
await sb.disconnect()
|
|
|
|
|
|
@skip_no_key
|
|
async def test_cloud_keyboard_mouse():
|
|
"""Basic keyboard and mouse operations on a cloud VM."""
|
|
sb = await Sandbox.connect(VM_NAME, api_key=API_KEY)
|
|
await sb.mouse.move(100, 100)
|
|
await sb.mouse.click(100, 100)
|
|
await sb.keyboard.type("hello")
|
|
await sb.disconnect()
|
|
|
|
|
|
@skip_no_key
|
|
async def test_cloud_environment():
|
|
"""Get environment info from a cloud VM."""
|
|
sb = await Sandbox.connect(VM_NAME, api_key=API_KEY)
|
|
env = await sb.get_environment()
|
|
assert env in ("windows", "mac", "linux", "browser")
|
|
await sb.disconnect()
|
|
|
|
|
|
async def test_cloud_no_api_key_errors():
|
|
"""Connecting with no API key gives a clear error."""
|
|
old = os.environ.pop("CUA_API_KEY", None)
|
|
try:
|
|
with pytest.raises(ValueError, match="No CUA API key found"):
|
|
await Sandbox.connect("anything")
|
|
finally:
|
|
if old:
|
|
os.environ["CUA_API_KEY"] = old
|
|
|
|
|
|
async def test_cloud_no_image_no_name_errors():
|
|
"""Creating without an image raises a clear error."""
|
|
with pytest.raises((ValueError, TypeError)):
|
|
await Sandbox._create(api_key="sk-test-fake-key")
|
|
|
|
|
|
@skip_no_key
|
|
async def test_cloud_ephemeral_linux():
|
|
"""Create an ephemeral cloud Linux VM, use it, and destroy on exit."""
|
|
async with Sandbox.ephemeral(Image.linux(), api_key=API_KEY) as sb:
|
|
assert sb.name is not None
|
|
screenshot = await sb.screenshot()
|
|
assert screenshot[:4] == b"\x89PNG"
|
|
assert len(screenshot) > 1000
|
|
result = await sb.shell.run("echo ephemeral-test")
|
|
assert result.success
|
|
assert "ephemeral-test" in result.stdout
|
|
|
|
|
|
@skip_no_key
|
|
async def test_cloud_ephemeral_android():
|
|
"""Create an ephemeral Android cloud VM, verify screenshot and display URL."""
|
|
async with Sandbox.ephemeral(Image.android("14"), api_key=API_KEY) as sb:
|
|
assert sb.name is not None
|
|
screenshot = await sb.screenshot()
|
|
assert screenshot[:4] == b"\x89PNG"
|
|
assert len(screenshot) > 1000
|
|
env = await sb.get_environment()
|
|
assert env == "android"
|
|
display_url = await sb.get_display_url(share=True)
|
|
assert ".cua.sh" in display_url
|
|
assert "password=" in display_url
|
|
|
|
|
|
@skip_no_key
|
|
async def test_cloud_invalid_api_key_errors():
|
|
"""An invalid (reversed) API key should get an HTTP error from the API."""
|
|
reversed_key = API_KEY[::-1]
|
|
with pytest.raises(Exception):
|
|
sb = await Sandbox.connect(VM_NAME, api_key=reversed_key)
|
|
await sb.screenshot()
|
|
await sb.disconnect()
|