refactor: migrate AI tree generator to provider abstraction

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-02-26 17:20:48 -05:00
parent 55be033ecb
commit eb7ea7ddd9
3 changed files with 76 additions and 106 deletions

View File

@@ -1,6 +1,6 @@
"""Integration tests for AI Flow Builder endpoints.
All Anthropic API calls are mocked — zero real API spend.
All AI provider calls are mocked — zero real API spend.
"""
import json
from unittest.mock import AsyncMock, patch, MagicMock
@@ -64,12 +64,11 @@ BRANCH_DETAIL_JSON = json.dumps({
})
def _mock_anthropic_response(text: str, input_tokens: int = 100, output_tokens: int = 200):
"""Create a mock Anthropic API response."""
response = MagicMock()
response.content = [MagicMock(text=text)]
response.usage = MagicMock(input_tokens=input_tokens, output_tokens=output_tokens)
return response
def _mock_ai_provider(text: str, input_tokens: int = 100, output_tokens: int = 200):
"""Create a mock AI provider whose generate_json returns the given text and token counts."""
provider = MagicMock()
provider.generate_json = AsyncMock(return_value=(text, input_tokens, output_tokens))
return provider
@pytest.fixture
@@ -194,11 +193,9 @@ async def test_scaffold_success(client, auth_headers, enable_ai):
)
conversation_id = start_resp.json()["conversation_id"]
# Mock Anthropic
mock_response = _mock_anthropic_response(SCAFFOLD_RESPONSE_JSON)
with patch("app.core.ai_tree_generator_service._get_client") as mock_client:
mock_client.return_value.messages.create = AsyncMock(return_value=mock_response)
# Mock AI provider
mock_provider = _mock_ai_provider(SCAFFOLD_RESPONSE_JSON)
with patch("app.core.ai_tree_generator_service.get_ai_provider", return_value=mock_provider):
response = await client.post(
"/api/v1/ai/scaffold",
json={"conversation_id": conversation_id},
@@ -241,9 +238,8 @@ async def test_branch_detail_success(client, auth_headers, enable_ai):
)
conversation_id = start_resp.json()["conversation_id"]
scaffold_mock = _mock_anthropic_response(SCAFFOLD_RESPONSE_JSON)
with patch("app.core.ai_tree_generator_service._get_client") as mock_client:
mock_client.return_value.messages.create = AsyncMock(return_value=scaffold_mock)
scaffold_provider = _mock_ai_provider(SCAFFOLD_RESPONSE_JSON)
with patch("app.core.ai_tree_generator_service.get_ai_provider", return_value=scaffold_provider):
await client.post(
"/api/v1/ai/scaffold",
json={"conversation_id": conversation_id},
@@ -251,10 +247,8 @@ async def test_branch_detail_success(client, auth_headers, enable_ai):
)
# Now generate branch detail
detail_mock = _mock_anthropic_response(BRANCH_DETAIL_JSON)
with patch("app.core.ai_tree_generator_service._get_client") as mock_client:
mock_client.return_value.messages.create = AsyncMock(return_value=detail_mock)
detail_provider = _mock_ai_provider(BRANCH_DETAIL_JSON)
with patch("app.core.ai_tree_generator_service.get_ai_provider", return_value=detail_provider):
response = await client.post(
"/api/v1/ai/branch-detail",
json={
@@ -290,9 +284,8 @@ async def test_assemble_success(client, auth_headers, enable_ai):
conversation_id = start_resp.json()["conversation_id"]
# Scaffold
scaffold_mock = _mock_anthropic_response(SCAFFOLD_RESPONSE_JSON)
with patch("app.core.ai_tree_generator_service._get_client") as mock_client:
mock_client.return_value.messages.create = AsyncMock(return_value=scaffold_mock)
scaffold_provider = _mock_ai_provider(SCAFFOLD_RESPONSE_JSON)
with patch("app.core.ai_tree_generator_service.get_ai_provider", return_value=scaffold_provider):
await client.post(
"/api/v1/ai/scaffold",
json={"conversation_id": conversation_id},