mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-07-18 06:24:25 +02:00
Added invokable test
This commit is contained in:
parent
c09dec8b0f
commit
34d5c415bb
56
tests/integration/test_categories_invokable_parents.py
Normal file
56
tests/integration/test_categories_invokable_parents.py
Normal file
@ -0,0 +1,56 @@
|
||||
import os
|
||||
import unittest
|
||||
import yaml
|
||||
|
||||
class TestCategoriesInvokableExclusion(unittest.TestCase):
|
||||
def test_no_child_invokable_if_any_parent_is_invokable(self):
|
||||
"""
|
||||
Verify that if any ancestor in the hierarchy is invokable,
|
||||
none of its descendants may be invokable.
|
||||
"""
|
||||
# locate roles/categories.yml
|
||||
base_dir = os.path.dirname(__file__)
|
||||
yaml_path = os.path.abspath(
|
||||
os.path.join(base_dir, '..', '..', 'roles', 'categories.yml')
|
||||
)
|
||||
|
||||
with open(yaml_path, 'r', encoding='utf-8') as f:
|
||||
data = yaml.safe_load(f)
|
||||
|
||||
violations = []
|
||||
|
||||
def recurse(node: dict, path: list[str], ancestor_invokable: bool):
|
||||
for key, value in node.items():
|
||||
if not isinstance(value, dict):
|
||||
continue
|
||||
|
||||
is_invokable = value.get('invokable', False)
|
||||
current_path = path + [key]
|
||||
|
||||
# Violation: a descendant is invokable despite an invokable ancestor
|
||||
if ancestor_invokable and is_invokable:
|
||||
ancestor_name = '.'.join(path) if path else '<root>'
|
||||
violations.append(
|
||||
f"{'.'.join(current_path)} is invokable, "
|
||||
f"but its ancestor ({ancestor_name}) is also invokable."
|
||||
)
|
||||
|
||||
# Any_invokable = True if this node or any ancestor is invokable
|
||||
new_ancestor_flag = ancestor_invokable or is_invokable
|
||||
|
||||
# Recurse into subcategories
|
||||
for subkey, subval in value.items():
|
||||
if isinstance(subval, dict):
|
||||
recurse({subkey: subval}, current_path, new_ancestor_flag)
|
||||
|
||||
# start at top-level roles, with no invokable ancestor
|
||||
recurse(data.get('roles', {}), [], False)
|
||||
|
||||
if violations:
|
||||
self.fail(
|
||||
"Found invokable descendants under invokable parents:\n"
|
||||
+ "\n".join(violations)
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user