Files
wehub-resource-sync 91e75e620b
CI: cua-driver distro-compat matrix / Resolve release version (push) Waiting to run
CI: cua-driver distro-compat matrix / debian:12 (glibc 2.36) (push) Blocked by required conditions
CI: cua-driver distro-compat matrix / fedora:41 (glibc 2.40) (push) Blocked by required conditions
CI: cua-driver distro-compat matrix / rockylinux:9 (glibc 2.34) (push) Blocked by required conditions
CI: cua-driver distro-compat matrix / ubuntu:22.04 (glibc 2.35) (push) Blocked by required conditions
CI: cua-driver distro-compat matrix / ubuntu:24.04 (glibc 2.39) (push) Blocked by required conditions
CI: cua-driver distro-compat matrix / Distro compat summary (push) Blocked by required conditions
CI: Nix Linux Rust source / Nix / compositor build (push) Waiting to run
CI: Nix Linux Rust source / Nix / driver package (push) Waiting to run
CI: Nix Linux Rust source / Nix / Rust unit tests (push) Waiting to run
CI: Rust Linux unit / Rust Linux unit and compile (push) Waiting to run
CI: Rust Windows unit / Rust Windows unit and compile (push) Waiting to run
CI: SPDX Headers / Check SPDX headers (warn-only) (push) Waiting to run
CD: Docs MCP Server / build (linux/amd64) (push) Waiting to run
CD: Docs MCP Server / build (linux/arm64) (push) Waiting to run
CD: Docs MCP Server / merge (push) Blocked by required conditions
chore: import upstream snapshot with attribution
2026-07-13 13:03:19 +08:00

233 lines
8.6 KiB
Python

"""Tests for MCP server command module."""
import argparse
import sys
from unittest.mock import patch
from cua_cli.commands.mcp import (
PERMISSION_GROUPS,
Permission,
execute,
parse_permissions,
register_parser,
)
class TestPermission:
"""Tests for Permission enum."""
def test_all_permissions_have_values(self):
"""Test that all permissions have string values."""
for perm in Permission:
assert isinstance(perm.value, str)
assert ":" in perm.value
def test_sandbox_permissions(self):
"""Test sandbox permission values."""
assert Permission.SANDBOX_LIST.value == "sandbox:list"
assert Permission.SANDBOX_CREATE.value == "sandbox:create"
assert Permission.SANDBOX_DELETE.value == "sandbox:delete"
def test_computer_permissions(self):
"""Test computer permission values."""
assert Permission.COMPUTER_SCREENSHOT.value == "computer:screenshot"
assert Permission.COMPUTER_CLICK.value == "computer:click"
assert Permission.COMPUTER_TYPE.value == "computer:type"
def test_skills_permissions(self):
"""Test skills permission values."""
assert Permission.SKILLS_LIST.value == "skills:list"
assert Permission.SKILLS_READ.value == "skills:read"
assert Permission.SKILLS_RECORD.value == "skills:record"
class TestPermissionGroups:
"""Tests for permission groups."""
def test_sandbox_all_group(self):
"""Test sandbox:all group contains all sandbox permissions."""
group = PERMISSION_GROUPS["sandbox:all"]
assert Permission.SANDBOX_LIST in group
assert Permission.SANDBOX_CREATE in group
assert Permission.SANDBOX_DELETE in group
assert Permission.SANDBOX_START in group
assert Permission.SANDBOX_STOP in group
def test_sandbox_readonly_group(self):
"""Test sandbox:readonly group contains only read permissions."""
group = PERMISSION_GROUPS["sandbox:readonly"]
assert Permission.SANDBOX_LIST in group
assert Permission.SANDBOX_GET in group
assert Permission.SANDBOX_CREATE not in group
assert Permission.SANDBOX_DELETE not in group
def test_computer_all_group(self):
"""Test computer:all group contains all computer permissions."""
group = PERMISSION_GROUPS["computer:all"]
assert Permission.COMPUTER_SCREENSHOT in group
assert Permission.COMPUTER_CLICK in group
assert Permission.COMPUTER_TYPE in group
assert Permission.COMPUTER_SHELL in group
def test_computer_readonly_group(self):
"""Test computer:readonly group contains only screenshot."""
group = PERMISSION_GROUPS["computer:readonly"]
assert Permission.COMPUTER_SCREENSHOT in group
assert Permission.COMPUTER_CLICK not in group
def test_all_group_contains_everything(self):
"""Test that 'all' group contains all permissions."""
group = PERMISSION_GROUPS["all"]
assert len(group) == len(Permission)
class TestParsePermissions:
"""Tests for parse_permissions function."""
def test_empty_string_returns_empty_set(self):
"""Test that empty string returns empty set."""
result = parse_permissions("")
assert result == set()
def test_single_permission(self):
"""Test parsing a single permission."""
result = parse_permissions("sandbox:list")
assert result == {Permission.SANDBOX_LIST}
def test_multiple_permissions(self):
"""Test parsing multiple permissions."""
result = parse_permissions("sandbox:list,sandbox:create")
assert result == {Permission.SANDBOX_LIST, Permission.SANDBOX_CREATE}
def test_permission_with_spaces(self):
"""Test parsing permissions with spaces."""
result = parse_permissions("sandbox:list, sandbox:create")
assert result == {Permission.SANDBOX_LIST, Permission.SANDBOX_CREATE}
def test_group_expansion(self):
"""Test that groups are expanded."""
result = parse_permissions("sandbox:readonly")
assert Permission.SANDBOX_LIST in result
assert Permission.SANDBOX_GET in result
def test_all_group(self):
"""Test that 'all' group includes everything."""
result = parse_permissions("all")
assert len(result) == len(Permission)
def test_mixed_groups_and_permissions(self):
"""Test mixing groups and individual permissions."""
result = parse_permissions("sandbox:readonly,computer:screenshot")
assert Permission.SANDBOX_LIST in result
assert Permission.SANDBOX_GET in result
assert Permission.COMPUTER_SCREENSHOT in result
def test_unknown_permission_ignored(self):
"""Test that unknown permissions are ignored with warning."""
with patch("cua_cli.commands.mcp.logger") as mock_logger:
result = parse_permissions("sandbox:list,unknown:perm")
assert result == {Permission.SANDBOX_LIST}
mock_logger.warning.assert_called()
class TestRegisterParser:
"""Tests for register_parser function."""
def test_registers_serve_mcp_command(self):
"""Test that serve-mcp command is registered."""
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
register_parser(subparsers)
args = parser.parse_args(["serve-mcp"])
assert hasattr(args, "permissions")
def test_has_permissions_flag(self):
"""Test that --permissions flag is available."""
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
register_parser(subparsers)
args = parser.parse_args(["serve-mcp", "--permissions", "sandbox:all"])
assert args.permissions == "sandbox:all"
def test_has_sandbox_flag(self):
"""Test that --sandbox flag is available."""
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
register_parser(subparsers)
args = parser.parse_args(["serve-mcp", "--sandbox", "my-sandbox"])
assert args.sandbox == "my-sandbox"
class TestExecute:
"""Tests for execute function."""
def test_missing_fastmcp_returns_error(self, args_namespace, capsys):
"""Test that missing fastmcp dependency returns error."""
args = args_namespace(permissions="", sandbox="")
# Temporarily remove mcp modules to simulate ImportError
original_modules = {}
for mod in list(sys.modules.keys()):
if mod.startswith("mcp"):
original_modules[mod] = sys.modules.pop(mod)
try:
with patch.dict(
"sys.modules", {"mcp": None, "mcp.server": None, "mcp.server.fastmcp": None}
):
result = execute(args)
finally:
# Restore modules
sys.modules.update(original_modules)
assert result == 1
def test_permissions_from_env_var(self, args_namespace, monkeypatch):
"""Test that permissions are read from environment variable."""
monkeypatch.setenv("CUA_MCP_PERMISSIONS", "sandbox:readonly")
permissions = parse_permissions("sandbox:readonly")
assert Permission.SANDBOX_LIST in permissions
assert Permission.SANDBOX_CREATE not in permissions
def test_permissions_from_args_override_env(self, args_namespace, monkeypatch):
"""Test that command line args override environment variable."""
args = args_namespace(permissions="computer:all", sandbox="")
monkeypatch.setenv("CUA_MCP_PERMISSIONS", "sandbox:readonly")
# The args.permissions should take precedence
assert args.permissions == "computer:all"
class TestMCPToolRegistration:
"""Tests for MCP tool registration based on permissions."""
def test_permission_affects_tool_registration(self):
"""Test that permissions control which tools would be registered."""
# This is a unit test of the permission logic, not the actual registration
# The actual registration requires fastmcp which may not be installed
all_perms = parse_permissions("all")
assert len(all_perms) == len(Permission)
readonly_perms = parse_permissions("sandbox:readonly")
assert Permission.SANDBOX_LIST in readonly_perms
assert Permission.SANDBOX_CREATE not in readonly_perms
# Test that the registration functions exist and are callable
from cua_cli.commands.mcp import (
_register_computer_tools,
_register_sandbox_tools,
_register_skills_tools,
)
assert callable(_register_sandbox_tools)
assert callable(_register_computer_tools)
assert callable(_register_skills_tools)