62 lines
1.9 KiB
Python
62 lines
1.9 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
|
|
from govoplan_core.core.access import (
|
|
AccessGovernanceProjectionV1,
|
|
GovernanceProjectionBatch,
|
|
GovernanceProjectionCommand,
|
|
GovernanceProjectionResult,
|
|
GovernanceTemplateMaterialization,
|
|
)
|
|
|
|
|
|
def _command(assignment_id: str) -> GovernanceProjectionCommand:
|
|
return GovernanceProjectionCommand(
|
|
assignment_id=assignment_id,
|
|
operation="upsert",
|
|
template=GovernanceTemplateMaterialization(
|
|
template_id="template-1",
|
|
kind="role",
|
|
tenant_id=f"tenant-{assignment_id}",
|
|
slug="reader",
|
|
name="Reader",
|
|
),
|
|
provenance={"source": "contract-test"},
|
|
)
|
|
|
|
|
|
class _Projection:
|
|
def reconcile(self, session: object, batch: GovernanceProjectionBatch) -> GovernanceProjectionResult:
|
|
del session
|
|
return GovernanceProjectionResult(
|
|
operation_id=batch.operation_id,
|
|
outcomes=(),
|
|
dry_run=batch.dry_run,
|
|
)
|
|
|
|
|
|
class GovernanceProjectionContractTests(unittest.TestCase):
|
|
def test_protocol_is_runtime_checkable(self) -> None:
|
|
self.assertIsInstance(_Projection(), AccessGovernanceProjectionV1)
|
|
|
|
def test_batch_rejects_duplicate_assignment_ids(self) -> None:
|
|
with self.assertRaisesRegex(ValueError, "unique"):
|
|
GovernanceProjectionBatch(
|
|
operation_id="duplicate",
|
|
commands=(_command("same"), _command("same")),
|
|
)
|
|
|
|
def test_batch_enforces_bounds(self) -> None:
|
|
with self.assertRaisesRegex(ValueError, "between 1 and 500"):
|
|
GovernanceProjectionBatch(operation_id="empty", commands=())
|
|
with self.assertRaisesRegex(ValueError, "between 1 and 500"):
|
|
GovernanceProjectionBatch(
|
|
operation_id="large",
|
|
commands=tuple(_command(str(index)) for index in range(501)),
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|