Files
AIPass/src/aipass/cli/tests/test_integration.py
T

154 lines
5.2 KiB
Python

# =================== AIPass ====================
# Name: tests/test_integration.py
# Description: Integration tests for CLI main() flow
# Version: 2.0.0
# Created: 2026-03-29
# Modified: 2026-03-30
# =============================================
"""Integration tests for CLI main() entry point."""
import subprocess
import sys
from io import StringIO
from pathlib import Path
from unittest.mock import patch
import pytest
from rich.console import Console
from aipass.cli import cli_entry
from aipass.cli.apps import cli as cli_module
from aipass.cli.apps.cli import main
from aipass.cli.apps.modules import display
# =============================================================================
# Helpers
# =============================================================================
def _make_capture_console():
"""Return (console, get_output) for capturing Rich output.
Uses no_color=True so assertions can match plain text without ANSI escapes.
"""
buf = StringIO()
cons = Console(file=buf, no_color=True, width=120, highlight=False)
def get_output() -> str:
return buf.getvalue()
return cons, get_output
# =============================================================================
# main() flow tests — mock sys.argv to simulate CLI invocation
# =============================================================================
class TestMainFlow:
"""Integration tests for the main() entry point."""
def test_main_no_args_returns_zero(self):
"""No args shows introspection and returns 0."""
cons, _get_output = _make_capture_console()
with (
patch.object(cli_module, "CONSOLE", cons),
patch.object(display, "CONSOLE", cons),
patch("sys.argv", ["cli"]),
):
result = main()
assert result == 0
def test_main_help_flag_returns_zero(self):
"""--help returns 0."""
cons, _get_output = _make_capture_console()
err_cons, _get_err = _make_capture_console()
with (
patch.object(cli_module, "CONSOLE", cons),
patch.object(display, "CONSOLE", cons),
patch.object(display, "err_console", err_cons),
patch.object(display, "_TRIGGER", None),
patch.object(display, "_TRIGGER_LOADED", True),
patch("sys.argv", ["cli", "--help"]),
):
result = main()
assert result == 0
def test_main_version_flag_returns_zero(self):
"""--version returns 0."""
cons, get_output = _make_capture_console()
with (
patch.object(cli_module, "CONSOLE", cons),
patch.object(display, "CONSOLE", cons),
patch("sys.argv", ["cli", "--version"]),
):
result = main()
assert result == 0
output = get_output()
assert "CLI v" in output
def test_main_unknown_command_returns_one(self):
"""Unknown command returns 1."""
cons, _get_output = _make_capture_console()
err_cons, get_err = _make_capture_console()
with (
patch.object(cli_module, "CONSOLE", cons),
patch.object(display, "CONSOLE", cons),
patch.object(display, "err_console", err_cons),
patch("sys.argv", ["cli", "nonexistent_cmd_xyz"]),
):
result = main()
assert result == 1
err_output = get_err()
assert "Unknown command" in err_output
def test_main_display_demo_returns_zero(self):
"""'display demo' returns 0."""
cons, _get_output = _make_capture_console()
err_cons, _get_err = _make_capture_console()
with (
patch.object(cli_module, "CONSOLE", cons),
patch.object(display, "CONSOLE", cons),
patch.object(display, "err_console", err_cons),
patch.object(display, "_TRIGGER", None),
patch.object(display, "_TRIGGER_LOADED", True),
patch("aipass.cli.apps.handlers.json.json_handler.log_operation"),
patch("sys.argv", ["cli", "display", "demo"]),
):
result = main()
assert result == 0
# =============================================================================
# __main__.py test — verify module is runnable
# =============================================================================
class TestModuleRunnable:
"""Verify python -m aipass.cli works as a subprocess."""
def test_module_runnable(self):
"""python -m aipass.cli --version runs successfully."""
result = subprocess.run(
[sys.executable, "-m", "aipass.cli", "--version"],
capture_output=True,
text=True,
timeout=30,
cwd=str(Path(__file__).resolve().parents[3]),
)
assert result.returncode == 0
def test_cli_entry_callable(self):
"""cli_entry() is the console_scripts entry point — verify it's callable."""
cons, _get_output = _make_capture_console()
with (
patch.object(cli_module, "CONSOLE", cons),
patch.object(display, "CONSOLE", cons),
patch("sys.argv", ["aipass", "--version"]),
pytest.raises(SystemExit) as exc_info,
):
cli_entry()
assert exc_info.value.code == 0