Files
wehub-resource-sync 7a0da7932b
Backwards Compatibility / Verify Encryption Constants (push) Waiting to run
Backwards Compatibility / PyPI Version Compatibility (push) Waiting to run
Backwards Compatibility / Database Migration Tests (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
CodeQL Advanced / Analyze (python) (push) Waiting to run
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Blocked by required conditions
Docker Tests (Consolidated) / detect-changes (push) Waiting to run
Docker Tests (Consolidated) / Build Test Image (push) Waiting to run
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Blocked by required conditions
Docker Tests (Consolidated) / Accessibility Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Unit Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Example Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / Production Image Smoke Test (push) Blocked by required conditions
Docker Tests (Consolidated) / Infrastructure Tests (push) Blocked by required conditions
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Waiting to run
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

335 lines
12 KiB
Python

"""
Tests for citation_handler.py
Tests cover:
- CitationHandler initialization
- Handler type selection
- Method delegation
"""
from unittest.mock import Mock, patch
class TestCitationHandlerInit:
"""Tests for CitationHandler initialization."""
def test_default_handler_type(self):
"""Test default handler type is standard."""
mock_llm = Mock()
with patch(
"local_deep_research.citation_handlers.standard_citation_handler.StandardCitationHandler"
) as mock_handler_class:
mock_handler = Mock()
mock_handler._create_documents = Mock()
mock_handler._format_sources = Mock()
mock_handler_class.return_value = mock_handler
from local_deep_research.citation_handler import CitationHandler
handler = CitationHandler(mock_llm)
mock_handler_class.assert_called_once()
assert handler._handler == mock_handler
def test_explicit_standard_handler(self):
"""Test explicit standard handler type."""
mock_llm = Mock()
with patch(
"local_deep_research.citation_handlers.standard_citation_handler.StandardCitationHandler"
) as mock_handler_class:
mock_handler = Mock()
mock_handler._create_documents = Mock()
mock_handler._format_sources = Mock()
mock_handler_class.return_value = mock_handler
from local_deep_research.citation_handler import CitationHandler
CitationHandler(mock_llm, handler_type="standard")
mock_handler_class.assert_called_once()
def test_forced_handler_type(self):
"""Test forced handler type."""
mock_llm = Mock()
with patch(
"local_deep_research.citation_handlers.forced_answer_citation_handler.ForcedAnswerCitationHandler"
) as mock_handler_class:
mock_handler = Mock()
mock_handler._create_documents = Mock()
mock_handler._format_sources = Mock()
mock_handler_class.return_value = mock_handler
from local_deep_research.citation_handler import CitationHandler
CitationHandler(mock_llm, handler_type="forced")
mock_handler_class.assert_called_once()
def test_browsecomp_handler_type(self):
"""Test browsecomp handler type maps to forced."""
mock_llm = Mock()
with patch(
"local_deep_research.citation_handlers.forced_answer_citation_handler.ForcedAnswerCitationHandler"
) as mock_handler_class:
mock_handler = Mock()
mock_handler._create_documents = Mock()
mock_handler._format_sources = Mock()
mock_handler_class.return_value = mock_handler
from local_deep_research.citation_handler import CitationHandler
CitationHandler(mock_llm, handler_type="browsecomp")
mock_handler_class.assert_called_once()
def test_precision_handler_type(self):
"""Test precision handler type."""
mock_llm = Mock()
with patch(
"local_deep_research.citation_handlers.precision_extraction_handler.PrecisionExtractionHandler"
) as mock_handler_class:
mock_handler = Mock()
mock_handler._create_documents = Mock()
mock_handler._format_sources = Mock()
mock_handler_class.return_value = mock_handler
from local_deep_research.citation_handler import CitationHandler
CitationHandler(mock_llm, handler_type="precision")
mock_handler_class.assert_called_once()
def test_simpleqa_handler_type(self):
"""Test simpleqa handler type maps to precision."""
mock_llm = Mock()
with patch(
"local_deep_research.citation_handlers.precision_extraction_handler.PrecisionExtractionHandler"
) as mock_handler_class:
mock_handler = Mock()
mock_handler._create_documents = Mock()
mock_handler._format_sources = Mock()
mock_handler_class.return_value = mock_handler
from local_deep_research.citation_handler import CitationHandler
CitationHandler(mock_llm, handler_type="simpleqa")
mock_handler_class.assert_called_once()
def test_unknown_handler_type_fallback(self):
"""Test unknown handler type falls back to standard."""
mock_llm = Mock()
with patch(
"local_deep_research.citation_handlers.standard_citation_handler.StandardCitationHandler"
) as mock_handler_class:
mock_handler = Mock()
mock_handler._create_documents = Mock()
mock_handler._format_sources = Mock()
mock_handler_class.return_value = mock_handler
from local_deep_research.citation_handler import CitationHandler
CitationHandler(mock_llm, handler_type="unknown_type")
# Called twice - once for unknown fallback
assert mock_handler_class.call_count >= 1
def test_handler_type_from_settings_snapshot(self):
"""Test handler type from settings snapshot."""
mock_llm = Mock()
settings_snapshot = {"citation.handler_type": "forced"}
with patch(
"local_deep_research.citation_handlers.forced_answer_citation_handler.ForcedAnswerCitationHandler"
) as mock_handler_class:
mock_handler = Mock()
mock_handler._create_documents = Mock()
mock_handler._format_sources = Mock()
mock_handler_class.return_value = mock_handler
from local_deep_research.citation_handler import CitationHandler
CitationHandler(mock_llm, settings_snapshot=settings_snapshot)
mock_handler_class.assert_called_once()
def test_handler_type_from_settings_snapshot_dict_value(self):
"""Test handler type from settings snapshot with dict value."""
mock_llm = Mock()
settings_snapshot = {"citation.handler_type": {"value": "precision"}}
with patch(
"local_deep_research.citation_handlers.precision_extraction_handler.PrecisionExtractionHandler"
) as mock_handler_class:
mock_handler = Mock()
mock_handler._create_documents = Mock()
mock_handler._format_sources = Mock()
mock_handler_class.return_value = mock_handler
from local_deep_research.citation_handler import CitationHandler
CitationHandler(mock_llm, settings_snapshot=settings_snapshot)
mock_handler_class.assert_called_once()
def test_handler_type_case_insensitive(self):
"""Test handler type is case insensitive."""
mock_llm = Mock()
with patch(
"local_deep_research.citation_handlers.forced_answer_citation_handler.ForcedAnswerCitationHandler"
) as mock_handler_class:
mock_handler = Mock()
mock_handler._create_documents = Mock()
mock_handler._format_sources = Mock()
mock_handler_class.return_value = mock_handler
from local_deep_research.citation_handler import CitationHandler
CitationHandler(mock_llm, handler_type="FORCED")
mock_handler_class.assert_called_once()
class TestCitationHandlerMethods:
"""Tests for CitationHandler method delegation."""
def test_analyze_initial_delegation(self):
"""Test analyze_initial delegates to handler."""
mock_llm = Mock()
with patch(
"local_deep_research.citation_handlers.standard_citation_handler.StandardCitationHandler"
) as mock_handler_class:
mock_handler = Mock()
mock_handler._create_documents = Mock()
mock_handler._format_sources = Mock()
mock_handler.analyze_initial.return_value = {"result": "test"}
mock_handler_class.return_value = mock_handler
from local_deep_research.citation_handler import CitationHandler
handler = CitationHandler(mock_llm)
result = handler.analyze_initial("test query", [])
mock_handler.analyze_initial.assert_called_once_with(
"test query", []
)
assert result == {"result": "test"}
def test_analyze_followup_delegation(self):
"""Test analyze_followup delegates to handler."""
mock_llm = Mock()
with patch(
"local_deep_research.citation_handlers.standard_citation_handler.StandardCitationHandler"
) as mock_handler_class:
mock_handler = Mock()
mock_handler._create_documents = Mock()
mock_handler._format_sources = Mock()
mock_handler.analyze_followup.return_value = {"result": "followup"}
mock_handler_class.return_value = mock_handler
from local_deep_research.citation_handler import CitationHandler
handler = CitationHandler(mock_llm)
result = handler.analyze_followup(
"test question", [], "previous knowledge", 5
)
mock_handler.analyze_followup.assert_called_once_with(
"test question", [], "previous knowledge", 5
)
assert result == {"result": "followup"}
def test_backward_compatibility_methods_exposed(self):
"""Test backward compatibility methods are exposed."""
mock_llm = Mock()
with patch(
"local_deep_research.citation_handlers.standard_citation_handler.StandardCitationHandler"
) as mock_handler_class:
mock_create_docs = Mock()
mock_format_sources = Mock()
mock_handler = Mock()
mock_handler._create_documents = mock_create_docs
mock_handler._format_sources = mock_format_sources
mock_handler_class.return_value = mock_handler
from local_deep_research.citation_handler import CitationHandler
handler = CitationHandler(mock_llm)
assert handler._create_documents == mock_create_docs
assert handler._format_sources == mock_format_sources
class TestCitationHandlerSettings:
"""Tests for CitationHandler settings handling."""
def test_empty_settings_snapshot(self):
"""Test with empty settings snapshot."""
mock_llm = Mock()
with patch(
"local_deep_research.citation_handlers.standard_citation_handler.StandardCitationHandler"
) as mock_handler_class:
mock_handler = Mock()
mock_handler._create_documents = Mock()
mock_handler._format_sources = Mock()
mock_handler_class.return_value = mock_handler
from local_deep_research.citation_handler import CitationHandler
CitationHandler(mock_llm, settings_snapshot={})
# Should use standard handler as default
mock_handler_class.assert_called_once()
def test_settings_passed_to_handler(self):
"""Test settings are passed to underlying handler."""
mock_llm = Mock()
settings_snapshot = {"some_setting": "value"}
with patch(
"local_deep_research.citation_handlers.standard_citation_handler.StandardCitationHandler"
) as mock_handler_class:
mock_handler = Mock()
mock_handler._create_documents = Mock()
mock_handler._format_sources = Mock()
mock_handler_class.return_value = mock_handler
from local_deep_research.citation_handler import CitationHandler
CitationHandler(mock_llm, settings_snapshot=settings_snapshot)
call_kwargs = mock_handler_class.call_args[1]
assert call_kwargs["settings_snapshot"] == settings_snapshot
def test_llm_passed_to_handler(self):
"""Test LLM is passed to underlying handler."""
mock_llm = Mock()
with patch(
"local_deep_research.citation_handlers.standard_citation_handler.StandardCitationHandler"
) as mock_handler_class:
mock_handler = Mock()
mock_handler._create_documents = Mock()
mock_handler._format_sources = Mock()
mock_handler_class.return_value = mock_handler
from local_deep_research.citation_handler import CitationHandler
CitationHandler(mock_llm)
call_args = mock_handler_class.call_args[0]
assert call_args[0] == mock_llm