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

298 lines
9.8 KiB
Python

"""Tests for image command module."""
import argparse
from unittest.mock import patch
from cua_cli.commands import image
class TestRegisterParser:
"""Tests for register_parser function."""
def test_registers_image_command(self):
"""Test that image command is registered."""
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
image.register_parser(subparsers)
args = parser.parse_args(["image", "list"])
assert args.image_command == "list"
def test_registers_img_alias(self):
"""Test that img alias is registered."""
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
image.register_parser(subparsers)
args = parser.parse_args(["img", "list"])
assert args.image_command == "list"
def test_list_has_json_flag(self):
"""Test that list command has --json flag."""
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
image.register_parser(subparsers)
args = parser.parse_args(["image", "list", "--json"])
assert args.json is True
def test_list_has_local_flag(self):
"""Test that list command has --local flag."""
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
image.register_parser(subparsers)
args = parser.parse_args(["image", "list", "--local"])
assert args.local is True
def test_push_command(self):
"""Test that push command is registered."""
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
image.register_parser(subparsers)
args = parser.parse_args(["image", "push", "my-image"])
assert args.image_command == "push"
assert args.name == "my-image"
def test_pull_command(self):
"""Test that pull command is registered."""
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
image.register_parser(subparsers)
args = parser.parse_args(["image", "pull", "my-image"])
assert args.image_command == "pull"
assert args.name == "my-image"
def test_delete_command(self):
"""Test that delete command is registered."""
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
image.register_parser(subparsers)
args = parser.parse_args(["image", "delete", "my-image", "--force"])
assert args.image_command == "delete"
assert args.name == "my-image"
assert args.force is True
class TestExecute:
"""Tests for execute function."""
def test_dispatch_to_list(self, args_namespace):
"""Test dispatch to list command."""
args = args_namespace(
command="image",
image_command="list",
json=False,
local=False,
cloud=False,
)
with patch.object(image, "cmd_list", return_value=0) as mock_cmd:
result = image.execute(args)
mock_cmd.assert_called_once_with(args)
assert result == 0
def test_dispatch_to_push(self, args_namespace):
"""Test dispatch to push command."""
args = args_namespace(command="image", image_command="push", name="my-image")
with patch.object(image, "cmd_push", return_value=0) as mock_cmd:
image.execute(args)
mock_cmd.assert_called_once_with(args)
def test_dispatch_to_pull(self, args_namespace):
"""Test dispatch to pull command."""
args = args_namespace(command="image", image_command="pull", name="my-image")
with patch.object(image, "cmd_pull", return_value=0) as mock_cmd:
image.execute(args)
mock_cmd.assert_called_once_with(args)
def test_dispatch_to_delete(self, args_namespace):
"""Test dispatch to delete command."""
args = args_namespace(command="image", image_command="delete", name="my-image")
with patch.object(image, "cmd_delete", return_value=0) as mock_cmd:
image.execute(args)
mock_cmd.assert_called_once_with(args)
def test_unknown_command_returns_error(self, args_namespace):
"""Test that unknown command returns error."""
args = args_namespace(command="image", image_command=None)
with patch.object(image, "print_error"):
result = image.execute(args)
assert result == 1
class TestCmdList:
"""Tests for cmd_list function."""
def test_list_cloud_images(self, args_namespace, sample_cloud_images, mock_api_key):
"""Test listing cloud images."""
args = args_namespace(json=False, local=False, cloud=True)
with patch.object(image, "run_async") as mock_run:
mock_run.return_value = [
{
"name": "ubuntu-22.04",
"type": "qcow2",
"tag": "latest",
"size": "5.0 GB",
"status": "ready",
"created": "2024-01-10",
"source": "cloud",
}
]
with patch.object(image, "print_table") as mock_print:
result = image.cmd_list(args)
assert result == 0
mock_print.assert_called_once()
def test_list_local_images(self, args_namespace, tmp_path, monkeypatch):
"""Test listing local images delegates to local_image."""
args = args_namespace(json=False, local=True, cloud=False)
with patch("cua_cli.commands.local_image.cmd_local_list", return_value=0) as mock_local:
result = image.cmd_list(args)
assert result == 0
mock_local.assert_called_once_with(args)
def test_list_empty(self, args_namespace, tmp_path, monkeypatch):
"""Test listing when no local images exist."""
args = args_namespace(json=False, local=True, cloud=False)
with patch("cua_cli.commands.local_image.cmd_local_list", return_value=0) as mock_local:
result = image.cmd_list(args)
assert result == 0
mock_local.assert_called_once()
def test_list_json_output(self, args_namespace, mock_api_key):
"""Test JSON output format."""
args = args_namespace(json=True, local=False, cloud=True)
with patch.object(image, "run_async") as mock_run:
mock_run.return_value = [{"name": "test", "source": "cloud"}]
with patch.object(image, "print_json") as mock_print:
result = image.cmd_list(args)
assert result == 0
mock_print.assert_called_once()
class TestCmdPush:
"""Tests for cmd_push function."""
def test_push_success(self, args_namespace, temp_image_file, mock_api_key):
"""Test successful image push."""
args = args_namespace(
name="test-image",
tag="latest",
type="qcow2",
file=str(temp_image_file),
)
with patch.object(image, "run_async") as mock_run:
mock_run.return_value = 0
result = image.cmd_push(args)
assert result == 0
def test_push_file_not_found(self, args_namespace, mock_api_key):
"""Test push with nonexistent file."""
args = args_namespace(
name="test-image",
tag="latest",
type="qcow2",
file="/nonexistent/path",
)
with patch.object(image, "print_error") as mock_error:
result = image.cmd_push(args)
assert result == 1
mock_error.assert_called()
class TestCmdPull:
"""Tests for cmd_pull function."""
def test_pull_success(self, args_namespace, tmp_path, mock_api_key):
"""Test successful image pull."""
args = args_namespace(
name="test-image",
tag="latest",
output=str(tmp_path / "output.qcow2"),
)
with patch.object(image, "run_async") as mock_run:
mock_run.return_value = 0
result = image.cmd_pull(args)
assert result == 0
class TestCmdDelete:
"""Tests for cmd_delete function."""
def test_delete_with_force(self, args_namespace, mock_api_key):
"""Test delete with --force flag."""
args = args_namespace(name="test-image", tag="latest", force=True, local=False)
with patch.object(image, "run_async") as mock_run:
mock_run.return_value = 0
result = image.cmd_delete(args)
assert result == 0
def test_delete_without_force_prompts(self, args_namespace, mock_api_key):
"""Test delete without --force shows prompt."""
args = args_namespace(name="test-image", tag="latest", force=False, local=False)
with patch.object(image, "print_info") as mock_print:
result = image.cmd_delete(args)
assert result == 1
mock_print.assert_called()
def test_delete_local_delegates(self, args_namespace):
"""Test delete with --local delegates to local_image."""
args = args_namespace(name="test-image", tag="latest", force=True, local=True)
with patch("cua_cli.commands.local_image.cmd_local_delete", return_value=0) as mock_local:
result = image.cmd_delete(args)
assert result == 0
mock_local.assert_called_once_with(args)
class TestHelperFunctions:
"""Tests for helper functions."""
def test_format_date_valid(self):
"""Test formatting a valid ISO date."""
result = image._format_date("2024-01-15T10:30:00Z")
assert result == "2024-01-15"
def test_format_date_empty(self):
"""Test formatting empty string."""
result = image._format_date("")
assert result == "-"
def test_format_date_invalid(self):
"""Test formatting invalid date."""
result = image._format_date("not-a-date")
assert result == "not-a-date" # Falls back to first 10 chars