""" Coverage tests for local_deep_research/domain_classifier/classifier.py Tests focus on paths not exercised by existing tests: - DOMAIN_CATEGORIES structure - DomainClassifier.__init__ stores attributes correctly - _get_llm() lazy-initialises and caches the LLM - _build_classification_prompt() with and without samples - _get_domain_samples() SQL query is built correctly (mocked session) - classify_domain() returns None on exception - get_classification() returns None on exception - get_all_classifications() returns [] on exception - get_categories_summary() returns {} on exception - classify_all_domains() with force_update=True skips existing check """ from unittest.mock import MagicMock, patch # --------------------------------------------------------------------------- # DOMAIN_CATEGORIES constant # --------------------------------------------------------------------------- class TestDomainCategories: def test_categories_dict_is_not_empty(self): from local_deep_research.domain_classifier.classifier import ( DOMAIN_CATEGORIES, ) assert isinstance(DOMAIN_CATEGORIES, dict) assert len(DOMAIN_CATEGORIES) > 0 def test_other_category_present(self): from local_deep_research.domain_classifier.classifier import ( DOMAIN_CATEGORIES, ) assert "Other" in DOMAIN_CATEGORIES def test_all_values_are_lists(self): from local_deep_research.domain_classifier.classifier import ( DOMAIN_CATEGORIES, ) for cat, subcats in DOMAIN_CATEGORIES.items(): assert isinstance(subcats, list), f"{cat} should have a list" # --------------------------------------------------------------------------- # DomainClassifier.__init__ # --------------------------------------------------------------------------- class TestDomainClassifierInit: def test_stores_username_and_snapshot(self): from local_deep_research.domain_classifier.classifier import ( DomainClassifier, ) clf = DomainClassifier(username="alice", settings_snapshot={"k": "v"}) assert clf.username == "alice" assert clf.settings_snapshot == {"k": "v"} assert clf.llm is None def test_defaults_snapshot_to_none(self): from local_deep_research.domain_classifier.classifier import ( DomainClassifier, ) clf = DomainClassifier(username="bob") assert clf.settings_snapshot is None # --------------------------------------------------------------------------- # _get_llm – lazy initialisation # --------------------------------------------------------------------------- class TestGetLlm: def test_llm_created_only_once(self): from local_deep_research.domain_classifier.classifier import ( DomainClassifier, ) clf = DomainClassifier(username="u") mock_llm = MagicMock() with patch( "local_deep_research.domain_classifier.classifier.get_llm", return_value=mock_llm, ) as mock_get: r1 = clf._get_llm() r2 = clf._get_llm() assert r1 is mock_llm assert r2 is mock_llm mock_get.assert_called_once() # --------------------------------------------------------------------------- # _build_classification_prompt # --------------------------------------------------------------------------- class TestBuildClassificationPrompt: def _make_clf(self): from local_deep_research.domain_classifier.classifier import ( DomainClassifier, ) return DomainClassifier(username="u") def test_prompt_contains_domain(self): clf = self._make_clf() prompt = clf._build_classification_prompt("example.com", []) assert "example.com" in prompt def test_prompt_contains_json_instruction(self): clf = self._make_clf() prompt = clf._build_classification_prompt("example.com", []) assert "JSON" in prompt def test_prompt_includes_sample_titles(self): clf = self._make_clf() samples = [{"title": "Hello World", "preview": "short preview"}] prompt = clf._build_classification_prompt("blog.io", samples) assert "Hello World" in prompt def test_prompt_without_samples_uses_fallback_text(self): clf = self._make_clf() prompt = clf._build_classification_prompt("unknown.io", []) assert "No samples available" in prompt # --------------------------------------------------------------------------- # classify_domain – exception returns None # --------------------------------------------------------------------------- class TestClassifyDomainException: def test_db_exception_returns_none(self): from local_deep_research.domain_classifier.classifier import ( DomainClassifier, ) clf = DomainClassifier(username="u") with patch( "local_deep_research.domain_classifier.classifier.get_user_db_session", side_effect=Exception("db fail"), ): result = clf.classify_domain("example.com") assert result is None # --------------------------------------------------------------------------- # get_classification – exception returns None # --------------------------------------------------------------------------- class TestGetClassificationException: def test_db_exception_returns_none(self): from local_deep_research.domain_classifier.classifier import ( DomainClassifier, ) clf = DomainClassifier(username="u") with patch( "local_deep_research.domain_classifier.classifier.get_user_db_session", side_effect=Exception("db fail"), ): result = clf.get_classification("example.com") assert result is None # --------------------------------------------------------------------------- # get_all_classifications – exception returns [] # --------------------------------------------------------------------------- class TestGetAllClassificationsException: def test_db_exception_returns_empty_list(self): from local_deep_research.domain_classifier.classifier import ( DomainClassifier, ) clf = DomainClassifier(username="u") with patch( "local_deep_research.domain_classifier.classifier.get_user_db_session", side_effect=Exception("db fail"), ): result = clf.get_all_classifications() assert result == [] # --------------------------------------------------------------------------- # get_categories_summary – exception returns {} # --------------------------------------------------------------------------- class TestGetCategoriesSummaryException: def test_db_exception_returns_empty_dict(self): from local_deep_research.domain_classifier.classifier import ( DomainClassifier, ) clf = DomainClassifier(username="u") with patch( "local_deep_research.domain_classifier.classifier.get_user_db_session", side_effect=Exception("db fail"), ): result = clf.get_categories_summary() assert result == {} # --------------------------------------------------------------------------- # classify_all_domains – outer exception # --------------------------------------------------------------------------- class TestClassifyAllDomainsException: def test_outer_exception_returns_error_dict(self): from local_deep_research.domain_classifier.classifier import ( DomainClassifier, ) clf = DomainClassifier(username="u") with patch( "local_deep_research.domain_classifier.classifier.get_user_db_session", side_effect=Exception("db fail"), ): result = clf.classify_all_domains() assert isinstance(result, dict) assert ( "error" in result or "failed" in result or result.get("total", -1) >= 0 )