Skip to main content
Glama
test_parameter_parser.py18 kB
#!/usr/bin/env python3 """Unit tests for ParameterParser component. This test suite validates the parsing of Swagger parameter definitions, including path, query, and body parameters, as well as the generation of comprehensive tool descriptions. """ import sys from pathlib import Path import pytest # Add parent directory to path to import from parsers sys.path.insert(0, str(Path(__file__).parent.parent)) from mcp_swagger.models import SwaggerOperation, SwaggerParameter from mcp_swagger.parsers.parameter_parser import ParameterParser class TestParameterParser: """Test suite for ParameterParser functionality.""" def setup_method(self) -> None: """Set up test fixtures for each test method.""" self.sample_path_param = { "name": "userId", "in": "path", "type": "string", "required": True, "description": "The user ID", } self.sample_query_param = { "name": "limit", "in": "query", "type": "integer", "required": False, "default": 10, "description": "Maximum number of results", } self.sample_body_param = { "name": "body", "in": "body", "required": True, "schema": { "type": "object", "properties": {"name": {"type": "string"}, "age": {"type": "integer"}}, }, } def test_parse_path_parameters(self) -> None: """Test parsing of path parameters.""" # Arrange swagger_param = SwaggerParameter.from_dict(self.sample_path_param) operation = SwaggerOperation(parameters=[swagger_param]) # Act parameters, path_params, query_params, body_schema = ( ParameterParser.parse_operation_parameters(operation) ) # Assert assert len(parameters) == 1, "Should parse one parameter" assert len(path_params) == 1, "Should have one path parameter" assert "userId" in path_params, "Path parameter should be keyed by name" assert len(query_params) == 0, "Should have no query parameters" assert body_schema is None, "Should have no body schema" param_info = path_params["userId"] assert param_info.name == "userId" assert param_info.location == "path" assert param_info.required is True def test_parse_query_parameters(self) -> None: """Test parsing of query parameters.""" # Arrange operation_dict = {"parameters": [self.sample_query_param]} operation = SwaggerOperation.from_dict(operation_dict) # Act parameters, path_params, query_params, _body_schema = ( ParameterParser.parse_operation_parameters(operation) ) # Assert assert len(parameters) == 1, "Should parse one parameter" assert len(query_params) == 1, "Should have one query parameter" assert "limit" in query_params, "Query parameter should be keyed by name" assert len(path_params) == 0, "Should have no path parameters" param_info = query_params["limit"] assert param_info.name == "limit" assert param_info.location == "query" assert param_info.required is False default_limit = 10 assert param_info.default == default_limit def test_parse_body_parameter(self) -> None: """Test parsing of body parameters.""" # Arrange operation_dict = {"parameters": [self.sample_body_param]} operation = SwaggerOperation.from_dict(operation_dict) # Act parameters, path_params, query_params, body_schema = ( ParameterParser.parse_operation_parameters(operation) ) # Assert assert len(parameters) == 1, "Should parse one parameter" assert body_schema is not None, "Should have body schema" assert body_schema["type"] == "object" assert "properties" in body_schema assert len(path_params) == 0, "Should have no path parameters" assert len(query_params) == 0, "Should have no query parameters" def test_parse_mixed_parameters(self) -> None: """Test parsing of mixed parameter types.""" # Arrange operation_dict = { "parameters": [ self.sample_path_param, self.sample_query_param, self.sample_body_param, ] } operation = SwaggerOperation.from_dict(operation_dict) # Act parameters, path_params, query_params, body_schema = ( ParameterParser.parse_operation_parameters(operation) ) # Assert expected_param_count = 3 assert len(parameters) == expected_param_count, "Should parse all parameters" assert len(path_params) == 1, "Should have one path parameter" assert len(query_params) == 1, "Should have one query parameter" assert body_schema is not None, "Should have body schema" assert "userId" in path_params assert "limit" in query_params def test_parse_empty_parameters(self) -> None: """Test parsing when no parameters are present.""" # Arrange operation_dict = {} # No parameters key operation = SwaggerOperation.from_dict(operation_dict) # Act parameters, path_params, query_params, body_schema = ( ParameterParser.parse_operation_parameters(operation) ) # Assert assert len(parameters) == 0, "Should have no parameters" assert len(path_params) == 0, "Should have no path parameters" assert len(query_params) == 0, "Should have no query parameters" assert body_schema is None, "Should have no body schema" def test_build_basic_tool_description(self) -> None: """Test building a basic tool description.""" # Arrange operation_dict = { "summary": "Get user details", "description": "Retrieves detailed information about a specific user", } operation = SwaggerOperation.from_dict(operation_dict) # Act description = ParameterParser.build_tool_description( operation, "get", "/users/{userId}" ) # Assert assert "Get user details" in description assert "Retrieves detailed information" in description def test_build_description_with_parameters(self) -> None: """Test building description with parameter documentation.""" # Arrange operation_dict = { "summary": "List users", "parameters": [ { "name": "limit", "in": "query", "type": "integer", "description": "Maximum results", "required": False, }, { "name": "offset", "in": "query", "type": "integer", "description": "Skip results", "required": True, }, ], } operation = SwaggerOperation.from_dict(operation_dict) # Act description = ParameterParser.build_tool_description(operation, "get", "/users") # Assert assert "Parameters:" in description assert "limit: Maximum results [integer in query] (optional)" in description assert "offset: Skip results [integer in query] (required)" in description def test_build_description_with_responses(self) -> None: """Test building description with response documentation.""" # Arrange operation_dict = { "summary": "Create user", "responses": { "201": {"description": "User successfully created"}, "400": {"description": "Invalid input"}, }, } operation = SwaggerOperation.from_dict(operation_dict) # Act description = ParameterParser.build_tool_description( operation, "post", "/users" ) # Assert assert "Returns: User successfully created" in description assert "Invalid input" not in description # Only success response included def test_build_description_with_example(self) -> None: """Test building description with example documentation.""" # Arrange example_data = {"name": "John Doe", "age": 30} operation_dict = {"summary": "Create user", "x-example": example_data} operation = SwaggerOperation.from_dict(operation_dict) # Act description = ParameterParser.build_tool_description( operation, "post", "/users" ) # Assert # Note: x-example functionality is not currently implemented # Just verify the basic description is generated assert "Create user" in description def test_build_description_fallback(self) -> None: """Test description fallback when no metadata is available.""" # Arrange operation_dict = {} # No summary or description operation = SwaggerOperation.from_dict(operation_dict) # Act description = ParameterParser.build_tool_description( operation, "delete", "/users/123" ) # Assert assert "Execute DELETE request to /users/123" in description def test_parameter_with_enum_values(self) -> None: """Test parsing parameters with enum constraints.""" # Arrange enum_param = { "name": "status", "in": "query", "type": "string", "enum": ["active", "inactive", "pending"], "description": "User status filter", } operation_dict = {"parameters": [enum_param]} operation = SwaggerOperation.from_dict(operation_dict) # Act _parameters, _, query_params, _ = ParameterParser.parse_operation_parameters( operation ) # Assert param_info = query_params["status"] assert param_info.enum == ["active", "inactive", "pending"] def test_parameter_with_constraints(self) -> None: """Test parsing parameters with min/max constraints.""" # Arrange constrained_param = { "name": "age", "in": "query", "type": "integer", "minimum": 0, "maximum": 150, "description": "User age", } operation_dict = {"parameters": [constrained_param]} operation = SwaggerOperation.from_dict(operation_dict) # Act _parameters, _, query_params, _ = ParameterParser.parse_operation_parameters( operation ) # Assert param_info = query_params["age"] assert param_info.minimum == 0 max_age = 150 assert param_info.maximum == max_age def test_header_parameters_handling(self) -> None: """Test that header parameters are parsed correctly.""" # Arrange header_param = { "name": "X-API-Key", "in": "header", "type": "string", "required": True, "description": "API authentication key", } operation_dict = {"parameters": [header_param]} operation = SwaggerOperation.from_dict(operation_dict) # Act parameters, path_params, query_params, _body_schema = ( ParameterParser.parse_operation_parameters(operation) ) # Assert assert len(parameters) == 1, "Should parse header parameter" assert parameters[0].location == "header" assert parameters[0].name == "X-API-Key" # Header params shouldn't be in path or query dicts assert len(path_params) == 0 assert len(query_params) == 0 def test_form_data_parameters(self) -> None: """Test parsing of form data parameters.""" # Arrange form_param = { "name": "file", "in": "formData", "type": "file", "required": True, "description": "File to upload", } operation_dict = {"parameters": [form_param]} operation = SwaggerOperation.from_dict(operation_dict) # Act parameters, _, _, _ = ParameterParser.parse_operation_parameters(operation) # Assert assert len(parameters) == 1 assert parameters[0].location == "formData" assert parameters[0].param_type == "file" def test_array_type_parameters(self) -> None: """Test parsing of array type parameters.""" # Arrange array_param = { "name": "tags", "in": "query", "type": "array", "items": {"type": "string"}, "collectionFormat": "csv", "description": "Filter by tags", } operation_dict = {"parameters": [array_param]} operation = SwaggerOperation.from_dict(operation_dict) # Act _parameters, _, query_params, _ = ParameterParser.parse_operation_parameters( operation ) # Assert param_info = query_params["tags"] assert param_info.param_type == "array" assert param_info.items_type == "string" # Changed from items to items_type # Note: collection_format is not tracked in current model def test_complex_body_schema(self) -> None: """Test parsing of complex nested body schemas.""" # Arrange complex_schema = { "type": "object", "required": ["name", "email"], "properties": { "name": {"type": "string", "minLength": 1, "maxLength": 100}, "email": {"type": "string", "format": "email"}, "profile": { "type": "object", "properties": { "bio": {"type": "string"}, "avatar": {"type": "string", "format": "uri"}, }, }, "tags": {"type": "array", "items": {"type": "string"}}, }, } body_param = { "name": "body", "in": "body", "required": True, "schema": complex_schema, } operation_dict = {"parameters": [body_param]} operation = SwaggerOperation.from_dict(operation_dict) # Act _parameters, _, _, body_schema = ParameterParser.parse_operation_parameters( operation ) # Assert assert body_schema == complex_schema assert body_schema["properties"]["profile"]["type"] == "object" assert body_schema["required"] == ["name", "email"] def test_description_with_all_components(self) -> None: """Test building description with all possible components.""" # Arrange operation_dict = { "summary": "Update user profile", "description": "Updates a user's profile information with validation", "parameters": [ { "name": "userId", "in": "path", "type": "string", "description": "User identifier", "required": True, }, { "name": "validate", "in": "query", "type": "boolean", "description": "Enable validation", "required": False, }, ], "responses": {"200": {"description": "Profile updated successfully"}}, "x-example": {"userId": "user123", "validate": True}, } operation = SwaggerOperation.from_dict(operation_dict) # Act description = ParameterParser.build_tool_description( operation, "put", "/users/{userId}/profile" ) # Assert assert "Update user profile" in description assert "Updates a user's profile information" in description assert "Parameters:" in description assert "userId: User identifier" in description assert "validate: Enable validation" in description assert "Returns: Profile updated successfully" in description # Note: x-example functionality is not currently implemented def test_missing_parameter_fields(self) -> None: """Test handling of parameters with missing optional fields.""" # Arrange minimal_param = {"name": "id", "in": "path"} # Missing type, description, etc. operation_dict = {"parameters": [minimal_param]} operation = SwaggerOperation.from_dict(operation_dict) # Act _parameters, path_params, _, _ = ParameterParser.parse_operation_parameters( operation ) # Assert param_info = path_params["id"] assert param_info.name == "id" assert param_info.location == "path" assert param_info.param_type == "string" # Default type assert param_info.description == "Parameter id" # Default description format if __name__ == "__main__": # Run tests with pytest if available, otherwise run basic tests try: pytest.main([__file__, "-v"]) except ImportError: print("pytest not installed, running basic tests...") test_suite = TestParameterParser() test_methods = [m for m in dir(test_suite) if m.startswith("test_")] for method_name in test_methods: test_suite.setup_method() method = getattr(test_suite, method_name) try: method() print(f"✓ {method_name}") except AssertionError as e: print(f"✗ {method_name}: {e}") print("\nBasic tests completed!")

Latest Blog Posts

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/zecure/mcp_swagger'

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