Skip to main content
Glama

Vultr MCP

by rsp2k
test_cli.pyโ€ข19.2 kB
"""Tests for the CLI module.""" from unittest.mock import AsyncMock, patch import pytest from click.testing import CliRunner from mcp_vultr.cli_main import cli @pytest.fixture def cli_runner(): """Create a CLI test runner.""" return CliRunner() @pytest.fixture def mock_client_for_cli(): """Create a mock VultrDNSClient for CLI tests.""" mock_client = AsyncMock() # Configure mock responses mock_client.domains.return_value = [ {"domain": "example.com", "date_created": "2024-01-01"}, {"domain": "test.com", "date_created": "2024-01-02"}, ] mock_client.get_domain_summary.return_value = { "domain": "example.com", "total_records": 5, "record_types": {"A": 2, "MX": 1, "TXT": 2}, "configuration": { "has_root_record": True, "has_www_subdomain": True, "has_email_setup": True, }, } mock_client.records.return_value = [ {"id": "rec1", "type": "A", "name": "@", "data": "192.168.1.100", "ttl": 300}, {"id": "rec2", "type": "A", "name": "www", "data": "192.168.1.100", "ttl": 300}, ] mock_client.add_domain.return_value = {"domain": "newdomain.com"} mock_client.add_record.return_value = { "id": "new-rec", "type": "A", "name": "www", "data": "192.168.1.100", } mock_client.remove_record.return_value = True mock_client.setup_basic_website.return_value = { "domain": "example.com", "created_records": ["A record for root domain", "A record for www subdomain"], "errors": [], } mock_client.setup_email.return_value = { "domain": "example.com", "created_records": ["MX record for mail.example.com"], "errors": [], } return mock_client @pytest.mark.unit class TestCLIBasics: """Test basic CLI functionality.""" def test_cli_help(self, cli_runner): """Test CLI help output.""" result = cli_runner.invoke(cli, ["--help"]) assert result.exit_code == 0 assert "Vultr DNS MCP" in result.output def test_cli_version(self, cli_runner): """Test CLI version output.""" result = cli_runner.invoke(cli, ["--version"]) assert result.exit_code == 0 def test_cli_without_api_key(self, cli_runner): """Test CLI behavior without API key.""" with patch.dict("os.environ", {}, clear=True): result = cli_runner.invoke(cli, ["domains", "list"]) assert result.exit_code == 1 assert "VULTR_API_KEY is required" in result.output @pytest.mark.unit class TestServerCommand: """Test the server command.""" def test_server_command_without_api_key(self, cli_runner): """Test server command without API key.""" with patch.dict("os.environ", {}, clear=True): result = cli_runner.invoke(cli, ["server"]) assert result.exit_code == 1 assert "VULTR_API_KEY is required" in result.output @pytest.mark.xfail(reason="FastMCP server has import issues that need fixing") @patch("mcp_vultr.fastmcp_server.run_server") def test_server_command_with_api_key(self, mock_run_server, cli_runner): """Test server command with API key.""" with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): # Mock run_server to return immediately without doing anything mock_run_server.return_value = None result = cli_runner.invoke(cli, ["server"]) # Should exit normally after calling run_server assert result.exit_code == 0 assert "Starting Vultr DNS MCP Server" in result.output mock_run_server.assert_called_once_with("test-key") @patch("mcp_vultr.fastmcp_server.run_server") def test_server_command_with_error(self, mock_run_server, cli_runner): """Test server command with error.""" with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): mock_run_server.side_effect = Exception("Server error") result = cli_runner.invoke(cli, ["server"]) assert result.exit_code == 1 assert "Error starting server:" in result.output @pytest.mark.unit class TestDomainsCommands: """Test domain management commands.""" @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_list_domains(self, mock_client_class, cli_runner, mock_client_for_cli): """Test domains list command.""" mock_client_class.return_value = mock_client_for_cli with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke(cli, ["domains", "list"]) assert result.exit_code == 0 assert "example.com" in result.output assert "test.com" in result.output mock_client_for_cli.domains.assert_called_once() @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_list_domains_empty(self, mock_client_class, cli_runner): """Test domains list command with no domains.""" mock_client = AsyncMock() mock_client.domains.return_value = [] mock_client_class.return_value = mock_client with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke(cli, ["domains", "list"]) assert result.exit_code == 0 assert "No domains found" in result.output @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_domain_info(self, mock_client_class, cli_runner, mock_client_for_cli): """Test domains info command.""" mock_client_class.return_value = mock_client_for_cli with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke(cli, ["domains", "info", "example.com"]) assert result.exit_code == 0 assert "example.com" in result.output assert "Total Records: 5" in result.output mock_client_for_cli.get_domain_summary.assert_called_once_with( "example.com" ) @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_domain_info_error(self, mock_client_class, cli_runner): """Test domains info command with error.""" mock_client = AsyncMock() mock_client.get_domain_summary.return_value = {"error": "Domain not found"} mock_client_class.return_value = mock_client with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke(cli, ["domains", "info", "nonexistent.com"]) assert result.exit_code == 1 assert "Domain not found" in result.output @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_create_domain(self, mock_client_class, cli_runner, mock_client_for_cli): """Test domains create command.""" mock_client_class.return_value = mock_client_for_cli with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke( cli, ["domains", "create", "newdomain.com", "192.168.1.100"] ) assert result.exit_code == 0 assert "Created domain newdomain.com" in result.output mock_client_for_cli.add_domain.assert_called_once_with( "newdomain.com", "192.168.1.100" ) @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_create_domain_error(self, mock_client_class, cli_runner): """Test domains create command with error.""" mock_client = AsyncMock() mock_client.add_domain.return_value = {"error": "Domain already exists"} mock_client_class.return_value = mock_client with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke( cli, ["domains", "create", "existing.com", "192.168.1.100"] ) assert result.exit_code == 1 assert "Domain already exists" in result.output @pytest.mark.unit class TestRecordsCommands: """Test DNS records commands.""" @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_list_records(self, mock_client_class, cli_runner, mock_client_for_cli): """Test records list command.""" mock_client_class.return_value = mock_client_for_cli with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke(cli, ["records", "list", "example.com"]) assert result.exit_code == 0 assert "example.com" in result.output assert "192.168.1.100" in result.output # Check for record data instead mock_client_for_cli.records.assert_called_once_with("example.com") @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_list_records_filtered( self, mock_client_class, cli_runner, mock_client_for_cli ): """Test records list command with type filter.""" mock_client_class.return_value = mock_client_for_cli with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke( cli, ["records", "list", "example.com", "--type", "A"] ) assert result.exit_code == 0 mock_client_for_cli.find_records_by_type.assert_called_once_with( "example.com", "A" ) @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_list_records_empty(self, mock_client_class, cli_runner): """Test records list command with no records.""" mock_client = AsyncMock() mock_client.records.return_value = [] mock_client_class.return_value = mock_client with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke(cli, ["records", "list", "example.com"]) assert result.exit_code == 0 assert "No records found" in result.output @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_add_record(self, mock_client_class, cli_runner, mock_client_for_cli): """Test records add command.""" mock_client_class.return_value = mock_client_for_cli with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke( cli, ["records", "add", "example.com", "A", "www", "192.168.1.100"] ) assert result.exit_code == 0 assert "Created A record" in result.output mock_client_for_cli.add_record.assert_called_once_with( "example.com", "A", "www", "192.168.1.100", None, None ) @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_add_record_with_ttl_and_priority( self, mock_client_class, cli_runner, mock_client_for_cli ): """Test records add command with TTL and priority.""" mock_client_class.return_value = mock_client_for_cli with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke( cli, [ "records", "add", "example.com", "MX", "@", "mail.example.com", "--ttl", "600", "--priority", "10", ], ) assert result.exit_code == 0 mock_client_for_cli.add_record.assert_called_once_with( "example.com", "MX", "@", "mail.example.com", 600, 10 ) @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_add_record_error(self, mock_client_class, cli_runner): """Test records add command with error.""" mock_client = AsyncMock() mock_client.add_record.return_value = {"error": "Invalid record"} mock_client_class.return_value = mock_client with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke( cli, ["records", "add", "example.com", "A", "www", "invalid-ip"] ) assert result.exit_code == 1 assert "Invalid record" in result.output @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_delete_record(self, mock_client_class, cli_runner, mock_client_for_cli): """Test records delete command.""" mock_client_class.return_value = mock_client_for_cli with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke( cli, ["records", "delete", "example.com", "record-123"], input="y\n" ) # Confirm deletion assert result.exit_code == 0 assert "Deleted record record-123" in result.output mock_client_for_cli.remove_record.assert_called_once_with( "example.com", "record-123" ) @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_delete_record_failure(self, mock_client_class, cli_runner): """Test records delete command failure.""" mock_client = AsyncMock() mock_client.remove_record.return_value = False mock_client_class.return_value = mock_client with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke( cli, ["records", "delete", "example.com", "record-123"], input="y\n" ) assert result.exit_code == 1 assert "Failed to delete" in result.output @pytest.mark.unit class TestSetupCommands: """Test setup utility commands.""" @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_setup_website(self, mock_client_class, cli_runner, mock_client_for_cli): """Test setup-website command.""" mock_client_class.return_value = mock_client_for_cli with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke( cli, ["setup-website", "example.com", "192.168.1.100"] ) assert result.exit_code == 0 assert "Setting up website" in result.output assert "Website setup complete" in result.output mock_client_for_cli.setup_basic_website.assert_called_once_with( "example.com", "192.168.1.100", include_www=True, ttl=None ) @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_setup_website_no_www( self, mock_client_class, cli_runner, mock_client_for_cli ): """Test setup-website command without www.""" mock_client_class.return_value = mock_client_for_cli with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke( cli, ["setup-website", "example.com", "192.168.1.100", "--no-www"] ) assert result.exit_code == 0 mock_client_for_cli.setup_basic_website.assert_called_once_with( "example.com", "192.168.1.100", include_www=False, ttl=None ) @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_setup_website_with_ttl( self, mock_client_class, cli_runner, mock_client_for_cli ): """Test setup-website command with custom TTL.""" mock_client_class.return_value = mock_client_for_cli with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke( cli, ["setup-website", "example.com", "192.168.1.100", "--ttl", "600"] ) assert result.exit_code == 0 mock_client_for_cli.setup_basic_website.assert_called_once_with( "example.com", "192.168.1.100", include_www=True, ttl=600 ) @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_setup_website_with_errors(self, mock_client_class, cli_runner): """Test setup-website command with errors.""" mock_client = AsyncMock() mock_client.setup_basic_website.return_value = { "domain": "example.com", "created_records": ["A record for root domain"], "errors": ["Failed to create www record"], } mock_client_class.return_value = mock_client with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke( cli, ["setup-website", "example.com", "192.168.1.100"] ) assert result.exit_code == 0 assert "Setup completed with some errors" in result.output @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_setup_email(self, mock_client_class, cli_runner, mock_client_for_cli): """Test setup-email command.""" mock_client_class.return_value = mock_client_for_cli with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke( cli, ["setup-email", "example.com", "mail.example.com"] ) assert result.exit_code == 0 assert "Setting up email" in result.output assert "Email setup complete" in result.output mock_client_for_cli.setup_email.assert_called_once_with( "example.com", "mail.example.com", priority=10, ttl=None ) @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_setup_email_custom_priority( self, mock_client_class, cli_runner, mock_client_for_cli ): """Test setup-email command with custom priority.""" mock_client_class.return_value = mock_client_for_cli with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke( cli, ["setup-email", "example.com", "mail.example.com", "--priority", "5"], ) assert result.exit_code == 0 mock_client_for_cli.setup_email.assert_called_once_with( "example.com", "mail.example.com", priority=5, ttl=None ) @pytest.mark.unit class TestCLIErrorHandling: """Test CLI error handling.""" @patch("mcp_vultr.cli.dns.VultrDNSClient") def test_api_exception_handling(self, mock_client_class, cli_runner): """Test CLI handling of API exceptions.""" mock_client = AsyncMock() mock_client.domains.side_effect = Exception("Network error") mock_client_class.return_value = mock_client with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke(cli, ["domains", "list"]) assert result.exit_code == 1 assert "Network error" in result.output def test_missing_arguments(self, cli_runner): """Test CLI behavior with missing arguments.""" with patch.dict("os.environ", {"VULTR_API_KEY": "test-key"}): result = cli_runner.invoke(cli, ["domains", "info"]) assert result.exit_code == 2 # Click argument error def test_invalid_command(self, cli_runner): """Test CLI behavior with invalid command.""" result = cli_runner.invoke(cli, ["invalid-command"]) assert result.exit_code == 2 if __name__ == "__main__": pytest.main([__file__])

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/rsp2k/mcp-vultr'

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