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
637 lines
24 KiB
Python
637 lines
24 KiB
Python
"""Tests for API research functions."""
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from local_deep_research.api.research_functions import (
|
|
_init_search_system,
|
|
quick_summary,
|
|
generate_report,
|
|
detailed_research,
|
|
analyze_documents,
|
|
)
|
|
|
|
|
|
class TestInitSearchSystem:
|
|
"""Tests for _init_search_system function."""
|
|
|
|
def test_returns_search_system(self, mock_get_llm, mock_get_search):
|
|
"""Test that function returns an AdvancedSearchSystem."""
|
|
with patch(
|
|
"local_deep_research.api.research_functions.AdvancedSearchSystem"
|
|
) as mock_class:
|
|
mock_system = MagicMock()
|
|
mock_class.return_value = mock_system
|
|
|
|
result = _init_search_system()
|
|
|
|
assert result == mock_system
|
|
mock_class.assert_called_once()
|
|
|
|
def test_passes_custom_temperature(self, mock_get_llm, mock_get_search):
|
|
"""Test that custom temperature is passed to get_llm."""
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.AdvancedSearchSystem"
|
|
),
|
|
patch(
|
|
"local_deep_research.api.research_functions.get_llm"
|
|
) as mock_llm,
|
|
):
|
|
_init_search_system(temperature=0.5)
|
|
mock_llm.assert_called_once()
|
|
assert mock_llm.call_args[1]["temperature"] == 0.5
|
|
|
|
def test_passes_model_name(self, mock_get_llm, mock_get_search):
|
|
"""Test that model_name is passed to get_llm."""
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.AdvancedSearchSystem"
|
|
),
|
|
patch(
|
|
"local_deep_research.api.research_functions.get_llm"
|
|
) as mock_llm,
|
|
):
|
|
_init_search_system(model_name="gpt-4")
|
|
assert mock_llm.call_args[1]["model_name"] == "gpt-4"
|
|
|
|
def test_passes_provider(self, mock_get_llm, mock_get_search):
|
|
"""Test that provider is passed to get_llm."""
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.AdvancedSearchSystem"
|
|
),
|
|
patch(
|
|
"local_deep_research.api.research_functions.get_llm"
|
|
) as mock_llm,
|
|
):
|
|
_init_search_system(provider="openai")
|
|
assert mock_llm.call_args[1]["provider"] == "openai"
|
|
|
|
def test_creates_search_engine(self, mock_get_llm, mock_get_search):
|
|
"""Test that search engine is created when search_tool specified."""
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.AdvancedSearchSystem"
|
|
),
|
|
patch(
|
|
"local_deep_research.api.research_functions.get_search"
|
|
) as mock_search,
|
|
):
|
|
_init_search_system(search_tool="wikipedia")
|
|
mock_search.assert_called_once()
|
|
assert mock_search.call_args[0][0] == "wikipedia"
|
|
|
|
def test_sets_iterations(self, mock_get_llm, mock_get_search):
|
|
"""Test that max_iterations is set on system."""
|
|
with patch(
|
|
"local_deep_research.api.research_functions.AdvancedSearchSystem"
|
|
) as mock_class:
|
|
mock_system = MagicMock()
|
|
mock_class.return_value = mock_system
|
|
|
|
_init_search_system(iterations=5)
|
|
|
|
assert mock_system.max_iterations == 5
|
|
|
|
def test_sets_questions_per_iteration(self, mock_get_llm, mock_get_search):
|
|
"""Test that questions_per_iteration is set on system."""
|
|
with patch(
|
|
"local_deep_research.api.research_functions.AdvancedSearchSystem"
|
|
) as mock_class:
|
|
mock_system = MagicMock()
|
|
mock_class.return_value = mock_system
|
|
|
|
_init_search_system(questions_per_iteration=10)
|
|
|
|
assert mock_system.questions_per_iteration == 10
|
|
|
|
def test_sets_progress_callback(self, mock_get_llm, mock_get_search):
|
|
"""Test that progress callback is set."""
|
|
callback = MagicMock()
|
|
with patch(
|
|
"local_deep_research.api.research_functions.AdvancedSearchSystem"
|
|
) as mock_class:
|
|
mock_system = MagicMock()
|
|
mock_class.return_value = mock_system
|
|
|
|
_init_search_system(progress_callback=callback)
|
|
|
|
mock_system.set_progress_callback.assert_called_once_with(callback)
|
|
|
|
def test_registers_retrievers(self, mock_get_llm, mock_get_search):
|
|
"""Test that custom retrievers are registered."""
|
|
retriever = MagicMock()
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.AdvancedSearchSystem"
|
|
),
|
|
patch(
|
|
"local_deep_research.web_search_engines.retriever_registry.retriever_registry"
|
|
) as mock_registry,
|
|
):
|
|
_init_search_system(retrievers={"custom": retriever})
|
|
mock_registry.register_multiple.assert_called_once_with(
|
|
{"custom": retriever}
|
|
)
|
|
|
|
def test_registers_llms(self, mock_get_llm, mock_get_search):
|
|
"""Test that custom LLMs are registered."""
|
|
custom_llm = MagicMock()
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.AdvancedSearchSystem"
|
|
),
|
|
patch("local_deep_research.llm.register_llm") as mock_register,
|
|
):
|
|
_init_search_system(llms={"custom_llm": custom_llm})
|
|
mock_register.assert_called_once_with("custom_llm", custom_llm)
|
|
|
|
def test_uses_settings_snapshot(
|
|
self, mock_get_llm, mock_get_search, sample_settings_snapshot
|
|
):
|
|
"""Test that settings_snapshot is passed through."""
|
|
with patch(
|
|
"local_deep_research.api.research_functions.AdvancedSearchSystem"
|
|
) as mock_class:
|
|
_init_search_system(settings_snapshot=sample_settings_snapshot)
|
|
call_kwargs = mock_class.call_args[1]
|
|
assert call_kwargs["settings_snapshot"] == sample_settings_snapshot
|
|
|
|
|
|
class TestQuickSummary:
|
|
"""Tests for quick_summary function."""
|
|
|
|
def test_returns_dict(self, mock_get_llm, mock_advanced_search_system):
|
|
"""Test that function returns a dictionary."""
|
|
with patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
):
|
|
result = quick_summary("test query")
|
|
assert isinstance(result, dict)
|
|
|
|
def test_returns_summary_key(
|
|
self, mock_get_llm, mock_advanced_search_system
|
|
):
|
|
"""Test that result contains 'summary' key."""
|
|
with patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
):
|
|
result = quick_summary("test query")
|
|
assert "summary" in result
|
|
|
|
def test_returns_findings_key(
|
|
self, mock_get_llm, mock_advanced_search_system
|
|
):
|
|
"""Test that result contains 'findings' key."""
|
|
with patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
):
|
|
result = quick_summary("test query")
|
|
assert "findings" in result
|
|
|
|
def test_returns_iterations_key(
|
|
self, mock_get_llm, mock_advanced_search_system
|
|
):
|
|
"""Test that result contains 'iterations' key."""
|
|
with patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
):
|
|
result = quick_summary("test query")
|
|
assert "iterations" in result
|
|
|
|
def test_returns_sources_key(
|
|
self, mock_get_llm, mock_advanced_search_system
|
|
):
|
|
"""Test that result contains 'sources' key."""
|
|
with patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
):
|
|
result = quick_summary("test query")
|
|
assert "sources" in result
|
|
|
|
def test_generates_research_id_if_none(
|
|
self, mock_get_llm, mock_advanced_search_system
|
|
):
|
|
"""Test that research_id is generated if not provided."""
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
),
|
|
patch(
|
|
"local_deep_research.api.research_functions.set_search_context"
|
|
) as mock_set_context,
|
|
):
|
|
quick_summary("test query")
|
|
call_args = mock_set_context.call_args[0][0]
|
|
assert "research_id" in call_args
|
|
# Should be a valid UUID
|
|
assert len(call_args["research_id"]) == 36
|
|
|
|
def test_uses_provided_research_id(
|
|
self, mock_get_llm, mock_advanced_search_system
|
|
):
|
|
"""Test that provided research_id is used."""
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
),
|
|
patch(
|
|
"local_deep_research.api.research_functions.set_search_context"
|
|
) as mock_set_context,
|
|
):
|
|
quick_summary("test query", research_id="custom-id")
|
|
call_args = mock_set_context.call_args[0][0]
|
|
assert call_args["research_id"] == "custom-id"
|
|
|
|
def test_registers_custom_retrievers(
|
|
self, mock_get_llm, mock_advanced_search_system
|
|
):
|
|
"""Test that custom retrievers are registered."""
|
|
retriever = MagicMock()
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
),
|
|
patch(
|
|
"local_deep_research.web_search_engines.retriever_registry.retriever_registry"
|
|
) as mock_registry,
|
|
):
|
|
quick_summary("test query", retrievers={"custom": retriever})
|
|
mock_registry.register_multiple.assert_called()
|
|
|
|
def test_calls_analyze_topic(
|
|
self, mock_get_llm, mock_advanced_search_system
|
|
):
|
|
"""Test that analyze_topic is called with query."""
|
|
with patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
):
|
|
quick_summary("test query")
|
|
mock_advanced_search_system.analyze_topic.assert_called_once_with(
|
|
"test query"
|
|
)
|
|
|
|
def test_handles_empty_results(self, mock_get_llm):
|
|
"""Test handling when analyze_topic returns empty results."""
|
|
mock_system = MagicMock()
|
|
mock_system.analyze_topic.return_value = {}
|
|
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.AdvancedSearchSystem",
|
|
return_value=mock_system,
|
|
),
|
|
patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
),
|
|
):
|
|
result = quick_summary("test query")
|
|
assert (
|
|
result["summary"] == "Unable to generate summary for the query."
|
|
)
|
|
|
|
def test_creates_settings_snapshot_when_not_provided(
|
|
self, mock_get_llm, mock_advanced_search_system
|
|
):
|
|
"""Test that settings snapshot is created if not provided."""
|
|
with patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
) as mock_create:
|
|
quick_summary("test query", provider="openai", temperature=0.5)
|
|
mock_create.assert_called_once()
|
|
|
|
def test_uses_provided_settings_snapshot(
|
|
self, mock_get_llm, mock_advanced_search_system
|
|
):
|
|
"""Test that provided settings_snapshot is used."""
|
|
# Create a valid settings snapshot with required keys
|
|
custom_snapshot = {
|
|
# "library" is always available without extra engine config
|
|
# (searxng needs an instance URL before the factory accepts it).
|
|
"search.tool": {"value": "library"},
|
|
"custom": "settings",
|
|
}
|
|
with patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value=custom_snapshot,
|
|
) as mock_create:
|
|
quick_summary("test query", settings_snapshot=custom_snapshot)
|
|
# Should not call create_settings_snapshot when snapshot is provided
|
|
mock_create.assert_not_called()
|
|
|
|
|
|
class TestGenerateReport:
|
|
"""Tests for generate_report function."""
|
|
|
|
def test_returns_dict(
|
|
self, mock_get_llm, mock_advanced_search_system, mock_report_generator
|
|
):
|
|
"""Test that function returns a dictionary."""
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.IntegratedReportGenerator",
|
|
return_value=mock_report_generator,
|
|
),
|
|
patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
),
|
|
):
|
|
result = generate_report("test query")
|
|
assert isinstance(result, dict)
|
|
|
|
def test_returns_content_key(
|
|
self, mock_get_llm, mock_advanced_search_system, mock_report_generator
|
|
):
|
|
"""Test that result contains 'content' key."""
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.IntegratedReportGenerator",
|
|
return_value=mock_report_generator,
|
|
),
|
|
patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
),
|
|
):
|
|
result = generate_report("test query")
|
|
assert "content" in result
|
|
|
|
def test_calls_analyze_topic(
|
|
self, mock_get_llm, mock_advanced_search_system, mock_report_generator
|
|
):
|
|
"""Test that analyze_topic is called."""
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.IntegratedReportGenerator",
|
|
return_value=mock_report_generator,
|
|
),
|
|
patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
),
|
|
):
|
|
generate_report("test query")
|
|
mock_advanced_search_system.analyze_topic.assert_called_once_with(
|
|
"test query"
|
|
)
|
|
|
|
def test_calls_report_generator(
|
|
self, mock_get_llm, mock_advanced_search_system, mock_report_generator
|
|
):
|
|
"""Test that report generator is called."""
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.IntegratedReportGenerator",
|
|
return_value=mock_report_generator,
|
|
),
|
|
patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
),
|
|
):
|
|
generate_report("test query")
|
|
mock_report_generator.generate_report.assert_called_once()
|
|
|
|
def test_saves_to_file(
|
|
self,
|
|
mock_get_llm,
|
|
mock_advanced_search_system,
|
|
mock_report_generator,
|
|
tmp_path,
|
|
):
|
|
"""Test saving report to file."""
|
|
output_file = str(tmp_path / "report.md")
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.IntegratedReportGenerator",
|
|
return_value=mock_report_generator,
|
|
),
|
|
patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
),
|
|
patch(
|
|
"local_deep_research.security.file_write_verifier.write_file_verified"
|
|
) as mock_write,
|
|
):
|
|
result = generate_report("test query", output_file=output_file)
|
|
mock_write.assert_called_once()
|
|
assert result["file_path"] == output_file
|
|
|
|
def test_sets_progress_callback(
|
|
self, mock_get_llm, mock_advanced_search_system, mock_report_generator
|
|
):
|
|
"""Test that progress callback is set."""
|
|
callback = MagicMock()
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.IntegratedReportGenerator",
|
|
return_value=mock_report_generator,
|
|
),
|
|
patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
),
|
|
):
|
|
generate_report("test query", progress_callback=callback)
|
|
mock_advanced_search_system.set_progress_callback.assert_called_once_with(
|
|
callback
|
|
)
|
|
|
|
def test_searches_per_section(
|
|
self, mock_get_llm, mock_advanced_search_system, mock_report_generator
|
|
):
|
|
"""Test that searches_per_section is passed to generator."""
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.IntegratedReportGenerator"
|
|
) as mock_gen_class,
|
|
patch(
|
|
"local_deep_research.api.research_functions.create_settings_snapshot",
|
|
return_value={},
|
|
),
|
|
):
|
|
mock_gen_class.return_value = mock_report_generator
|
|
generate_report("test query", searches_per_section=5)
|
|
call_kwargs = mock_gen_class.call_args[1]
|
|
assert call_kwargs["searches_per_section"] == 5
|
|
|
|
|
|
class TestDetailedResearch:
|
|
"""Tests for detailed_research function."""
|
|
|
|
def test_returns_dict(self, mock_get_llm, mock_advanced_search_system):
|
|
"""Test that function returns a dictionary."""
|
|
result = detailed_research("test query")
|
|
assert isinstance(result, dict)
|
|
|
|
def test_returns_query(self, mock_get_llm, mock_advanced_search_system):
|
|
"""Test that result contains 'query' key."""
|
|
result = detailed_research("test query")
|
|
assert result["query"] == "test query"
|
|
|
|
def test_returns_research_id(
|
|
self, mock_get_llm, mock_advanced_search_system
|
|
):
|
|
"""Test that result contains 'research_id' key."""
|
|
result = detailed_research("test query")
|
|
assert "research_id" in result
|
|
|
|
def test_uses_provided_research_id(
|
|
self, mock_get_llm, mock_advanced_search_system
|
|
):
|
|
"""Test that provided research_id is used."""
|
|
result = detailed_research("test query", research_id="custom-id")
|
|
assert result["research_id"] == "custom-id"
|
|
|
|
def test_generates_research_id(
|
|
self, mock_get_llm, mock_advanced_search_system
|
|
):
|
|
"""Test that research_id is generated if not provided."""
|
|
result = detailed_research("test query")
|
|
# Should be a valid UUID
|
|
assert len(result["research_id"]) == 36
|
|
|
|
def test_returns_summary(self, mock_get_llm, mock_advanced_search_system):
|
|
"""Test that result contains 'summary' key."""
|
|
result = detailed_research("test query")
|
|
assert "summary" in result
|
|
|
|
def test_returns_findings(self, mock_get_llm, mock_advanced_search_system):
|
|
"""Test that result contains 'findings' key."""
|
|
result = detailed_research("test query")
|
|
assert "findings" in result
|
|
|
|
def test_returns_metadata(self, mock_get_llm, mock_advanced_search_system):
|
|
"""Test that result contains 'metadata' key."""
|
|
result = detailed_research("test query")
|
|
assert "metadata" in result
|
|
assert "timestamp" in result["metadata"]
|
|
|
|
def test_calls_analyze_topic(
|
|
self, mock_get_llm, mock_advanced_search_system
|
|
):
|
|
"""Test that analyze_topic is called with query."""
|
|
detailed_research("test query")
|
|
mock_advanced_search_system.analyze_topic.assert_called_once_with(
|
|
"test query"
|
|
)
|
|
|
|
|
|
class TestAnalyzeDocuments:
|
|
"""Tests for analyze_documents function."""
|
|
|
|
def test_returns_dict(self, mock_get_llm, mock_get_search):
|
|
"""Test that function returns a dictionary."""
|
|
result = analyze_documents("test query", "test_collection")
|
|
assert isinstance(result, dict)
|
|
|
|
def test_returns_summary(self, mock_get_llm, mock_get_search):
|
|
"""Test that result contains 'summary' key."""
|
|
result = analyze_documents("test query", "test_collection")
|
|
assert "summary" in result
|
|
|
|
def test_returns_documents(self, mock_get_llm, mock_get_search):
|
|
"""Test that result contains 'documents' key."""
|
|
result = analyze_documents("test query", "test_collection")
|
|
assert "documents" in result
|
|
|
|
def test_collection_not_found(self, mock_get_llm):
|
|
"""Test handling when collection is not found."""
|
|
with patch(
|
|
"local_deep_research.api.research_functions.get_search",
|
|
return_value=None,
|
|
):
|
|
result = analyze_documents("test query", "nonexistent_collection")
|
|
assert "Error" in result["summary"]
|
|
assert result["documents"] == []
|
|
|
|
def test_no_results_found(self, mock_get_llm):
|
|
"""Test handling when no documents are found."""
|
|
mock_search = MagicMock()
|
|
mock_search.run.return_value = []
|
|
|
|
with patch(
|
|
"local_deep_research.api.research_functions.get_search",
|
|
return_value=mock_search,
|
|
):
|
|
result = analyze_documents("test query", "test_collection")
|
|
assert "No documents found" in result["summary"]
|
|
assert result["documents"] == []
|
|
|
|
def test_sets_max_results(self, mock_get_llm):
|
|
"""Test that max_results is set on search engine."""
|
|
mock_search = MagicMock()
|
|
mock_search.run.return_value = []
|
|
|
|
with patch(
|
|
"local_deep_research.api.research_functions.get_search",
|
|
return_value=mock_search,
|
|
):
|
|
analyze_documents("test query", "test_collection", max_results=50)
|
|
assert mock_search.max_results == 50
|
|
|
|
def test_uses_custom_temperature(self, mock_get_search):
|
|
"""Test that custom temperature is passed to get_llm."""
|
|
with patch(
|
|
"local_deep_research.api.research_functions.get_llm"
|
|
) as mock_llm:
|
|
# Create a mock LLM that returns a proper response
|
|
mock_llm_instance = MagicMock()
|
|
mock_llm_instance.invoke.return_value = MagicMock(
|
|
content="Summary text"
|
|
)
|
|
mock_llm.return_value = mock_llm_instance
|
|
analyze_documents("test query", "test_collection", temperature=0.3)
|
|
mock_llm.assert_called_once()
|
|
assert mock_llm.call_args[1]["temperature"] == 0.3
|
|
|
|
def test_saves_to_file(self, mock_get_llm, tmp_path):
|
|
"""Test saving analysis to file."""
|
|
output_file = str(tmp_path / "analysis.md")
|
|
mock_search = MagicMock()
|
|
mock_search.run.return_value = [
|
|
{
|
|
"title": "Doc 1",
|
|
"link": "https://example.com",
|
|
"content": "Content",
|
|
}
|
|
]
|
|
|
|
with (
|
|
patch(
|
|
"local_deep_research.api.research_functions.get_search",
|
|
return_value=mock_search,
|
|
),
|
|
patch(
|
|
"local_deep_research.security.file_write_verifier.write_file_verified"
|
|
) as mock_write,
|
|
):
|
|
result = analyze_documents(
|
|
"test query", "test_collection", output_file=output_file
|
|
)
|
|
mock_write.assert_called_once()
|
|
assert result["file_path"] == output_file
|
|
|
|
def test_returns_collection_name(self, mock_get_llm, mock_get_search):
|
|
"""Test that result includes collection name."""
|
|
result = analyze_documents("test query", "my_collection")
|
|
assert result["collection"] == "my_collection"
|
|
|
|
def test_returns_document_count(self, mock_get_llm, mock_get_search):
|
|
"""Test that result includes document count."""
|
|
result = analyze_documents("test query", "test_collection")
|
|
assert "document_count" in result
|