"""Behavioral coverage for registry-aware picker and deprecation UX.""" from io import StringIO import sys import time from unittest.mock import patch import cmdforge.cli.picker as picker import pytest from cmdforge import __version__ from cmdforge.cli.picker import PickerResult class FakeTTY: def __init__(self, *characters): self.characters = iter(characters) def getch(self, timeout=None): if timeout is not None: time.sleep(0.01) return None return next(self.characters) def setup_function(): picker._registry_cache.clear() picker._ui_out = StringIO() def test_public_registry_search_does_not_require_token(): class Client: token = "" def semantic_search(self, query, limit): return {"available": False, "data": [], "error": None} def search_tools(self, query, per_page): return [{ "owner": "official", "name": "weather", "description": "Weather", "score": 0.8, "quality_score": 91, "quality_coverage": 70, }] with patch("cmdforge.registry_client.get_client", return_value=Client()): results = picker.search_registry("weather") assert results[0]["name"] == "official/weather" assert results[0]["quality_score"] == 91 assert results[0]["quality_coverage"] == 70 def test_picker_can_install_when_no_local_tools(): registry_tool = { "name": "official/weather", "desc": "Weather", "args": [], "registry": True, "quality_score": 91, "quality_coverage": 70, "relevance": 0.8, } with patch.object(picker, "get_tools", return_value=[]), patch.object( picker, "search_registry", return_value=[registry_tool] ), patch.object( picker, "_install_registry_selection", return_value=PickerResult("official/weather", {}), ) as install: result = picker.run_picker(FakeTTY("w", "e", "\n")) install.assert_called_once() assert result.tool_name == "official/weather" assert "Q91/70%" in picker._ui_out.getvalue() def test_tab_installs_registry_selection_too(): registry_tool = { "name": "official/weather", "desc": "Weather", "args": [], "registry": True, } with patch.object(picker, "get_tools", return_value=[]), patch.object( picker, "search_registry", return_value=[registry_tool] ), patch.object( picker, "_install_registry_selection", return_value=PickerResult("official/weather", {}), ) as install: result = picker.run_picker(FakeTTY("w", "e", "\t")) install.assert_called_once() assert result.tool_name == "official/weather" def test_local_deprecation_selection_prints_migration_guidance(): tool = { "name": "old", "desc": "", "args": [], "deprecated": True, "deprecated_message": "Moved.", "replacement": "official/new", } result = picker._local_selection(tool) assert result.tool_name == "old" output = picker._ui_out.getvalue() assert "Moved." in output assert "official/new" in output def test_picker_help_does_not_require_a_terminal(capsys): with patch.object(sys, "argv", ["cf", "--help"]), pytest.raises(SystemExit) as exc: picker.main() assert exc.value.code == 0 assert "Interactively find and run" in capsys.readouterr().out def test_picker_version_does_not_require_a_terminal(capsys): with patch.object(sys, "argv", ["cf", "--version"]), pytest.raises(SystemExit) as exc: picker.main() assert exc.value.code == 0 assert f"cf {__version__}" in capsys.readouterr().out