Files
temp/features/steps/domain_repository_protocols_steps.py
freemo 8ea00f5185 fix: restore CI quality tests to passing state (#4175)
Co-authored-by: Jeffrey Phillips Freeman <the@jeffreyfreeman.me>
Co-committed-by: Jeffrey Phillips Freeman <the@jeffreyfreeman.me>
2026-04-08 11:02:14 +00:00

252 lines
8.9 KiB
Python

"""Behave step definitions for domain repository protocol compliance tests.
Verifies that:
1. Protocol interfaces are defined in the domain layer (not infrastructure)
2. Infrastructure repositories satisfy the domain protocols
3. All protocols are runtime-checkable
"""
from __future__ import annotations
from typing import Any
from behave import given, then, when
# ---------------------------------------------------------------------------
# Background
# ---------------------------------------------------------------------------
@given("the domain repository protocols are importable")
def step_protocols_importable(context: Any) -> None:
"""Verify all domain repository protocols can be imported."""
from cleveragents.domain.repositories import (
ActionRepositoryProtocol,
DecisionRepositoryProtocol,
LifecyclePlanRepositoryProtocol,
ProjectRepositoryProtocol,
)
context.protocols = {
"LifecyclePlanRepositoryProtocol": LifecyclePlanRepositoryProtocol,
"ActionRepositoryProtocol": ActionRepositoryProtocol,
"DecisionRepositoryProtocol": DecisionRepositoryProtocol,
"ProjectRepositoryProtocol": ProjectRepositoryProtocol,
}
context.current_protocol = None
# ---------------------------------------------------------------------------
# When — inspect protocol
# ---------------------------------------------------------------------------
@when("I inspect the LifecyclePlanRepositoryProtocol")
def step_inspect_plan_protocol(context: Any) -> None:
context.current_protocol = context.protocols["LifecyclePlanRepositoryProtocol"]
@when("I inspect the ActionRepositoryProtocol")
def step_inspect_action_protocol(context: Any) -> None:
context.current_protocol = context.protocols["ActionRepositoryProtocol"]
@when("I inspect the DecisionRepositoryProtocol")
def step_inspect_decision_protocol(context: Any) -> None:
context.current_protocol = context.protocols["DecisionRepositoryProtocol"]
@when("I inspect the ProjectRepositoryProtocol")
def step_inspect_project_protocol(context: Any) -> None:
context.current_protocol = context.protocols["ProjectRepositoryProtocol"]
# ---------------------------------------------------------------------------
# Then — protocol assertions
# ---------------------------------------------------------------------------
@then("it should be a runtime-checkable Protocol")
def step_is_runtime_checkable(context: Any) -> None:
"""Verify the protocol is decorated with @runtime_checkable."""
proto = context.current_protocol
assert hasattr(proto, "__protocol_attrs__") or hasattr(proto, "_is_protocol"), (
f"{proto} is not a Protocol"
)
is_runtime = getattr(proto, "_is_runtime_protocol", False)
assert is_runtime, f"{proto.__name__} is not @runtime_checkable"
@then('it should define a "{method_name}" method')
def step_defines_method(context: Any, method_name: str) -> None:
"""Verify the protocol defines the named method."""
proto = context.current_protocol
assert hasattr(proto, method_name), (
f"{proto.__name__} does not define method '{method_name}'"
)
assert callable(getattr(proto, method_name)), (
f"{proto.__name__}.{method_name} is not callable"
)
# ---------------------------------------------------------------------------
# Given — infrastructure classes
# ---------------------------------------------------------------------------
@given("the infrastructure LifecyclePlanRepository class")
def step_given_plan_repo(context: Any) -> None:
from cleveragents.infrastructure.database.repositories import (
LifecyclePlanRepository,
)
context.infra_class = LifecyclePlanRepository
context.check_protocol = context.protocols["LifecyclePlanRepositoryProtocol"]
@given("the infrastructure ActionRepository class")
def step_given_action_repo(context: Any) -> None:
from cleveragents.infrastructure.database.repositories import ActionRepository
context.infra_class = ActionRepository
context.check_protocol = context.protocols["ActionRepositoryProtocol"]
@given("the infrastructure DecisionRepository class")
def step_given_decision_repo(context: Any) -> None:
from cleveragents.infrastructure.database.repositories import DecisionRepository
context.infra_class = DecisionRepository
context.check_protocol = context.protocols["DecisionRepositoryProtocol"]
@given("the infrastructure NamespacedProjectRepository class")
def step_given_project_repo(context: Any) -> None:
from cleveragents.infrastructure.database.repositories import (
NamespacedProjectRepository,
)
context.infra_class = NamespacedProjectRepository
context.check_protocol = context.protocols["ProjectRepositoryProtocol"]
# ---------------------------------------------------------------------------
# When — check protocol satisfaction
# ---------------------------------------------------------------------------
@when("I check if it satisfies LifecyclePlanRepositoryProtocol")
def step_check_plan_protocol(context: Any) -> None:
context.protocol_check_result = issubclass(
context.infra_class, context.check_protocol
)
@when("I check if it satisfies ActionRepositoryProtocol")
def step_check_action_protocol(context: Any) -> None:
context.protocol_check_result = issubclass(
context.infra_class, context.check_protocol
)
@when("I check if it satisfies DecisionRepositoryProtocol")
def step_check_decision_protocol(context: Any) -> None:
context.protocol_check_result = issubclass(
context.infra_class, context.check_protocol
)
@when("I check if it satisfies ProjectRepositoryProtocol")
def step_check_project_protocol(context: Any) -> None:
context.protocol_check_result = issubclass(
context.infra_class, context.check_protocol
)
@then("the isinstance check should pass")
def step_isinstance_passes(context: Any) -> None:
assert context.protocol_check_result, (
f"{context.infra_class.__name__} does not satisfy "
f"{context.check_protocol.__name__}"
)
# ---------------------------------------------------------------------------
# When/Then — package exports
# ---------------------------------------------------------------------------
@when("I import from cleveragents.domain.repositories")
def step_import_domain_repositories(context: Any) -> None:
import cleveragents.domain.repositories as repo_pkg
context.repo_pkg = repo_pkg
@then("LifecyclePlanRepositoryProtocol should be available")
def step_plan_protocol_available(context: Any) -> None:
assert hasattr(context.repo_pkg, "LifecyclePlanRepositoryProtocol"), (
"LifecyclePlanRepositoryProtocol not exported from domain.repositories"
)
@then("ActionRepositoryProtocol should be available")
def step_action_protocol_available(context: Any) -> None:
assert hasattr(context.repo_pkg, "ActionRepositoryProtocol"), (
"ActionRepositoryProtocol not exported from domain.repositories"
)
@then("DecisionRepositoryProtocol should be available")
def step_decision_protocol_available(context: Any) -> None:
assert hasattr(context.repo_pkg, "DecisionRepositoryProtocol"), (
"DecisionRepositoryProtocol not exported from domain.repositories"
)
@then("ProjectRepositoryProtocol should be available")
def step_project_protocol_available(context: Any) -> None:
assert hasattr(context.repo_pkg, "ProjectRepositoryProtocol"), (
"ProjectRepositoryProtocol not exported from domain.repositories"
)
# ---------------------------------------------------------------------------
# When/Then — module path checks
# ---------------------------------------------------------------------------
@when("I check the module path of LifecyclePlanRepositoryProtocol")
def step_check_plan_module(context: Any) -> None:
from cleveragents.domain.repositories import LifecyclePlanRepositoryProtocol
context.current_module = LifecyclePlanRepositoryProtocol.__module__
@when("I check the module path of ActionRepositoryProtocol")
def step_check_action_module(context: Any) -> None:
from cleveragents.domain.repositories import ActionRepositoryProtocol
context.current_module = ActionRepositoryProtocol.__module__
@when("I check the module path of DecisionRepositoryProtocol")
def step_check_decision_module(context: Any) -> None:
from cleveragents.domain.repositories import DecisionRepositoryProtocol
context.current_module = DecisionRepositoryProtocol.__module__
@when("I check the module path of ProjectRepositoryProtocol")
def step_check_project_module(context: Any) -> None:
from cleveragents.domain.repositories import ProjectRepositoryProtocol
context.current_module = ProjectRepositoryProtocol.__module__
@then('the module should be under "cleveragents.domain"')
def step_module_under_domain(context: Any) -> None:
assert context.current_module.startswith("cleveragents.domain"), (
f"Protocol module '{context.current_module}' is not under 'cleveragents.domain'"
)