Skip to main content
Glama

mcp-nixos

by utensils
test_plain_text_output.py11 kB
"""Test suite for plain text output validation.""" from unittest.mock import Mock, patch import pytest from mcp_nixos import server from mcp_nixos.server import error def get_tool_function(tool_name: str): """Get the underlying function from a FastMCP tool.""" tool = getattr(server, tool_name) if hasattr(tool, "fn"): return tool.fn return tool # Get the underlying functions for direct use darwin_search = get_tool_function("darwin_search") home_manager_info = get_tool_function("home_manager_info") home_manager_list_options = get_tool_function("home_manager_list_options") home_manager_search = get_tool_function("home_manager_search") home_manager_stats = get_tool_function("home_manager_stats") nixos_info = get_tool_function("nixos_info") nixos_search = get_tool_function("nixos_search") nixos_stats = get_tool_function("nixos_stats") @pytest.fixture(autouse=True) def mock_channel_cache(): """Mock channel cache to avoid API calls during tests.""" with patch("mcp_nixos.server.channel_cache") as mock_cache: # Mock the channel cache methods mock_cache.get_resolved.return_value = { "unstable": "latest-43-nixos-unstable", "stable": "latest-43-nixos-25.05", "25.05": "latest-43-nixos-25.05", "24.11": "latest-43-nixos-24.11", } mock_cache.get_available.return_value = { "latest-43-nixos-unstable": 150000, "latest-43-nixos-25.05": 140000, "latest-43-nixos-24.11": 130000, } yield mock_cache class TestPlainTextOutput: """Validate all functions return plain text, not XML.""" def test_error_plain_text(self): """Test error returns plain text.""" result = error("Test message") assert result == "Error (ERROR): Test message" assert "<error>" not in result def test_error_with_code_plain_text(self): """Test error with code returns plain text.""" result = error("Not found", "NOT_FOUND") assert result == "Error (NOT_FOUND): Not found" assert "<error>" not in result @patch("mcp_nixos.server.requests.post") @pytest.mark.asyncio async def test_nixos_search_plain_text(self, mock_post): """Test nixos_search returns plain text.""" # Mock response mock_response = Mock() mock_response.json.return_value = { "hits": { "hits": [ { "_source": { "package_pname": "firefox", "package_pversion": "123.0", "package_description": "A web browser", } } ] } } mock_response.raise_for_status = Mock() mock_post.return_value = mock_response result = await nixos_search("firefox", search_type="packages", limit=5) assert "Found 1 packages matching 'firefox':" in result assert "• firefox (123.0)" in result assert " A web browser" in result assert "<package>" not in result assert "<name>" not in result @patch("mcp_nixos.server.requests.post") @pytest.mark.asyncio async def test_nixos_info_plain_text(self, mock_post): """Test nixos_info returns plain text.""" # Mock response mock_response = Mock() mock_response.json.return_value = { "hits": { "hits": [ { "_source": { "package_pname": "firefox", "package_pversion": "123.0", "package_description": "A web browser", "package_homepage": ["https://firefox.com"], "package_license_set": ["MPL-2.0"], } } ] } } mock_response.raise_for_status = Mock() mock_post.return_value = mock_response result = await nixos_info("firefox", type="package") assert "Package: firefox" in result assert "Version: 123.0" in result assert "Description: A web browser" in result assert "Homepage: https://firefox.com" in result assert "License: MPL-2.0" in result assert "<package_info>" not in result @patch("mcp_nixos.server.requests.post") @pytest.mark.asyncio async def test_nixos_stats_plain_text(self, mock_post): """Test nixos_stats returns plain text.""" # Mock response mock_response = Mock() mock_response.json.return_value = {"count": 12345} mock_response.raise_for_status = Mock() mock_post.return_value = mock_response result = await nixos_stats() assert "NixOS Statistics for unstable channel:" in result assert "• Packages: 12,345" in result assert "• Options: 12,345" in result assert "<nixos_stats>" not in result @patch("mcp_nixos.server.requests.get") @pytest.mark.asyncio async def test_home_manager_search_plain_text(self, mock_get): """Test home_manager_search returns plain text.""" # Mock HTML response mock_response = Mock() mock_response.text = """ <html> <dt>programs.git.enable</dt> <dd> <p>Enable git</p> <span class="term">Type: boolean</span> </dd> </html> """ mock_response.raise_for_status = Mock() mock_get.return_value = mock_response result = await home_manager_search("git", limit=5) assert "Found 1 Home Manager options matching 'git':" in result assert "• programs.git.enable" in result assert " Type: boolean" in result assert " Enable git" in result assert "<option>" not in result @patch("mcp_nixos.server.requests.get") @pytest.mark.asyncio async def test_home_manager_info_plain_text(self, mock_get): """Test home_manager_info returns plain text.""" # Mock HTML response mock_response = Mock() mock_response.text = """ <html> <dt>programs.git.enable</dt> <dd> <p>Enable git</p> <span class="term">Type: boolean</span> </dd> </html> """ mock_response.raise_for_status = Mock() mock_get.return_value = mock_response result = await home_manager_info("programs.git.enable") assert "Option: programs.git.enable" in result assert "Type: boolean" in result assert "Description: Enable git" in result assert "<option_info>" not in result @patch("mcp_nixos.server.parse_html_options") @pytest.mark.asyncio async def test_home_manager_stats_plain_text(self, mock_parse): """Test home_manager_stats returns plain text.""" # Mock parsed options mock_parse.return_value = [ {"name": "programs.git.enable", "type": "boolean", "description": "Enable git"}, {"name": "programs.zsh.enable", "type": "boolean", "description": "Enable zsh"}, {"name": "services.gpg-agent.enable", "type": "boolean", "description": "Enable GPG agent"}, {"name": "home.packages", "type": "list", "description": "Packages to install"}, {"name": "wayland.windowManager.sway.enable", "type": "boolean", "description": "Enable Sway"}, {"name": "xsession.enable", "type": "boolean", "description": "Enable X session"}, ] result = await home_manager_stats() assert "Home Manager Statistics:" in result assert "Total options:" in result assert "Categories:" in result assert "Top categories:" in result assert "programs:" in result assert "services:" in result assert "<home_manager_stats>" not in result @patch("mcp_nixos.server.requests.get") @pytest.mark.asyncio async def test_home_manager_list_options_plain_text(self, mock_get): """Test home_manager_list_options returns plain text.""" # Mock HTML response mock_response = Mock() mock_response.text = """ <html> <dt>programs.git.enable</dt> <dd><p>Enable git</p></dd> <dt>services.ssh.enable</dt> <dd><p>Enable SSH</p></dd> </html> """ mock_response.raise_for_status = Mock() mock_get.return_value = mock_response result = await home_manager_list_options() assert "Home Manager option categories (2 total):" in result assert "• programs (1 options)" in result assert "• services (1 options)" in result assert "<option_categories>" not in result @patch("mcp_nixos.server.requests.get") @pytest.mark.asyncio async def test_darwin_search_plain_text(self, mock_get): """Test darwin_search returns plain text.""" # Mock HTML response mock_response = Mock() mock_response.text = """ <html> <dt>system.defaults.dock.autohide</dt> <dd> <p>Auto-hide the dock</p> <span class="term">Type: boolean</span> </dd> </html> """ mock_response.raise_for_status = Mock() mock_get.return_value = mock_response result = await darwin_search("dock", limit=5) assert "Found 1 nix-darwin options matching 'dock':" in result assert "• system.defaults.dock.autohide" in result assert " Type: boolean" in result assert " Auto-hide the dock" in result assert "<option>" not in result @patch("mcp_nixos.server.requests.get") @pytest.mark.asyncio async def test_no_results_plain_text(self, mock_get): """Test empty results return appropriate plain text.""" # Mock empty HTML response mock_response = Mock() mock_response.text = "<html></html>" mock_response.raise_for_status = Mock() mock_get.return_value = mock_response result = await home_manager_search("nonexistent", limit=5) assert result == "No Home Manager options found matching 'nonexistent'" assert "<" not in result @patch("mcp_nixos.server.requests.post") @pytest.mark.asyncio async def test_nixos_empty_search_plain_text(self, mock_post): """Test nixos_search with no results returns plain text.""" # Mock empty response mock_response = Mock() mock_response.json.return_value = {"hits": {"hits": []}} mock_response.raise_for_status = Mock() mock_post.return_value = mock_response result = await nixos_search("nonexistent", search_type="packages") assert result == "No packages found matching 'nonexistent'" assert "<" not in result

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/utensils/mcp-nixos'

If you have feedback or need assistance with the MCP directory API, please join our Discord server