Release govoplan-search v0.1.20: centralize filtering and refresh behavior
Module Package Release / publish-packages (push) Successful in 11s
Module Package Release / publish-packages (push) Successful in 11s
This commit is contained in:
@@ -26,6 +26,27 @@ class SearchDocumentationTests(unittest.TestCase):
|
||||
for topic in manifest.documentation:
|
||||
self.assertEqual((), user_workflow_scope_condition_issues(topic))
|
||||
|
||||
def test_filter_workflow_documents_tri_state_context_and_stale_reads(self) -> None:
|
||||
topic = next(
|
||||
item
|
||||
for item in manifest.documentation
|
||||
if item.id == "search.global-and-contextual"
|
||||
)
|
||||
steps = " ".join(topic.metadata["steps"])
|
||||
german = topic.structured_translations["de"]
|
||||
german_steps = " ".join(german["steps"])
|
||||
self.assertIn("Modules and Result types dropdowns", steps)
|
||||
self.assertIn("Deselect all intentionally shows no results", steps)
|
||||
self.assertIn("Clear filters keeps the selected context and query", steps)
|
||||
self.assertIn("Escape closes the open dropdown first", steps)
|
||||
self.assertIn("Alle abwählen zeigt bewusst keine Ergebnisse", german_steps)
|
||||
self.assertIn("gewählten Kontext und Suchbegriff", german_steps)
|
||||
self.assertIn("Escape schließt zuerst", german_steps)
|
||||
for metadata in (topic.metadata, german):
|
||||
self.assertIn("change_filters", metadata["operational_consequences"])
|
||||
self.assertEqual(4, len(metadata["limitations"]))
|
||||
self.assertEqual(5, len(metadata["verification"]))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -232,6 +232,63 @@ class SearchServiceTests(unittest.TestCase):
|
||||
self.assertEqual("Cases", catalogue[0].label)
|
||||
self.assertEqual(25, catalogue[0].order)
|
||||
|
||||
def test_legacy_empty_filters_remain_unrestricted_with_current_acl(self) -> None:
|
||||
service = SearchIndexService(_Registry(active_modules=("search", "cases", "files", "mail")))
|
||||
for module_id, resource_type, resource_id, title, allowed in (
|
||||
("cases", "case", "case-1", "Permit A", True),
|
||||
("files", "file", "file-1", "Permit B", True),
|
||||
("mail", "message", "message-1", "Permit C", True),
|
||||
("files", "folder", "folder-1", "Permit D", True),
|
||||
("files", "file", "restricted", "Permit E", False),
|
||||
):
|
||||
service.upsert_document(self.session, self.principal, document=SearchDocument(
|
||||
tenant_id="tenant-1", module_id=module_id, resource_type=resource_type,
|
||||
resource_id=resource_id, title=title, url=f"/{module_id}/{resource_id}",
|
||||
acl_tokens=("account:account-1" if allowed else "account:someone-else",),
|
||||
))
|
||||
self.session.flush()
|
||||
|
||||
results = service.search(self.session, self.principal, query=SearchQuery(
|
||||
text="permit", tenant_id="tenant-1", module_ids=(), resource_types=(),
|
||||
))
|
||||
self.assertEqual(
|
||||
{"case-1", "file-1", "message-1", "folder-1"},
|
||||
{result.resource_id for result in results},
|
||||
)
|
||||
# The UI's explicit-none state must not be serialized as legacy empty
|
||||
# tuples: empty tuples intentionally keep existing callers unrestricted.
|
||||
narrowed = service.search(self.session, self.principal, query=SearchQuery(
|
||||
text="permit", tenant_id="tenant-1",
|
||||
module_ids=("cases", "files"), resource_types=("case", "file"),
|
||||
))
|
||||
self.assertEqual({"case-1", "file-1"}, {result.resource_id for result in narrowed})
|
||||
before_limit = service.search(self.session, self.principal, query=SearchQuery(
|
||||
text="permit", tenant_id="tenant-1", module_ids=("files",), resource_types=("file",), limit=1,
|
||||
))
|
||||
self.assertEqual(["file-1"], [result.resource_id for result in before_limit])
|
||||
unknown = service.search(self.session, self.principal, query=SearchQuery(
|
||||
text="permit", tenant_id="tenant-1", module_ids=("not-an-installed-module",),
|
||||
))
|
||||
self.assertEqual((), unknown)
|
||||
|
||||
def test_cursor_cannot_be_reused_after_filter_or_context_changes(self) -> None:
|
||||
registry = _AggregateRegistry()
|
||||
first = aggregate_search_page(registry, self.session, self.principal, query=SearchQuery(
|
||||
text="permit", tenant_id="tenant-1", limit=2,
|
||||
))
|
||||
self.assertIsNotNone(first.next_cursor)
|
||||
for changed in (
|
||||
{"module_ids": ("cases",)},
|
||||
{"resource_types": ("case",)},
|
||||
{"context_kind": "module"},
|
||||
{"context_id": "cases.selected-case"},
|
||||
{"language": "german"},
|
||||
):
|
||||
with self.subTest(changed=changed), self.assertRaisesRegex(ValueError, "cursor"):
|
||||
aggregate_search_page(registry, self.session, self.principal, query=SearchQuery(
|
||||
text="permit", tenant_id="tenant-1", limit=2, cursor=first.next_cursor, **changed,
|
||||
))
|
||||
|
||||
def test_upsert_replaces_acl_tokens_and_delete_is_idempotent(self) -> None:
|
||||
document = SearchDocument(
|
||||
tenant_id="tenant-1",
|
||||
|
||||
Reference in New Issue
Block a user