feat: strengthen module contracts and shared WebUI runtime
This commit is contained in:
173
tests/test_reference_options.py
Normal file
173
tests/test_reference_options.py
Normal file
@@ -0,0 +1,173 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
from types import SimpleNamespace
|
||||
|
||||
from govoplan_core.core.access import (
|
||||
CAPABILITY_ACCESS_DIRECTORY,
|
||||
AccountRef,
|
||||
GroupRef,
|
||||
UserRef,
|
||||
)
|
||||
from govoplan_core.core.references import (
|
||||
access_scope_reference_options,
|
||||
validate_access_scope_reference,
|
||||
)
|
||||
|
||||
|
||||
class _Directory:
|
||||
users = (
|
||||
UserRef(
|
||||
id="membership-1",
|
||||
account_id="account-1",
|
||||
tenant_id="tenant-1",
|
||||
email="ada@example.test",
|
||||
display_name="Ada",
|
||||
),
|
||||
UserRef(
|
||||
id="membership-2",
|
||||
account_id="account-2",
|
||||
tenant_id="tenant-1",
|
||||
email="inactive@example.test",
|
||||
display_name="Inactive",
|
||||
status="inactive",
|
||||
),
|
||||
)
|
||||
groups = (
|
||||
GroupRef(id="group-1", tenant_id="tenant-1", name="Finance"),
|
||||
GroupRef(
|
||||
id="group-2",
|
||||
tenant_id="tenant-1",
|
||||
name="Former team",
|
||||
status="inactive",
|
||||
),
|
||||
)
|
||||
|
||||
def get_account(self, account_id):
|
||||
if account_id not in {"account-1", "account-2"}:
|
||||
return None
|
||||
return AccountRef(id=account_id, email=f"{account_id}@example.test")
|
||||
|
||||
def get_user(self, user_id):
|
||||
return next((item for item in self.users if item.id == user_id), None)
|
||||
|
||||
def get_users(self, user_ids):
|
||||
return {item.id: item for item in self.users if item.id in set(user_ids)}
|
||||
|
||||
def users_for_tenant(self, tenant_id):
|
||||
return tuple(item for item in self.users if item.tenant_id == tenant_id)
|
||||
|
||||
def get_group(self, group_id):
|
||||
return next((item for item in self.groups if item.id == group_id), None)
|
||||
|
||||
def get_groups(self, group_ids):
|
||||
return {item.id: item for item in self.groups if item.id in set(group_ids)}
|
||||
|
||||
def groups_for_tenant(self, tenant_id):
|
||||
return tuple(item for item in self.groups if item.tenant_id == tenant_id)
|
||||
|
||||
def groups_for_user(self, user_id, *, tenant_id):
|
||||
del user_id
|
||||
return self.groups_for_tenant(tenant_id)
|
||||
|
||||
def display_label(self, subject):
|
||||
return subject.label
|
||||
|
||||
|
||||
class _Registry:
|
||||
directory = _Directory()
|
||||
|
||||
def has_capability(self, name):
|
||||
return name == CAPABILITY_ACCESS_DIRECTORY
|
||||
|
||||
def capability(self, name):
|
||||
return self.directory if self.has_capability(name) else None
|
||||
|
||||
|
||||
class ReferenceOptionTests(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.principal = SimpleNamespace(
|
||||
tenant_id="tenant-1",
|
||||
account_id="account-1",
|
||||
display_name="Ada",
|
||||
email="ada@example.test",
|
||||
group_ids=frozenset({"group-1"}),
|
||||
)
|
||||
|
||||
def test_user_values_are_canonical_account_ids(self) -> None:
|
||||
options = access_scope_reference_options(
|
||||
_Registry(),
|
||||
self.principal,
|
||||
scope_type="user",
|
||||
administrative=True,
|
||||
)
|
||||
|
||||
self.assertEqual(["account-1", "account-2"], [item.value for item in options])
|
||||
self.assertEqual("membership-1", options[0].provenance["membership_id"])
|
||||
self.assertTrue(options[1].disabled)
|
||||
self.assertEqual("inactive", options[1].availability)
|
||||
|
||||
def test_unavailable_selected_values_remain_readable(self) -> None:
|
||||
options = access_scope_reference_options(
|
||||
_Registry(),
|
||||
self.principal,
|
||||
scope_type="group",
|
||||
query="missing",
|
||||
selected_values=("removed-group",),
|
||||
administrative=True,
|
||||
)
|
||||
|
||||
self.assertEqual(1, len(options))
|
||||
self.assertEqual("removed-group", options[0].value)
|
||||
self.assertEqual("unavailable", options[0].availability)
|
||||
self.assertTrue(options[0].disabled)
|
||||
|
||||
def test_non_administrators_only_receive_permitted_scope_targets(self) -> None:
|
||||
users = access_scope_reference_options(
|
||||
_Registry(),
|
||||
self.principal,
|
||||
scope_type="user",
|
||||
administrative=False,
|
||||
)
|
||||
groups = access_scope_reference_options(
|
||||
_Registry(),
|
||||
self.principal,
|
||||
scope_type="group",
|
||||
administrative=False,
|
||||
)
|
||||
|
||||
self.assertEqual(["account-1"], [item.value for item in users])
|
||||
self.assertEqual(["group-1"], [item.value for item in groups])
|
||||
|
||||
def test_inactive_targets_are_rejected_but_existing_values_survive(self) -> None:
|
||||
with self.assertRaisesRegex(ValueError, "Inactive groups"):
|
||||
validate_access_scope_reference(
|
||||
_Registry(),
|
||||
tenant_id="tenant-1",
|
||||
scope_type="group",
|
||||
scope_id="group-2",
|
||||
)
|
||||
self.assertEqual(
|
||||
"group-2",
|
||||
validate_access_scope_reference(
|
||||
_Registry(),
|
||||
tenant_id="tenant-1",
|
||||
scope_type="group",
|
||||
scope_id="group-2",
|
||||
preserve_existing="group-2",
|
||||
),
|
||||
)
|
||||
|
||||
def test_missing_optional_access_provider_keeps_reduced_mode(self) -> None:
|
||||
options = access_scope_reference_options(
|
||||
None,
|
||||
self.principal,
|
||||
scope_type="user",
|
||||
)
|
||||
|
||||
self.assertEqual("account-1", options[0].value)
|
||||
self.assertEqual("core", options[0].source_module)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user