""" Tests for Learning Generator Service """ import pytest from unittest.mock import patch, MagicMock, AsyncMock import json import sys sys.path.insert(0, '/app') from services.learning_generator import LearningGeneratorService from models.learning_node import LearningTheme, NodeType class TestLearningGeneratorService: """Tests for Learning Generator Service.""" @pytest.fixture def service(self): """Create service instance.""" return LearningGeneratorService() def test_build_generation_prompt_topographie(self, service): """Test prompt building for topography theme.""" aoi_info = { "bounds": {"west": 9.18, "south": 47.70, "east": 9.20, "north": 47.72}, "center": {"latitude": 47.71, "longitude": 9.19}, "area_km2": 0.5, } prompt = service._build_generation_prompt( aoi_info=aoi_info, theme=LearningTheme.TOPOGRAPHIE, difficulty="mittel", node_count=5, grade_level="7-8", language="de", ) assert "Topographie" in prompt or "topographie" in prompt assert "47.71" in prompt # center latitude assert "9.19" in prompt # center longitude assert "5" in prompt # node count assert "mittel" in prompt # difficulty assert "7-8" in prompt # grade level assert "JSON" in prompt def test_build_generation_prompt_landnutzung(self, service): """Test prompt building for land use theme.""" aoi_info = { "bounds": {"west": 9.18, "south": 47.70, "east": 9.20, "north": 47.72}, "center": {"latitude": 47.71, "longitude": 9.19}, "area_km2": 0.5, } prompt = service._build_generation_prompt( aoi_info=aoi_info, theme=LearningTheme.LANDNUTZUNG, difficulty="leicht", node_count=3, grade_level=None, language="de", ) assert "Landnutzung" in prompt or "landnutzung" in prompt def test_parse_llm_response_valid(self, service): """Test parsing valid LLM response.""" response = """ Here are the learning nodes: [ { "title": "Höhenbestimmung", "position": {"latitude": 47.71, "longitude": 9.19}, "question": "Schätze die Höhe dieses Punktes.", "hints": ["Schau auf die Vegetation", "Vergleiche mit dem See"], "answer": "Ca. 500m", "explanation": "Die Höhe lässt sich...", "node_type": "question", "points": 10 } ] """ nodes = service._parse_llm_response( response, "test-aoi-id", LearningTheme.TOPOGRAPHIE ) assert len(nodes) == 1 assert nodes[0].title == "Höhenbestimmung" assert nodes[0].aoi_id == "test-aoi-id" assert nodes[0].theme == LearningTheme.TOPOGRAPHIE assert nodes[0].points == 10 def test_parse_llm_response_invalid_json(self, service): """Test parsing invalid LLM response.""" response = "This is not valid JSON" nodes = service._parse_llm_response( response, "test-aoi-id", LearningTheme.TOPOGRAPHIE ) assert len(nodes) == 0 def test_generate_mock_nodes(self, service): """Test mock node generation.""" nodes = service._generate_mock_nodes( aoi_id="test-aoi-id", theme=LearningTheme.TOPOGRAPHIE, difficulty="mittel", node_count=3, ) assert len(nodes) == 3 for node in nodes: assert node.aoi_id == "test-aoi-id" assert node.theme == LearningTheme.TOPOGRAPHIE assert node.approved == False assert len(node.hints) > 0 def test_generate_mock_nodes_orientierung(self, service): """Test mock node generation for orientation theme.""" nodes = service._generate_mock_nodes( aoi_id="test-aoi-id", theme=LearningTheme.ORIENTIERUNG, difficulty="leicht", node_count=2, ) assert len(nodes) == 2 for node in nodes: assert node.theme == LearningTheme.ORIENTIERUNG @pytest.mark.asyncio async def test_get_nodes_for_aoi_empty(self, service): """Test getting nodes for non-existent AOI.""" nodes = await service.get_nodes_for_aoi("nonexistent-aoi") assert nodes is None @pytest.mark.asyncio async def test_get_statistics_empty(self, service): """Test statistics with no data.""" stats = await service.get_statistics() assert stats["total_nodes"] == 0 assert stats["by_theme"] == {} class TestLearningNodeModel: """Tests for Learning Node model.""" def test_learning_theme_values(self): """Test all theme enum values exist.""" themes = [ LearningTheme.TOPOGRAPHIE, LearningTheme.LANDNUTZUNG, LearningTheme.ORIENTIERUNG, LearningTheme.GEOLOGIE, LearningTheme.HYDROLOGIE, LearningTheme.VEGETATION, ] assert len(themes) == 6 def test_node_type_values(self): """Test all node type enum values exist.""" types = [ NodeType.QUESTION, NodeType.OBSERVATION, NodeType.EXPLORATION, ] assert len(types) == 3 def test_create_learning_node(self): """Test creating a learning node.""" from models.learning_node import LearningNode node = LearningNode( id="test-id", aoi_id="test-aoi", title="Test Station", theme=LearningTheme.TOPOGRAPHIE, position={"latitude": 47.71, "longitude": 9.19}, question="Test question?", hints=["Hint 1", "Hint 2"], answer="Test answer", explanation="Test explanation", node_type=NodeType.QUESTION, points=10, approved=False, ) assert node.id == "test-id" assert node.title == "Test Station" assert node.points == 10 assert len(node.hints) == 2