Add scoped postbox template previews

This commit is contained in:
2026-08-06 12:42:20 +02:00
parent c53646a8aa
commit d107c09f74
15 changed files with 1300 additions and 56 deletions
+73
View File
@@ -250,6 +250,63 @@ class PostboxRouterTests(unittest.TestCase):
self.assertEqual(response.status_code, 403)
self.assertIn("not active for this principal", response.text)
def test_template_impact_preview_is_available_without_writes(self) -> None:
with Session(self.engine) as session:
before = session.query(Postbox).count()
response = self.client.post(
"/api/v1/postbox/admin/templates/preview",
json={
"slug": "case-intake",
"name": "Case intake",
"scope_kind": "tenant",
"name_pattern": "{unit_name} / {function_name}",
"address_pattern": "{template_slug}.{unit_slug}.{function_slug}",
"classification": "internal",
},
)
self.assertEqual(200, response.status_code, response.text)
self.assertEqual(1, response.json()["total"])
self.assertEqual(1, response.json()["ready_count"])
with Session(self.engine) as session:
self.assertEqual(before, session.query(Postbox).count())
def test_legacy_subtree_template_remains_readable_but_cannot_be_created_by_api(
self,
) -> None:
with Session(self.engine) as session:
self.service.create_template(
session,
tenant_id="tenant-1",
slug="legacy-subtree",
name="Legacy subtree",
description=None,
function_type_id="clerk-type",
scope_kind="subtree",
scope_id="unit-1",
name_pattern="{unit_name} / {function_name}",
address_pattern="{template_slug}.{unit_slug}.{function_slug}",
classification="internal",
allow_vacant_delivery=True,
actor_id="account-1",
)
session.commit()
listing = self.client.get("/api/v1/postbox/admin/templates")
self.assertEqual(200, listing.status_code, listing.text)
revision = listing.json()["templates"][0]["revisions"][0]
self.assertIsNone(revision["scope_structure_id"])
rejected = self.client.post(
"/api/v1/postbox/admin/templates",
json={
"slug": "new-subtree",
"name": "New subtree",
"scope_kind": "subtree",
"scope_id": "unit-1",
},
)
self.assertEqual(422, rejected.status_code, rejected.text)
def test_directory_delivery_message_and_receipt_round_trip(self) -> None:
directory = self.client.get("/api/v1/postbox/directory")
self.assertEqual(200, directory.status_code, directory.text)
@@ -289,6 +346,20 @@ class PostboxRouterTests(unittest.TestCase):
self.assertEqual(200, filtered.status_code, filtered.text)
self.assertEqual(1, filtered.json()["total"])
grouping = self.client.post(
"/api/v1/postbox/groupings",
json={
"name": "Assigned work",
"is_default": True,
"postbox_ids": [self.postbox_id],
},
)
self.assertEqual(201, grouping.status_code, grouping.text)
grouped_before_read = self.client.get("/api/v1/postbox/groupings")
self.assertEqual(200, grouped_before_read.status_code)
self.assertEqual(1, grouped_before_read.json()["groupings"][0]["total_count"])
self.assertEqual(1, grouped_before_read.json()["groupings"][0]["unread_count"])
acknowledged = self.client.patch(
f"/api/v1/postbox/messages/{message_id}/state",
json={"state": "acknowledged"},
@@ -306,6 +377,8 @@ class PostboxRouterTests(unittest.TestCase):
)
self.assertEqual(200, unread.status_code, unread.text)
self.assertEqual(0, unread.json()["total"])
grouped_after_read = self.client.get("/api/v1/postbox/groupings")
self.assertEqual(0, grouped_after_read.json()["groupings"][0]["unread_count"])
def test_routing_dry_run_explains_default_disabled_state(self) -> None:
response = self.client.post(