feat: add environment endpoint for weather, forecast, and sun data
Add GET /tools/environment endpoint that fetches weather, forecast, sun times, and air quality data from user's volatile Qdrant collection. - Add qdrant-client dependency - Create QdrantReadClient wrapper for read-only queries - Add environment schemas and service in tools domain - Parse weather, forecast, sun times, and air quality from Qdrant payloads - Support user-specific collections via preferred_username from OIDC - Add comprehensive service tests (13 tests) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
b8fca7060f
commit
6045c6ac6a
@@ -0,0 +1,159 @@
|
||||
"""Tests for environment service and schemas."""
|
||||
import pytest
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class TestEnvironmentService:
|
||||
"""Test EnvironmentService methods."""
|
||||
|
||||
def test_aqi_to_quality_good(self):
|
||||
"""AQI 0-50 should return Good."""
|
||||
from src.domains.tools.environment.service import EnvironmentService
|
||||
service = EnvironmentService.__new__(EnvironmentService)
|
||||
|
||||
assert service._aqi_to_quality(0) == "Good"
|
||||
assert service._aqi_to_quality(25) == "Good"
|
||||
assert service._aqi_to_quality(50) == "Good"
|
||||
|
||||
def test_aqi_to_quality_moderate(self):
|
||||
"""AQI 51-100 should return Moderate."""
|
||||
from src.domains.tools.environment.service import EnvironmentService
|
||||
service = EnvironmentService.__new__(EnvironmentService)
|
||||
|
||||
assert service._aqi_to_quality(51) == "Moderate"
|
||||
assert service._aqi_to_quality(75) == "Moderate"
|
||||
assert service._aqi_to_quality(100) == "Moderate"
|
||||
|
||||
def test_aqi_to_quality_unhealthy_sensitive(self):
|
||||
"""AQI 101-150 should return Unhealthy for Sensitive Groups."""
|
||||
from src.domains.tools.environment.service import EnvironmentService
|
||||
service = EnvironmentService.__new__(EnvironmentService)
|
||||
|
||||
assert service._aqi_to_quality(101) == "Unhealthy for Sensitive Groups"
|
||||
assert service._aqi_to_quality(150) == "Unhealthy for Sensitive Groups"
|
||||
|
||||
def test_aqi_to_quality_unhealthy(self):
|
||||
"""AQI 151-200 should return Unhealthy."""
|
||||
from src.domains.tools.environment.service import EnvironmentService
|
||||
service = EnvironmentService.__new__(EnvironmentService)
|
||||
|
||||
assert service._aqi_to_quality(151) == "Unhealthy"
|
||||
assert service._aqi_to_quality(200) == "Unhealthy"
|
||||
|
||||
def test_aqi_to_quality_very_unhealthy(self):
|
||||
"""AQI 201-300 should return Very Unhealthy."""
|
||||
from src.domains.tools.environment.service import EnvironmentService
|
||||
service = EnvironmentService.__new__(EnvironmentService)
|
||||
|
||||
assert service._aqi_to_quality(201) == "Very Unhealthy"
|
||||
assert service._aqi_to_quality(300) == "Very Unhealthy"
|
||||
|
||||
def test_aqi_to_quality_hazardous(self):
|
||||
"""AQI >300 should return Hazardous."""
|
||||
from src.domains.tools.environment.service import EnvironmentService
|
||||
service = EnvironmentService.__new__(EnvironmentService)
|
||||
|
||||
assert service._aqi_to_quality(301) == "Hazardous"
|
||||
assert service._aqi_to_quality(500) == "Hazardous"
|
||||
|
||||
def test_parse_weather_with_valid_data(self):
|
||||
"""Parse weather should return WeatherData for valid input."""
|
||||
from src.domains.tools.environment.service import EnvironmentService
|
||||
service = EnvironmentService.__new__(EnvironmentService)
|
||||
|
||||
raw = {
|
||||
"temperature": 15.5,
|
||||
"conditions": "Cloudy",
|
||||
"humidity": 72,
|
||||
"location": "Rotterdam",
|
||||
}
|
||||
result = service._parse_weather(raw)
|
||||
|
||||
assert result is not None
|
||||
assert result.temperature == 15.5
|
||||
assert result.conditions == "Cloudy"
|
||||
assert result.humidity == 72
|
||||
|
||||
def test_parse_weather_with_none(self):
|
||||
"""Parse weather should return None for None input."""
|
||||
from src.domains.tools.environment.service import EnvironmentService
|
||||
service = EnvironmentService.__new__(EnvironmentService)
|
||||
|
||||
result = service._parse_weather(None)
|
||||
assert result is None
|
||||
|
||||
def test_parse_forecast_with_list(self):
|
||||
"""Parse forecast should handle list format."""
|
||||
from src.domains.tools.environment.service import EnvironmentService
|
||||
service = EnvironmentService.__new__(EnvironmentService)
|
||||
|
||||
raw = [
|
||||
{"date": "2026-01-06", "high": 12, "low": 5, "conditions": "Cloudy"},
|
||||
{"date": "2026-01-07", "high": 14, "low": 6, "conditions": "Sunny"},
|
||||
]
|
||||
result = service._parse_forecast(raw)
|
||||
|
||||
assert result is not None
|
||||
assert len(result) == 2
|
||||
assert result[0].date == "2026-01-06"
|
||||
assert result[0].high == 12
|
||||
|
||||
def test_parse_forecast_with_dict(self):
|
||||
"""Parse forecast should handle dict with days key."""
|
||||
from src.domains.tools.environment.service import EnvironmentService
|
||||
service = EnvironmentService.__new__(EnvironmentService)
|
||||
|
||||
raw = {
|
||||
"days": [
|
||||
{"date": "2026-01-06", "high": 12, "low": 5, "conditions": "Cloudy"},
|
||||
]
|
||||
}
|
||||
result = service._parse_forecast(raw)
|
||||
|
||||
assert result is not None
|
||||
assert len(result) == 1
|
||||
|
||||
def test_parse_sun_times_with_strings(self):
|
||||
"""Parse sun times should handle ISO datetime strings."""
|
||||
from src.domains.tools.environment.service import EnvironmentService
|
||||
service = EnvironmentService.__new__(EnvironmentService)
|
||||
|
||||
raw = {
|
||||
"sunrise": "2026-01-06T08:45:00",
|
||||
"sunset": "2026-01-06T16:50:00",
|
||||
}
|
||||
result = service._parse_sun_times(raw)
|
||||
|
||||
assert result is not None
|
||||
assert result.sunrise.hour == 8
|
||||
assert result.sunrise.minute == 45
|
||||
assert result.sunset.hour == 16
|
||||
assert result.daylight_minutes == 485
|
||||
|
||||
def test_parse_air_quality_with_int(self):
|
||||
"""Parse air quality should handle simple integer AQI."""
|
||||
from src.domains.tools.environment.service import EnvironmentService
|
||||
service = EnvironmentService.__new__(EnvironmentService)
|
||||
|
||||
result = service._parse_air_quality(42)
|
||||
|
||||
assert result is not None
|
||||
assert result.aqi == 42
|
||||
assert result.quality == "Good"
|
||||
|
||||
def test_parse_air_quality_with_dict(self):
|
||||
"""Parse air quality should handle dict format."""
|
||||
from src.domains.tools.environment.service import EnvironmentService
|
||||
service = EnvironmentService.__new__(EnvironmentService)
|
||||
|
||||
raw = {
|
||||
"aqi": 75,
|
||||
"pm25": 8.5,
|
||||
"pm10": 15,
|
||||
}
|
||||
result = service._parse_air_quality(raw)
|
||||
|
||||
assert result is not None
|
||||
assert result.aqi == 75
|
||||
assert result.quality == "Moderate"
|
||||
assert result.pm25 == 8.5
|
||||
Reference in New Issue
Block a user