"""Tests for CVParser — mocks LLM, tests extraction logic and summarize().""" from pathlib import Path from unittest.mock import MagicMock import pytest from agent.cv.parser import CVParser from agent.llm_client import LLMClient PROFILE_JSON = """{ "name": "Alice Rossi", "contact": {"email": "alice@example.com", "phone": "", "linkedin": "", "github": "", "website": ""}, "summary": "ML researcher with focus on NLP", "education": [{"degree": "PhD", "institution": "ETH Zurich", "field": "Computer Science", "year": "2023", "thesis_topic": "Transformers for low-resource NLP"}], "experience": [{"title": "Research Assistant", "institution": "ETH Zurich", "dates": "2019-2023", "description": "LLM research"}], "research_interests": ["NLP", "machine learning", "low-resource languages"], "publications": [{"title": "Efficient NLP", "venue": "ACL 2022", "year": "2022", "authors": "Rossi et al."}], "skills": {"programming": ["Python", "PyTorch"], "tools": ["HuggingFace"], "languages": ["LaTeX"], "lab_techniques": []}, "awards": ["Best Paper ACL 2022"], "languages": [{"language": "English", "level": "Fluent"}, {"language": "Italian", "level": "Native"}], "references": [] }""" def _make_parser(response: str) -> CVParser: llm = MagicMock(spec=LLMClient) llm.generate.return_value = response return CVParser(llm) class TestSummarize: def _profile(self): import json return json.loads(PROFILE_JSON) def test_name_in_summary(self): parser = _make_parser("") text = parser.summarize(self._profile()) assert "Alice Rossi" in text def test_research_interests_in_summary(self): parser = _make_parser("") text = parser.summarize(self._profile()) assert "NLP" in text def test_education_in_summary(self): parser = _make_parser("") text = parser.summarize(self._profile()) assert "ETH Zurich" in text def test_publication_in_summary(self): parser = _make_parser("") text = parser.summarize(self._profile()) assert "Efficient NLP" in text def test_skills_in_summary(self): parser = _make_parser("") text = parser.summarize(self._profile()) assert "Python" in text def test_empty_profile_no_crash(self): parser = _make_parser("") text = parser.summarize({}) assert isinstance(text, str) class TestExtractRawText: def test_txt_file(self, tmp_path): f = tmp_path / "cv.txt" f.write_text("My research CV content") text = CVParser.extract_raw_text(f) assert "My research CV content" in text def test_missing_file_raises(self, tmp_path): with pytest.raises(FileNotFoundError): CVParser.extract_raw_text(tmp_path / "nonexistent.txt") def test_unsupported_format_raises(self, tmp_path): f = tmp_path / "cv.odt" f.write_text("content") with pytest.raises(ValueError, match="Unsupported"): CVParser.extract_raw_text(f)