import pytest
import os
from unittest.mock import patch, MagicMock
from swagger_mcp.openapi_mcp_server import OpenAPIMCPServer
class TestConstValues:
@pytest.fixture
def server(self):
# Define a simple OpenAPI spec with parameters that will be set as const
openapi_spec = {
"openapi": "3.0.0",
"info": {
"title": "Test API",
"version": "1.0.0"
},
"servers": [{"url": "https://api.example.com"}],
"paths": {
"/test": {
"get": {
"operationId": "test_endpoint",
"summary": "Test endpoint",
"parameters": [
{
"name": "required_param",
"in": "query",
"required": True,
"schema": {
"type": "string"
},
"description": "A required parameter"
},
{
"name": "const_param",
"in": "query",
"required": True,
"schema": {
"type": "string"
},
"description": "A parameter that will be set as const"
},
{
"name": "other_param",
"in": "query",
"schema": {
"type": "string"
},
"description": "Another parameter"
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"type": "object"
}
}
}
}
}
}
}
}
}
server = OpenAPIMCPServer(
'Test Server',
openapi_spec,
const_values={"const_param": "fixed_value"}
)
return server
@pytest.fixture
def countries_server(self):
"""Fixture that creates a server using the countries.yaml spec with const fields parameter."""
current_dir = os.path.dirname(os.path.abspath(__file__))
spec_path = os.path.join(current_dir, 'fixtures', 'countries.yaml')
server = OpenAPIMCPServer(
'Countries Server',
spec_path,
const_values={"fields": "name"}
)
return server
@pytest.mark.asyncio
async def test_const_parameter_handling(self, server):
"""Test that const parameters are handled correctly in tool definitions."""
handlers = server._register_handlers()
list_tools = handlers["list_tools"]
tools = await list_tools()
assert len(tools) == 1
tool = tools[0]
# Verify const parameter is not in tool definition
tool_params = tool.inputSchema["properties"]
assert "const_param" not in tool_params
assert "required_param" in tool_params
assert "other_param" in tool_params
# Verify required parameters don't include const param
assert "const_param" not in tool.inputSchema["required"]
assert "required_param" in tool.inputSchema["required"]
@pytest.mark.asyncio
async def test_const_value_usage(self, server):
"""Test that const values are used when invoking endpoints."""
handlers = server._register_handlers()
call_tool = handlers["call_tool"]
# Mock the endpoint invocation
with patch('swagger_mcp.openapi_mcp_server.EndpointInvoker') as MockInvoker:
invoker_instance = MockInvoker.return_value
invoker_instance.invoke_with_params.return_value.json.return_value = {"result": "success"}
invoker_instance.invoke_with_params.return_value.status_code = 200
# Call the tool
result = await call_tool("test_endpoint", {
"required_param": "test",
"other_param": "value"
})
# Verify the const value was included in the endpoint call
invoker_instance.invoke_with_params.assert_called_once()
call_args = invoker_instance.invoke_with_params.call_args[1]
assert call_args["params"]["const_param"] == "fixed_value"
assert call_args["params"]["required_param"] == "test"
assert call_args["params"]["other_param"] == "value"
@pytest.mark.asyncio
async def test_countries_const_fields(self, countries_server):
"""Test that const fields parameter is handled correctly in countries API tools."""
handlers = countries_server._register_handlers()
list_tools = handlers["list_tools"]
tools = await list_tools()
# Check each tool to ensure 'fields' parameter is not included
for tool in tools:
tool_params = tool.inputSchema["properties"]
assert "fields" not in tool_params, f"Tool {tool.name} should not have 'fields' parameter"
if "required" in tool.inputSchema:
assert "fields" not in tool.inputSchema["required"], f"Tool {tool.name} should not require 'fields' parameter"