"""Unit tests for MCP tool response helpers and error formatting.""" import json from src.utils.errors import ( AuthorizationError, AuthServiceError, DeltaError, NetworkError, PrometheusAPIError, PrometheusTimeoutError, ValidationError, ) from src.utils.tool_response import ( format_tool_error, tool_json_response, tool_text_response, ) class TestToolTextResponse: """tool_text_response returns standard MCP text content.""" def test_returns_list_with_one_text_item(self): result = tool_text_response("hello") assert isinstance(result, list) assert len(result) == 1 assert result[0]["type"] == "text" assert result[0]["text"] == "hello" def test_empty_string(self): result = tool_text_response("") assert result[0]["text"] == "" def test_preserves_newlines_and_formatting(self): text = "line1\nline2\n" result = tool_text_response(text) assert result[0]["text"] == text class TestToolJsonResponse: """tool_json_response returns MCP content with JSON-serialized data.""" def test_returns_list_with_one_text_item(self): result = tool_json_response({"a": 1}) assert isinstance(result, list) assert len(result) == 1 assert result[0]["type"] == "text" assert isinstance(result[0]["text"], str) def test_text_is_valid_json_roundtrip_list(self): data = [1, 2, {"x": "y"}] result = tool_json_response(data) parsed = json.loads(result[0]["text"]) assert parsed == data def test_text_is_valid_json_roundtrip_dict(self): data = {"key": "value", "n": 42} result = tool_json_response(data) parsed = json.loads(result[0]["text"]) assert parsed == data def test_scalar(self): result = tool_json_response(123) assert json.loads(result[0]["text"]) == 123 def test_indent_affects_output(self): data = {"a": 1} default = tool_json_response(data)[0]["text"] compact = tool_json_response(data, indent=0)[0]["text"] assert "\n" in default assert json.loads(compact) == data assert compact != default # indent option changes output def test_ensure_ascii(self): data = {"msg": "café"} result_ascii = tool_json_response(data, ensure_ascii=True)[0]["text"] result_utf8 = tool_json_response(data, ensure_ascii=False)[0]["text"] assert "\\u00e9" in result_ascii or "caf" in result_ascii assert "café" in result_utf8 or "caf" in result_utf8 class TestFormatToolError: """format_tool_error formats known exception types with consistent prefixes.""" def test_auth_service_error_without_status(self): exc = AuthServiceError("Token invalid") out = format_tool_error(exc) assert "**Auth Error**" in out assert "Token invalid" in out assert "HTTP" not in out def test_auth_service_error_with_status(self): exc = AuthServiceError("Forbidden", status_code=403) out = format_tool_error(exc) assert "**Auth Error**" in out assert "Forbidden" in out assert "403" in out def test_authorization_error(self): exc = AuthorizationError("Access denied") out = format_tool_error(exc) assert "**Error**" in out assert "Access denied" in out assert "401" in out def test_validation_error(self): exc = ValidationError("table_path is required") out = format_tool_error(exc) assert "**Validation Error**" in out assert "table_path is required" in out def test_network_error(self): exc = NetworkError("Connection refused") out = format_tool_error(exc) assert "**Error**" in out assert "Connection refused" in out def test_prometheus_timeout_error(self): exc = PrometheusTimeoutError("Query exceeded 20-second timeout") out = format_tool_error(exc) assert "**Error**" in out assert "timeout" in out def test_prometheus_api_error_without_detail(self): exc = PrometheusAPIError("Bad request") out = format_tool_error(exc) assert "**Error**" in out assert "Bad request" in out def test_prometheus_api_error_with_detail(self): exc = PrometheusAPIError("Invalid query", prometheus_error="parse error at 1:2") out = format_tool_error(exc) assert "**Error**" in out assert "Invalid PromQL" in out or "PromQL" in out assert "parse error" in out def test_delta_error(self): exc = DeltaError("Table not found") out = format_tool_error(exc) assert "**Delta Error**" in out assert "Table not found" in out def test_unexpected_error_fallback(self): exc = ValueError("something went wrong") out = format_tool_error(exc) assert "**Unexpected Error**" in out assert "something went wrong" in out def test_runtime_error_fallback(self): exc = RuntimeError("internal") out = format_tool_error(exc) assert "**Unexpected Error**" in out assert "internal" in out