"""Unit tests for Pydantic models.""" import pytest from pydantic import ValidationError from src.models.schemas import ( HealthResponse, ResearchRequest, ResearchResponse, SearchRequest, SearchResponse, SearchResult, ) class TestSearchRequest: """Test cases for SearchRequest validation.""" def test_valid_request(self): """Test valid search request.""" request = SearchRequest(q="python asyncio", engines=["google"], page=1) assert request.q == "python asyncio" assert request.engines == ["google"] assert request.page == 1 def test_default_engines(self): """Test default engines.""" request = SearchRequest(q="test") assert "google" in request.engines assert "bing" in request.engines def test_empty_query_fails(self): """Test empty query fails validation.""" with pytest.raises(ValidationError) as exc_info: SearchRequest(q="", engines=["google"]) assert "String should have at least 1 character" in str(exc_info.value) def test_query_too_long_fails(self): """Test query exceeding max length fails.""" with pytest.raises(ValidationError) as exc_info: SearchRequest(q="x" * 501, engines=["google"]) assert "String should have at most 500 characters" in str(exc_info.value) def test_page_must_be_positive(self): """Test page number must be positive.""" with pytest.raises(ValidationError) as exc_info: SearchRequest(q="test", page=0) assert "Input should be greater than or equal to 1" in str(exc_info.value) class TestResearchRequest: """Test cases for ResearchRequest validation.""" def test_valid_request(self): """Test valid research request.""" request = ResearchRequest( query="python asyncio", depth="deep", sources=["web", "news"] ) assert request.query == "python asyncio" assert request.depth == "deep" def test_default_values(self): """Test default values.""" request = ResearchRequest(query="test") assert request.depth == "shallow" assert request.sources == ["web"] assert request.language == "en" assert request.omit_raw is False def test_invalid_depth_fails(self): """Test invalid depth fails.""" with pytest.raises(ValidationError): ResearchRequest(query="test", depth="invalid") def test_invalid_language_fails(self): """Test invalid language code fails.""" with pytest.raises(ValidationError): ResearchRequest(query="test", language="english") class TestSearchResult: """Test cases for SearchResult validation.""" def test_valid_result(self): """Test valid search result.""" result = SearchResult( title="Python Documentation", url="https://docs.python.org", content="Python docs", source="google", score=0.95 ) assert result.title == "Python Documentation" assert str(result.url) == "https://docs.python.org/" def test_title_required(self): """Test title is required.""" with pytest.raises(ValidationError): SearchResult(url="https://example.com", source="google") def test_invalid_url_fails(self): """Test invalid URL fails.""" with pytest.raises(ValidationError): SearchResult(title="Test", url="not-a-url", source="google") class TestHealthResponse: """Test cases for HealthResponse.""" def test_valid_response(self): """Test valid health response.""" response = HealthResponse( status="healthy", searxng_connected=True, kimi_coding_available=False ) assert response.status == "healthy" assert response.version == "0.1.0" class TestResearchResponse: """Test cases for ResearchResponse.""" def test_phase1_response(self): """Test Phase 1 response without synthesis.""" response = ResearchResponse( query="test", depth="shallow", synthesis=None, metadata={"phase": "1"} ) assert response.synthesis is None assert response.metadata["phase"] == "1"