Files
wehub-resource-sync 7a0da7932b
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
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

225 lines
7.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Coverage tests for es_utils.ElasticsearchManager.
Focuses on paths not exercised by the existing test_es_utils.py:
- close() delegates to safe_close
- create_index with no mappings / no settings (default generation paths)
- index_document with refresh=False (default) vs True
- bulk_index_documents with id_field but field absent from doc
- search without highlight (highlight=False branch already covered; add coverage
for custom multi_match type expectation)
- index_file with explicit title_field=None
- index_directory with multiple glob patterns
"""
from unittest.mock import Mock, patch
import pytest
MODULE = "local_deep_research.utilities.es_utils"
# ---------------------------------------------------------------------------
# Shared fixture
# ---------------------------------------------------------------------------
def _make_manager():
"""Return an ElasticsearchManager with a fully mocked ES client."""
mock_client = Mock()
mock_client.info.return_value = {
"cluster_name": "test-cluster",
"version": {"number": "8.0.0"},
}
with patch(f"{MODULE}.Elasticsearch", return_value=mock_client):
from local_deep_research.utilities.es_utils import ElasticsearchManager
mgr = ElasticsearchManager()
return mgr
# ---------------------------------------------------------------------------
# close()
# ---------------------------------------------------------------------------
class TestClose:
def test_close_delegates_to_safe_close(self):
mgr = _make_manager()
with patch(
"local_deep_research.utilities.resource_utils.safe_close"
) as mock_safe_close:
mgr.close()
mock_safe_close.assert_called_once()
# ---------------------------------------------------------------------------
# create_index default mappings / settings paths
# ---------------------------------------------------------------------------
class TestCreateIndexDefaults:
def test_creates_default_mappings_when_none_provided(self):
mgr = _make_manager()
mgr.client.indices.exists.return_value = False
mgr.client.indices.create.return_value = {"acknowledged": True}
result = mgr.create_index("my-index")
assert result is True
call_kwargs = mgr.client.indices.create.call_args[1]
# Default mappings should contain "properties"
assert "properties" in call_kwargs["mappings"]
def test_creates_default_settings_when_none_provided(self):
mgr = _make_manager()
mgr.client.indices.exists.return_value = False
mgr.client.indices.create.return_value = {"acknowledged": True}
mgr.create_index("my-index")
call_kwargs = mgr.client.indices.create.call_args[1]
assert "number_of_shards" in call_kwargs["settings"]
def test_custom_mappings_bypass_defaults(self):
mgr = _make_manager()
mgr.client.indices.exists.return_value = False
mgr.client.indices.create.return_value = {"acknowledged": True}
custom = {"properties": {"field_x": {"type": "keyword"}}}
mgr.create_index("idx", mappings=custom)
call_kwargs = mgr.client.indices.create.call_args[1]
assert call_kwargs["mappings"] == custom
def test_custom_settings_bypass_defaults(self):
mgr = _make_manager()
mgr.client.indices.exists.return_value = False
mgr.client.indices.create.return_value = {"acknowledged": True}
custom_settings = {"number_of_shards": 5, "number_of_replicas": 1}
mgr.create_index("idx", settings=custom_settings)
call_kwargs = mgr.client.indices.create.call_args[1]
assert call_kwargs["settings"] == custom_settings
# ---------------------------------------------------------------------------
# index_document refresh variants and document_id=None
# ---------------------------------------------------------------------------
class TestIndexDocumentVariants:
def test_document_id_none_passes_none_to_client(self):
mgr = _make_manager()
mgr.client.index.return_value = {"_id": "auto-generated-id"}
result = mgr.index_document("idx", {"title": "doc"}, document_id=None)
assert result == "auto-generated-id"
call_kwargs = mgr.client.index.call_args[1]
assert call_kwargs["id"] is None
def test_refresh_false_is_default(self):
mgr = _make_manager()
mgr.client.index.return_value = {"_id": "abc"}
mgr.index_document("idx", {"title": "doc"})
call_kwargs = mgr.client.index.call_args[1]
assert call_kwargs["refresh"] is False
# ---------------------------------------------------------------------------
# bulk_index_documents id_field absent from doc
# ---------------------------------------------------------------------------
class TestBulkIndexIdFieldAbsent:
def test_missing_id_field_docs_omit_id(self):
mgr = _make_manager()
with patch(f"{MODULE}.bulk", return_value=(2, 0)) as mock_bulk:
docs = [{"title": "no-id-field-here"}, {"title": "also-no-id"}]
result = mgr.bulk_index_documents("idx", docs, id_field="doc_id")
assert result == 2
actions = mock_bulk.call_args[0][1]
for action in actions:
assert "_id" not in action
# ---------------------------------------------------------------------------
# search query structure
# ---------------------------------------------------------------------------
class TestSearchQueryStructure:
def test_search_uses_best_fields_type(self):
mgr = _make_manager()
mgr.client.search.return_value = {"hits": {"hits": []}}
mgr.search("idx", "quantum computing")
call_kwargs = mgr.client.search.call_args[1]
body = call_kwargs["body"]
assert body["query"]["multi_match"]["type"] == "best_fields"
def test_search_uses_tie_breaker(self):
mgr = _make_manager()
mgr.client.search.return_value = {"hits": {"hits": []}}
mgr.search("idx", "test")
body = mgr.client.search.call_args[1]["body"]
assert body["query"]["multi_match"]["tie_breaker"] == pytest.approx(0.3)
def test_search_highlight_uses_em_tags(self):
mgr = _make_manager()
mgr.client.search.return_value = {"hits": {"hits": []}}
mgr.search("idx", "test", highlight=True)
body = mgr.client.search.call_args[1]["body"]
assert body["highlight"]["pre_tags"] == ["<em>"]
assert body["highlight"]["post_tags"] == ["</em>"]
# ---------------------------------------------------------------------------
# index_file title_field=None branch
# ---------------------------------------------------------------------------
class TestIndexFileTitleFieldNone:
def test_title_field_none_excludes_title_from_doc(self, tmp_path):
mgr = _make_manager()
mock_doc = Mock()
mock_doc.page_content = "file content"
mock_doc.metadata = {"source": "test"}
mock_loader = Mock()
mock_loader.load.return_value = [mock_doc]
mock_loader_class = Mock(return_value=mock_loader)
indexed_doc = {}
def _capture_index(index_name, document, refresh=False):
indexed_doc.update(document)
return "doc-id"
mgr.index_document = _capture_index
with patch(
"langchain_community.document_loaders.UnstructuredFileLoader",
mock_loader_class,
):
mgr.index_file(
"idx",
str(tmp_path / "report.txt"),
title_field=None,
)
# title should not be in the document when title_field is None
assert "title" not in indexed_doc