feat(core): require scoped user workflows
This commit is contained in:
85
tests/test_documentation_topic_contract.py
Normal file
85
tests/test_documentation_topic_contract.py
Normal file
@@ -0,0 +1,85 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
|
||||
from govoplan_core.core.modules import (
|
||||
DocumentationCondition,
|
||||
DocumentationTopic,
|
||||
ModuleManifest,
|
||||
user_workflow_scope_condition_issues,
|
||||
)
|
||||
from govoplan_core.core.registry import PlatformRegistry, RegistryError
|
||||
|
||||
|
||||
def workflow_topic(
|
||||
*,
|
||||
conditions: tuple[DocumentationCondition, ...],
|
||||
documentation_types: tuple[str, ...] = ("user",),
|
||||
kind: str = "workflow",
|
||||
) -> DocumentationTopic:
|
||||
return DocumentationTopic(
|
||||
id="example.workflow.task",
|
||||
title="Complete a task",
|
||||
summary="Complete the example task.",
|
||||
documentation_types=documentation_types, # type: ignore[arg-type]
|
||||
conditions=conditions,
|
||||
metadata={"kind": kind},
|
||||
)
|
||||
|
||||
|
||||
class DocumentationTopicContractTests(unittest.TestCase):
|
||||
def test_user_workflow_requires_scope_conditions(self) -> None:
|
||||
topic = workflow_topic(conditions=())
|
||||
|
||||
self.assertEqual(
|
||||
user_workflow_scope_condition_issues(topic),
|
||||
("user workflow topics must declare at least one scope-conditioned alternative",),
|
||||
)
|
||||
with self.assertRaisesRegex(RegistryError, "scope-conditioned alternative"):
|
||||
registry_for(topic).validate()
|
||||
|
||||
def test_every_condition_alternative_must_be_scope_conditioned(self) -> None:
|
||||
topic = workflow_topic(
|
||||
conditions=(
|
||||
DocumentationCondition(required_scopes=("example:item:read",)),
|
||||
DocumentationCondition(required_modules=("example",)),
|
||||
)
|
||||
)
|
||||
|
||||
with self.assertRaisesRegex(RegistryError, r"unscoped alternative\(s\): 2"):
|
||||
registry_for(topic).validate()
|
||||
|
||||
def test_scoped_user_workflow_and_non_user_topics_are_accepted(self) -> None:
|
||||
scoped = workflow_topic(
|
||||
conditions=(
|
||||
DocumentationCondition(required_scopes=("example:item:read",)),
|
||||
DocumentationCondition(any_scopes=("example:item:write", "example:item:admin")),
|
||||
)
|
||||
)
|
||||
admin_workflow = workflow_topic(
|
||||
conditions=(),
|
||||
documentation_types=("admin",),
|
||||
)
|
||||
user_reference = workflow_topic(conditions=(), kind="reference")
|
||||
|
||||
self.assertEqual(user_workflow_scope_condition_issues(scoped), ())
|
||||
self.assertEqual(user_workflow_scope_condition_issues(admin_workflow), ())
|
||||
self.assertEqual(user_workflow_scope_condition_issues(user_reference), ())
|
||||
registry_for(scoped, admin_workflow, user_reference).validate()
|
||||
|
||||
|
||||
def registry_for(*topics: DocumentationTopic) -> PlatformRegistry:
|
||||
registry = PlatformRegistry()
|
||||
registry.register(
|
||||
ModuleManifest(
|
||||
id="example",
|
||||
name="Example",
|
||||
version="1.0.0",
|
||||
documentation=topics,
|
||||
)
|
||||
)
|
||||
return registry
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user