"""Tests for CLI.""" import os import subprocess import sys from typer.testing import CliRunner from flow.cli import app runner = CliRunner() def test_typer_runner_version(): result = runner.invoke(app, ["--version"]) assert result.exit_code == 0 assert "flow" in result.stdout def test_version_flag(): """Test --version flag works.""" result = subprocess.run( [sys.executable, "-m", "flow", "--version"], capture_output=True, text=True, ) assert result.returncode == 0 assert "flow" in result.stdout def test_help_flag(): """Test --help shows commands.""" result = subprocess.run( [sys.executable, "-m", "flow", "--help"], capture_output=True, text=True, ) assert result.returncode == 0 assert "dotfiles" in result.stdout assert "packages" in result.stdout assert "setup" in result.stdout def test_short_help_flag(): """Test -h shows commands.""" result = subprocess.run( [sys.executable, "-m", "flow", "-h"], capture_output=True, text=True, ) assert result.returncode == 0 assert "dotfiles" in result.stdout assert "packages" in result.stdout assert "setup" in result.stdout def test_help_groups_aliases(): result = subprocess.run( [sys.executable, "-m", "flow", "--help"], capture_output=True, text=True, ) assert result.returncode == 0 lines = [line for line in result.stdout.splitlines() if "│" in line] dotfiles_line = next(line for line in lines if "dotfiles" in line and "dot" in line) assert "dotfiles, dot" in dotfiles_line assert next(line for line in lines if "packages" in line and "package" in line).startswith("│") packages_line = next(line for line in lines if "packages" in line and "pkg" in line) assert "packages, package, pkg" in packages_line setup_line = next(line for line in lines if "setup" in line and "bootstrap" in line) assert "setup, bootstrap, provision" in setup_line projects_line = next(line for line in lines if "projects" in line and "project" in line) assert "projects, project" in projects_line def test_no_color_flag(): """Test --no-color flag is accepted.""" result = subprocess.run( [sys.executable, "-m", "flow", "--no-color", "--help"], capture_output=True, text=True, ) assert result.returncode == 0 def test_dotfiles_help(): result = subprocess.run( [sys.executable, "-m", "flow", "dotfiles", "--help"], capture_output=True, text=True, ) assert result.returncode == 0 assert "link" in result.stdout assert "unlink" in result.stdout # Removed commands should not appear assert "relink" not in result.stdout assert "undo" not in result.stdout assert "clean" not in result.stdout assert "sync" not in result.stdout assert "modules" not in result.stdout repos_lines = [line for line in result.stdout.splitlines() if "repos" in line] assert len(repos_lines) == 1 assert "repos, repo" in repos_lines[0] def test_packages_help(): result = subprocess.run( [sys.executable, "-m", "flow", "packages", "--help"], capture_output=True, text=True, ) assert result.returncode == 0 assert "install" in result.stdout def test_invalid_config_is_reported_without_traceback(tmp_path): config_root = tmp_path / "config" (config_root / "flow").mkdir(parents=True) (config_root / "flow" / "config.yaml").write_text(":\n bad\n") env = dict(os.environ) env["XDG_CONFIG_HOME"] = str(config_root) result = subprocess.run( [sys.executable, "-m", "flow", "completion"], capture_output=True, text=True, env=env, ) assert result.returncode == 1 assert "Invalid YAML" in result.stderr assert "Traceback" not in result.stderr def test_local_manifest_is_loaded(tmp_path): config_root = tmp_path / "config" flow_dir = config_root / "flow" flow_dir.mkdir(parents=True) (flow_dir / "manifest.yaml").write_text( "profiles:\n" " demo:\n" " os: linux\n" ) env = dict(os.environ) env["XDG_CONFIG_HOME"] = str(config_root) result = subprocess.run( [sys.executable, "-m", "flow", "setup", "list"], capture_output=True, text=True, env=env, ) assert result.returncode == 0 assert "demo" in result.stdout