feat: strengthen module contracts and shared WebUI runtime
This commit is contained in:
@@ -8,6 +8,8 @@ from unittest.mock import patch
|
||||
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.testclient import TestClient
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from govoplan_core.audit.logging import audit_event, audit_operation_context
|
||||
from govoplan_core.core.events import (
|
||||
@@ -17,6 +19,7 @@ from govoplan_core.core.events import (
|
||||
EventTenantRef,
|
||||
PlatformEvent,
|
||||
current_event_trace,
|
||||
emit_platform_event,
|
||||
event_bus_context,
|
||||
event_context,
|
||||
normalize_trace_id,
|
||||
@@ -31,13 +34,60 @@ from tests.db_isolation import temporary_database
|
||||
|
||||
|
||||
def _configure_audit_runtime() -> None:
|
||||
registry = build_platform_registry(("audit",))
|
||||
registry = build_platform_registry(("access", "audit"))
|
||||
context = ModuleContext(registry=registry, settings=object())
|
||||
registry.configure_capability_context(context)
|
||||
configure_runtime(context)
|
||||
|
||||
|
||||
class CoreEventTests(unittest.TestCase):
|
||||
def test_fallback_event_waits_for_outer_commit_after_savepoint(self) -> None:
|
||||
engine = create_engine("sqlite:///:memory:")
|
||||
seen: list[PlatformEvent] = []
|
||||
bus = EventBus()
|
||||
bus.subscribe("*", seen.append)
|
||||
try:
|
||||
with Session(engine) as session, event_bus_context(bus):
|
||||
with session.begin():
|
||||
with session.begin_nested():
|
||||
emit_platform_event(
|
||||
session,
|
||||
PlatformEvent(type="nested.created", module_id="core"),
|
||||
)
|
||||
self.assertEqual([], seen)
|
||||
self.assertEqual(
|
||||
["nested.created"],
|
||||
[event.type for event in seen],
|
||||
)
|
||||
finally:
|
||||
engine.dispose()
|
||||
|
||||
def test_fallback_event_discards_only_rolled_back_savepoint(self) -> None:
|
||||
engine = create_engine("sqlite:///:memory:")
|
||||
seen: list[PlatformEvent] = []
|
||||
bus = EventBus()
|
||||
bus.subscribe("*", seen.append)
|
||||
try:
|
||||
with Session(engine) as session, event_bus_context(bus):
|
||||
with session.begin():
|
||||
emit_platform_event(
|
||||
session,
|
||||
PlatformEvent(type="outer.created", module_id="core"),
|
||||
)
|
||||
savepoint = session.begin_nested()
|
||||
emit_platform_event(
|
||||
session,
|
||||
PlatformEvent(type="nested.created", module_id="core"),
|
||||
)
|
||||
savepoint.rollback()
|
||||
self.assertEqual([], seen)
|
||||
self.assertEqual(
|
||||
["outer.created"],
|
||||
[event.type for event in seen],
|
||||
)
|
||||
finally:
|
||||
engine.dispose()
|
||||
|
||||
def test_event_bus_adds_trace_ids_and_propagates_causation_to_nested_events(self) -> None:
|
||||
bus = EventBus()
|
||||
seen: list[PlatformEvent] = []
|
||||
@@ -267,6 +317,11 @@ class CoreEventTests(unittest.TestCase):
|
||||
object_id="user-2",
|
||||
details={"password": "secret", "field": "display_name"},
|
||||
)
|
||||
session.commit()
|
||||
from govoplan_audit.backend.outbox import SqlAuditOutbox
|
||||
|
||||
SqlAuditOutbox().dispatch_pending(session)
|
||||
session.commit()
|
||||
|
||||
action_events = [event for event in seen if event.type == "user.updated"]
|
||||
self.assertEqual(1, len(action_events))
|
||||
@@ -315,6 +370,11 @@ class CoreEventTests(unittest.TestCase):
|
||||
object_type="demo",
|
||||
object_id=action,
|
||||
)
|
||||
session.commit()
|
||||
from govoplan_audit.backend.outbox import SqlAuditOutbox
|
||||
|
||||
SqlAuditOutbox().dispatch_pending(session)
|
||||
session.commit()
|
||||
|
||||
by_type = {event.type: event.module_id for event in seen if event.type in cases}
|
||||
self.assertEqual(cases, by_type)
|
||||
|
||||
Reference in New Issue
Block a user