test_utils.py•6.13 kB
"""
Unit tests for utility functions.
Tests cover functionality for parameter sanitization.
"""
import pytest
import copy
import logging
from rootly_mcp_server.utils import (
sanitize_parameter_name,
sanitize_parameters_in_spec
)
@pytest.mark.unit
class TestSanitizeParameterName:
"""Test the sanitize_parameter_name function."""
def test_api_style_parameters(self):
"""Test real-world API parameter patterns."""
assert sanitize_parameter_name("filter[kind]") == "filter_kind"
assert sanitize_parameter_name("sort[created_at]") == "sort_created_at"
assert sanitize_parameter_name("include[user,team]") == "include_user_team"
assert sanitize_parameter_name("data[user][name]") == "data_user_name"
def test_edge_cases(self):
"""Test edge cases."""
# Empty/invalid inputs
assert sanitize_parameter_name("") == "param"
assert sanitize_parameter_name("@#$%") == "param"
assert sanitize_parameter_name("123param") == "param_123param"
# Multiple underscores cleanup
assert sanitize_parameter_name("param___name") == "param_name"
# Leading/trailing underscores
assert sanitize_parameter_name("_param_") == "param"
def test_parameter_name_length_boundaries(self):
"""Test boundary cases for the 64-character limit."""
# Below limit (63 chars) - should remain unchanged
name_63 = "a" * 63
assert sanitize_parameter_name(name_63) == name_63
assert len(sanitize_parameter_name(name_63)) == 63
# At limit (64 chars) - should remain unchanged
name_64 = "a" * 64
assert sanitize_parameter_name(name_64) == name_64
assert len(sanitize_parameter_name(name_64)) == 64
# Over limit (65 chars) - should be truncated
name_65 = "a" * 65
assert len(sanitize_parameter_name(name_65)) == 64
# Over limit (70 chars) - should be truncated
name_70 = "a" * 70
result = sanitize_parameter_name(name_70)
assert len(result) == 64
def test_valid_names_unchanged(self):
"""Test that already valid names are preserved."""
valid_names = ["param_name", "param-name", "param.name", "param123"]
for name in valid_names:
assert sanitize_parameter_name(name) == name
def test_special_characters(self):
"""Test handling of various special characters."""
assert sanitize_parameter_name("param@test") == "param_test"
assert sanitize_parameter_name("param#test") == "param_test"
assert sanitize_parameter_name("param$test") == "param_test"
assert sanitize_parameter_name("param%test") == "param_test"
@pytest.mark.unit
class TestSanitizeParametersInSpec:
"""Test the sanitize_parameters_in_spec function."""
def test_complete_spec_processing(self):
"""Test processing a realistic OpenAPI spec with various parameter locations."""
spec = {
"paths": {
"/incidents": {
"parameters": [{"name": "filter[kind]", "in": "query"}],
"get": {
"parameters": [{"name": "sort[created_at]", "in": "query"}]
}
}
},
"components": {
"parameters": {
"FilterParam": {"name": "include[user]", "in": "query"}
}
}
}
result = sanitize_parameters_in_spec(spec)
# Check all parameters were processed
assert len(result) == 3
assert result["filter_kind"] == "filter[kind]"
assert result["sort_created_at"] == "sort[created_at]"
assert result["include_user"] == "include[user]"
# Verify spec was modified in-place
assert spec["paths"]["/incidents"]["parameters"][0]["name"] == "filter_kind"
assert spec["paths"]["/incidents"]["get"]["parameters"][0]["name"] == "sort_created_at"
assert spec["components"]["parameters"]["FilterParam"]["name"] == "include_user"
def test_empty_and_invalid_specs(self):
"""Test handling of empty or malformed specifications."""
# Empty spec
assert sanitize_parameters_in_spec({}) == {}
# Spec with no parameters
spec = {"paths": {"/test": {"get": {"operationId": "test"}}}}
original = copy.deepcopy(spec)
result = sanitize_parameters_in_spec(spec)
assert result == {}
assert spec == original
# Malformed spec structure
spec = {"paths": {"/test": "not_a_dict"}}
result = sanitize_parameters_in_spec(spec)
assert result == {}
def test_parameters_without_changes(self):
"""Test that valid parameters don't get changed."""
spec = {
"paths": {
"/test": {
"get": {
"parameters": [{"name": "valid_param", "in": "query"}]
}
}
}
}
result = sanitize_parameters_in_spec(spec)
# No changes should be made
assert result == {}
assert spec["paths"]["/test"]["get"]["parameters"][0]["name"] == "valid_param"
def test_logging_integration(self, caplog):
"""Test that parameter changes are properly logged."""
spec = {
"paths": {
"/test": {
"get": {
"parameters": [{"name": "filter[test]", "in": "query"}]
}
}
}
}
with caplog.at_level(logging.DEBUG):
sanitize_parameters_in_spec(spec)
# Verify logging was called for the parameter change
assert any("filter[test]" in record.message and "filter_test" in record.message
for record in caplog.records)