Sure, fine cover these lines with tests

This commit is contained in:
stumpylog
2026-08-13 14:15:48 -07:00
parent 7d1e2c3164
commit f113cc030f
2 changed files with 121 additions and 5 deletions
@@ -1079,6 +1079,46 @@ def test_retrieve_similar_nodes_returns_raw_nodes_from_retriever(
assert nodes == [fake_node]
@pytest.mark.django_db
def test_retrieve_similar_nodes_drops_result_outside_allow_list(
mocker: pytest_mock.MockerFixture,
) -> None:
"""
GIVEN:
- An allow-list naming only one document
- A mocked retriever that returns a node for a DIFFERENT document
(as if the vec0-level MetadataFilters had failed to apply)
WHEN:
- retrieve_similar_nodes() is called with that allow-list
THEN:
- The out-of-allow-list node is dropped by this function's own
Python-level re-check, independent of whatever filtering the
vector store itself applied - this is the defense-in-depth layer
for a permission boundary, so it must work standalone.
"""
source = DocumentFactory.create()
allowed = DocumentFactory.create()
not_allowed = DocumentFactory.create()
allowed_node = mocker.MagicMock()
allowed_node.metadata = {"document_id": str(allowed.pk)}
disallowed_node = mocker.MagicMock()
disallowed_node.metadata = {"document_id": str(not_allowed.pk)}
mocker.patch("paperless_ai.indexing.llm_index_exists", return_value=True)
mock_retriever_cls = mocker.patch(
"llama_index.core.retrievers.VectorIndexRetriever",
)
mock_retriever_cls.return_value.retrieve.return_value = [
allowed_node,
disallowed_node,
]
mocker.patch("paperless_ai.indexing.load_or_build_index")
mocker.patch("paperless_ai.indexing.read_store")
nodes = indexing.retrieve_similar_nodes(source, document_ids=[allowed.pk])
assert nodes == [allowed_node]
@pytest.mark.django_db
def test_retrieve_similar_nodes_returns_empty_when_index_missing(
mocker: pytest_mock.MockerFixture,
+81 -5
View File
@@ -273,16 +273,92 @@ class TestBuildTaxonomyCandidates:
THEN:
- Only 5 correspondents are returned
"""
nodes = []
for i in range(7):
correspondent = CorrespondentFactory.create(name=f"Corr{i}")
document = DocumentFactory.create(correspondent=correspondent)
nodes.append(make_node(document.pk, 0.5))
correspondents = CorrespondentFactory.create_batch(7)
nodes = [
make_node(DocumentFactory.create(correspondent=c).pk, 0.5)
for c in correspondents
]
result = build_taxonomy_candidates(nodes, user=None)
assert len(result["correspondents"]) == 5
def test_document_type_candidate_is_surfaced(self) -> None:
"""
GIVEN:
- A neighbour document with a document_type assigned
WHEN:
- build_taxonomy_candidates() is called
THEN:
- The document_type is returned as a candidate
"""
document_type = DocumentTypeFactory.create(name="Invoice")
document = DocumentFactory.create(document_type=document_type)
nodes = [make_node(document.pk, 0.5)]
result = build_taxonomy_candidates(nodes, user=None)
assert len(result["document_types"]) == 1
assert result["document_types"][0]["id"] == document_type.pk
assert result["document_types"][0]["name"] == "Invoice"
def test_document_type_candidates_capped_at_five(self) -> None:
"""
GIVEN:
- 7 documents with different document_types
WHEN:
- build_taxonomy_candidates() is called
THEN:
- Only 5 document_types are returned
"""
document_types = DocumentTypeFactory.create_batch(7)
nodes = [
make_node(DocumentFactory.create(document_type=dt).pk, 0.5)
for dt in document_types
]
result = build_taxonomy_candidates(nodes, user=None)
assert len(result["document_types"]) == 5
def test_storage_path_candidate_is_surfaced(self) -> None:
"""
GIVEN:
- A neighbour document with a storage_path assigned
WHEN:
- build_taxonomy_candidates() is called
THEN:
- The storage_path is returned as a candidate
"""
storage_path = StoragePathFactory.create(name="Invoices")
document = DocumentFactory.create(storage_path=storage_path)
nodes = [make_node(document.pk, 0.5)]
result = build_taxonomy_candidates(nodes, user=None)
assert len(result["storage_paths"]) == 1
assert result["storage_paths"][0]["id"] == storage_path.pk
assert result["storage_paths"][0]["name"] == "Invoices"
def test_storage_path_candidates_capped_at_five(self) -> None:
"""
GIVEN:
- 7 documents with different storage_paths
WHEN:
- build_taxonomy_candidates() is called
THEN:
- Only 5 storage_paths are returned
"""
storage_paths = StoragePathFactory.create_batch(7)
nodes = [
make_node(DocumentFactory.create(storage_path=sp).pk, 0.5)
for sp in storage_paths
]
result = build_taxonomy_candidates(nodes, user=None)
assert len(result["storage_paths"]) == 5
def test_permission_filters_independent_of_neighbour_document_visibility(
self,
mocker: pytest_mock.MockerFixture,