import subprocess from collections.abc import Callable from pathlib import Path from cli.exit_codes import SUCCESS def test_root_help_shows_commands_without_completion_options( run_cli_command: Callable[..., subprocess.CompletedProcess[str]], ) -> None: completed = run_cli_command('--help') assert completed.returncode == 0 assert 'Usage: shierfeng [OPTIONS] COMMAND [ARGS]...' in completed.stdout assert 'app' in completed.stdout assert 'db' in completed.stdout assert 'completion' in completed.stdout assert 'wizard' in completed.stdout assert 'tui' in completed.stdout assert completed.stdout.index('wizard') < completed.stdout.index('tui') assert '--install-completion' not in completed.stdout assert '--show-completion' not in completed.stdout def test_completion_show_bash_outputs_completion_script( run_cli_command: Callable[..., subprocess.CompletedProcess[str]], ) -> None: completed = run_cli_command('completion', 'show', 'bash') assert completed.returncode == SUCCESS assert completed.stderr == '' assert '_SHIERFENG_COMPLETE=bash_complete' in completed.stdout assert '_shierfeng_completion()' in completed.stdout assert 'if command -v compopt >/dev/null 2>&1; then' in completed.stdout assert 'if complete -o nosort -F _shierfeng_completion shierfeng 2>/dev/null; then' in completed.stdout assert 'complete -F _shierfeng_completion shierfeng' in completed.stdout def test_completion_show_powershell_outputs_completion_script( run_cli_command: Callable[..., subprocess.CompletedProcess[str]], ) -> None: completed = run_cli_command('completion', 'show', 'powershell') assert completed.returncode == SUCCESS assert completed.stderr == '' assert 'Register-ArgumentCompleter -Native -CommandName shierfeng' in completed.stdout assert '$env:_SHIERFENG_COMPLETE = "powershell_complete"' in completed.stdout def test_bash_completion_protocol_returns_candidates_without_not_supported_error( run_cli_completion_command: Callable[..., subprocess.CompletedProcess[str]], ) -> None: completed = run_cli_completion_command(comp_words='shierfeng comp', comp_cword=1) assert completed.returncode == SUCCESS assert 'plain,completion' in completed.stdout assert 'not supported' not in completed.stdout.lower() assert completed.stderr == '' def test_powershell_completion_protocol_returns_candidates_without_not_supported_error( run_cli_completion_command: Callable[..., subprocess.CompletedProcess[str]], ) -> None: completed = run_cli_completion_command( comp_words='shierfeng comp', comp_cword='comp', instruction='powershell_complete', ) assert completed.returncode == SUCCESS assert 'completion' in completed.stdout assert 'not supported' not in completed.stdout.lower() assert completed.stderr == '' def test_completion_doctor_json_output_has_stable_contract( run_cli_command: Callable[..., subprocess.CompletedProcess[str]], parse_json_stdout: Callable[[subprocess.CompletedProcess[str]], dict], ) -> None: completed = run_cli_command('completion', 'doctor', '--output=json') payload = parse_json_stdout(completed) assert completed.returncode == SUCCESS assert payload['ok'] is True assert payload['message'] == 'completion 诊断信息已生成' assert set(payload) == { 'ok', 'message', 'activeShell', 'projectDir', 'envChoices', 'completeEnvVar', 'recommendedInstallCommand', 'shells', } assert isinstance(payload['envChoices'], list) assert payload['completeEnvVar'] == '_SHIERFENG_COMPLETE' assert isinstance(payload['shells'], dict) assert set(payload['shells']) == {'bash', 'zsh', 'fish', 'powershell'} assert payload['shells']['bash']['supported'] is True assert payload['shells']['fish']['autoDiscovery'] is True assert payload['shells']['powershell']['supported'] is True assert isinstance(payload['shells']['bash']['sourceCommand'], str) assert isinstance(payload['shells']['bash']['recommendedInstallCommand'], str) assert isinstance(payload['shells']['powershell']['sourceCommand'], str) assert isinstance(payload['shells']['powershell']['recommendedInstallCommand'], str) def test_completion_install_json_output_has_stable_contract( tmp_path: Path, run_cli_command: Callable[..., subprocess.CompletedProcess[str]], parse_json_stdout: Callable[[subprocess.CompletedProcess[str]], dict], ) -> None: target_file = tmp_path / 'shierfeng.bash' rc_file = tmp_path / '.bashrc' completed = run_cli_command( 'completion', 'install', '--shell=bash', '--target-file', str(target_file), '--activate', '--rc-file', str(rc_file), '--output=json', ) payload = parse_json_stdout(completed) assert completed.returncode == SUCCESS assert payload['ok'] is True assert set(payload) == { 'ok', 'message', 'shell', 'detectedShell', 'targetFile', 'activated', 'activateRequested', 'rcFile', 'rcFileUpdated', 'sourceCommand', 'autoDiscovery', 'activationRequired', 'nextStep', 'completeEnvVar', } assert payload['shell'] == 'bash' assert payload['targetFile'] == str(target_file.resolve()) assert payload['activated'] is True assert payload['activateRequested'] is True assert payload['rcFile'] == str(rc_file.resolve()) assert payload['rcFileUpdated'] is True assert payload['autoDiscovery'] is False assert payload['activationRequired'] is True assert isinstance(payload['nextStep'], str) assert target_file.exists() assert rc_file.exists() assert '_SHIERFENG_COMPLETE=bash_complete' in target_file.read_text(encoding='utf-8') assert payload['sourceCommand'] in rc_file.read_text(encoding='utf-8') def test_completion_install_powershell_json_output_has_stable_contract( tmp_path: Path, run_cli_command: Callable[..., subprocess.CompletedProcess[str]], parse_json_stdout: Callable[[subprocess.CompletedProcess[str]], dict], ) -> None: target_file = tmp_path / 'shierfeng.ps1' rc_file = tmp_path / 'Microsoft.PowerShell_profile.ps1' completed = run_cli_command( 'completion', 'install', '--shell=powershell', '--target-file', str(target_file), '--activate', '--rc-file', str(rc_file), '--output=json', ) payload = parse_json_stdout(completed) assert completed.returncode == SUCCESS assert payload['ok'] is True assert payload['shell'] == 'powershell' assert payload['targetFile'] == str(target_file.resolve()) assert payload['activated'] is True assert payload['activateRequested'] is True assert payload['rcFile'] == str(rc_file.resolve()) assert payload['rcFileUpdated'] is True assert payload['autoDiscovery'] is False assert payload['activationRequired'] is True assert payload['sourceCommand'] == f'. "{target_file.resolve()}"' assert target_file.exists() assert rc_file.exists() assert 'Register-ArgumentCompleter -Native -CommandName shierfeng' in target_file.read_text(encoding='utf-8') assert payload['sourceCommand'] in rc_file.read_text(encoding='utf-8') def test_app_run_help_only_exposes_env_option( run_cli_command: Callable[..., subprocess.CompletedProcess[str]], ) -> None: completed = run_cli_command('app', 'run', '--help') assert completed.returncode == 0 assert 'Usage: shierfeng app run [OPTIONS]' in completed.stdout assert '--env' in completed.stdout assert '--output' not in completed.stdout