legco_ai_assistant/backend/app/test/test_phase1_query_decompose...

58 lines
1.8 KiB
Python

"""Tests for the Phase 1.3 QueryDecomposer component."""
import json
from typing import List
import pytest
from app.services.query_decomposer import QueryDecomposer
class MockLLMClient:
def __init__(self, response: str):
self._response = response
self.last_prompt = None
self.last_step_name = None
async def complete(self, prompt: str, temperature: float = 0.7, step_name: str = "LLM") -> str:
self.last_prompt = prompt
self.last_step_name = step_name
return self._response
async def test_decompose_valid_json():
llm = MockLLMClient('["alpha", "beta", "gamma"]')
decomposer = QueryDecomposer(llm)
result: List[str] = await decomposer.decompose("What are keywords for X?")
assert result == ["alpha", "beta", "gamma"]
assert llm.last_prompt == "Given question: 'What are keywords for X?', extract key search keywords as JSON array"
async def test_decompose_empty_question_returns_empty():
llm = MockLLMClient('["should_not_be_used"]')
decomposer = QueryDecomposer(llm)
result = await decomposer.decompose("")
assert result == []
assert llm.last_prompt is None
async def test_decompose_invalid_json_returns_empty():
llm = MockLLMClient("not-json")
decomposer = QueryDecomposer(llm)
result = await decomposer.decompose("Question?")
assert result == []
async def test_decompose_non_list_json_returns_empty():
llm = MockLLMClient("{\"a\": 1}")
decomposer = QueryDecomposer(llm)
result = await decomposer.decompose("Question?")
assert result == []
async def test_decompose_mixed_types_coerced_to_strings():
llm = MockLLMClient('["a", 2, null]')
decomposer = QueryDecomposer(llm)
result = await decomposer.decompose("Question?")
assert result == ["a", "2", "None"]