arcade-mcp/toolkits/zendesk/tests/conftest.py
Eric Gustin c50699d5e6
Migrate OSS toolkits to MCPApp (#782)
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> **Medium Risk**
> Touches multiple toolkits’ runtime entrypoints and context/error/auth
plumbing, so breakage risk is mainly around invocation/packaging and
tool execution wiring rather than business logic.
> 
> **Overview**
> Migrates the BrightData, ClickHouse, LinkedIn, Math, MongoDB,
Postgres, and Zendesk OSS toolkits from `arcade-tdk` to
`arcade-mcp-server` APIs by updating tool decorators, `Context` types,
auth classes, and exception imports.
> 
> Adds per-toolkit `__main__.py` files that construct an `MCPApp`,
register module tools, and run via configurable transport/host/port;
corresponding `pyproject.toml` updates bump versions, drop
`arcade-tdk`/`arcade-serve` deps, and add `project.scripts` console
entrypoints.
> 
> Updates tests and eval suites to use `arcade_mcp_server.Context`
(mocked) and switches eval `ToolCatalog` imports to `arcade_core`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9b3e31acb4b35e1d72efd47e2d279c5b19e3ecb0. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
2026-02-25 14:29:18 -08:00

84 lines
2.3 KiB
Python

from unittest.mock import AsyncMock, MagicMock
import pytest
from arcade_mcp_server import Context
@pytest.fixture
def mock_context():
"""Standard mock context fixture used across all arcade toolkits."""
context = MagicMock(spec=Context)
context.get_auth_token_or_empty = MagicMock(return_value="fake-token")
context.get_secret = MagicMock()
return context
@pytest.fixture
def mock_httpx_client(mocker):
"""Mock httpx.AsyncClient for API calls."""
mock_client_class = mocker.patch("httpx.AsyncClient", autospec=True)
mock_client = AsyncMock()
mock_client_class.return_value.__aenter__.return_value = mock_client
return mock_client
@pytest.fixture
def sample_article_response():
"""Sample article data for testing."""
return {
"id": 123456,
"title": "How to reset your password",
"body": "<p>To reset your password, follow these steps:</p>"
"<ol><li>Click forgot password</li><li>Enter your email</li></ol>",
"url": "https://support.example.com/hc/en-us/articles/123456",
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-06-01T15:30:00Z",
"section_id": 789,
"category_id": 456,
"label_names": ["password", "security", "account"],
}
@pytest.fixture
def build_search_response(sample_article_response):
"""Builder for search API responses."""
def builder(articles=None, next_page=None, count=None):
if articles is None:
articles = [sample_article_response]
response = {
"results": articles,
"next_page": next_page,
"page": 1,
"per_page": len(articles),
"page_count": 1,
}
if count is not None:
response["count"] = count
return response
return builder
@pytest.fixture
def mock_http_response():
"""Factory for creating mock HTTP responses."""
def create_response(json_data=None, status_code=200, raise_for_status=True):
response = MagicMock()
response.json.return_value = json_data
response.status_code = status_code
if raise_for_status and status_code >= 400:
response.raise_for_status.side_effect = Exception(f"HTTP {status_code}")
else:
response.raise_for_status.return_value = None
return response
return create_response