| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 |
- from __future__ import annotations
- import pytest
- class Repository:
- def __init__(self):
- self.calls = []
- def find_property_paths(self, property_uid, *, depth, limit, after_uid):
- self.calls.append((property_uid, depth, limit, after_uid))
- return [
- {
- "path_uid": "path-1",
- "ontology_uid": "ontology-1",
- "ontology_status": "published",
- "property_uid": property_uid,
- "data_element_uid": "element-1",
- "field_uid": "field-1",
- "evidence_uid": "evidence-1",
- "business_domain_uid": "sales",
- "password": "must-not-leak",
- },
- {
- "path_uid": "path-2",
- "ontology_uid": "ontology-draft",
- "ontology_status": "draft",
- "property_uid": property_uid,
- "business_domain_uid": "sales",
- },
- {
- "path_uid": "path-3",
- "ontology_uid": "ontology-hr",
- "ontology_status": "published",
- "property_uid": property_uid,
- "business_domain_uid": "hr",
- },
- ]
- def test_semantic_query_is_bounded_published_permission_filtered_and_redacted():
- from app.core.data_research.ontology.query import SemanticQueryService
- repository = Repository()
- result = SemanticQueryService(repository).trace_property(
- "property-1", allowed_domains={"sales"}, limit=10, after_uid=None
- )
- assert [item["path_uid"] for item in result["items"]] == ["path-1"]
- assert "password" not in repr(result).lower()
- assert repository.calls == [("property-1", 3, 11, None)]
- with pytest.raises(ValueError, match="limit"):
- SemanticQueryService(repository).trace_property(
- "property-1", allowed_domains={"sales"}, limit=51
- )
- def test_semantic_query_has_stable_cursor_and_no_arbitrary_cypher_interface():
- from app.core.data_research.ontology.query import SemanticQueryService
- service = SemanticQueryService(Repository())
- result = service.trace_property("property-1", allowed_domains={"*"}, limit=1)
- assert result["next_cursor"] == "path-1"
- assert not hasattr(service, "execute_cypher")
|