"""CLI command tests (ARTIFACT-STORE-WP-0001-T014).""" from __future__ import annotations import json from pathlib import Path import pytest from sqlalchemy import create_engine, insert, inspect from typer.testing import CliRunner from artifactstore.cli import app as cli_app from artifactstore.db.schema import metadata, retention_classes from artifactstore.db.seed import RETENTION_CLASS_SEEDS REPO_ROOT = Path(__file__).resolve().parents[2] @pytest.fixture def runner() -> CliRunner: return CliRunner() @pytest.fixture def env_db(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path: db_path = tmp_path / "cli-test.db" storage_root = tmp_path / "storage" storage_root.mkdir(parents=True, exist_ok=True) monkeypatch.setenv("ARTIFACTSTORE_DATABASE_URL", f"sqlite+aiosqlite:///{db_path}") monkeypatch.setenv("ARTIFACTSTORE_STORAGE_LOCAL_ROOT", str(storage_root)) return db_path def test_cli_version_prints_version(runner: CliRunner) -> None: result = runner.invoke(cli_app, ["version"]) assert result.exit_code == 0 assert result.output.strip() def test_cli_migrate_creates_schema( runner: CliRunner, env_db: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: monkeypatch.chdir(REPO_ROOT) result = runner.invoke(cli_app, ["migrate"]) assert result.exit_code == 0, result.output assert "ok" in result.output sync_engine = create_engine(f"sqlite:///{env_db}", future=True) names = set(inspect(sync_engine).get_table_names()) sync_engine.dispose() assert {"events", "retention_classes", "alembic_version"}.issubset(names) def test_cli_replay_against_empty_log( runner: CliRunner, env_db: Path, ) -> None: # Pre-create schema (without using migrate command to keep the test # focused on the replay surface). sync_engine = create_engine(f"sqlite:///{env_db}", future=True) metadata.create_all(sync_engine) with sync_engine.begin() as conn: conn.execute(insert(retention_classes), [dict(s) for s in RETENTION_CLASS_SEEDS]) sync_engine.dispose() result = runner.invoke(cli_app, ["replay"]) assert result.exit_code == 0, result.output assert "replayed up to sequence 0" in result.output def test_cli_health_reports_ok( runner: CliRunner, env_db: Path, ) -> None: sync_engine = create_engine(f"sqlite:///{env_db}", future=True) metadata.create_all(sync_engine) sync_engine.dispose() result = runner.invoke(cli_app, ["health"]) assert result.exit_code == 0, result.output payload = json.loads(result.output) assert payload["status"] == "ok" assert payload["db"]["healthy"] is True assert payload["backend"]["healthy"] is True