Files
govoplan-decisions/tests/test_search_source.py
T

134 lines
4.5 KiB
Python

from __future__ import annotations
from datetime import UTC, datetime
from types import SimpleNamespace
import unittest
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
from govoplan_core.auth import ApiPrincipal
from govoplan_core.core.access import PrincipalRef
from govoplan_core.core.events import EventObjectRef, EventTenantRef, PlatformEvent
from govoplan_core.core.search import (
SearchAuthorizationRequest,
SearchBackfillRequest,
SearchResourceReference,
)
from govoplan_decisions.backend.db.models import FormalDecisionRevision
from govoplan_decisions.backend.search_source import DecisionsSearchSource, PROVIDER_ID
NOW = datetime(2026, 8, 6, 11, 0, tzinfo=UTC)
class DecisionsSearchSourceTests(unittest.TestCase):
def setUp(self) -> None:
self.engine = create_engine("sqlite+pysqlite:///:memory:")
FormalDecisionRevision.__table__.create(self.engine)
self.session = Session(self.engine)
self.session.add(
FormalDecisionRevision(
tenant_id="tenant-1",
decision_id="decision-1",
revision="1",
decision_type="permit",
state="decided",
valid_from=NOW,
recorded_at=NOW,
payload={
"operative_result": "PROTECTED-RESULT",
"reasoning": "PROTECTED-REASONING",
"conditions": ["PROTECTED-CONDITION"],
"subject_refs": [
{"kind": "party", "owner_module": "parties", "object_id": "applicant-1"}
],
"legal_bases": [
{"authority": "Example", "reference": "law:3", "version": "2026"}
],
"authority_context": {
"case_ref": {"object_id": "case-1"}
},
"delivery_refs": ["postbox:delivery-1"],
"remedy_refs": ["remedy:appeal"],
"review_refs": [],
},
created_by="account-1",
)
)
self.session.commit()
self.source = DecisionsSearchSource()
def tearDown(self) -> None:
self.session.close()
self.engine.dispose()
def test_search_projection_excludes_protected_decision_content(self) -> None:
page = self.source.backfill(
self.session,
request=SearchBackfillRequest(
tenant_id="tenant-1",
provider_id=PROVIDER_ID,
resource_type="formal_decision",
rebuild_id="rebuild-1",
),
)
document = page.documents[0]
serialized = repr(
(document.title, document.summary, document.body, document.keywords, document.metadata)
)
self.assertNotIn("PROTECTED-", serialized)
self.assertEqual("/cases/case-1", document.url)
self.assertFalse(document.metadata["protected_content_indexed"])
reference = SearchResourceReference(
tenant_id="tenant-1",
module_id="decisions",
resource_type="formal_decision",
resource_id="decision-1",
)
request = SearchAuthorizationRequest(reference=reference, source_revision="1")
self.assertTrue(
self.source.authorize(
self.session,
_principal({"decisions:decision:read"}),
requests=(request,),
)[reference.key]
)
self.assertFalse(
self.source.authorize(
self.session,
_principal(set()),
requests=(request,),
)[reference.key]
)
changes = self.source.index_changes_for_event(
self.session,
event=PlatformEvent(
type="decisions.decision.recorded",
module_id="decisions",
tenant=EventTenantRef(id="tenant-1"),
resource=EventObjectRef(type="formal_decision", id="decision-1"),
),
delivery_key="delivery-1",
)
self.assertEqual("upsert", changes[0].kind)
def _principal(scopes: set[str]) -> ApiPrincipal:
return ApiPrincipal(
principal=PrincipalRef(
account_id="account-1",
membership_id="membership-1",
tenant_id="tenant-1",
scopes=frozenset(scopes),
),
account=SimpleNamespace(id="account-1"),
user=SimpleNamespace(id="membership-1"),
)
if __name__ == "__main__":
unittest.main()